Working with MS VM
 
 

Microsoft VM    PreviousVM
Just-In-Time Compilation and the Microsoft Win32 VM for Java     Previous VM

 


The JIT Compiler/VM Interface

The following diagram illustrates the relationship between the JIT compiler and the Microsoft VM for Java.

The JIT compiler and the VM provide interfaces that both use to enable effective JIT code compilation. The "compilation unit" for the JIT compiler is a single method. The VM alone decides which method to compile. Tools vendors might want to provide facilities in their tools (for example, through language constructs or user interface) to augment .class files so that they indicate which methods to JIT (the precise format of such .class file attributes is TBD).

These interfaces are designed to allow clean separation and independence between the VM and the JIT compiler. This will enable other vendors to replace one JIT compiler with another, as appropriate.

A JIT compiler (vendor) can make the following assumptions.

  • Code and data blocks allocated through the respective VM helper functions will stay in place. Therefore, most references to methods and data members can be resolved at compilation time.
  • The first element in every object contains the reference to the respective class's vtable (method-pointer table).
  • For arrays (which are also Java objects) the offset for the element count as well as the offset for the first array element are always at the same fixed offset relative to the beginning of the object (array).
  • Every loaded interface is assigned a unique handle, which allows quick access at run time.
  • The vtable offsets of interface methods are always the same across all implementations of the interface. Therefore, all vtable offsets for methods can be resolved at compile time.

At the same time, the code and data that a JIT compiler generates for the Microsoft VM for Java must meet the following criteria.

  • All methods must have a local stack frame.
  • For the x86 platform, the calling convention is basically "__pascal": parameters must be pushed from left to right ("this" is pushed before any user arguments), the callee pops arguments, EBX/ESI/EDI are the callee-saved registers, and the FP stack is always empty on entry to methods, return values in EAX (32-bit scalars), EDX:EAX (64-bit integers), or on the FP stack (floats and doubles).
  • The JIT compiler must provide an API that enumerates all live references in a method while it calls a method (stack crawling support for GC).
  • Optionally, the JIT compiler may provide an API that enumerates all live references in a method at any time (this allows GC to occur at any time).
  • Currently only "base" pointers can be live at points where GC might occur (for example, the code might not have a pointer to the interior of an object/array that is live across a method call).
  • Code sharing across multiple namespaces is supported (optional).

The JIT compiler decides whether to allow interruption by the garbage collector at any time or just while a method calls another method. The latter is certainly easier to implement and needs less information at run time, but in certain scenarios it could disable the garbage collection process for an extended period of time (for example, a method executes a loop that does not contain a method call). In those cases, the JIT compiler must insert code that (conditionally) invokes the garbage collector directly unless it can be determined that the code will execute method calls frequently enough. To give the JIT maximal flexibility, it can make this decision for every method individually.

Beyond just generating code for a method, the JIT must provide additional information to enable proper execution and debugging of Java applications. Depending on the type of information, that is done in two ways:

  • Information defined by the VM: The JIT compiler provides this information at compile time to the VM, and the VM records and interprets it (for example, exception handler tables and line number information).
  • Private JIT information: The JIT compiler can store any private information along with each method so that it can provide the requested information to the VM at run time; the VM saves the information (to the VM it is just a single block of opaque data) and passes it back to the JIT compiler at run time (for example, enumeration of live object references in a stack frame, decision if a method is "GC-safe" at the current offset, and so on).

Top © 1998 Microsoft Corporation. All rights reserved. Terms of use.