org.jikesrvm.jni.ia32
Class JNICompiler

java.lang.Object
  extended by org.jikesrvm.jni.ia32.JNICompiler
All Implemented Interfaces:
Constants, HeapLayoutConstants, ArchConstants, BaselineConstants, RegisterConstants, StackframeLayoutConstants, TrapConstants, ThinLockConstants, TIBLayoutConstants, SizeConstants
Direct Known Subclasses:
ArchitectureSpecific.JNICompiler

public abstract class JNICompiler
extends Object
implements BaselineConstants

This class compiles the prolog and epilog for all code that makes the transition between Java and Native C for the 2 cases:

When performing the transitions the values in registers and on the stack need to be treated with care, but also when transitioning into Java we need to do a spin-wait if a GC is underway. Transitioning from Java to C then back:
  1. Set up stack frame and save non-volatile registers
  2. Move all native method arguments on to stack (NB at this point all non-volatile state is saved)
  3. Set up jniEnv
  4. Record the frame pointer of the last Java frame (this) in the jniEnv
  5. Set up JNI refs, a stack that holds references accessed via JNI
  6. Call out to convert reference arguments to IDs
  7. Set processor as being "in native"
  8. Set up stack frame and registers for transition to C
  9. Call out to C
  10. Save result to stack
  11. Transition back from "in native" to "in Java", take care that the Processor isn't "blocked in native", ie other processors have decided to start a GC and we're not permitted to execute Java code whilst this occurs
  12. Convert a reference result (currently a JNI ref) into a true reference
  13. Release JNI refs
  14. Restore stack and place result in register
    1. Prologue generation from C to Java:
      1. Set up stack frame with C arguments in Jikes RVM convention
      2. Set up extra stack frame entry that records the previous last top Java FP
      3. Transition from "in native" to "in Java" taking care of blocked (in GC) case
      Epilogue generation from Java to C:
      1. Restore record of the previous last top Java FP in the jniEnv
      2. Transition from "in Java" to "in native"
      3. Set up result in registers. NB. JNIFunctions don't return references but JNI refs directly, so we don't need to transition these


      Nested Class Summary
       
      Nested classes/interfaces inherited from interface org.jikesrvm.ia32.RegisterConstants
      RegisterConstants.FloatingPointMachineRegister, RegisterConstants.FPR, RegisterConstants.GPR, RegisterConstants.MachineRegister, RegisterConstants.MM, RegisterConstants.XMM
       
      Field Summary
      private static Offset BP_ON_ENTRY_OFFSET
                Location of a saved version of the field JNIEnvironment.basePointerOnEntryToNative
      (package private) static Offset EBP_SAVE_OFFSET
                Location of non-volatile EBP register when saved to stack
      (package private) static Offset EBX_SAVE_OFFSET
                Location of non-volatile EBX register when saved to stack
      (package private) static Offset EDI_SAVE_OFFSET
                Location of non-volatile EDI register when saved to stack
      private static Offset JNI_ENV_OFFSET
                Location of an extra copy of the RVMThread.jniEnv when saved to stack
      private static int jniExternalFunctionsFieldOffset
                Offset of external functions field in JNIEnvironment
      static int SAVED_GPRS_FOR_JNI
                The following is used in BaselineCompilerImpl to compute offset to first local.
      private static Offset SAVED_JAVA_FP_OFFSET
                Stack frame location for saved JNIEnvironment.JNITopJavaFP that will be clobbered by a transition from Java to C.
      private  JNIExceptionDeliverer unused
                Dummy field to force compilation of the exception deliverer
       
      Fields inherited from interface org.jikesrvm.ia32.BaselineConstants
      BRIDGE_FRAME_EXTRA_SIZE, FPU_SAVE_OFFSET, LG_WORDSIZE, S0, S1, SAVED_GPRS, SAVED_GPRS_FOR_SAVE_LS_REGISTERS, SP, STACKFRAME_FIRST_PARAMETER_OFFSET, STACKFRAME_REG_SAVE_OFFSET, T0, T0_int, T0_SAVE_OFFSET, T1, T1_int, T1_SAVE_OFFSET, TR, WORDSIZE, XMM_SAVE_OFFSET
       
      Fields inherited from interface org.jikesrvm.Constants
      NOT_REACHED, REFLECTION_FPRS_BITS, REFLECTION_FPRS_MASK, REFLECTION_GPRS_BITS, REFLECTION_GPRS_MASK
       
      Fields inherited from interface org.jikesrvm.objectmodel.ThinLockConstants
      TL_DEDICATED_U16_OFFSET, TL_DEDICATED_U16_SHIFT, TL_LOCK_COUNT_MASK, TL_LOCK_COUNT_SHIFT, TL_LOCK_COUNT_UNIT, TL_LOCK_ID_MASK, TL_LOCK_ID_SHIFT, TL_NUM_BITS_RC, TL_NUM_BITS_STAT, TL_NUM_BITS_TID, TL_STAT_BIASABLE, TL_STAT_FAT, TL_STAT_MASK, TL_STAT_SHIFT, TL_STAT_THIN, TL_THREAD_ID_MASK, TL_THREAD_ID_SHIFT, TL_UNLOCK_MASK
       
      Fields inherited from interface org.jikesrvm.SizeConstants
      BITS_IN_ADDRESS, BITS_IN_BOOLEAN, BITS_IN_BYTE, BITS_IN_CHAR, BITS_IN_DOUBLE, BITS_IN_EXTENT, BITS_IN_FLOAT, BITS_IN_INT, BITS_IN_LONG, BITS_IN_OFFSET, BITS_IN_PAGE, BITS_IN_SHORT, BITS_IN_WORD, BYTES_IN_ADDRESS, BYTES_IN_BOOLEAN, BYTES_IN_BYTE, BYTES_IN_CHAR, BYTES_IN_DOUBLE, BYTES_IN_EXTENT, BYTES_IN_FLOAT, BYTES_IN_INT, BYTES_IN_LONG, BYTES_IN_OFFSET, BYTES_IN_PAGE, BYTES_IN_SHORT, BYTES_IN_WORD, LOG_BITS_IN_ADDRESS, LOG_BITS_IN_BOOLEAN, LOG_BITS_IN_BYTE, LOG_BITS_IN_CHAR, LOG_BITS_IN_DOUBLE, LOG_BITS_IN_EXTENT, LOG_BITS_IN_FLOAT, LOG_BITS_IN_INT, LOG_BITS_IN_LONG, LOG_BITS_IN_OFFSET, LOG_BITS_IN_PAGE, LOG_BITS_IN_SHORT, LOG_BITS_IN_WORD, LOG_BYTES_IN_ADDRESS, LOG_BYTES_IN_BOOLEAN, LOG_BYTES_IN_BYTE, LOG_BYTES_IN_CHAR, LOG_BYTES_IN_DOUBLE, LOG_BYTES_IN_EXTENT, LOG_BYTES_IN_FLOAT, LOG_BYTES_IN_INT, LOG_BYTES_IN_LONG, LOG_BYTES_IN_OFFSET, LOG_BYTES_IN_PAGE, LOG_BYTES_IN_SHORT, LOG_BYTES_IN_WORD
       
      Fields inherited from interface org.jikesrvm.objectmodel.TIBLayoutConstants
      IMT_METHOD_SLOTS, NEEDS_DYNAMIC_LINK, TIB_ARRAY_ELEMENT_TIB_INDEX, TIB_DOES_IMPLEMENT_INDEX, TIB_FIRST_SPECIALIZED_METHOD_INDEX, TIB_FIRST_VIRTUAL_METHOD_INDEX, TIB_INTERFACE_DISPATCH_TABLE_INDEX, TIB_SUPERCLASS_IDS_INDEX, TIB_TYPE_INDEX
       
      Fields inherited from interface org.jikesrvm.HeapLayoutConstants
      BAD_MAP_COMPRESSION, BOOT_IMAGE_CODE_END, BOOT_IMAGE_CODE_SIZE, BOOT_IMAGE_CODE_START, BOOT_IMAGE_DATA_END, BOOT_IMAGE_DATA_SIZE, BOOT_IMAGE_DATA_START, BOOT_IMAGE_END, BOOT_IMAGE_RMAP_END, BOOT_IMAGE_RMAP_START, MAX_BOOT_IMAGE_RMAP_SIZE, MAXIMUM_MAPPABLE
       
      Fields inherited from interface org.jikesrvm.ia32.ArchConstants
      SSE2_BASE, SSE2_FULL
       
      Fields inherited from interface org.jikesrvm.ia32.StackframeLayoutConstants
      BYTES_IN_STACKSLOT, FPU_STATE_SIZE, INVISIBLE_METHOD_ID, LOG_BYTES_IN_STACKSLOT, STACK_SIZE_BOOT, STACK_SIZE_COLLECTOR, STACK_SIZE_DLOPEN, STACK_SIZE_GCDISABLED, STACK_SIZE_GROW, STACK_SIZE_GUARD, STACK_SIZE_JNINATIVE_GROW, STACK_SIZE_MAX, STACK_SIZE_NORMAL, STACK_SIZE_SYSCALL, STACKFRAME_ALIGNMENT, STACKFRAME_BODY_OFFSET, STACKFRAME_FRAME_POINTER_OFFSET, STACKFRAME_HEADER_SIZE, STACKFRAME_METHOD_ID_OFFSET, STACKFRAME_RETURN_ADDRESS_OFFSET, STACKFRAME_SENTINEL_FP, XMM_STATE_SIZE
       
      Fields inherited from interface org.jikesrvm.ia32.RegisterConstants
      ALL_FPRS, ALL_GPRS, EAX, EBP, EBX, ECX, EDI, EDX, ESI, ESP, FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7, INSTRUCTION_WIDTH, LG_INSTRUCTION_WIDTH, MM0, MM1, MM10, MM11, MM12, MM13, MM14, MM15, MM2, MM3, MM4, MM5, MM6, MM7, MM8, MM9, NATIVE_NONVOLATILE_FPRS, NATIVE_NONVOLATILE_GPRS, NATIVE_PARAMETER_FPRS, NATIVE_PARAMETER_GPRS, NATIVE_VOLATILE_FPRS, NATIVE_VOLATILE_GPRS, NONVOLATILE_FPRS, NONVOLATILE_GPRS, NUM_FPRS, NUM_GPRS, NUM_NONVOLATILE_FPRS, NUM_NONVOLATILE_GPRS, NUM_PARAMETER_FPRS, NUM_PARAMETER_GPRS, NUM_RETURN_FPRS, NUM_RETURN_GPRS, NUM_VOLATILE_FPRS, NUM_VOLATILE_GPRS, PARAMETER_FPRS, PARAMETER_GPRS, R0, R1, R10, R11, R12, R13, R14, R15, R2, R3, R4, R5, R6, R7, R8, R9, RETURN_FPRS, RETURN_GPRS, STACK_POINTER, THREAD_REGISTER, VOLATILE_FPRS, VOLATILE_GPRS, XMM0, XMM1, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9
       
      Fields inherited from interface org.jikesrvm.ia32.TrapConstants
      RVM_TRAP_BASE
       
      Constructor Summary
      JNICompiler()
                 
       
      Method Summary
      static CompiledMethod compile(NativeMethod method)
                Compile a method to handle the Java to C transition and back Transitioning from Java to C then back: Set up stack frame and save non-volatile registers Set up jniEnv - set up a register to hold JNIEnv and store the Processor in the JNIEnv for easy access Move all native method arguments on to stack (NB at this point all non-volatile state is saved) Record the frame pointer of the last Java frame (this) in the jniEnv Call out to convert reference arguments to IDs Set processor as being "in native" Set up stack frame and registers for transition to C Call out to C Save result to stack Transition back from "in native" to "in Java", take care that the Processor isn't "blocked in native", ie other processors have decided to start a GC and we're not permitted to execute Java code whilst this occurs Convert a reference result (currently a JNI ref) into a true reference Release JNI refs Restore stack and place result in register
      static void generateEpilogForJNIMethod(Assembler asm, RVMMethod method)
                Handle the C to Java transition: JNI methods in JNIFunctions.java.
      static void generateGlueCodeForJNIMethod(Assembler asm, NormalMethod method, int methodID)
                Handle the C to Java transition: JNI methods in JNIFunctions.java.
       
      Methods inherited from class java.lang.Object
      clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
       

      Field Detail

      unused

      private JNIExceptionDeliverer unused
      Dummy field to force compilation of the exception deliverer


      jniExternalFunctionsFieldOffset

      private static final int jniExternalFunctionsFieldOffset
      Offset of external functions field in JNIEnvironment


      EDI_SAVE_OFFSET

      static final Offset EDI_SAVE_OFFSET
      Location of non-volatile EDI register when saved to stack


      EBX_SAVE_OFFSET

      static final Offset EBX_SAVE_OFFSET
      Location of non-volatile EBX register when saved to stack


      EBP_SAVE_OFFSET

      static final Offset EBP_SAVE_OFFSET
      Location of non-volatile EBP register when saved to stack


      JNI_ENV_OFFSET

      private static final Offset JNI_ENV_OFFSET
      Location of an extra copy of the RVMThread.jniEnv when saved to stack


      BP_ON_ENTRY_OFFSET

      private static final Offset BP_ON_ENTRY_OFFSET
      Location of a saved version of the field JNIEnvironment.basePointerOnEntryToNative


      SAVED_JAVA_FP_OFFSET

      private static final Offset SAVED_JAVA_FP_OFFSET
      Stack frame location for saved JNIEnvironment.JNITopJavaFP that will be clobbered by a transition from Java to C. Only used in the prologue & epilogue for JNIFunctions.


      SAVED_GPRS_FOR_JNI

      public static final int SAVED_GPRS_FOR_JNI
      The following is used in BaselineCompilerImpl to compute offset to first local. Number of non-volatile GPRs and FPRs and then 1 slot for the SAVED_JAVA_FP.

      Constructor Detail

      JNICompiler

      public JNICompiler()
      Method Detail

      compile

      public static CompiledMethod compile(NativeMethod method)
      Compile a method to handle the Java to C transition and back Transitioning from Java to C then back:
      1. Set up stack frame and save non-volatile registers
      2. Set up jniEnv - set up a register to hold JNIEnv and store the Processor in the JNIEnv for easy access
      3. Move all native method arguments on to stack (NB at this point all non-volatile state is saved)
      4. Record the frame pointer of the last Java frame (this) in the jniEnv
      5. Call out to convert reference arguments to IDs
      6. Set processor as being "in native"
      7. Set up stack frame and registers for transition to C
      8. Call out to C
      9. Save result to stack
      10. Transition back from "in native" to "in Java", take care that the Processor isn't "blocked in native", ie other processors have decided to start a GC and we're not permitted to execute Java code whilst this occurs
      11. Convert a reference result (currently a JNI ref) into a true reference
      12. Release JNI refs
      13. Restore stack and place result in register

      generateGlueCodeForJNIMethod

      public static void generateGlueCodeForJNIMethod(Assembler asm,
                                                      NormalMethod method,
                                                      int methodID)
      Handle the C to Java transition: JNI methods in JNIFunctions.java. Create a prologue for the baseline compiler.
       NOTE:
         -We need THREAD_REGISTER to access Java environment; we can get it from
          the JNIEnv* (which is an interior pointer to the JNIEnvironment)
         -Unlike the powerPC scheme which has a special prolog preceding
          the normal Java prolog, the Intel scheme replaces the Java prolog
          completely with the special prolog
      
                  Stack on entry            Stack at end of prolog after call
                   high memory                       high memory
                  |            |                   |            |
          EBP ->  |saved FP    |                   |saved FP    |
                  |  ...       |                   |  ...       |
                  |            |                   |            |
                  |arg n-1     |                   |arg n-1     |
       native     |  ...       |                   |  ...       |
       caller     |arg 0       | JNIEnv*           |arg 0       | JNIEnvironment
          ESP ->  |return addr |                   |return addr |
                  |            |           EBP ->  |saved FP    | outer most native frame pointer
                  |            |                   |methodID    | normal MethodID for JNI function
                  |            |                   |saved JavaFP| offset to preceeding java frame
                  |            |                   |saved nonvol| to be used for nonvolatile storage
                  |            |                   |  ...       |   including ebp on entry
                  |            |                   |arg 0       | copied in reverse order (JNIEnvironment)
                  |            |                   |  ...       |
                  |            |           ESP ->  |arg n-1     |
                  |            |                   |            | normally compiled Java code continue
                  |            |                   |            |
                  |            |                   |            |
                  |            |                   |            |
                   low memory                        low memory
       


      generateEpilogForJNIMethod

      public static void generateEpilogForJNIMethod(Assembler asm,
                                                    RVMMethod method)
      Handle the C to Java transition: JNI methods in JNIFunctions.java. Create an epilogue for the baseline compiler.