The example system 100 comprises computer instructions HIR source and annotations (HIRSA) 102, bytecode 106, HIR binary 112, HIR and annotations 114, low-level intermediate representation (LIR) and annotations 118, native function 120, and machine code 124. To perform the example methods described herein, the example system also includes an HIR assembler 104, a bytecode translator 108, an HIR input/output (I/O) 110, a high-level optimizer 115, a code selector 116, and a code emitter 122. In the example system 100, the computer instructions illustrated with darkened borders are provided as inputs to the system 100. For example, a user may author and/or generate the computer instructions illustrated with darkened borders. The dashed lines (e.g., the line between the HIRSA 102 and the HIR assembler 104) represent operations that are performed prior to runtime. The solid lines (e.g., the line between the bytecode 106 and the bytecode translator 108) represent operations that are performed at runtime via just-in-time (JIT) compilation.
The example HIRSA 102 comprises HIR instructions that enable (e.g., instruct) a computer (e.g., computer 800 of
The example HIRSA 102 includes instructions that enable the computer to receive the annotations and call the native function. The example HIRSA 102 also includes instructions that enable the computer to return the result of the call to the native function 120 to the program or application that required the call to the native function 120. If the native function 120 is to operate on an array that is a part of the managed environment, then the HIRSA 102 will also include instructions to retrieve the memory location of the array's first element and pass the memory location of the array's first element to the native function 120. The HIRSA 102 also includes instructions to indicate that the memory location associated with the array is pinned or locked so that the garbage collection service of the managed environment does not move or remove the array. An example of the HIRSA 102 is illustrated in
The HIR assembler 104 receives the HIRSA 102 and converts the HIRSA 102 into the HIR binary code 112. The HIR binary code 112 is transferred to memory via the HIR I/O 110. For example, the HIR assembler 104 may generate the HIR binary code 112 and store the HIR binary code 112 on an available memory or hard disk storage device (not shown in
The bytecode 106, of the illustrated example, is Java bytecode output from a Java compiler. The bytecode 106 may alternatively be any type of managed application bytecode. For example, the bytecode 106 may be bytecode for a language associated with the CLR.
A compilation driver (not illustrated) may be provided to control the compilation process by invoking the illustrated components (bytecode translator 108, high-level optimizer 115, code selector 116, and code emitter 122). The compilation driver may serve two types of requests from the VM. The first request is for compilation of a method's bytecode. A compilation request is fulfilled by the compilation driver by pushing the bytecode into the compilation pipeline starting from the bytecode translator 108. The second request is for handling an HIR of a method. An HIR handling request is fulfilled by pushing the HIR into the compilation pipeline starting from the high-level optimizer 115 or code selector 116. The HIR is loaded from an HIR binary by the class loading subsystem. Upon class loading, the VM determines which native methods of the loaded class are overridden in the HIR binary and loads the overriding HIR of the methods from the binary. The VM also arranges the data of internal methods so that upon invocation of each overridden method, the HIR of the overridden method will be passed to the JIT compiler for generating executable code from it.
The bytecode translator 108 receives the bytecode 106 and translates the bytecode 106 to HIR in-memory format. For example, the bytecode 106 may be translated and included in the HIR and annotations 114 when the managed application or program is executed.
The HIR and annotations 114 is representative of the collection of HIR binary code including annotations that are available for use in the managed application or program.
The high-level optimizer 115, among other optimizations, analyzes the HIR of the compiled method to determine if any of the native methods called from the compiled method have been overridden by methods in the HIR binary 112 and inlines the overriding methods into the HIR of the method being compiled. For example, if the translated HIR includes a call to a native method and the HIR binary contains an overriding method for the called method, the high-level optimizer 115 replaces the call with the overriding method.
The code selector 116 translates the modified HIR and annotations 114 received from the high-level optimizer 115 into the LIR and annotations 118. The LIR and annotations 118 are low-level intermediate representation instructions corresponding to the HIR and annotations 114 translated by the code selector 116. The LIR and annotations 118 are transmitted to the code emitter 122.
The native function 120 is any program, function, or method compiled to native code. For example, the native function 120 may be compiled from C language source code. The native function 120 may alternatively be compiled from any other native code language such as, for example, C++, assembly, etc.
The code emitter 122 receives the LIR and annotations 118 and compiles them into machine code instructions 124 that may be executed by a processor. According to the illustrated example, the machine code instructions 124 are machine-dependent. In other words, the machine code instructions 124 are designed to be executed on a system with the same architecture as the machine that generated them. The code emitter 122 also links the machine code instructions with the native function 120. For example, the code emitter 122 may store an address associated with the native function 120 in memory that is accessed by the machine code 124 to call a native method.
As discussed in further detail below, if a user has created optimized HIR and/or LIR, then the class loading subsystem 205 finds such stored binaries and forwards them to the JIT compiler 210 instead of bytecode 202 and 215. For example, if the user has created HIR code to access a native method, the HIR code will replace a call to the native method in the HIRs of all methods whose bytecode contain such a call. The JIT compiler 210 may receive IR source code 215 generated by a user (e.g., HIR source code, LIR source code), IR source code 220 from the class loading subsystem 205, bytecode 225, and IR binaries 235, 240 from the class loading subsystem 205 or directly from a library in an external storage 242 as discussed in further detail below. Users may generate HIR and LIR source code as, for example, a text file. The example JIT compiler 210 also includes an IR translator 245, an IR loader 230, and a JIT compiler pipeline 250. The JIT compiler pipeline 250 includes in-memory HIR 255, in-memory LIR 260, a code selector 265, a bytecode translator 270, a code emitter 275, and generated code 280. Additionally, the JIT compiler pipeline 250 includes a high-level optimizer (H-OPT) 285 and a low-level optimizer (L-OPT) 290.
The example VM 201 may operate in either an ahead-of-time mode or a just-in-time mode. The ahead-of-time mode allows the user to translate hand-tuned HIR and/or the LIR source code 215 to a binary format for future use. For example, dotted arrows indicate various VM 201 components employed during the ahead-of-time mode, and solid arrows indicate components that may be used during the just-in-time (or runtime) mode. In particular, the IR source code 215 is provided to the IR translator 245 to translate textual representations of an HIR and/or LIR program to the in-memory HIR 255 representations and/or the in-memory LIR 260 representations (e.g., data structures). The in-memory format is provided to the IR loader 230, which contains an HIR serializer/deserializer (SERDES) 231 to convert the HIR in-memory representations into a binary format and to convert the HIR binary format to an HIR in-memory representation. Similarly, the IR loader 230 contains an LIR SERDES 232 to convert the LIR in-memory representations into a binary format and to convert the LIR binary format to an LIR in-memory representation. The IR binaries 240 resulting from the HIR and/or LIR serializers 231 and 232 are stored in the external storage 242 in, for example, user-defined attributes of class files or external libraries in proprietary formats.
During the run-time mode, IR binaries of the external memory are embedded into the JIT compiler pipeline 250. In particular, the class loading subsystem 205 determines if an IR binary of the method is represented in the external storage 242. If so, rather than compiling the bytecode 202, 225 with the bytecode translator 270, the IR binaries 240 are retrieved from the class loading subsystem 205 or directly from a library in the external storage 242 and deserialized into IR in-memory representations 255, 260 by the deserializers of the IR loader 230. HIR in-memory representations of the JIT compiler pipeline 250 are translated to the in-memory LIR 260 by the code selector 265 during run-time. The code emitter 275 produces code 280 from the IR in-memory representations that are suitable for a target machine. The code emitter 275 also links the code 280 with the native function 276. For example, the code emitter 275 may store an address associated with the native function 276 in memory that is accessed by the code 280 to call a native method.
To help reduce the traditional bottleneck that occurs during the transition from managed code to native code (e.g., using the JNI), users may develop HIR and/or LIR as an alternative to JNI stubs that traditionally allow safe operation of managed entities. Rather than reliance upon the JNI for management of the formal parameters of the native call, proper exception handling (should it occur in the native method), garbage collector safepoints, and/or other tasks associated with managed-to-native code transition (which may depend on a particular JNI implementation), the user is provided an opportunity to develop HIR/LIR to handle such calls in any desired manner.
Although the foregoing discloses example methods and apparatus including, among other components, firmware and/or software executed on hardware, it should be noted that such methods and apparatus are merely illustrative and should not be considered as limiting. For example, it is contemplated that any or all of these hardware and software components could be embodied exclusively in dedicated hardware, exclusively in software, exclusively in firmware, or in some combination of hardware, firmware and/or software. Accordingly, while the following describes example methods and apparatus, persons of ordinary skill in the art will readily appreciate that the examples are not the only way to implement such systems.
Flowcharts representative of example processes for implementing the example system 100 of
The execution of the example process of
In the illustrated example, after creation of the HIR binary 112, the HIR binary 112 is stored and the system 100 waits for runtime; a portion of which is illustrated in
The execution of the example process begins when a VM calls a JIT compiler to process the native method (block 306b). Depending on the VM design this can happen when the native method is called for the first time or when VM loads a class containing the native method. In any case, the VM requests the JIT compiler to check whether the native method is overridden in HIR binary.
When requested to process a native method, the JIT compiler determines if the native method is overridden in the HIR binary (block 308b). If the method is not overridden, control returns to the virtual machine and all invocations of the native method will result in execution of the original native method. If the method is overridden in the HIR binary, the HIR version of the method is loaded and advanced further to the JIT compiler pipeline and optimized by the high-level optimizer 115 (block 310b). The HIR is then translated to LIR by the code selector 116 (block 312b). Then, the LIR is translated to machine code by the code emitter 122 (block 314b). The code emitter 122 writes or stores the address of the generated machine code in a global data location associated with the native method (block 316b) so that all invocations to the native method will result in execution of the version compiled by the JIT compiler from the HIR binary. After the machine code has been output and the code address has been written to the global data location, control returns to the virtual machine to continue executing the managed application.
The execution of the example process begins when a virtual machine handling the managed application requests the JIT compiler to produce the machine code from the bytecode (block 305c). For example, the virtual machine can be designed to call the JIT compiler upon first execution of a managed method.
The bytecode translator 270 translates the bytecode into HIR in-memory representation 255 which is then advanced to the high-level optimizer H-OPT 285. The H-OPT 285 analyzes the next instruction of the HIR in-memory representation 255 (e.g., the first instruction if no instructions have yet been analyzed) (block 306c). The H-OPT 285 determines if the instruction includes a call to a native method (block 307c). If the instruction does not include a call to a native method, control proceeds to block 314c, which will be described in detail below.
If the H-OPT 285 determines that the instruction does include a call to a native method, the H-OPT 285 determines if the native method is overridden in the HIR binary (block 308c). If the H-OPT 285 determines that the native method is not overridden in the HIR binary, control proceeds to block 314c, which will be described in detail below. If the H-OPT 285 determines that the native method is overridden in the HIR binary, H-OPT 285 loads the HIR binary (block 310c). For example, H-OPT 285 may load the HIR binary from a memory, a disk storage, etc.
After loading the overriding HIR instructions in the HIR binary, H-OPT 285 replaces the call to the native method with the overriding HIR instructions from the HIR binary (block 312c). For example, the HIR translated from the bytecode 225 may include a call to a native method wherein the native method is overridden by the HIR binary 240. H-OPT 285 will replace the call to the native method with the HIR instructions in the HIR binary 240. This inlining process can be done recursively for invocation instructions in the HIR inlined from the HIR binary.
After the inlining process is finished (exit from the loop controlled by the block 314c) the resulting HIR in-memory representation 255 is advanced for further transformation in the JIT compiler pipeline (not shown on
Persons of ordinary skill in the art will appreciate that processes similar to those described on
Persons of ordinary skill in the art will recognize that all HIR may not be processed prior to generating the machine code. For example, a first part of an application may be converted to machine code and executed. At a time when the first part of the application references a second part of the application, the second part of the application is converted to machine code so that it may be executed. In other words, the second part of the application is compiled just-in-time for execution.
The JAVA source code in
The HIR source code of
The first annotation 702 is associated with the standard C-runtime function “malloc” used to allocate memory. The instruction ‘Int32(IntPtr)’ instructs the machine that the “malloc” function returns void* and accepts an integer as a parameter. The instruction ‘cdecl’ instructs the machine that the native function is compiled with the cdecl IA32 calling convention. The second annotation 704 is associated with the native function 701 of
The first method 706 overrides the method 502 of
The second method 708 overrides the method 504 of
The third method 710 overrides the method 506 of
Persons of ordinary skill in the art will recognize that the code shown in
The system 800 of the instant example includes a processor 812 such as a general purpose programmable processor. The processor 812 includes a local memory 814, and executes coded instructions 816 present in random access memory 818 and/or in another memory device. The processor 812 may execute, among other things, the machine readable instructions illustrated in
The processor 812 is in communication with a main memory including a volatile memory 818 and a non-volatile memory 820 via a bus 822. The volatile memory 818 may be implemented by Synchronous Dynamic Random Access Memory (SDRAM), Dynamic Random Access Memory (DRAM), RAMBUS Dynamic Random Access Memory (RDRAM) and/or any other type of random access memory device. The non-volatile memory 820 may be implemented by flash memory and/or any other desired type of memory device. Access to the main memory 818, 820 is typically controlled by a memory controller (not shown) in a conventional manner.
The computer 800 also includes a conventional interface circuit 824. The interface circuit 824 may be implemented by any type of well known interface standard, such as an Ethernet interface, a universal serial bus (USB), and/or a third generation input/output (3GIO) interface.
One or more input devices 826 are connected to the interface circuit 824. The input device(s) 826 permit a user to enter data and commands into the processor 812. The input device(s) can be implemented by, for example, a keyboard, a mouse, a touchscreen, a track-pad, a trackball, isopoint and/or a voice recognition system.
One or more output devices 828 are also connected to the interface circuit 824. The output devices 828 can be implemented, for example, by display devices (e.g., a liquid crystal display, a cathode ray tube display (CRT), a printer and/or speakers). The interface circuit 824, thus, typically includes a graphics driver card.
The interface circuit 824 also includes a communication device such as a modem or network interface card to facilitate exchange of data with external computers via a network (e.g., an Ethernet connection, a digital subscriber line (DSL), a telephone line, coaxial cable, a cellular telephone system, etc.).
The computer 800 also includes one or more mass storage devices 830 for storing software and data. Examples of such mass storage devices 830 include floppy disk drives, hard drive disks, compact disk drives and digital versatile disk (DVD) drives.
As an alternative to implementing the methods and/or apparatus described herein in a system such as the device of
Although certain example methods, apparatus, and articles of manufacture have been described herein, the scope of coverage of this patent is not limited thereto. On the contrary, this patent covers all methods, apparatus and articles of manufacture fairly falling within the scope of the appended claims either literally or under the doctrine of equivalents.
Number | Date | Country | Kind |
---|---|---|---|
PCTRU2006000321 | Jun 2006 | WO | international |
This patent arises from a continuation of International Patent Application No. PCT/RU2006/000321, entitled “METHODS AND APPARATUS TO CALL NATIVE CODE FROM A MANAGED CODE APPLICATION” which was filed on Jun. 20, 2006. International Patent Application No. PCT/RU2006/000321 is hereby incorporated by reference in its entirety.