static VM_MachineCode generateGlueCodeForNative ( int compiledMethodId, VM_Method method ) {
static VM_MachineCode generateGlueCodeForNative (VM_CompiledMethod cm) { int compiledMethodId = cm.getId(); VM_Method method     = cm.getMethod();
  static VM_MachineCode generateGlueCodeForNative ( int compiledMethodId, VM_Method method ) {    VM_Assembler asm	 = new VM_Assembler(100);   // some size for the instruction array    int nativeIP         = method.getNativeIP();    // recompute some constants    int parameterWords   = method.getParameterWords();    // Meaning of constant offset into frame:    // STACKFRAME_HEADER_SIZE =  12              (CHECK ??)    // SAVED_GPRS = 4 words/registers    // Stack frame:    //        on entry          after prolog    //    //      high address	high address    //      |          |	|          | Caller frame    //      |          |	|          |    // +    |arg 0     |	|arg 0     |    -> firstParameterOffset    // +    |arg 1     |	|arg 1     |    // +    |...       |	|...       |    // +8   |arg n-1   |	|arg n-1   |        // +4   |returnAddr|	|returnAddr|    //  0   +	       +	+saved FP  + <---- FP for glue frame    // -4   |	       |	|methodID  |    // -8   |	       |	|saved EDI |    -> STACKFRAME_BODY_OFFSET = -8    // -C   |	       |	|saved EBX |    // -10  |	       |	|saved EBP |    // -14  |	       |	|returnAddr|  (return from OutOfLine to generated epilog)        // -18  |	       |	|saved PR  |    // -1C  |	       |	|arg n-1   |  reordered args to native method    // -20  |	       |	| ...      |  ...    // -24  |	       |	|arg 1     |  ...    // -28  |	       |	|arg 0     |  ...    // -2C  |	       |	|class/obj |  required second arg to native method    // -30  |	       |	|jniEnv    |  required first arg to native method    // -34  |	       |	|          |        //      |	       |	|          |        //      |	       |	|          |        //       low address	 low address    // TODO:  check and resize stack once on the lowest Java to C transition    // on the stack.  Not needed if we use the thread original stack    // Fill in frame header - similar to normal prolog    prepareStackHeader(asm, method, compiledMethodId);    // Process the arguments - specific to method being called    storeParametersForLintel(asm, method);        // load address of native into S0    asm.emitMOV_Reg_Imm (S0, nativeIP);      // branch to outofline code in bootimage    asm.emitCALL_RegDisp(JTOC, VM_Entrypoints.invokeNativeFunctionInstructionsField.getOffset());    // return here from VM_OutOfLineMachineCode upon return from native code    // PR and RVM JTOC restored, T0,T1 contain return from native call    //If the return type is reference, look up the real value in the JNIref array     // S0 <- VM_Thread    VM_ProcessorLocalState.emitMoveFieldToReg(asm, S0,                                              VM_Entrypoints.activeThreadField.getOffset());    asm.emitMOV_Reg_RegDisp (S0, S0, VM_Entrypoints.jniEnvField.getOffset());        // S0 <- jniEnv        if (method.getReturnType().isReferenceType()) {      asm.emitADD_Reg_RegDisp(T0, S0, VM_Entrypoints.JNIRefsField.getOffset());      // T0 <- address of entry (not index)      asm.emitMOV_Reg_RegInd (T0, T0);   // get the reference    } else if (method.getReturnType().isLongType()) {      asm.emitPUSH_Reg(T1);    // need to use T1 in popJNIrefForEpilog and to swap order T0-T1      }    // CHECK - may not do anything - leave below will remove whole frame    // asm.emitPUSH_Reg(T0);                // push the return value onto the stack    // pop frame in JNIRefs array (need to use    // S0 <- VM_Thread    VM_ProcessorLocalState.emitMoveFieldToReg(asm, S0,                                              VM_Entrypoints.activeThreadField.getOffset());    asm.emitMOV_Reg_RegDisp (S0, S0, VM_Entrypoints.jniEnvField.getOffset());        // S0 <- jniEnv        popJNIrefForEpilog(asm);                                        // then swap order of T0 and T1 for long    if (method.getReturnType().isLongType()) {      asm.emitMOV_Reg_Reg(T1, T0);        asm.emitPOP_Reg(T0);    }    // CHECK EXCEPTION AND BRANCH TO ATHROW CODE OR RETURN NORMALLY    // get pending exception from JNIEnv    VM_ProcessorLocalState.emitMoveFieldToReg(asm, S0,                                              VM_Entrypoints.activeThreadField.getOffset());    asm.emitMOV_Reg_RegDisp (S0,  S0, VM_Entrypoints.jniEnvField.getOffset());        	  // S0 <- jniEnv        asm.emitMOV_Reg_RegDisp (EBX, S0, VM_Entrypoints.JNIPendingExceptionField.getOffset());  // EBX <- JNIPendingException    asm.emitMOV_RegDisp_Imm (S0, VM_Entrypoints.JNIPendingExceptionField.getOffset(), 0);    // clear the current pending exception    asm.emitCMP_Reg_Imm(EBX, 0);   // check for exception pending:  JNIPendingException = non zero    VM_ForwardReference fr = asm.forwardJcc(asm.EQ);            // Br if yes    // if pending exception, discard the return value and current stack frame    // then jump to athrow     asm.emitMOV_Reg_Reg     (T0, EBX);    asm.emitMOV_Reg_RegDisp (T1, JTOC, VM_Entrypoints.athrowMethod.getOffset()); // acquire jump addr before restoring nonvolatiles    asm.emitMOV_Reg_Reg     (SP, EBP);                      // discard current stack frame    asm.emitMOV_Reg_RegDisp (JTOC, SP, EDI_SAVE_OFFSET);   // restore nonvolatile EDI/JTOC register    asm.emitMOV_Reg_RegDisp (EBX, SP, EBX_SAVE_OFFSET);    // restore nonvolatile EBX register    asm.emitMOV_Reg_RegDisp (EBP, SP, EBP_SAVE_OFFSET);    // restore nonvolatile EBP register    asm.emitPOP_RegDisp     (PR, VM_Entrypoints.framePointerField.getOffset());    // don't use CALL since it will push on the stack frame the return address to here     asm.emitJMP_Reg(T1); // jumps to VM_Runtime.athrow    fr.resolve(asm);  // branch to here if no exception     // no exception, proceed to return to caller        asm.emitMOV_Reg_Reg(SP, EBP);                           // discard current stack frame    asm.emitMOV_Reg_RegDisp (JTOC, SP, EDI_SAVE_OFFSET);   // restore nonvolatile EDI/JTOC register    asm.emitMOV_Reg_RegDisp (EBX, SP, EBX_SAVE_OFFSET);    // restore nonvolatile EBX register    asm.emitMOV_Reg_RegDisp (EBP, SP, EBP_SAVE_OFFSET);    // restore nonvolatile EBP register    asm.emitPOP_RegDisp     (PR, VM_Entrypoints.framePointerField.getOffset());    // return to caller     // pop parameters from stack (Note that parameterWords does not include "this")    if (method.isStatic())      asm.emitRET_Imm(parameterWords << LG_WORDSIZE);     else      asm.emitRET_Imm((parameterWords+1) << LG_WORDSIZE);     // return asm.makeMachineCode();    return new VM_MachineCode(asm.getMachineCodes(), null);  }