WO2024045379A1 - 编译方法和编译器、Wasm虚拟机 - Google Patents
编译方法和编译器、Wasm虚拟机 Download PDFInfo
- Publication number
- WO2024045379A1 WO2024045379A1 PCT/CN2022/135270 CN2022135270W WO2024045379A1 WO 2024045379 A1 WO2024045379 A1 WO 2024045379A1 CN 2022135270 W CN2022135270 W CN 2022135270W WO 2024045379 A1 WO2024045379 A1 WO 2024045379A1
- Authority
- WO
- WIPO (PCT)
- Prior art keywords
- code
- class
- function
- wasm
- reflection function
- Prior art date
Links
- 238000000034 method Methods 0.000 title claims abstract description 149
- 230000006870 function Effects 0.000 claims description 348
- 230000001419 dependent effect Effects 0.000 claims description 20
- 238000003860 storage Methods 0.000 claims description 17
- 230000008569 process Effects 0.000 description 56
- 238000011161 development Methods 0.000 description 12
- 238000012545 processing Methods 0.000 description 12
- 238000010586 diagram Methods 0.000 description 11
- 230000006872 improvement Effects 0.000 description 10
- 238000004458 analytical method Methods 0.000 description 9
- 238000004590 computer program Methods 0.000 description 8
- 230000007246 mechanism Effects 0.000 description 8
- 230000006399 behavior Effects 0.000 description 6
- 238000005516 engineering process Methods 0.000 description 6
- 230000008676 import Effects 0.000 description 6
- 230000003068 static effect Effects 0.000 description 6
- 239000008186 active pharmaceutical agent Substances 0.000 description 5
- 238000004364 calculation method Methods 0.000 description 5
- 239000000047 product Substances 0.000 description 5
- 238000013507 mapping Methods 0.000 description 4
- 230000004048 modification Effects 0.000 description 4
- 238000012986 modification Methods 0.000 description 4
- 244000035744 Hura crepitans Species 0.000 description 3
- 229910052799 carbon Inorganic materials 0.000 description 3
- 238000004891 communication Methods 0.000 description 3
- 230000008878 coupling Effects 0.000 description 3
- 238000010168 coupling process Methods 0.000 description 3
- 238000005859 coupling reaction Methods 0.000 description 3
- 230000014509 gene expression Effects 0.000 description 3
- 238000013519 translation Methods 0.000 description 3
- 238000006243 chemical reaction Methods 0.000 description 2
- 239000000463 material Substances 0.000 description 2
- 230000003287 optical effect Effects 0.000 description 2
- 238000005457 optimization Methods 0.000 description 2
- OKTJSMMVPCPJKN-UHFFFAOYSA-N Carbon Chemical compound [C] OKTJSMMVPCPJKN-UHFFFAOYSA-N 0.000 description 1
- 108010001267 Protein Subunits Proteins 0.000 description 1
- 238000009825 accumulation Methods 0.000 description 1
- 230000005540 biological transmission Effects 0.000 description 1
- 239000006227 byproduct Substances 0.000 description 1
- 230000001413 cellular effect Effects 0.000 description 1
- 230000008859 change Effects 0.000 description 1
- 238000013461 design Methods 0.000 description 1
- 230000000694 effects Effects 0.000 description 1
- 229910021389 graphene Inorganic materials 0.000 description 1
- 230000003993 interaction Effects 0.000 description 1
- 230000002452 interceptive effect Effects 0.000 description 1
- JEIPFZHSYJVQDO-UHFFFAOYSA-N iron(III) oxide Inorganic materials O=[Fe]O[Fe]=O JEIPFZHSYJVQDO-UHFFFAOYSA-N 0.000 description 1
- 238000004519 manufacturing process Methods 0.000 description 1
- 230000008520 organization Effects 0.000 description 1
- 230000002085 persistent effect Effects 0.000 description 1
- 229920001296 polysiloxane Polymers 0.000 description 1
- 230000000750 progressive effect Effects 0.000 description 1
- 239000010979 ruby Substances 0.000 description 1
- 229910001750 ruby Inorganic materials 0.000 description 1
- 238000006467 substitution reaction Methods 0.000 description 1
- 238000012795 verification Methods 0.000 description 1
Images
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/40—Transformation of program code
- G06F8/41—Compilation
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/40—Transformation of program code
- G06F8/41—Compilation
- G06F8/44—Encoding
- G06F8/443—Optimisation
- G06F8/4434—Reducing the memory space required by the program code
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/70—Software maintenance or management
- G06F8/73—Program documentation
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F9/00—Arrangements for program control, e.g. control units
- G06F9/06—Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
- G06F9/44—Arrangements for executing specific programs
- G06F9/455—Emulation; Interpretation; Software simulation, e.g. virtualisation or emulation of application or operating system execution engines
- G06F9/45504—Abstract machines for programme code execution, e.g. Java virtual machine [JVM], interpreters, emulators
Definitions
- the embodiments of this specification belong to the field of compiler technology, and particularly relate to a compilation method, compiler, and Wasm virtual machine.
- WebAssembly (also abbreviated as Wasm) is an open standard developed by the W3C Community Group. It is a safe and portable low-level code format designed for efficient execution and compact representation. It can run with near-native performance and is used for applications such as C , C++, Java, Go and other languages provide a compilation target.
- the Wasm virtual machine was originally designed to solve the increasingly severe performance problems of Web programs. Due to its superior features, it is adopted by more and more non-Web projects, such as replacing the blockchain smart contract execution engine EVM.
- the object of the present invention is to provide a compilation method, a compiler, and a Wasm virtual machine, including: a method for compiling codes containing reflection functions, including: the compiler scans the reflection function codes starting from the program entry of the code, and passes The annotation obtains the class used in the reflection function code and the functions used by the class; the compiler obtains the class used by the annotation and the function used in the class that the code containing the reflection function depends on. The codes of the functions used by the class are added to the to-be-compiled list; the compiler compiles the to-be-compiled list to obtain Wasm bytecode.
- a compiler includes: a scanning unit, which scans reflection function codes starting from the program entry of the code, and obtains the classes used in the reflection function codes and the functions used by the classes through annotations; an adding unit, which includes In the class on which the code of the reflection function depends, the class used by the annotation and the code of the function used in the class are added to the to-be-compiled list; the compilation unit compiles the to-be-compiled list to obtain the Wasm word section code.
- a computer device including: a processor; and a memory, in which a program is stored, wherein when the processor executes the program, the following operations are performed: scanning the reflection function code starting from the program entry of the code, and obtaining all the results through annotations. Describe the classes used in the reflection function code and the functions used by this class; the code of the class used and the functions used by this class obtained from the annotation in the class on which the code containing the reflection function depends Add it to the list to be compiled; compile the list to be compiled to obtain Wasm bytecode.
- a storage medium used to store a program wherein the program performs the following operations when executed: scanning the reflection function code starting from the program entry of the code, and obtaining the classes used in the reflection function code and the class through annotations The functions used; add the code of the class used by the annotation and the functions used by the class in the class on which the code containing the reflection function depends to the list to be compiled; to the list to be compiled Compile and get Wasm bytecode.
- Compilation enables the compiler's compilation process to have the ability to "compile on demand". In this way, not only the complexity and workload of the compiler are reduced, but the size of the compilation results can also be greatly reduced. Moreover, the smaller size of the compilation result will also greatly reduce the code loaded into the linear memory of the Wasm virtual machine, thereby improving the overall performance of the Wasm virtual machine.
- Figure 1 is a schematic diagram of the compilation and execution process of a Java program in an embodiment
- Figure 2 is a flow chart of the process in which a compiler can compile Java source code into a Wasm file
- Figure 3 is a schematic diagram of the bytecode structure and virtual machine module in an embodiment
- Figure 4 is a schematic diagram, that is, a relationship diagram of tables in linear memory and tables in ordinary memory in one embodiment
- FIG. 5 is a flowchart of an embodiment in which Java is used to develop and the Wasm bytecode is obtained after compilation by a compiler.
- the Wasm bytecode is run on various platforms integrated with the Wasm virtual machine;
- Figure 6 is a flow chart of a compilation method in an embodiment.
- High-level computer language is convenient for people to write, read, communicate, and maintain, while machine language can be directly interpreted and run by computers.
- a compiler can take an assembly or high-level computer language source program (Source program) as input and translate it into an equivalent program in the target language (Target language) machine code.
- the source code is generally a high-level language (High-level language), such as C, C++, etc., while the target is the object code (Object code) of machine language, sometimes also called machine code (Machine code).
- object code object code
- Machine code Machine code
- machine code also referred to as "microprocessor instructions”
- This method is generally called “compilation and execution”.
- Compiled execution generally does not have cross-platform scalability. Since there are different manufacturers, different brands and different generations of CPUs, the instruction sets supported by these different CPUs are often different, such as x86 instruction set, ARM instruction set, etc., and CPUs of the same brand but different generations from the same manufacturer ( For example, the instruction sets supported by different generations of Intel CPUs are not exactly the same. Therefore, the same program code written in the same high-level language may have different machine codes converted by the compiler on different CPUs. Specifically, in the process of converting program code written in a high-level language into machine code, the compiler will optimize based on the characteristics of specific CPU instruction sets (such as vector instruction sets, etc.) to improve the speed of program execution, and such optimizations often Depends on specific CPU hardware.
- specific CPU instruction sets such as vector instruction sets, etc.
- one of the same machine codes can run on the x86 platform, but the other one may not run on ARM; even for the same x86 platform, the instruction set continues to be enriched and expanded over time, which leads to different The machine code running on different generations of x86 platforms is also different. Moreover, since executing machine code requires the CPU to be scheduled by the operating system kernel, even the same hardware may support different machine codes running under different operating systems.
- Java source code is compiled into standard bytecode through the Java compiler.
- the compiler here does not target the instruction set of any actual hardware processor, but defines a set of abstract standard instruction sets.
- the compiled standard bytecode generally cannot be run directly on the hardware CPU, so a virtual machine, namely JVM, is introduced.
- the JVM runs on a specific hardware processor to interpret and execute the compiled standard bytecode.
- JVM is the abbreviation of Java Virtual Machine. It is a fictitious computer that is often implemented by simulating various computer functions on an actual computer.
- the JVM shields information related to specific hardware platforms, operating systems, etc., so that Java programs only need to be generated standard bytecode that can be run on the Java virtual machine, and can run on multiple platforms without modification.
- Java virtual machine A very important feature of the Java language is its independence from the platform.
- the use of Java virtual machine is the key to achieving this feature. If a general high-level language wants to run on different platforms, it must at least be compiled into different target codes. After the introduction of the Java language virtual machine, the Java language does not need to be recompiled when running on different platforms.
- the Java language uses the Java virtual machine to shield information related to specific platforms, so that the Java language compiler only needs to generate the target code (bytecode) that runs on the Java virtual machine, and it can run on multiple platforms without modification. .
- the Java virtual machine executes bytecode, it interprets the bytecode into machine instructions for execution on the specific platform. This is why Java can "compile once, run anywhere". In this way, as long as the JVM can correctly execute the .class file, it can run on different operating system platforms such as Linux, Windows, and MacOS.
- the JVM runs on a specific hardware processor and is responsible for interpreting and executing bytecodes for the specific processor it is running on, shielding these underlying differences upwards and presenting standard development specifications to developers.
- the JVM executes bytecode, it actually ultimately interprets the bytecode into machine instructions for execution on the specific platform. Specifically, after the JVM receives the input bytecode, it interprets each instruction step by step and translates it into machine code suitable for the current machine to run. These processes are interpreted and executed, for example, by an interpreter called an Interpreter. In this way, developers who write Java programs do not need to consider which hardware platform the written program code will run on.
- the development of the JVM itself is done by professional developers from the Java organization to adapt the JVM to different processor architectures.
- the compilation and execution process of the above Java program is shown in Figure 1.
- the Java source code developed by developers generally uses .java as the extension.
- the source files are compiled by the compiler to generate files with a .class extension.
- These .class files are bytecodes.
- Bytecode instructions also known as opcodes.
- the JVM completes program execution by parsing these opcodes and operands.
- When using the Java command to run a .class file it is actually equivalent to starting a JVM process in the operating system and applying for a portion of memory from the operating system.
- This part of memory is generally managed directly by the virtual machine, and can specifically include method area, heap area, stack area, etc.
- JVM executes by translating these bytecodes, including two execution methods.
- Java has become a mature programming language.
- One aspect is to reduce the size of the .class file compiled by the compiler.
- a large number of dependent libraries are integrated into the JVM and a standardized API is provided.
- the Java source code developed by the developer includes two files, Person.java and Main.java, and the header statement of the main.java file imports Person.
- Main and its dependent Person files will also involve more dependent classes at runtime, such as the default parent class and ancestor classes (a specific example is the indirectly dependent string class String.class).
- JVM does not integrate a large number of dependent libraries, person, main and dependent classes need to be compiled together during the compilation process, and the resulting compiled .class files will be larger and the overall volume will be larger.
- the JVM needs to load fewer .class files from the outside through the class loader during the execution of the Java program, and the size is also smaller. However, it still needs to load dependent classes from the inside, such as It is loaded via local file or network.
- dependent classes from the inside, such as It is loaded via local file or network.
- JVM dynamic loading feature of JVM.
- the dynamic loading feature means that the JVM does not load all classes into memory at once, but loads classes on demand. Specifically, the JVM only loads a class when it uses a class that has not yet been loaded.
- the dynamic class loading feature of the JVM allows the Java program to control the loading of different implementation classes based on conditions during runtime, thereby reducing memory usage. The amount of memory occupied directly affects the execution efficiency of the JVM.
- Java use a virtual machine running on a common hardware instruction set such as x86, and then execute their own "assembly language" (such as Java Bytecode).
- the Web platform also uses a virtual machine environment similar to Java and Python on the browser.
- the browser provides a virtual machine environment to execute some JavaScript or other scripting languages, thereby realizing the interactive behavior of HTML pages and the specific behaviors of some web pages.
- Specific behaviors of web pages such as embedding dynamic text.
- JavaScript In addition to the complex logic and large amount of code, there is another reason for the shortcomings of the JavaScript language itself - JavaScript does not have static variable types, which reduces efficiency. Specifically, the JavaScript engine will cache and optimize functions that are executed more frequently in the JavaScript code. For example, the JavaScript engine will compile such code into machine code, package it and send it to the JIT Compiler, which will compile it into machine code; next time When this function is executed, the compiled machine code will be executed directly. However, since JavaScript uses dynamic variables, this variable may have been an array (Array) last time and may become an object (Object) next time. In this way, the optimization done by JIT Compiler last time will lose its effect, and it will have to be optimized again next time.
- Array array
- Object object
- WebAssembly (also abbreviated as Wasm) appeared.
- WebAssembly is an open standard developed by the W3C Community Group. It is a safe, portable, low-level code format designed for efficient execution and compact representation, and can run with near-native performance.
- WebAssembly is code compiled by a compiler. It is small in size, fast to start, completely separated from JavaScript in syntax, and has a sandboxed execution environment. WebAssembly uses static types, which improves execution efficiency.
- WebAssembly brings many programming languages to the Web.
- WebAssembly further simplifies some execution processes, which also brings about a significant improvement in execution efficiency.
- WebAssembly is a new format that is portable, small, fast loading, and compatible with the Web. It can be used as a compilation target for C/C++/Rust/Java, etc. WebAssembly can be regarded as the x86 hardware general instruction set of the Web platform. As a layer of intermediate language, the upper layer connects to Java, Python, Rust, C++, etc., so that these languages can be compiled into a unified format for running on the Web platform.
- source files developed in C++ language generally have .cpp as the extension.
- the cpp file is compiled by the compiler and can generate bytecode in Wasm format.
- source files developed in the Java language generally have .java as the extension.
- the java file is compiled by the compiler and can generate bytecode in Wasm format.
- Wasm format bytecode can be encapsulated in wasc files.
- wasc is a file that combines bytecode and ABI (Application Binary Interface, Application Binary Interface).
- the WebAssembly virtual machine (also known as the Wasm virtual machine or the Wasm runtime environment, which is a virtual machine runtime environment that executes Wasm bytecode) implemented in accordance with the W3C community open standard is implemented by loading the Wasm bytecode at runtime and interpreting the execution.
- the Wasm virtual machine was originally designed to solve the increasingly severe performance problems of Web programs. Due to its superior features, it is adopted by more and more non-Web projects, such as replacing the smart contract execution engine EVM in the blockchain. .
- Reflection mechanism also known as reflective programming, refers to the ability of a computer program to access, detect, and modify its own state or behavior while it is running.
- the reflective programming function in the Java programming language is a commonly used function, which typically supports dynamic execution, while the Wasm bytecode standard does not directly support the reflection function.
- high-level languages with reflective programming functions also include C#, Python, Go language, etc. Some parts of this application mainly use Java as an example for explanation. Of course, it is also applicable to C#, Python, Go language, etc.
- smart contracts developed by developers can provide different functions to achieve different functions, and subsequent contract callers can dynamically call one or some functions in the contract to achieve specific functions.
- developers For high-level programming languages that do not support the reflection function, developers generally need to explicitly write in the code the conversion of method names to method calls involved in calling different functions when developing contracts. The code is relatively cumbersome and lengthy.
- developers can use the reflection function in the code to flexibly and easily implement the conversion from method names to method calls involved in calling different functions when developing contracts.
- the above code segment 1 in the C++ contract provides functions such as sum and multiply for contract callers to initiate calls and pass in parameters. Because in a certain contract call, the contract cannot know in advance which specific function in the contract will be called by the initiated contract call transaction, so if branches are usually used to match the initiated contract call. After matching, pass in the corresponding parameters to execute the function and return the result. This method simulates dynamic execution. For situations where there are many functions in the contract, this part of the code is more cumbersome and lengthy.
- Main.java of code segment 3 Person is first imported and the class main is defined.
- the function main is defined in class main.
- the method name and two integer type parameters are obtained through the method on lines 5-6.
- the function corresponding to the method name is called and parameters 123 and 234 are entered.
- lines 5-6 contain the reflection function, that is, through person.class.getMethod(methodName, int.class, int.class), the class to which the object person belongs (including other subclasses inherited from the Object class) has the same
- the function name has the same input parameters and output parameters (or return type) (the function name, input parameters, and output parameters are also called function signatures); in the code on line 7, the retrieved function is used to complete the calculation and return the calculation result. In this way, especially when there are multiple functions, it is not necessary to match each function name like the multi-conditional branch structure used to simulate dynamic execution in the above C++ code.
- the java files of the above code segment 2 and code segment 3 are compiled by the compiler and can generate bytecode in Wasm format.
- the Wasm virtual machine is different from the JVM.
- the Wasm virtual machine does not integrate a large number of libraries that Java/Wasm files need to depend on. Therefore, in the process of compiling Java files into Wasm bytecode, the compiler needs to convert the dependent classes into Compile together. For example, the Person in the code segment 2 imported in line 1 of the above code segment 3, that is, in the process of compiling the Wasm bytecode of main, all functions of the dependent Person class need to be compiled together.
- the above only shows two classes, Person and Main.
- the Person type depends on the String type (because the parameters and return type of the Person type method hello are String types).
- the String class includes many methods, but most of the time only a small part of them are used in a program. In this way, a large number of indirectly dependent classes will also be compiled together, and a large number of functions in these indirectly dependent classes that will not be called later are also compiled by the compiler, and the resulting compilation results will occupy a larger area. volume.
- the Wasm virtual machine does not have the ability to dynamically load, but needs to load all dependent classes into linear memory at once.
- the Wasm virtual machine manages linear memory and non-linear memory.
- the linear memory managed by the Wasm virtual machine has logical addresses, not logical addresses in system memory.
- the Wasm virtual machine achieves at least part of the sandbox goals through linear memory.
- the memory addresses in the Wasm file are in the range of 0 to the linear memory capacity, and will not exceed this linear memory area. This ensures that the Wasm bytecode will not be read outside the linear memory managed by Wasm when executed by the virtual machine.
- Memory that is, no external information can be read at all, unless called through the host API (HostAPI). In this way, all reading and writing of Wasm instructions are the addresses of the linear memory accessed and cannot cross the boundary, thus achieving the sandbox goal.
- HostAPI host API
- the linear memory usage has a great impact on the performance of the Wasm virtual machine. Therefore, during the compilation process, a large number of functions in classes that are not actually called are compiled together to generate compiled bytecode files. When the Wasm virtual machine interprets and executes such bytecode files, these will first be The meta-information of classes and functions is loaded into the linear memory managed by the Wasm virtual machine, thus occupying a large amount of linear memory space and affecting the performance of the Wasm virtual machine.
- the compiler can perform the following process as shown in Figure 2 during the process of compiling the Java source code into the Wasm file.
- S110 Generate meta-information of the first type and the first function in the first type according to the code defining the first type in the source code, and use the generated meta-information of the first type and the first function in the first type to Meta information is encapsulated in the Wasm file.
- classes can include member variables and member functions.
- Multiple classes can be defined in a Java file, and multiple member functions can be defined in each class.
- For each member function it can generally include the return type, function name, input parameters, etc.
- first types can be collectively called first types, and these member functions can be collectively called first functions.
- the "first” here can be understood as "the first kind” or "the first type”.
- objects can be generated based on the class. Using classes and objects is the main means of object-oriented programming. Objects are abstractions of objective things; classes are abstractions of objects. Their relationship is that objects are instances of classes, and classes are templates of objects.
- the meta-information of the first type and the first function can be encapsulated in the Wasm file.
- the meta-information of the first type and the first function may at least include the structure of the first type object and the structure of the first function. Because everything in Java is an object, and a type is also a special object, so for a special object like a type, it also has its own type and fields. Subsequently, the type to which it belongs can be found based on this first type object.
- the first type structure and/or the first type field structure may also be included. Whether the first type structure and the first type field structure are included depends on the compilation scheme of the compiler, and may also depend on whether the first type field is used in the first function.
- the implementation in the first function needs to use the first One or more fields in the type.
- the meta-information of the first type and the first function may include the structure of the first type object, the first type structure, the first type field structure, the first function structure, etc. Specific examples are as follows:
- the preceding "-" indicates the first level
- "--" indicates the second level.
- the second level is subordinate to the nearest first level above it.
- the above-mentioned first type and the meta-information of the first function in the first type can be encapsulated in the Wasm file.
- these meta-information after being subsequently loaded by the Wasm virtual machine, can be loaded into the linear memory managed by the Wasm virtual machine.
- the linear memory managed by the Wasm virtual machine has logical addresses, not logical addresses in system memory.
- the logical address in the linear memory where these meta-information is located can be determined.
- the virtual machine can also manage non-linear memory, which is called ordinary memory later.
- the Wasm virtual machine achieves at least part of its sandboxing and deterministic goals through linear memory.
- the memory addresses in the Wasm file are in the range of 0 to linear memory capacity, and will not exceed this linear memory area. This ensures that the Wasm bytecode will not read into the linear memory managed by Wasm when executed by the virtual machine.
- External memory means that no external information can be read at all unless called through the host API (HostAPI). In this way, all reading and writing of Wasm instructions are the addresses of the linear memory accessed and cannot cross the boundary, thus achieving the sandbox goal.
- various meta-information of the class (i.e. type) in the Wasm file has been determined at compile time.
- the logical address of the class and its member variables and member functions in the linear memory is also determined.
- the process of loading the same contract Wasm file through the Wasm virtual machine on different blockchain nodes and executing the contract bytecode in it can ensure that the various meta-information in the class is consistent, specifically
- the logical addresses of the classes, member variables, and member functions in the class in the linear memory are also consistent (even the various information generated based on the logical address is consistent and will not be different due to the randomness of ordinary memory), that is, it does not Due to small differences, the execution results of the same contract bytecode in the Wasm virtual machines of different nodes are inconsistent, thus achieving the deterministic goal.
- the hash table is calculated based on the address of the object. This will also cause the hash table to be saved in an inconsistent order. If there is a subsequent operation to traverse the hash table, the order will also be inconsistent.
- the meta-information of the first type and the first function can be as follows:
- each field in Table 1 point to some fields in Table 2. This mapping relationship is detailed later. It should be noted that the memory where each field in Table 1 is located is generally continuous, which makes it easy to find structures and fields related to the same type in the memory; in addition, among the four blocks in Table 1, at least the fields in each block are Continuous, so that each field can be accessed through pointer traversal from the starting address in the subsequent code segment 4. Each field in Table 1 stores an address pointing to each field in Table 2. That is, each field in Table 2 in memory can be found through the address in Table 1, so the memory where each field in Table 2 is located does not need to be continuous.
- the Wasm function module (module) is processed as follows:
- the above code snippet 3 means to fill in the name string, return result type, and input parameter type of the function in the class, so that each corresponding field in Table 2 can be filled in, and the corresponding fields of the class in Table 2 can be filled in in Table 1.
- create an index for this type of function and create an entry corresponding to index 3 in Table 3.
- the index will also be filled in the corresponding field of Table 1.
- the getSum function is placed in the table with an index of 1
- the getMultiply function is also placed in the table with an index of 2.
- S120 Generate a second function bytecode that obtains the first function type and the first function content according to the dynamic parameters at runtime according to the reflection function code in the source code.
- the compilation process of the compiler is to organize the structure of the Java source code into a suitable format, including lexical/syntactic analysis based on the abstract syntax tree during the compilation process, filling symbols according to the symbol table, annotation processing, semantic analysis and code generation, etc., so that ultimately Encode the source code into Wasm bytecode.
- the compiler when the compiler compiles the reflection function code, it can generate the corresponding second function bytecode that obtains the first function type and the first function content according to the dynamic parameters at runtime. For example, for code segment 3 in the above example, lines 5-7 are reflection function codes, and the corresponding bytecode is the second function bytecode.
- a reflection library can generally be provided, which includes some classes that support reflection functions.
- developers can import this reflection library at the head of the class file, for example, through the import statement.
- the compiler compiles the source code, it can replace the reflection function code in the project file with the relevant statements in the reflection library, and then perform the lexical/syntactic analysis, filling symbols, annotation processing, semantic analysis and code generation processes as mentioned above. This generates the bytecode in the Wasm file.
- the imported reflection library contains the specific implementation of Class.getMethod() and Method.invoke() in lines 5-7 of the code above.
- the reflection function code involved in the source code that is, the Class.getMethod() and Method.invoke() methods in lines 5-7, can be replaced with the corresponding specific implementation in the reflection library.
- the provided reflection library can include specific implementations of Class.getMethod() and Method.invoke().
- the above code segment 5 is the pseudo code for the specific implementation of Class.getMethod in the reflection library.
- the reflection library where these codes are located can be imported. In this way, the calls in the Java code written by the user can be replaced with the imported code of the relevant reflection function during the compilation process.
- the function name spliced in line 11 is used to traverse the method object array of the type obtained in code segment 5 until the first function with the same name string is matched, so that the first function can be obtained Index in table 1.
- the above code segment 6 is the pseudo code of the specific implementation of Method.invoke in the reflection library.
- the index of the first function whose name string matches in Table 1 is obtained through the Class.getMethod() function on line 5. Specifically, it can be obtained through the above p.getClass().getMethod() , the specific implementation of this function is as implemented in code segment 5 above.
- line 7 in code segment 3 can be executed, that is, the corresponding first function is called.
- code segment 6 if the number of parameters of the corresponding case is consistent with the corresponding number in Table 1, an indirect call is made based on the number of input parameters. For example, the index of getSum in Table 1 is 1.
- the getSum string can be matched in Table 1 to find that the index is 1, and then the two parameters input by the getSum function that initiates the call can be passed through the code again.
- Verification of the switch statement in paragraph 6 shows that funcIndex in case 2 is 1 and there are also 2 parameters.
- funcIndex in case 2 is 1 and there are also 2 parameters.
- an indirect call to the function with funcIndex of 1 can be initiated, that is, the starting address of the getSum() function in subsequent Table 4 is found through index 1 in subsequent Table 3, and then the virtual machine parses the corresponding start address in Table 4. The code at the address is executed later.
- the virtual machine Before the virtual machine executes the above compiled Wasm bytecode, it can load the Wasm bytecode first. First, you can pass an entry function, for example, you can match a function like sum(),1 with the input parameters. For example, the following code:
- sum(),a is converted into the implementation of getProperty().
- the input parameters of sum() can be different from the input parameters of getProperty().
- the input parameter of sum() here is a parameter a
- the input parameters of getProperty() in addition to the called object and the name of the called method, are Two parameters a, b.
- one parameter a of the two input parameters of getProperty() is the input parameter a of the sum() function
- the other parameter b of the two input parameters of getProperty() can be set It is a set value, which can be a constant or a global variable, the latter being read from other values, for example.
- sum() can be converted into the processing of the getProperty() function.
- the virtual machine Before the Wasm file is executed, the virtual machine first loads the Wasm file and executes the following process as shown in Figure 2.
- Physical memory is generally managed by the operating system, which is responsible for establishing the mapping relationship between logical addresses and physical addresses.
- the Wasm virtual machine can maintain a linear memory area. This linear memory area is part of the memory managed by the operating system and is managed and controlled by Wasm. Specifically, Wasm can add another layer of abstraction based on the memory managed by the operating system to obtain an address such as a linear memory area starting from 0, and can control access to the linear memory based on the offset. As mentioned before, the Wasm virtual machine can also manage a part of non-linear memory, which is called ordinary memory here.
- a linear memory area can be created before the bytecode is executed.
- S220 Initialize at least part of the memory in the linear memory area using the meta-information in the Wasm file.
- Wasm files contain meta-information about types and functions, bytecode.
- a linear memory area can be created, and the virtual machine can initialize at least part of the linear memory using the meta-information of the first type and the first function contained in the Wasm file.
- the address of a linear memory address can start from 0. This address can be called the base address of the linear memory in the operating system; other addresses in the linear memory are equivalent to offsets relative to this base address.
- the address a in the linear memory corresponds to the memory address in the operating system which is the base address of the linear memory in the operating system + the offset a in the linear memory.
- the linear memory is non-empty; before the wasm bytecode instruction is executed, the constants, classes and function meta-information in the code are pre-contained in the linear memory, and are stored in the linear memory.
- the address is fixed to facilitate subsequent deterministic calls of Wasm bytecode during execution.
- the Wasm virtual machine after the Wasm virtual machine loads the Wasm file, it can also create an ordinary memory area, and then the virtual machine can use the first function bytecode and the second function bytecode contained in the Wasm file to initialize at least part of the ordinary memory.
- the function called when the object instantiated by the class is executed it is in the storage area corresponding to the class.
- the storage area corresponding to this class is generally located in the ordinary memory created by the virtual machine. That is, the functions in the class are located in ordinary memory areas.
- the object created based on the class is an instantiation of the class. When executing a function in the class, the corresponding function needs to be loaded from ordinary memory and executed, including the first function and the second function.
- the virtual machine After the virtual machine uses the first function to initialize at least part of the ordinary memory, it can generate two tables, namely the function table (table) of Table 3 and the function code of Table 4.
- the function table can be as shown in the following table:
- the function code can be shown in the following table:
- the first function includes function 1, function 2, function 3....
- the code data block of function 1 is stored in ordinary memory and has a starting address in ordinary memory managed by the virtual machine.
- the code data block of function 2 has a starting address in ordinary memory.
- Starting address the code data block of function 3 has a starting address in ordinary memory.
- the function table in Table 3 can store the starting address of each function code in ordinary memory in a short and regular format. For example, each row in Table 3 has a 32-bit address.
- the first function in the above-mentioned first type may include multiple functions.
- the starting address of each function in the ordinary memory in Table 4 can be filled in the corresponding position in Table 3, so that this function table can be uniformly mapped to different function code.
- the starting address of Table 3 in ordinary memory can be obtained. In this way, based on the starting address and index in Table 3, the starting address of the corresponding function in Table 4 can be obtained.
- mapping table can be shown in Figure 3.
- Table 1 and Table 2 can be stored in linear memory, and their addresses are determined by the compiler during compilation and are fixed; Table 3 and Table 4 are stored in ordinary memory.
- the value of each item in the function table in Table 3 can point to the starting address of the corresponding function code in Table 3. From the perspective of the virtual machine, it can be shown in Figure 4.
- S230 Parse and execute the bytecode in the Wasm file, and when the bytecode of the second function is executed, determine the call based on the meta-information in the linear memory area according to the dynamic parameters of the calling function.
- the first function is executed.
- the functions in the class will also be loaded into the ordinary memory in the virtual machine, such as the initialization process of ordinary functions mentioned above.
- the Wasm bytecode When the bytecode in the Wasm file is loaded into the virtual machine, the functions in the class will also be loaded into the ordinary memory in the virtual machine, such as the initialization process of ordinary functions mentioned above.
- the Wasm bytecode When the Wasm bytecode is running, it involves numerical calculations, memory read and write operations, function calls, etc.
- the memory space operated by Wasm bytecode is linear memory created before running, and ordinary memory cannot be directly operated. Ordinary memory can be operated by a virtual machine, which ensures that the wasm bytecode will not directly modify the function bytecode in ordinary memory.
- the virtual machine parses and executes the Wasm bytecode and executes it according to the logic in the wasm bytecode.
- the actually called function can be dynamically determined based on the dynamic parameters of the calling function. Specifically, when the bytecode of the second function is executed, the following operations can be performed.
- the index of getMultiply in Table 1 is 2.
- the getMultiply string can be matched in Table 1 to find that the index is 2, and then it can be The two parameters entered through the getMultiply function that initiated the call are again verified by the switch statement in code segment 5. It can be verified that the funcIndex in case 2 is 2 and there are also 2 parameters. In this way, an indirect call to the function with funcIndex of 2 can be initiated, that is, the starting address of the getMultiply() function in subsequent Table 4 is found through index 2 in subsequent Table 3, and then the code corresponding to the starting address in Table 4 is parsed. executed later.
- the first function it is possible to determine and execute the first function to be called based on the meta-information in the linear memory area according to the function name string of the calling function.
- it can also be a string input by the user, or a string constructed based on integers or binary numbers.
- the reflection function can be implemented in the Wasm file, so that when the Wasm program is running, the ability to access, detect, and modify its own state or behavior is achieved.
- developers can develop Java source code that includes reflective programming capabilities.
- reflective programming is, for example, to obtain the type of an object, which fields and methods the obtained type includes, etc.
- blockchain platform manufacturers can provide auxiliary functions, which are, for example, located in a reflection library.
- the auxiliary functions may include some APIs for obtaining type and function meta-information.
- This function library can be provided to developers, and then developers can include this library function into the source code in the process of developing code using high-level languages, and call such APIs in the function library in the source code, so as to These auxiliary functions are used in the source code to obtain type and function meta-information.
- an original function library can also be used, such as a function library that provides reflective programming functions included in Java. In this way, developers can introduce the reflective programming functions provided by the function library when developing source code in the Java language.
- developers can generate corresponding source files after writing code edited in Java language, which is usually a source file with a .java extension.
- the .java file of the code can be compiled by the compiler to generate bytecode in Wasm format.
- Wasm format bytecode can be encapsulated in wasc files.
- Java bytecode may also be developed in other blockchain systems that support reflection function. For example, if it is a file with a .class extension, the Java bytecode contains code with reflection function.
- Such Java bytecode is an equivalent program of Java source code. Therefore, the compiler in the embodiment of the present application can also be used to compile such Java bytecode including reflection function again, thereby generating Wasm bytecode.
- the generated Wasm bytecode also has the reflection function, so that the reflection function can be implemented when the virtual machine executes the Wasm bytecode.
- high-level languages with reflective programming functions also include C#, Python, Go language, etc.
- Some codes developed in programming languages that do not support the reflection mechanism themselves can also implement reflection functions through the reflection library, compiler and virtual machine provided by this application, such as C++ and other languages.
- the code containing reflection function includes source code or intermediate bytecode.
- the source code is, for example, Java source code, such as source code with a .java extension.
- the intermediate bytecode is, for example, Java bytecode, such as the Java bytecode of .class.
- the compiler can integrate a Java compilation tool chain. For Java source code, you can first compile it into Java bytecode, and then perform the process of the following method embodiment.
- the method includes S610 to S630.
- S610 The compiler scans the reflection function code starting from the program entry of the code, and obtains the class used in the reflection function code and the functions used by the class through annotations.
- reflection mechanism which includes reflection function code.
- reflection function code represents the dynamics of program execution, allowing the program to dynamically detect its own status or behavior while running. More specifically, a function can be dynamically called based on input instructions or commands, and this function is not determined before it is called.
- snippet 2 before and snippet 8 below.
- three functions are defined in Person in code segment 2, namely getSum, getMultiply, and hello.
- the input parameters of the first two functions getSum and getMultiply are the same, both are two integer variables a and b; the input parameter of the latter function hello is different from the first two, it is a string variable name.
- Main.java in code segment 8 first imports Person in code segment 2 and defines class main.
- the function main is defined in class main.
- the method name and two integer type parameters are obtained through the method on lines 6-7.
- the function corresponding to the method name is called and parameters 123 and 234 are entered.
- lines 6-7 contain the reflection function, that is, through person.class.getMethod(methodName, int.class, int.class), the class to which the object person belongs (including other subclasses inherited from the Object class) has the same
- the function name has the same input parameters and output parameters (or return type) (the function name, input parameters, and output parameters are also called function signatures); in the code on line 8, the retrieved function is used to complete the calculation and return the calculation result.
- Java annotation is Java annotation in English, also known as Java annotation. It is a special code annotation method in the Java programming language. You can add Java annotations to types, fields, methods, constructors, etc. in Java code to describe some required information, and you can obtain the annotation objects of these types or fields or methods through Java's reflection mechanism, so as to obtain them at runtime. these annotation information.
- the class Person.class that is, the Person class
- the functions used in this Person class are getSum and getMultiply.
- the annotation includes the Person class, indicating the Person class imported in line 1 of code segment 8; the functions used in the Person class in the annotation are getSum and getMultiply, which means that only the two functions getSum and getMultiply in the Person class are needed during compilation.
- the code is compiled.
- the Person class in the annotation does not include hello, which means that the code of the hello function in the Person class does not need to be compiled during compilation.
- the compilation process of the compiler includes organizing the structure of Java source code (or Java bytecode) into a suitable format, including lexical/syntactic analysis based on the abstract syntax tree during the compilation process, filling symbols according to the symbol table, annotation processing, and semantic analysis and code generation, etc., resulting in final encoding into Wasm bytecode.
- the compiler starts scanning from the program entry of the code to be compiled, that is, starting from the function main, scanning the types used in the main function, the field types in the types, the method functions used, and the functions within the function. Call information to construct a list of types used by the program and each method function used.
- the compiler starts scanning the reflection function code from the program entry point of the code, and may start scanning from main. After scanning the reflection function code, if the reflection function code includes annotations before it, you can obtain the content in the annotations.
- Java annotations are a special type without functional logic, similar to special comments that can be read in Java code. The difference is that the content of the annotation cannot be obtained after Java is compiled into bytecode, but Java annotation, also known as java annotation, can be obtained at runtime, so that you can obtain the annotations in the head of a certain method.
- the annotations are Which properties.
- the compiler can read that the main method has the LinkClass annotation, and can read the attribute value of this annotation.
- Annotations can generally be represented by codes starting with @LinkClass or @LinkClasses.
- the code starting with @LinkClass can represent annotations on a single class, and the code starting with @LinkClasses can represent multiple LinkClass annotations.
- the above code snippet 8 shows the form starting with @LinkClass.
- the form starting with @LinkClasses includes multiple LinkClass annotations.
- methods ⁇ "getSum"
- getMultiply” ⁇ indicates that the functions to be used in the Person class include getSum. and getMultiply these two functions, excluding other functions in the Person class.
- code snippet 2 is a custom Person class, which describes in the form of an example that this class includes 3 member functions. In fact, it can be other classes, and the expression can be displayed through import at the top of code segment 8, or it can be included implicitly.
- the so-called implicit inclusion means inclusion without import.
- the other classes may be directly or indirectly dependent classes, such as the standard String.class class. There are many methods in the String.class class, perhaps hundreds. Through annotations, you can specify the methods used; for methods that are not specified in the annotations, you can think of them as methods that will not be used.
- S620 The compiler adds the code of the class used by the annotation and the functions used by the class in the class on which the code containing the reflection function depends to the list to be compiled.
- scanning can be started from the program entry.
- the functions here include code that relies on function prototypes in the library.
- TeaVM is a translator that can translate JVM bytecode into Wasm bytecode.
- TeaVM does not necessarily need Java source code, but it can be achieved with .class files (that is, java bytecode).
- .class files that is, java bytecode.
- the specific process of TeaVM translation has mature engineering implementation and public documents, so I won’t go into details here.
- Compilation enables the compiler's compilation process to have the ability to "compile on demand". In this way, not only the complexity and workload of the compiler are reduced, but the size of the compilation results can also be greatly reduced. Moreover, the smaller size of the compilation result will also greatly reduce the code loaded into the linear memory of the Wasm virtual machine, thereby improving the overall performance of the Wasm virtual machine.
- this method does not require the Wasm virtual machine to integrate dynamic loading capabilities, and the changes to Wasm are minor.
- this embodiment does not exclude the Wasm virtual machine from having dynamic loading capabilities.
- the aforementioned implementation process of S110 ⁇ S120 and S210 ⁇ S230 can not only be applied to high-level languages with reflective programming functions, such as Java, C#, Python, Go language, etc., but also can be applied to languages that do not originally support the reflection mechanism.
- Code developed in programming languages, such as C++ and other languages can also implement reflection functions through the reflection library, compiler and virtual machine provided by this application.
- the above-mentioned embodiments of S610 to S630 of the present application can also be applied to high-level languages that do not originally support the reflection function, such as C++ and other languages, which implement the reflection function through the reflection library, compiler and virtual machine provided by the present application.
- a compiler of the present application which includes: a scanning unit, which scans the reflection function code starting from the program entry of the code, and obtains the classes used in the reflection function code and the functions used in the class through annotations; Adding a unit, adding the code of the class used by the annotation and the functions used by the class in the class that the code containing the reflection function depends on to the to-be-compiled list; the compilation unit, adding the code to be compiled The list is compiled and the Wasm bytecode is obtained.
- a computer device of the present application which includes: a processor; and a memory in which a program is stored, wherein when the processor executes the program, the following operations are performed: scanning the reflection function code starting from the program entry of the code , and obtain the class used in the reflection function code and the functions used by the class through annotations; obtain the class used in the class and the class used by the annotation in the class that the code containing the reflection function depends on.
- the code of the used function is added to the list to be compiled; the list to be compiled is compiled to obtain the Wasm bytecode.
- the following uses an embodiment to introduce a storage medium of the present application, which is used to store a program.
- the following operations are performed: scanning the reflection function code starting from the program entry of the code, and obtaining the reflection function code through annotations.
- the class used in the class and the function used in the class add the code of the class used and the function used by the class obtained from the annotation in the class that the code containing the reflection function depends on to be compiled.
- List compile the list to be compiled to obtain Wasm bytecode.
- PLD Programmable Logic Device
- FPGA Field Programmable Gate Array
- HDL Hardware Description Language
- the controller may be implemented in any suitable manner, for example, the controller may take the form of, for example, a microprocessor or processor and a computer readable medium storing computer readable program code (eg, software or firmware) executable by the (micro)processor. , logic gates, switches, Application Specific Integrated Circuit (ASIC), programmable logic controllers and embedded microcontrollers.
- controllers include but are not limited to the following microcontrollers: ARC 625D, Atmel AT91SAM, For Microchip PIC18F26K20 and Silicone Labs C8051F320, the memory controller can also be implemented as part of the memory's control logic.
- the controller in addition to implementing the controller in the form of pure computer-readable program code, the controller can be completely programmed with logic gates, switches, application-specific integrated circuits, programmable logic controllers and embedded logic by logically programming the method steps. Microcontroller, etc. to achieve the same function. Therefore, this controller can be considered as a hardware component, and the devices included therein for implementing various functions can also be considered as structures within the hardware component. Or even, the means for implementing various functions can be considered as structures within hardware components as well as software modules implementing the methods.
- the systems, devices, modules or units described in the above embodiments may be implemented by computer chips or entities, or by products with certain functions.
- a typical implementation device is a server system.
- the computer that implements the functions of the above embodiments may be, for example, a personal computer, a laptop computer, a vehicle-mounted human-computer interaction device, a cellular phone, a camera phone, a smart phone, or a personal digital assistant. , media player, navigation device, email device, game console, tablet, wearable device, or a combination of any of these devices.
- the functions are divided into various modules and described separately.
- the functions of each module can be implemented in the same or multiple software and/or hardware, or the modules that implement the same function can be implemented by a combination of multiple sub-modules or sub-units, etc. .
- the device embodiments described above are only illustrative.
- the division of the units is only a logical function division. In actual implementation, there may be other division methods.
- multiple units or components may be combined or integrated. to another system, or some features can be ignored, or not implemented.
- the coupling or direct coupling or communication connection between each other shown or discussed may be through some interfaces, and the indirect coupling or communication connection of the devices or units may be in electrical, mechanical or other forms.
- These computer program instructions may also be stored in a computer-readable memory that causes a computer or other programmable data processing apparatus to operate in a particular manner, such that the instructions stored in the computer-readable memory produce an article of manufacture including the instruction means, the instructions
- the device implements the functions specified in a process or processes of the flowchart and/or a block or blocks of the block diagram.
- These computer program instructions may also be loaded onto a computer or other programmable data processing device, causing a series of operating steps to be performed on the computer or other programmable device to produce computer-implemented processing, thereby executing on the computer or other programmable device.
- Instructions provide steps for implementing the functions specified in a process or processes of a flowchart diagram and/or a block or blocks of a block diagram.
- a computing device includes one or more processors (CPUs), input/output interfaces, network interfaces, and memory.
- Memory may include non-permanent storage in computer-readable media, random access memory (RAM) and/or non-volatile memory in the form of read-only memory (ROM) or flash memory (flash RAM). Memory is an example of computer-readable media.
- Computer-readable media includes both persistent and non-volatile, removable and non-removable media that can be implemented by any method or technology for storage of information.
- Information may be computer-readable instructions, data structures, modules of programs, or other data.
- Examples of computer storage media include, but are not limited to, phase change memory (PRAM), static random access memory (SRAM), dynamic random access memory (DRAM), other types of random access memory (RAM), and read-only memory.
- PRAM phase change memory
- SRAM static random access memory
- DRAM dynamic random access memory
- RAM random access memory
- read-only memory read-only memory
- ROM read-only memory
- EEPROM electrically erasable programmable read-only memory
- flash memory or other memory technology
- compact disc read-only memory CD-ROM
- DVD digital versatile disc
- Magnetic tape magnetic tape storage, graphene storage or other magnetic storage devices or any other non-transmission medium can be used to store information that can be accessed by a computing device.
- computer-readable media does not include transitory media, such as modulated data signals and carrier waves.
- one or more embodiments of the present description may be provided as a method, system, or computer program product. Accordingly, one or more embodiments of the present description may take the form of an entirely hardware embodiment, an entirely software embodiment, or an embodiment that combines software and hardware aspects. Furthermore, one or more embodiments of the present description may employ a computer program implemented on one or more computer-usable storage media (including, but not limited to, disk storage, CD-ROM, optical storage, etc.) having computer-usable program code embodied therein. Product form.
- computer-usable storage media including, but not limited to, disk storage, CD-ROM, optical storage, etc.
- program modules include routines, programs, objects, components, data structures, etc. that perform specific tasks or implement specific abstract data types.
- program modules may also be practiced in distributed computing environments where tasks are performed by remote processing devices connected through a communications network.
- program modules may be located in both local and remote computer storage media including storage devices.
Landscapes
- Engineering & Computer Science (AREA)
- Software Systems (AREA)
- Theoretical Computer Science (AREA)
- General Engineering & Computer Science (AREA)
- Physics & Mathematics (AREA)
- General Physics & Mathematics (AREA)
- Library & Information Science (AREA)
- Devices For Executing Special Programs (AREA)
Abstract
一种对包含反射功能的代码进行编译的方法和编译器、Wasm虚拟机。其中,所述编译方法包括:编译器从代码的程序入口开始扫描反射功能代码,并通过注解得到所述反射功能代码中用到的类及该类所用到的函数;所述编译器将所述包含反射功能的代码所依赖的类中由所述注解得到的用到的这个类及该类所用到的函数的代码加入到待编译列表;所述编译器对所述待编译列表进行编译,得到Wasm字节码。所述方法可以应用于区块链。
Description
本说明书实施例属于编译器技术领域,尤其涉及一种编译方法和编译器、Wasm虚拟机。
WebAssembly(也简写为Wasm)是由W3C社区组开发的开放标准,是一种安全,可移植的低级代码格式,专为高效执行和紧凑表示而设计,可以接近原生的性能运行,并为诸如C、C++、Java、Go等语言提供一个编译目标。Wasm虚拟机起初设计的目的是用于解决Web程序日益严峻的性能问题,由于其具有的优越特性,被越来越多的非Web项目所采用,例如替代区块链智能合约执行引擎EVM。
发明内容
本发明的目的在于提供一种编译方法和编译器、Wasm虚拟机,包括:一种对包含反射功能的代码进行编译的方法,包括:编译器从代码的程序入口开始扫描反射功能代码,并通过注解得到所述反射功能代码中用到的类及该类所用到的函数;所述编译器将所述包含反射功能的代码所依赖的类中由所述注解得到的用到的这个类及该类所用到的函数的代码加入到待编译列表;所述编译器对所述待编译列表进行编译,得到Wasm字节码。
一种编译器,包括:扫描单元,从代码的程序入口开始扫描反射功能代码,并通过注解得到所述反射功能代码中用到的类及该类所用到的函数;添加单元,将所述包含反射功能的代码所依赖的类中由所述注解得到的用到的这个类及该类所用到的函数的代码加入到待编译列表;编译单元,对所述待编译列表进行编译,得到Wasm字节码。
一种计算机设备,包括:处理器;以及存储器,其中存储有程序,其中在所述处理器执行所述程序时,进行以下操作:从代码的程序入口开始扫描反射功能代码,并通过注解得到所述反射功能代码中用到的类及该类所用到的函数;将所述包含反射功能的代码所依赖的类中由所述注解得到的用到的这个类及该类所用到的函数的代码加入到待编译列表;对所述待编译列表进行编译,得到Wasm字节码。
一种存储介质,用于存储程序,其中所述程序在被执行时进行以下操作:从代码的程序入口开始扫描反射功能代码,并通过注解得到所述反射功能代码中用到的类及该类所用到的函数;将所述包含反射功能的代码所依赖的类中由所述注解得到的用到的这个类及该类所用到的函数的代码加入到待编译列表;对所述待编译列表进行编译,得到Wasm字节码。
通过上述实施例,对于直接或间接依赖的类,通过注解指明的函数才会被一并编译,而这些直接或间接依赖的类中有大量不会在后续被调用的函数则不会经过编译器编译,使得编译器的编译过程可以具有“按需编译”的能力。这样,不仅降低了编译器的复杂度和工作量,还可以大大减少编译结果的体积。而且,较小体积的编译结果,对于加载进Wasm虚拟机线性内存中的代码也将大大降低,从而可以提升Wasm虚拟机的整体性能。
为了更清楚地说明本说明书实施例的技术方案,下面将对实施例描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本说明书中记载的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动性的前提下,还可以根据这 些附图获得其他的附图。
图1是一实施例中Java程序的编译、执行过程的示意图;
图2是一编译器可以在将Java源代码编译成Wasm文件的过程的流程图;
图3是一实施例中字节码结构和虚拟机模块示意图;
图4是一实施例中线性内存中的表与普通内存中的表的示意图即关系图;
图5是一实施例中采用Java开发,经过编译器编译后得到Wasm字节码,Wasm字节码在集成有Wasm虚拟机的各种平台上运行的流程图;
图6是一实施例中编译方法的流程图。
为了使本技术领域的人员更好地理解本说明书中的技术方案,下面将结合本说明书实施例中的附图,对本说明书实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本说明书一部分实施例,而不是全部的实施例。基于本说明书中的实施例,本领域普通技术人员在没有作出创造性劳动前提下所获得的所有其他实施例,都应当属于本说明书保护的范围。
高级计算机语言便于人们编写,阅读交流,维护,机器语言则是计算机能直接解读、运行的。编译器可以将汇编或高级计算机语言源程序(Source program)作为输入,翻译成目标语言(Target language)机器代码的等价程序。源代码一般为高级语言(High-level language),如C、C++等,而目标则是机器语言的目标代码(Object code),有时也称作机器代码(Machine code)。进而,可以由CPU执行这样的机器码(或者称为“微处理器指令”)。这种方式一般称为“编译执行”。
编译执行一般不具有跨平台的可扩展性。由于存在不同厂商、不同品牌和不同代的CPU,而这些不同的CPU支持的指令集很多情况下是不同的,如x86指令集,ARM指令集等,且同一厂商同一品牌但不同代的CPU(如不同代的Intel CPU)支持的指令集也不完全相同,因此,用同样的高级语言编写的同样的程序代码,在不同CPU上被编译器转换出来的机器码可能不同。具体的,编译器在转换高级语言编写的程序代码到机器码的过程中,会结合具体的CPU指令集的特点(如向量指令集等)进行优化以提升程序执行的速度,而此类优化往往与具体的CPU硬件相关。这样,同样的机器码,一个在x86平台上可以运行,但另一个在ARM上就可能无法运行;甚至同样是x86平台,随着时间的推移,指令集也不断丰富和扩展,这就导致不同代的x86平台运行的机器码也有不同。而且,由于执行机器码需要由操作系统内核对CPU进行调度,因此即使是同样的硬件,在不同操作系统下支持运行的机器码也可能不同。
不同于编译执行,还存在一种“解释执行”的程序运行方式。例如对于Java、C#等高级语言而言,此时编译器完成的功能是把源码(SourceCode)编译成通用中间语言的字节码(ByteCode)。
比如Java语言,将Java源代码通过Java的编译器编译成标准的字节码,这里编译器不针对任何实际的硬件处理器的指令集,而是定义了一套抽象的标准指令集。编译成的标准字节码一般无法在硬件CPU上直接运行,因此引入了一个虚拟机,即JVM,JVM运行在特定的硬件处理器上,用以解释和执行编译后的标准字节码。
JVM是Java Virtual Machine(Java虚拟机)的缩写,是一种虚构出来的计算机,往往通过在实际的计算机上仿真模拟各种计算机功能来实现。JVM屏蔽了与具体的硬件平台、操作系统等相关的信息,使Java程序只需要是生成的可在Java虚拟机上运行的标准字节码,就可以在多种平台上不加修改地运行。
Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是Java的能够“一次编译,到处运行”的原因。这样,只要保证JVM能够正确执行.class文件,就可以运行在诸如Linux、Windows、MacOS等不同的操作系统平台上了。
JVM运行在特定的硬件处理器上,负责针对所运行的特定处理器而进行字节码的解释和执行,并向上屏蔽这些底层的差异,呈现给开发者以标准的开发规范。JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。具体的,JVM接收到输入的字节码后,逐句解释其中的每一条指令,并翻译成适合当前机器的机器码来运行,这些过程例如由称为Interpreter的解释器进行解释和执行。这样一来,编写Java程序的开发者不需要考虑编写后的程序代码将运行在哪种硬件平台上。JVM本身的开发是由Java组织的专业开发人员完成,以将JVM适配到不同的处理器架构上。迄今为止,主流的处理器架构只有有限的几种,如X86,ARM,RISC-V,MIPS。专业的开发人员将JVM分别移植到支持这几种特定硬件的平台后,Java程序理论上就可以在所有的机器上运行了。JVM的移植工作通常由Java开发组织专业的人员提供的,这就极大减轻了Java应用开发者的负担。
上述Java程序的编译、执行过程如图1所示。开发者开发的Java源代码一般是以.java作为扩展名。源文件经过编译器编译,生成.class扩展名的文件,这些.class文件即为字节码。字节码指令,也称为opcode。JVM就是靠解析这些opcode和操作数来完成程序的执行的。当使用Java命令运行.class文件的时候,实际上相当于在操作系统中启动了一个JVM进程,并向操作系统申请了一部分内存。这部分内存一般由虚拟机直接进行管理,具体又可以包括方法区、堆区、栈区等。JVM通过翻译这些字节码来执行,具体包括两种执行方式。一种是常见的解释执行,即将opcode+操作数翻译成机器代码后交给操作系统运行,另外一种执行方式就是JIT(Just In Time),也就是即时编译,这种方式会在一定条件下将字节码编译成机器码之后再执行。
解释执行带来了跨平台可移植性,但由于bytecode的执行经历了JVM中间翻译的过程,因此执行效率不如上述编译执行效率高,这种效率的差异有时甚至可达几十倍。
通过多年的发展和积累,Java已经是一门成熟的编程语言。其中一方面即降低编译器编译后的.class文件的大小。为了降低.class文件的大小,从而使Java字节码更易于传播,JVM中集成了大量的依赖库,并提供了标准化的API。例如,开发者开发的Java源代码中包括Person.java和Main.java两个文件,且main.java文件的头部声明导入Person。实际上,Main及其依赖的Person文件,在运行时还会涉及更多依赖的类,例如默认的父类和祖先类等(具体的一个例子例如是间接依赖的字符串类String.class)。如果JVM没有集成大量的依赖库,则在编译过程中需要对person、main及依赖的类一并进行编译,而这样得到的编译后的.class文件较多,整体体积也较大。JVM中集成大量的标准库之后,JVM在执行Java程序的过程中需要通过类加载器从外部加载的.class文件较少,且体积也较小,但是,仍然需要从内部加载依赖的类,例如是通过本地文件或网络加载。另一方面是JVM的动态加载特性。如前所述,JVM在执行java字节码的.class文件时,例如上述例子中的person.class和main.class,除了加载这两个字节码文件外,还需要加载很多依赖的类文件。动态加载特性,是JVM并不将所有的class一次性全部加载到内存中,而是按需加载class。具体的,JVM在使用到尚未被加载的class时,才去加载这个class。JVM的动态加载class特性,使得java程序在运行时可以根据条件来控制加载不同的实现类,从而降低内存的占用。内存的占用量直接影响JVM的执行效率。
Java等语言是使用运行在x86一类的通用硬件指令集的虚拟机,再执行自己的“汇编语言”(例如Java Bytecode)。实际上,Web平台在浏览器上也是采用类似于Java、Python的虚拟机环境,浏览器提供虚拟机环境执行一些JavaScript或者其他脚本语言,从而实现HTML页面的交互行为和一些网页的特定行为等,网页的特定行为例如是嵌入动态文本之类。随着业务需求越来越复杂,前端的开发逻辑也变得越来越复杂,相应的代码量随之变的越来越多,项目的开发周期也越来越长。除了逻辑复杂、代码量大,还有另一个原因是JavaScript这门语言本身的缺陷——JavaScript没有静态变量类型,从而会降低效率。具体的,JavaScript引擎会对JavaScript代码中执行次数较多的函数进行缓存和优化,例如JavaScript引擎将这样的代码编译成机器码后打包并发送到JIT Compiler,由JIT Compiler编译为机器码;下次再执行到这个函数时,就会直接执行编译好的机器码。但是由于JavaScript采用的是动态变量,这个变量上一次可能是数组(Array),下一次就可能变成对象(Object)。这样,上一次JIT Compiler所做的优化就失去了作用,下一次又要重新进行优化。
在2015年,出现了WebAssembly(也简写为Wasm)。WebAssembly是由W3C社区组开发的开放标准,是一种安全,可移植的低级代码格式,专为高效执行和紧凑表示而设计,可以接近原生的性能运行。WebAssembly是经过编译器编译之后的代码,体积小、起步快,在语法上完全脱离JavaScript,同时具有沙盒化的执行环境。WebAssembly使用静态类型,从而提升了执行效率。此外,WebAssembly将很多编程语言带到了Web中。而且,WebAssembly还进一步简化了一些执行过程,从而也带来执行效率的大幅提升。
WebAssembly是一个可移植、体积小、加载快并且兼容Web的全新格式,可以作为C/C++/Rust/Java等的编译目标。WebAssembly可以看做是Web平台的x86硬件通用指令集,作为一层中间语言,上层对接Java、Python、Rust、C++等,让这些语言都能编译成统一的格式,用于Web平台运行。
例如采用C++语言开发的源文件,一般以.cpp作为扩展名。cpp文件经过编译器编译,可以生成Wasm格式的字节码。类似的,采用Java语言开发的源文件,一般以.java作为扩展名。java文件经过编译器编译,可以生成Wasm格式的字节码。Wasm格式的字节码可以封装在wasc文件中。wasc是合并字节码和ABI(Application Binary Interface,应用程序二进制接口)的文件。根据W3C社区开放标准实现的WebAssembly虚拟机(也称为Wasm虚拟机或Wasm运行环境,是执行Wasm字节码的虚拟机运行环境),采用运行时加载Wasm字节码并解释执行的方式实现。
比如要开发一款应用,如果想实现跨平台,例如采用java完成在Linux平台上的开发,用Objective-C实现iOS上的开发,用C#实现在Windows平台的开发...。如果有了Wasm,只需要选择任意一门语言,然后编译成Wasm,就可以分发到各个平台上。例如图5中所示,采用Java开发,经过编译器编译后可以得到Wasm字节码,这个Wasm字节码可以在集成有Wasm虚拟机的各种平台上运行。
Wasm虚拟机起初设计的目的是用于解决Web程序日益严峻的性能问题,由于其具有的优越特性,被越来越多的非Web项目所采用,例如替代区块链中的智能合约执行引擎EVM。
不同高级语言开发的程序,由于这些高级语言的特性不同,这些程序的行为也可能有所不同。例如采用Java语言开发的程序,由于Java语言具有反射机制,因此在由其对应的JVM虚拟机运行时可以实现反射功能。反射机制,也称为反射编程,是指计算机程序在运行时可以访问、检测和修改它本身状态或行为的一种能力。Java编程语言中的反射编程功能是一种常用功能,典型的是可以支持动态执行,而Wasm字节码标准不直接支持反射功能。具有反射编程功能的高级语言除了Java外,还包括C#、Python、Go语言等。本申请某些地方主要以Java为例加以说明,当然也适用于C#、Python、Go 语言等。
例如在区块链中,开发者开发的智能合约可以提供不同的函数以实现不同功能,后续合约调用者可以动态调用合约中某个或某些函数以实现特定功能。对于不支持反射功能的高级编程语言,一般需要开发者在开发合约时在代码中显式的写好对于调用不同函数时涉及的方法名到方法调用的转换,代码比较繁琐和冗长。对于支持反射功能的高级编程语言,开发者可以在开发合约时在代码中通过反射功能灵活、简便的实现调用不同函数时涉及的方法名到方法调用的转换。
例如在C++这类不支持反射编程的高级语言中,如果要实现动态执行,一般可以通过分支结构的方式根据需求动态执行,比如以下C++程序模拟动态执行不同方法:
代码段1
C++合约中的上述代码段1,提供了sum、multiply等函数来供合约调用者发起调用并传入参数。因为某一次合约调用中,合约无法提前知道发起的调用合约交易将调用合约中的具体哪个函数,因此通常采用if分支来匹配发起的合约调用。匹配到后,传入对应的参数以执行函数,并返回结果。这种方式是模拟动态执行的方式,对于合约中函数较多的情况,这部分代码较为繁琐和冗长。
类似功能的代码,例如在Java中可以通过反射机制实现:
代码段2:Person.java
代码段3:Main.java
代码段2的Person.java中定义了三个函数,分别是getSum、getMultiply、hello。前 两个函数getSum、getMultiply的输入参数相同,都是两个整型变量a和b;后一个函数hello的输入参数与前两个不同,是一个字符串变量name。
代码段3的Main.java中首先导入了Person,并定义了类main。类main中定了函数main。函数main中,通过第5-6行的method获得方法名、两个整型类型的参数,在第7行对对应方法名的函数进行调用,并输入参数123和234。其中,第5-6行包含反射功能函数,即通过person.class.getMethod(methodName,int.class,int.class)获取对象person所属的类(包括继承自Object类的其它子类)中具有相同函数名和相同入参、出参(或返回类型)的函数(函数名和入参、出参也称为函数签名);在第7行的代码中采用取出的函数完成计算并返回计算结果。通过这样的方式,特别是对于有多个函数的情况,而不必像上述C++代码中模拟动态执行而采用的多条件分支结构将每个函数名进行匹配。
如前所述,上述代码段2和代码段3的java文件经过编译器编译,可以生成Wasm格式的字节码。但是Wasm虚拟机不同于JVM,Wasm虚拟机并没有集成Java/Wasm文件运行所需要依赖的大量的库,所以在将java文件编译为Wasm字节码的过程中,需要由编译器将依赖的类一并编译。例如上述代码段3中第1行导入的代码段2中的Person,即在编译得到main的Wasm字节码的过程中,需要将依赖的Person类的所有函数都一并编译。
显然的,上述代码段3中第5-6行,从函数的入参数量为2以及入参类型为int来看,只可能调用代码段1中的getSum或getMultiply函数,而不会调用hello这个函数。那么,对于编译过程来说,如果将包括hello函数在内的Person类一并打包,则会使得无用的函数占据较大的文件体积。上面的代码段仅仅是示例,实际情况中,一个类中可能存在若干类似hello函数的函数入参数量、入参类型、出参类型等与动态调用不一致的情况,则按照这种方式,这些类中大量不会在后续被调用的函数也经过编译器编译,则得到的编译结果将占据较大的体积。此外,上述仅仅示出了Person和Main两个类,实际上一般还会存在很多间接调用的类,例如Person类型依赖了String类型(因为Person类型的方法hello的参数和返回类型是String类型)。而String类作为标准类,其中包括有很多方法,但大多时候在一个程序中只会用到其中的一小部分方法。按照这种方式,大量间接依赖的类也会被一并编译,而这些间接依赖的类中有大量不会在后续被调用的函数也经过编译器编译,则得到的编译结果将占据较大的体积。
尽管在一般的编译过程中,可以通过静态分析来确定依赖的类,但是这种方式限于没有采用反射功能代码的情形。因为没有采用反射功能代码的情况下,调用的函数是明确的,编译器根据代码内容进行分析时可以确切的获得所要调用的是哪个函数。但是对于包括反射功能代码的情况,静态分析是无效的,因为静态分析手段无法确定反射功能代码在执行时实际发生调用的是哪个函数。
再者,Wasm虚拟机不具备动态加载的能力,而是需要将依赖的类一次性全部加载进线性内存中。Wasm虚拟机管理线性内存和非线性内存。Wasm虚拟机管理的线性内存具有逻辑地址,而非系统内存中的逻辑地址。Wasm虚拟机通过线性内存实现了至少一部分的沙箱目标。Wasm文件中的内存地址都是0~线性内存容量范围,而不会超过这个线性内存区域,这样就保证Wasm字节码在由虚拟机执行时不会读取到Wasm管理的线性内存之外的内存,即根本读取不到任何外界信息,除非通过主机API(HostAPI)来调用。这样,所有Wasm指令的读写都是访问的线性内存的地址,无法越界,从而实现沙箱目标。
线性内存的占用量,对Wasm虚拟机的性能有较大影响。因此,前述在编译过程中将大量不会实际调用的类中的函数一并编译,生成编译后的字节码文件,在Wasm虚拟机解释执行这样的字节码文件时,首先会将这些类和函数的元信息加载进Wasm虚拟机管理的线性内存中,从而占用大量线性内存空间,将影响Wasm虚拟机的性能。
对于开发者已经采用Java编写好的源代码,其中可能已经包括反射机制。为了能使得Wasm虚拟机能够在执行编译完的Wasm文件时实现反射功能,编译器可以在将Java源代码编译成Wasm文件的过程中执行如图2所示的以下过程。
S110:根据所述源代码中定义第一类型的代码生成所述第一类型和第一类型中第一函数的元信息,并将生成的所述第一类型和第一类型中第一函数的元信息封装在所述Wasm文件中。
例如Java源代码中,可以定义类型(通常也简称为类),如上述Java代码中的Class Person{...}。其中,{...}中可以包括成员变量和成员函数。一个Java文件中可以定义多个类,每个类中可以定义多个成员函数。对于每个成员函数,一般可以包括返回类型、函数名称、输入参数等。这些类型可以统称为第一类型,这些成员函数可以统称为第一函数。这里的“第一”可以理解为“第一种”或“第一类”。在定义了类的基础上,可以基于类生成对象。使用类和对象是面向对象编程的主要手段。对象是对客观事物的抽象;类是对对象的抽象。它们的关系是,对象是类的实例,类是对象的模板。
第一类型和第一函数的元信息可以封装在Wasm文件中。第一类型和第一函数的元信息至少可以包括第一类型对象的结构和第一函数的结构。因为在Java中皆为对象,类型也是一种特殊的对象,所以对于一个类型这样的特殊对象,其也有所属的类型和字段。后续根据这个第一类型对象可以找到其所属的类型。此外,还可以包括第一类型结构和/或第一类型的字段结构。是否包括第一类型结构、第一类型的字段结构,取决于编译器的编译方案,也可能取决于第一函数中是否有用到第一类型的字段,如第一函数中的实现需要采用第一类型中的某个或某些字段。在一个具体的例子中,第一类型和第一函数的元信息可以包括第一类型对象的结构、第一类型结构、第一类型的字段结构和第一函数的结构等,具体例如如下:
-第一类型对象结构:
--4字节的对象类型的线性内存地址;
--对象的各字段数组的线性内存地址;
-第一类型结构:
--4字节,类型名称字符串的线性内存地址;
--4字节,类型的字段数组的线性内存地址;
--4字节,类型的方法函数数组的线性内存地址;
-第一类型的字段结构:
--4字节,类型的字段数量;
--4字节,字段名称字符串的线性内存地址;
--4字节,字段的返回类型的线性内存地址;
-第一类型的函数结构:
--4字节,类型的方法函数数量;
--4字节,函数在函数表格中的索引;
--4字节,函数名称字符串的线性内存地址;
--4字节,函数返回类型的线性内存地址;
--4字节,函数的参数数量;
--各参数的类型数组的线性内存地址;
......
上述元信息中,前面的“-”表示第一层级,“--”表示第二层级,第二层级从属于其上最近的第一层级。
上述第一类型和第一类型中第一函数的元信息,可以封装在Wasm文件中。
特别的,这些元信息,后续由Wasm虚拟机加载后,可以加载到Wasm虚拟机管理的线性内存中。Wasm虚拟机管理的线性内存具有逻辑地址,而非系统内存中的逻辑地 址。这里,这些元信息封装在Wasm文件的过程中,可以确定这些元信息所在的线性内存中的逻辑地址。此外,虚拟机还可以管理非线性内存,即后续所说的普通内存。
Wasm虚拟机通过线性内存实现了至少一部分的沙箱和确定性目标。首先,Wasm文件中的内存地址都是0~线性内存容量范围,而不会超过这个线性内存区域,这样就保证Wasm字节码在由虚拟机执行时不会读取到Wasm管理的线性内存之外的内存,即根本读取不到任何外界信息,除非通过主机API(HostAPI)来调用。这样,所有Wasm指令的读写都是访问的线性内存的地址,无法越界,从而实现沙箱目标。其次,本申请上下文中Wasm文件中类(即类型)的各种元信息在编译时即已确定,特别是本申请上下文中类及类中成员变量、成员函数在线性内存中的逻辑地址也是确定的,则对于区块链来说,不同区块链节点上通过Wasm虚拟机加载相同的合约Wasm文件并执行其中的合约字节码的过程,可以保证类中的各种元信息一致,具体到其中的类及类中成员变量、成员函数在线性内存中的逻辑地址也是一致的(即使基于逻辑地址产生的各种信息也是一致的,不会因为普通内存的随机性而产生不同),即不会因为细小的差别而导致相同合约字节码在不同节点的Wasm虚拟机中执行结果存在不一致,从而实现了确定性目标。
与此相反的,如果不采用Wasm虚拟机而直接执行C++代码,会因为内存随机性而无法一致,不仅是不同节点运行结果不一致,即使同一节点多次执行同样程序也会导致结果不一致。例如根据类定义采用new语句创建一个对象的操作,每次执行时,生成的对象内存地址很可能是不一样的,因为这个内存地址一般是由操作系统根据内存情况随机分配的。如果这个程序逻辑中包括根据这个地址来计算后续的某些内容,就会导致执行结果不一致。再例如,哈希表在部分实现中会根据对象的地址来计算哈希,这也会导致哈希表的保存顺序不一致,如果后续有遍历哈希表的操作,顺序也将不一致。
结合上述Java源代码,第一类型和第一函数的元信息可以如下:
表1、类型结构
需要说明的是,上面的各个4字节,仅仅是为了举例,而并不是限定。
此外,如上面表格中所示,线性内存中还可以存储类型结构中的具体内容,如下表2所示:
表2、类型结构的内容
可见,表1中左侧的列中某些字段中的地址指向表2中的某些字段。这个映射关系后续详述。需要说明的是,表1中各个字段所在的内存一般是连续的,这样便于在内存中查找同一类型相关的结构和字段;此外,表1中4个块中,至少每个块内的字段是连续的,这样在后续的代码段4中才可以通过指针从起始地址遍历来访问每个字段。而表1中各个字段存储了指向表2中各个字段的地址,即通过在表1中的地址可以找到内存中表2的各个字段,所以表2中的各个字段所在的内存并不要求连续。
具体的,在编译过程中,Wasm函数模块(module)如下被处理:
代码段4
上述代码段3,意思是取类中函数的名称字符串、返回结果类型、入参类型填入, 从而可以填入表2中的各个对应字段,并在表1中填写表2中该类的函数各字段所在线性内存的地址以及参数个数,同时创建该类函数的索引,并将在表3中建立对应索引3的条目,还将该索引填入表1的对应字段中。这样,例如getSum函数放入table中,索引为1,getMultiply函数也放入table中,索引为2。
S120:根据所述源代码中的反射功能代码生成根据运行时的动态参数获取第一函数类型和第一函数内容的第二函数字节码。
在编译器进行编译的过程中,可以加入对源代码中反射功能代码的支持。编译器的编译过程是将java源代码的结构组织成合适的格式,包括编译过程中根据抽象语法树进行词法/语法分析,根据符号表填充符号,注解处理,语义分析和代码生成等,从而最终将源码编码成为Wasm字节码。在这个过程中,编译器在对反射功能代码进行编译时,可以生成对应的根据运行时的动态参数获取第一函数类型和第一函数内容的第二函数字节码。例如,对于上述示例中的代码段3,第5-7行为反射功能代码,对应的字节码为第二函数字节码。
具体的,为了支持反射功能的代码,一般可以提供反射库,其中包括一些支持反射功能的类。在编写源代码的过程中,按照语法规则,开发者可以在类文件的头部导入这个反射库,例如通过import语句导入。在编译器编译源代码时,可以用反射库中的相关语句替换项目文件中的反射功能代码,进而进行如上所述的词法/语法分析,填充符号,注解处理,语义分析和代码生成等过程,从而生成Wasm文件中的字节码。
例如导入的反射库中,包含了对上述第5-7行代码中Class.getMethod()和Method.invoke()的具体实现。这样,在编译过程中,可以对源代码中涉及的反射功能代码即第5-7行的Class.getMethod()和Method.invoke()方法用反射库中对应的具体实现来替换。
提供的反射库中,可以包括Class.getMethod()和Method.invoke()的具体实现。
Class.getMethod()的实现方法例如如下:
代码段5
上述代码段5是反射库中对Class.getMethod具体实现的伪代码,如前所述,这些代码所在的反射库可以被导入。这样,编译过程中可以用被导入的相关反射函数的代码替换用户编写的Java代码中的调用。上述代码段5中,采用第11行拼接后的函数名在代码段5中获取到的类型的方法对象数组中遍历,直到匹配到名称字符串相同的第一函数,从而可以获得该第一函数在表1中的索引。
Method.invoke()的实现方法例如如下:
代码段6
上述代码段6是反射库中对Method.invoke具体实现的伪代码。在上述代码段3中,通过第5行的Class.getMethod()函数来获得名称字符串匹配的第一函数在表1中的索引,具体可以是通过上述p.getClass().getMethod()获得,这个函数的具体实现的如上述在代码段5中的实现。进而,可以执行代码段3中的第7行,即对对应的第一函数发起调用。具体的,在代码段6中,根据输入参数的数量来再次验证对应case的参数数量与在表1中的对应的数量一致的情况下,进行间接(indirect)调用。例如getSum在表1中的索引是1,通过代码段3中第5行可以由getSum字符串在表1中匹配出索引是1,进而可以通过发起调用的getSum函数输入的2个参数再次通过代码段6中的switch语句验证,可以验证得到case2中funcIndex为1且参数也是2个。这样,可以发起对funcIndex为1的函数的间接调用,即在后续表3中通过索引1查找到getSum()函数在后续表4中的起始地址,进而由虚拟机解析表4中对应起始地址的代码后执行。
虚拟机在执行上述编译后的Wasm字节码前,可以先加载该Wasm字节码。首先,可以通过一个入口函数,例如可以将sum(),1这样的函数和入参匹配到的函数。例如如下代码:
代码段7
这样,将sum(),a转换为getProperty()的实现。其中,sum()的入参可以与getProperty()的入参不同,例如这里sum()的入参为一个参数a,而getProperty()的除了被调用对象以及被调用方法名称外,入参为两个参数a、b。根据上述代码,getProperty()的入参的两个参数中的一个参数a即为sum()函数的入参a,而getProperty()的入参的两个参数中的另一参数b可以设定为设定的值,这个值可以是常量也可以是某个全局变量,后者例如是从其它值中读取。结合代码段2中第10-14行定义的实现,可以将sum()转换为getProperty()函数的处理。
Wasm文件执行前,虚拟机先加载所述Wasm文件,并执行如图2所示的以下过程。
S210:创建线性内存区域。
物理内存一般由操作系统来管理,例如负责建立逻辑地址和物理地址之间的映射关系。Wasm虚拟机可以维护一个线性内存区域,这个线性内存区域是操作系统管理的内存中的一部分,并由Wasm管理和控制。具体的,Wasm可以在操作系统管理的内存基础之上再进行一层抽象,得到一个地址例如是从0开始的线性内存区域,并可以根据偏移量来控制对线性内存的访问。如前所述,Wasm虚拟机还可以管理一部分非线性内存,这里称非线性内存为普通内存。
Wasm虚拟机加载Wasm文件后,在执行字节码之前,可以创建线性内存区域。
S220:采用所述Wasm文件中的所述元信息初始化所述线性内存区域中的至少部分内存。
如前所述,Wasm文件包含类型和函数的元信息,字节码。上述Wasm虚拟机加载Wasm文件后,可以创建线性内存区域,进而虚拟机可以采用所述Wasm文件包含的第一类型和第一函数的元信息初始化至少部分线性内存。如上所述,线性内存地址的地址可以从0开始,这个地址在操作系统中可以称为线性内存的基地址;线性内存中的其它地址相当于是相对这个基地址的偏移量。这样,线性内存中的地址a,对应操作系统中的内存地址是线性内存在操作系统中的基地址+线性内存中的偏移量a。Wasm虚拟机通过对操作系统内存进行这样的抽象,利于Wasm虚拟机更好的管理和使用内存。
这样,在wasm字节码执行之前,线性内存就是非空的;wasm字节码指令执行前,代码中的常量、类及函数的元信息等就预先包含在线性内存中,并且在线性内存中的地址是固定的,便于后续Wasm字节码在执行时进行确定性的调用。
此外,如前所述,Wasm虚拟机加载Wasm文件后,还可以创建普通内存区域,进而虚拟机可以采用Wasm文件包含的第一函数字节码和第二函数字节码初始化至少部分普通内存。根据类实例化得到的对象在执行时所调用的函数,在类对应的存储区域中。这个类对应的存储区域,一般位于虚拟机创建的普通内存中。也就是说,类中的函数位于普通内存区域。根据类创建的对象是类的实例化,在执行类中的函数时,需要从普通内存中加载并执行对应的函数,包括第一函数和第二函数。
虚拟机采用第一函数初始化至少部分普通内存后,可以生成两张表,分别是表3的函数表(table)和表4的函数代码。
函数表可以如下表所示:
表3、普通内存中的函数表
函数代码可以如下表所示:
表4、普通内存中的函数
例如第一函数包括函数1、函数2、函数3......。如上所示,表4中,函数1的代码数据块存储于普通内存中,具有一个虚拟机管理的普通内存中的起始地址,类似的,函数2的代码数据块具有一个普通内存中的起始地址,函数3的代码数据块具有一个普通内存中的起始地址。表3中的函数表可以以简短、规整的格式存储普通内存中各个函数代码的起始地址,例如表3中每行一个32bits的地址。
可见,上述第一类型中的第一函数,可以包括多个函数。为了便于在内存中统一管理第一类型中的函数,可以将表4中每个函数在普通内存中的起始地址填入表3中对应的位置,从而可以由这个函数表统一映射到不同的函数代码。
虚拟机生成表3的过程中,可以获得表3在普通内存中的起始地址。这样,根据表3的起始地址和索引,可以得到对应函数在表4中的起始地址。
综合上述表1、表2、表3、表4,可以构成一个整体的映射表,这个映射表可以如图3所示。其中,表1和表2可以存储在线性内存中,其地址由编译器编译时确定,且是固定不变的;表3和表4存储于普通内存中。表3的函数表中的每一项的值,可以指向表3中对应的函数代码的起始地址。从虚拟机的角度看,可以如图4所示。
S230:解析并执行所述Wasm文件中的字节码,并在执行到第二函数的字节码时,根据所述调用函数的动态参数在所述线性内存区域中基于所述元信息确定调用的第一函数并执行。
Wasm文件中的字节码在加载进虚拟机的过程中,类中的函数也会加载进虚拟机中的普通内存中,如上述所说的普通函数的初始化过程。所述Wasm字节码在运行时,涉及数值计算、内存的读写操作、函数调用等。Wasm字节码操作的内存空间,是在运行前创建的线性内存,而无法直接操作普通内存。普通内存可以由虚拟机来操作,这样可以保证wasm字节码不会对普通内存中的函数字节码进行直接的修改。
虚拟机解析并执行所述Wasm字节码,按照wasm字节码中的逻辑执行。执行到第二函数字节码中的反射功能代码时,可以根据所述调用函数的动态参数动态确定实际调用的函数。具体的,当执行到第二函数的字节码时,可以执行以下操作。
当执行到上述代码段2中第11行,完成函数名的拼接。
当执行到第12行(实际还包括替换后的代码段4的内容),采用第11行拼接后的函数名在虚表中遍历,直到匹配到名称字符串相同的第一函数,从而可以获得该第一函数在表1中的索引。
当执行到代码段2中的第13行(实际还包括替换后的代码段5的内容),即对对应的第一函数发起调用。具体的,在代码段5中,根据输入参数的数量来再次验证对应case的参数数量与在表1中的对应的数量一致的情况下,进行间接(indirect)调用。例如getSum在表1中的索引是1,通过代码段2中第12行(及替换后的代码段4的内容)可以由getSum字符串在表1中匹配出索引是1,进而可以通过发起调用的getSum函数输入的2个参数再次通过代码段5中的switch语句验证,可以验证得到case2中funcIndex为1且参数也是2个。这样,可以发起对funcIndex为1的函数的间接调用,即在后续表3中通过索引1查找到getSum()函数在后续表4中的起始地址,进而解析表4中对应起始地址的代码后执行。
类似的,例如getMultiply在表1中的索引是2,通过代码段2中第12行(及替换后的代码段4的内容)可以由getMultiply字符串在表1中匹配出索引是2,进而可以通过发起调用的getMultiply函数输入的2个参数再次通过代码段5中的switch语句验证,可以验证得到case2中funcIndex为2且参数也是2个。这样,可以发起对funcIndex为2的函数的间接调用,即在后续表3中通过索引2查找到getMultiply()函数在后续表4中的起始地址,进而解析表4中对应起始地址的代码后执行。
上述的例子,可以实现根据所述调用函数的函数名字符串在所述线性内存区域中基于所述元信息确定调用的第一函数并执行。除了上述采用拼接的字符串,还可以是用户输入的字符串,或者是根据整数或者二进制构造得到的字符串。
通过上述实施例,可以在Wasm文件中实现反射功能,这样在Wasm程序运行时实现可以访问、检测以及修改本身状态或行为的能力。特别是对于有多个函数的情况,开发代码时方便开发者在代码中通过反射功能灵活、简便的实现调用不同函数。例如,开发者可以开发包含反射编程功能的Java源代码。其中,反射编程例如是获取某个对象的类型,获取的类型包括哪些字段、哪些方法等。具体的,区块链平台厂商可以提供辅助函数,这些辅助函数例如是位于一个反射库中。所述辅助函数可以包括一些获取类型和函数元信息的API。这个函数库可以提供给开发者,进而开发者在采用高级语言开发代码的过程中可以将这个库函数包括到源代码中,并且在源代码中调用所述函数库中的这类API,从而在源代码中通过这些辅助函数实现获取类型和函数元信息的功能。此外,也可以采用原有的函数库,例如Java中本身包含的提供反射编程功能的函数库,这样开发者在采用Java语言开发源代码的过程中可以引入所述函数库提供的反射编程功能。
前述提到,采用Java语言编辑的代码,开发者编写完后可以生成对应的源文件,一般是.java扩展名的源文件。代码的.java文件,可以经过编译器编译,生成Wasm格式的字节码。Wasm格式的字节码可以封装在wasc文件中。此外,还可能在其它支持反射功能的区块链系统中开发完成Java字节码,例如是.class扩展名的文件,则该Java字节码包含具有反射功能的代码。这样的Java字节码是Java源代码的一种等价程序,因此也可以采用本申请实施例中的编译器对这样的包含反射功能的Java字节码再次进行编译,从而生成Wasm字节码,则生成的Wasm字节码中也具有反射功能,从而在虚拟机执行该Wasm字节码时可以实现反射功能。
此外,如前所述,具有反射编程功能的高级语言除了Java外,还包括C#、Python、Go语言等。而有一些本身并不支持反射机制的编程语言开发的代码,也可以通过本申请提供的反射库、编译器和虚拟机实现反射功能,例如C++等语言。
以下介绍本申请一种对包含反射功能的代码进行编译方法实施例。其中,所述包含反射功能的代码,包括源代码或中间字节码。源代码例如是Java源代码,如.java扩展 名的源代码。中间字节码例如是Java字节码,如.class的Java字节码。所述编译器可以集成Java编译工具链。对于Java源代码,可以先将其编译为java字节码,并进行下述方法实施例的过程。
如图6所示,该方法包括S610至S630。
S610:编译器从代码的程序入口开始扫描反射功能代码,并通过注解得到所述反射功能代码中用到的类及该类所用到的函数。
开发者在开发源代码的过程中,可以采用反射机制,即包含反射功能代码。这样的反射功能代码,如前所述,表示程序执行时的动态性,可以使程序在运行时可以动态检测本身状态或行为。更具体的说,可以根据输入的指令或命令动态调用某个函数,而这个函数在被调用前是不确定的。
虽然不确定,但是开发者可以预期动态调用的函数,限定在一个较小的范围内。例如之前的代码段2和下面的代码段8。仍然如前所述,代码段2的Person中定义了三个函数,分别是getSum、getMultiply、hello。前两个函数getSum、getMultiply的输入参数相同,都是两个整型变量a和b;后一个函数hello的输入参数与前两个不同,是一个字符串变量name。
代码段8:Main.java
代码段8的Main.java中首先导入了代码段2中的Person,并定义了类main。类main中定了函数main。函数main中,通过第6-7行的method获得方法名、两个整型类型的参数,在第8行对对应方法名的函数进行调用,并输入参数123和234。其中,第6-7行包含反射功能函数,即通过person.class.getMethod(methodName,int.class,int.class)获取对象person所属的类(包括继承自Object类的其它子类)中具有相同函数名和相同入参、出参(或返回类型)的函数(函数名和入参、出参也称为函数签名);在第8行的代码中采用取出的函数完成计算并返回计算结果。
上述代码段8中第6-7行,从函数的入参数量为2以及入参类型为int来看,只可能调用代码段1中的getSum或getMultiply函数,而不会调用hello这个函数。那么,对于编译过程来说,如果将包括hello函数在内的Person类一并打包,则会使得无用的函数占据较大的文件体积。
为此,开发者可以在代码段8的第3行加入注解,例如"@LinkClass..."开始的代码。Java注解的英文为Java annotation,又称为Java标注,是Java编程语言中的一种特殊的代码注释方式。可以通过给Java代码中的类型、字段、方法、构造函数等添加Java注解来描述一些需要的信息,并可以通过Java的反射机制来获取这些类型或者字段或者方法的注解对象,从而运行时获取到这些注解信息。
这里,开发者可以通过第3行的注解来标注后面的类及该类所用到的函数。例如在第3行通过注解指明了Person.class这个类,即Person类,以及这个Person类中所用到的函数为getSum和getMultiply。注解中包括Person类,指明代码段8第1行导入的Person 类;注解中Person类中所用到的函数为getSum和getMultiply,意为编译时只需将Person类中的getSum和getMultiply这两个函数的代码进行编译。注解中的Person类中不包括hello,意为编译时不需要将Person类中hello函数的代码进行编译。
编译器的编译过程包括将Java源代码(或Java字节码)的结构组织成合适的格式,包括编译过程中根据抽象语法树进行词法/语法分析,根据符号表填充符号,注解处理,语义分析和代码生成等,从而最终编码为Wasm字节码。在这个过程中,编译器从待编译的代码的程序入口开始扫描,即从函数main开始扫描,扫描main函数内用到的类型,类型中的字段类型,使用到的方法函数,函数内的函数调用信息,构造出程序的使用到的类型列表,以及使用到的各方法函数。
所述编译器从代码的程序入口开始扫描反射功能代码,可以从main开始扫描。扫描到反射功能代码后,对于反射功能代码之前包括注解的,可以获取注解中的内容。Java注解是一种没有函数逻辑的特殊类型,类似Java代码中可以读取到的特殊注释。不同的是,注释的内容在Java编译到字节码后是无法获取到的,但Java注解也就是java annotation,可以在运行时获取到,从而可以获取某个方法头部有哪些注解,注解有哪些属性。编译器可以读取到main法有LinkClass注解,并可以读取到这个注解的属性值。注解一般可以采用@LinkClass或@LinkClasses开头的代码表示。其中,@LinkClass开头的代码可以表示对单一类的注解,@LinkClasses开头的可以表示包括多个LinkClass注解。上述代码段8示出了@LinkClass开头的形式。@LinkClasses开头的形式,即包括多个LinkClass注解。
@LinkClass开头的形式,如代码段8中所示,可以通过后面的属性值(target=Person.class,methods={"getSum","getMultiply"})来指定后续反射功能代码中用到的类和用到的函数。用到的类,如通过target=被引用类型.class的方式来表示。该类中用到的函数,如通过methods={"被引用方法1","被引用方法2",...}的形式表示。代码段8中,通过target=Person.class指明后续反射功能代码中用到的类是Person这个类,通过methods={"getSum","getMultiply"}表示Person这个类中将用到的函数包括getSum和getMultiply这两个函数,而不包括Person类中的其它函数。这些如前所述,可以被编译器读取到。
需要说明的是,上述代码段2中的是自定义的Person类,其中以示例的形式描述了这个类包括3个成员函数。实际上,可以是其它的类,并可以在代码段8的顶部通过import的方式显示的表达,或者隐式的包含,所谓隐式的包含即不通过import的方式包含。
所述其它的类,可以是直接或间接依赖的类,例如标准的String.class类。String.class类中的方法有很多,可能有上百个。通过注解的方式,可以指明用到的其中的方法;对于注解中没有指明的,则可以认为是不会用到的方法。
S620:所述编译器将所述包含反射功能的代码所依赖的类中由所述注解得到的用到的这个类及该类所用到的函数的代码加入到待编译列表。
编译器编译过程中,如S610中所述,可以从程序入口开始进行扫描。通过注解字段“target=...”可以获取类名,并通过注解字段“methods=...”获取函数列表。如果所述函数列表不为空,则可以将该函数列表中的函数分别加入到待编译的列表中。这里的函数,包括依赖库中的函数原型的代码。
S630:编译器对所述待编译列表进行编译,得到Wasm字节码。
对于Java,编译器底层例如可以采用TeaVM实现。TeaVM是一个翻译器,可以将JVM字节码翻译成Wasm字节码。翻译过程中,TeaVM并不是必须需要Java源代码,而具有.class文件(即java字节码)既可以实现。TeaVM进行翻译的具体过程有成熟的 工程实现和公开文件,这里不再赘述。
通过上述实施例,对于直接或间接依赖的类,通过注解指明的函数才会被一并编译,而这些直接或间接依赖的类中有大量不会在后续被调用的函数则不会经过编译器编译,使得编译器的编译过程可以具有“按需编译”的能力。这样,不仅降低了编译器的复杂度和工作量,还可以大大减少编译结果的体积。而且,较小体积的编译结果,对于加载进Wasm虚拟机线性内存中的代码也将大大降低,从而可以提升Wasm虚拟机的整体性能。
此外,这种方式并不要求Wasm虚拟机集成动态加载的能力,对Wasm的改动是较小的。当然,本领域技术人员知道,本实施例并不排斥Wasm虚拟机具备动态加载能力。
再者,前述S110~S120以及S210~S230的实现过程,不仅可以适用于具有反射编程功能的高级语言,例如Java、C#、Python、Go语言等,还可以适用于原本本身并不支持反射机制的编程语言开发的代码,即也可以通过本申请提供的反射库、编译器和虚拟机实现反射功能,例如C++等语言。进而,本申请上述S610~S630的实施例,也可以适用于通过本申请提供的反射库、编译器和虚拟机实现反射功能的原本不支持反射功能的高级语言,例如C++等语言。
以下介绍本申请一种编译器的实施例,包括:扫描单元,从代码的程序入口开始扫描反射功能代码,并通过注解得到所述反射功能代码中用到的类及该类所用到的函数;添加单元,将所述包含反射功能的代码所依赖的类中由所述注解得到的用到的这个类及该类所用到的函数的代码加入到待编译列表;编译单元,对所述待编译列表进行编译,得到Wasm字节码。
以下介绍本申请一种计算机设备实施例,包括:处理器;以及存储器,其中存储有程序,其中在所述处理器执行所述程序时,进行以下操作:从代码的程序入口开始扫描反射功能代码,并通过注解得到所述反射功能代码中用到的类及该类所用到的函数;将所述包含反射功能的代码所依赖的类中由所述注解得到的用到的这个类及该类所用到的函数的代码加入到待编译列表;对所述待编译列表进行编译,得到Wasm字节码。
以下以实施例介绍本申请的一种存储介质,用于存储程序,其中所述程序在被执行时进行以下操作:从代码的程序入口开始扫描反射功能代码,并通过注解得到所述反射功能代码中用到的类及该类所用到的函数;将所述包含反射功能的代码所依赖的类中由所述注解得到的用到的这个类及该类所用到的函数的代码加入到待编译列表;对所述待编译列表进行编译,得到Wasm字节码。
在20世纪90年代,对于一个技术的改进可以很明显地区分是硬件上的改进(例如,对二极管、晶体管、开关等电路结构的改进)还是软件上的改进(对于方法流程的改进)。然而,随着技术的发展,当今的很多方法流程的改进已经可以视为硬件电路结构的直接改进。设计人员几乎都通过将改进的方法流程编程到硬件电路中来得到相应的硬件电路结构。因此,不能说一个方法流程的改进就不能用硬件实体模块来实现。例如,可编程逻辑器件(Programmable Logic Device,PLD)(例如现场可编程门阵列(Field Programmable Gate Array,FPGA))就是这样一种集成电路,其逻辑功能由用户对器件编程来确定。由设计人员自行编程来把一个数字系统“集成”在一片PLD上,而不需要请芯片制造厂商来设计和制作专用的集成电路芯片。而且,如今,取代手工地制作集成电路芯片,这种编程也多半改用“逻辑编译器(logic compiler)”软件来实现,它与程序开发撰写时所用的软件编译器相类似,而要编译之前的原始代码也得用特定的编程语言来撰写,此称之为硬件描述语言(Hardware Description Language,HDL),而HDL也并非仅有一种,而是有许多种,如ABEL(Advanced Boolean Expression Language)、AHDL(Altera Hardware Description Language)、Confluence、CUPL(Cornell University Programming Language)、HDCal、JHDL(Java Hardware Description Language)、Lava、Lola、MyHDL、PALASM、RHDL(Ruby Hardware Description Language)等,目前最 普遍使用的是VHDL(Very-High-Speed Integrated Circuit Hardware Description Language)与Verilog。本领域技术人员也应该清楚,只需要将方法流程用上述几种硬件描述语言稍作逻辑编程并编程到集成电路中,就可以很容易得到实现该逻辑方法流程的硬件电路。
控制器可以按任何适当的方式实现,例如,控制器可以采取例如微处理器或处理器以及存储可由该(微)处理器执行的计算机可读程序代码(例如软件或固件)的计算机可读介质、逻辑门、开关、专用集成电路(Application Specific Integrated Circuit,ASIC)、可编程逻辑控制器和嵌入微控制器的形式,控制器的例子包括但不限于以下微控制器:ARC 625D、Atmel AT91SAM、Microchip PIC18F26K20以及Silicone Labs C8051F320,存储器控制器还可以被实现为存储器的控制逻辑的一部分。本领域技术人员也知道,除了以纯计算机可读程序代码方式实现控制器以外,完全可以通过将方法步骤进行逻辑编程来使得控制器以逻辑门、开关、专用集成电路、可编程逻辑控制器和嵌入微控制器等的形式来实现相同功能。因此这种控制器可以被认为是一种硬件部件,而对其内包括的用于实现各种功能的装置也可以视为硬件部件内的结构。或者甚至,可以将用于实现各种功能的装置视为既可以是实现方法的软件模块又可以是硬件部件内的结构。
上述实施例阐明的系统、装置、模块或单元,具体可以由计算机芯片或实体实现,或者由具有某种功能的产品来实现。一种典型的实现设备为服务器系统。当然,本申请不排除随着未来计算机技术的发展,实现上述实施例功能的计算机例如可以为个人计算机、膝上型计算机、车载人机交互设备、蜂窝电话、相机电话、智能电话、个人数字助理、媒体播放器、导航设备、电子邮件设备、游戏控制台、平板计算机、可穿戴设备或者这些设备中的任何设备的组合。
虽然本说明书一个或多个实施例提供了如实施例或流程图所述的方法操作步骤,但基于常规或者无创造性的手段可以包括更多或者更少的操作步骤。实施例中列举的步骤顺序仅仅为众多步骤执行顺序中的一种方式,不代表唯一的执行顺序。在实际中的装置或终端产品执行时,可以按照实施例或者附图所示的方法顺序执行或者并行执行(例如并行处理器或者多线程处理的环境,甚至为分布式数据处理环境)。术语“包括”、“包含”或者其任何其他变体意在涵盖非排他性的包含,从而使得包括一系列要素的过程、方法、产品或者设备不仅包括那些要素,而且还包括没有明确列出的其他要素,或者是还包括为这种过程、方法、产品或者设备所固有的要素。在没有更多限制的情况下,并不排除在包括所述要素的过程、方法、产品或者设备中还存在另外的相同或等同要素。例如若使用到第一,第二等词语用来表示名称,而并不表示任何特定的顺序。
为了描述的方便,描述以上装置时以功能分为各种模块分别描述。当然,在实施本说明书一个或多个时可以把各模块的功能在同一个或多个软件和/或硬件中实现,也可以将实现同一功能的模块由多个子模块或子单元的组合实现等。以上所描述的装置实施例仅仅是示意性的,例如,所述单元的划分,仅仅为一种逻辑功能划分,实际实现时可以有另外的划分方式,例如多个单元或组件可以结合或者可以集成到另一个系统,或一些特征可以忽略,或不执行。另一点,所显示或讨论的相互之间的耦合或直接耦合或通信连接可以是通过一些接口,装置或单元的间接耦合或通信连接,可以是电性,机械或其它的形式。
本发明是参照根据本发明实施例的方法、装置(系统)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。
这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定 方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。
这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。
在一个典型的配置中,计算设备包括一个或多个处理器(CPU)、输入/输出接口、网络接口和内存。内存可能包括计算机可读介质中的非永久性存储器,随机存取存储器(RAM)和/或非易失性内存等形式,如只读存储器(ROM)或闪存(flash RAM)。内存是计算机可读介质的示例。
计算机可读介质包括永久性和非永久性、可移动和非可移动媒体可以由任何方法或技术来实现信息存储。信息可以是计算机可读指令、数据结构、程序的模块或其他数据。计算机的存储介质的例子包括,但不限于相变内存(PRAM)、静态随机存取存储器(SRAM)、动态随机存取存储器(DRAM)、其他类型的随机存取存储器(RAM)、只读存储器(ROM)、电可擦除可编程只读存储器(EEPROM)、快闪记忆体或其他内存技术、只读光盘只读存储器(CD-ROM)、数字多功能光盘(DVD)或其他光学存储、磁盒式磁带,磁带磁磁盘存储、石墨烯存储或其他磁性存储设备或任何其他非传输介质,可用于存储可以被计算设备访问的信息。按照本文中的界定,计算机可读介质不包括暂存电脑可读媒体(transitory media),如调制的数据信号和载波。
本领域技术人员应明白,本说明书一个或多个实施例可提供为方法、系统或计算机程序产品。因此,本说明书一个或多个实施例可采用完全硬件实施例、完全软件实施例或结合软件和硬件方面的实施例的形式。而且,本说明书一个或多个实施例可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。
本说明书一个或多个实施例可以在由计算机执行的计算机可执行指令的一般上下文中描述,例如程序模块。一般地,程序模块包括执行特定任务或实现特定抽象数据类型的例程、程序、对象、组件、数据结构等等。也可以在分布式计算环境中实践本本说明书一个或多个实施例,在这些分布式计算环境中,由通过通信网络而被连接的远程处理设备来执行任务。在分布式计算环境中,程序模块可以位于包括存储设备在内的本地和远程计算机存储介质中。
本说明书中的各个实施例均采用递进的方式描述,各个实施例之间相同相似的部分互相参见即可,每个实施例重点说明的都是与其他实施例的不同之处。尤其,对于系统实施例而言,由于其基本相似于方法实施例,所以描述的比较简单,相关之处参见方法实施例的部分说明即可。在本说明书的描述中,参考术语“一个实施例”、“一些实施例”、“示例”、“具体示例”、或“一些示例”等的描述意指结合该实施例或示例描述的具体特征、结构、材料或者特点包含于本说明书的至少一个实施例或示例中。在本说明书中,对上述术语的示意性表述不必须针对的是相同的实施例或示例。而且,描述的具体特征、结构、材料或者特点可以在任一个或多个实施例或示例中以合适的方式结合。此外,在不相互矛盾的情况下,本领域的技术人员可以将本说明书中描述的不同实施例或示例以及不同实施例或示例的特征进行结合和组合。
以上所述仅为本说明书一个或多个实施例的实施例而已,并不用于限制本本说明书一个或多个实施例。对于本领域技术人员来说,本说明书一个或多个实施例可以有各种更改和变化。凡在本说明书的精神和原理之内所作的任何修改、等同替换、改进等,均应包含在权利要求范围之内。
Claims (12)
- 一种对包含反射功能的代码进行编译的方法,包括:编译器从代码的程序入口开始扫描反射功能代码,并通过注解得到所述反射功能代码中用到的类及该类所用到的函数;所述编译器将所述包含反射功能的代码所依赖的类中由所述注解得到的用到的这个类及该类所用到的函数的代码加入到待编译列表;所述编译器对所述待编译列表进行编译,得到Wasm字节码。
- 如权利要求1所述的方法,所述包含反射功能的代码,包括源代码或中间字节码。
- 如权利要求2所述的方法,所述编译器集成编译工具链,用于将源代码编译为中间字节码。
- 如权利要求1所述的方法,所述注解采用@LinkClass或@LinkClasses开头的代码表示。
- 如权利要求4所述的方法,所述@LinkClass开头的代码通过后面的属性值(target=被引用类型.class,methods={"被引用方法1","被引用方法2",...})来指定后续反射功能代码中用到的类和用到的该类中的函数。
- 如权利要求1所述的方法,所述反射功能的代码所依赖的类,包括显示或隐式的方式包含的依赖的类。
- 如权利要求1所述的方法,所述反射功能的代码所依赖的类,包括直接或间接依赖的类。
- 如权利要求1所述的方法,所述类所用到的函数的代码包括所述函数原型的代码。
- 如权利要求1-8任一方法,所述方法应用于区块链。
- 一种编译器,包括:扫描单元,从代码的程序入口开始扫描反射功能代码,并通过注解得到所述反射功能代码中用到的类及该类所用到的函数;添加单元,将所述包含反射功能的代码所依赖的类中由所述注解得到的用到的这个类及该类所用到的函数的代码加入到待编译列表;编译单元,对所述待编译列表进行编译,得到Wasm字节码。
- 一种计算机设备,包括:处理器;以及存储器,其中存储有程序,其中在所述处理器执行所述程序时,进行以下操作:从代码的程序入口开始扫描反射功能代码,并通过注解得到所述反射功能代码中用到的类及该类所用到的函数;将所述包含反射功能的代码所依赖的类中由所述注解得到的用到的这个类及该类所用到的函数的代码加入到待编译列表;对所述待编译列表进行编译,得到Wasm字节码。
- 一种存储介质,用于存储程序,其中所述程序在被执行时进行以下操作:从代码的程序入口开始扫描反射功能代码,并通过注解得到所述反射功能代码中用到的类及该类所用到的函数;将所述包含反射功能的代码所依赖的类中由所述注解得到的用到的这个类及该类所用到的函数的代码加入到待编译列表;对所述待编译列表进行编译,得到Wasm字节码。
Applications Claiming Priority (2)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202211066051.5 | 2022-08-31 | ||
CN202211066051.5A CN115495086A (zh) | 2022-08-31 | 2022-08-31 | 一种编译方法和编译器、Wasm虚拟机 |
Publications (1)
Publication Number | Publication Date |
---|---|
WO2024045379A1 true WO2024045379A1 (zh) | 2024-03-07 |
Family
ID=84468529
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
PCT/CN2022/135270 WO2024045379A1 (zh) | 2022-08-31 | 2022-11-30 | 编译方法和编译器、Wasm虚拟机 |
Country Status (2)
Country | Link |
---|---|
CN (1) | CN115495086A (zh) |
WO (1) | WO2024045379A1 (zh) |
Families Citing this family (5)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN117111904B (zh) * | 2023-04-26 | 2024-05-28 | 领悦数字信息技术有限公司 | 用于将Web应用自动转换成无服务器函数的方法和系统 |
CN116661910B (zh) * | 2023-08-01 | 2023-09-22 | 北京中电华大电子设计有限责任公司 | 一种应用调用的方法及装置 |
CN116680015B (zh) * | 2023-08-03 | 2023-09-26 | 北京中电华大电子设计有限责任公司 | 函数调用方法、装置、电子设备及可读存储介质 |
CN117215544B (zh) * | 2023-11-09 | 2024-02-09 | 中国科学院软件研究所 | 一种智能合约专用指令集的实现及运行方法 |
CN118426778A (zh) * | 2024-03-31 | 2024-08-02 | 司空定制家居科技有限公司 | Wasm编译方法、装置、电子设备及存储介质 |
Citations (6)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US20130311980A1 (en) * | 2010-06-29 | 2013-11-21 | Google Inc. | Selective compiling method, device, and corresponding computer program product |
CN109597621A (zh) * | 2018-08-24 | 2019-04-09 | 天津字节跳动科技有限公司 | 封装Dagger的方法、装置、Dagger、解耦方法、装置、设备及介质 |
CN112346778A (zh) * | 2020-10-28 | 2021-02-09 | 常州微亿智造科技有限公司 | 一种Java程序编译时自动生成字节码的优化方法 |
CN113867704A (zh) * | 2021-08-31 | 2021-12-31 | 五八有限公司 | 一种代码测试处理方法、装置、电子设备及存储介质 |
CN114064042A (zh) * | 2020-07-31 | 2022-02-18 | 阿里巴巴集团控股有限公司 | 一种工程源码编译系统、方法及装置 |
CN114416103A (zh) * | 2022-03-14 | 2022-04-29 | Oppo广东移动通信有限公司 | 代码编译方法及装置、计算机可读介质、电子设备 |
-
2022
- 2022-08-31 CN CN202211066051.5A patent/CN115495086A/zh active Pending
- 2022-11-30 WO PCT/CN2022/135270 patent/WO2024045379A1/zh unknown
Patent Citations (6)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US20130311980A1 (en) * | 2010-06-29 | 2013-11-21 | Google Inc. | Selective compiling method, device, and corresponding computer program product |
CN109597621A (zh) * | 2018-08-24 | 2019-04-09 | 天津字节跳动科技有限公司 | 封装Dagger的方法、装置、Dagger、解耦方法、装置、设备及介质 |
CN114064042A (zh) * | 2020-07-31 | 2022-02-18 | 阿里巴巴集团控股有限公司 | 一种工程源码编译系统、方法及装置 |
CN112346778A (zh) * | 2020-10-28 | 2021-02-09 | 常州微亿智造科技有限公司 | 一种Java程序编译时自动生成字节码的优化方法 |
CN113867704A (zh) * | 2021-08-31 | 2021-12-31 | 五八有限公司 | 一种代码测试处理方法、装置、电子设备及存储介质 |
CN114416103A (zh) * | 2022-03-14 | 2022-04-29 | Oppo广东移动通信有限公司 | 代码编译方法及装置、计算机可读介质、电子设备 |
Also Published As
Publication number | Publication date |
---|---|
CN115495086A (zh) | 2022-12-20 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
WO2024045379A1 (zh) | 编译方法和编译器、Wasm虚拟机 | |
US10367822B2 (en) | Restrictive access control for modular reflection | |
JP5905577B2 (ja) | オペレーティングシステムのネイティブプログラミングインターフェイスの他のプログラミング言語の中への投射 | |
US10853096B2 (en) | Container-based language runtime loading an isolated method | |
WO2024045382A1 (zh) | 区块链中实现反射机制 | |
US10789047B2 (en) | Returning a runtime type loaded from an archive in a module system | |
US11366684B2 (en) | Import mechanism for hardware intrinsics | |
WO2018013189A1 (en) | Overriding a migrated method of an updated type | |
US11687388B2 (en) | Implementing optional specialization when executing code | |
US10846417B2 (en) | Identifying permitted illegal access operations in a module system | |
US10983771B1 (en) | Quality checking inferred types in a set of code | |
US11048489B2 (en) | Metadata application constraints within a module system based on modular encapsulation | |
US10387142B2 (en) | Using annotation processors defined by modules with annotation processors defined by non-module code | |
US11347487B2 (en) | Confining reflective access based on module boundaries | |
WO2023061452A1 (zh) | 语言互操作方法、装置、存储介质及程序产品 | |
US20210311628A1 (en) | Methods for reducing unsafe memory access when interacting with native libraries | |
CN116909652A (zh) | 一种启动WebAssembly程序的方法、计算机设备及存储介质 | |
CN116932085A (zh) | 一种启动WebAssembly程序的方法、计算机设备及存储介质 | |
Bandyopadhyay et al. | Compiling dynamic languages via typed functional languages | |
WO2017034652A1 (en) | Restrictive access control for modular reflection |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
121 | Ep: the epo has been informed by wipo that ep was designated in this application |
Ref document number: 22957191 Country of ref document: EP Kind code of ref document: A1 |