Program: 150173
Project: 150173
Buggy source:
/** 
 * Handle the C to Java transition:  JNI methods in VM_JNIFunctions.java. <pre> NOTE: -We need PR to access Java environment; we can get it from the  JNIEnv* (which is an interior pointer to the VM_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       |                   |arg 0       | ESP ->  |return addr |                   |return addr | |            |           EBP ->  |saved FP    | |            |                   |methodID    | normal MethodID for JNI function |            |                   |saved JavaFP| offset to preceeding java frame |            |                   |saved edi   | to be used for JTOC |            |                   |  "   ebx   | to be used for nonvolatile |            |                   |  "   ecx   | to be used for scrach |            |                   |  "   esi   | to be used for PR |            |                   |arg 0       | copied in reverse order |            |                   |  ...       | |            |           ESP ->  |arg n-1     | |            |                   |            | normally compiled Java code continue |            |                   |            | |            |                   |            | |            |                   |            | low memory                        low memory </pre>
 */
public static void generateGlueCodeForJNIMethod(VM_Assembler asm,VM_NormalMethod method,int methodID){
  asm.emitPUSH_Reg(EBP);
  asm.emitMOV_Reg_Reg(EBP,SP);
  asm.emitPUSH_Imm(methodID);
  asm.emitSUB_Reg_Imm(SP,WORDSIZE);
  asm.emitPUSH_Reg(JTOC);
  asm.emitPUSH_Reg(EBX);
  asm.emitPUSH_Reg(S0);
  VM_ProcessorLocalState.emitPushProcessor(asm);
  asm.emitSUB_RegDisp_Imm(EBP,(2 * WORDSIZE),VM_Entrypoints.JNIExternalFunctionsField.getOffset());
  VM_TypeReference[] types=method.getParameterTypes();
  int numArguments=types.length;
  int argOffset=2;
  for (int i=0; i < numArguments; i++) {
    if (types[i].isLongType() || types[i].isDoubleType()) {
      asm.emitMOV_Reg_RegDisp(EBX,EBP,((argOffset + 1) * WORDSIZE));
      asm.emitPUSH_Reg(EBX);
      asm.emitMOV_Reg_RegDisp(EBX,EBP,(argOffset * WORDSIZE));
      asm.emitPUSH_Reg(EBX);
      argOffset+=2;
    }
 else {
      asm.emitMOV_Reg_RegDisp(EBX,EBP,(argOffset * WORDSIZE));
      asm.emitPUSH_Reg(EBX);
      argOffset++;
    }
  }
  int retryLabel=asm.getMachineCodeIndex();
  asm.emitMOV_Reg_RegDisp(EBX,EBP,(2 * WORDSIZE));
  VM_ProcessorLocalState.emitSetProcessor(asm,EBX,VM_Entrypoints.JNIEnvSavedPRField.getOffset());
  VM_ProcessorLocalState.emitMoveFieldToReg(asm,JTOC,VM_Entrypoints.jtocField.getOffset());
  VM_ProcessorLocalState.emitMoveFieldToReg(asm,T0,VM_Entrypoints.vpStatusField.getOffset());
  asm.emitCMP_Reg_Imm(T0,VM_Processor.IN_NATIVE);
  VM_ForwardReference fr=asm.forwardJcc(asm.EQ);
  asm.emitMOV_Reg_RegDisp(T0,JTOC,VM_Entrypoints.the_boot_recordField.getOffset());
  asm.emitCALL_RegDisp(T0,VM_Entrypoints.sysVirtualProcessorYieldIPField.getOffset());
  asm.emitJMP_Imm(retryLabel);
  fr.resolve(asm);
  asm.emitMOV_Reg_Imm(T1,VM_Processor.IN_JAVA);
  VM_ProcessorLocalState.emitCompareAndExchangeField(asm,VM_Entrypoints.vpStatusField.getOffset(),T1);
  asm.emitJCC_Cond_Imm(asm.NE,retryLabel);
  int numLocalVariables=method.getLocalWords() - method.getParameterWords();
  asm.emitSUB_Reg_Imm(SP,(numLocalVariables << LG_WORDSIZE));
  asm.emitMOV_Reg_RegDisp(S0,EBX,VM_Entrypoints.JNITopJavaFPField.getOffset());
  asm.emitSUB_Reg_Reg(S0,EBP);
  asm.emitMOV_RegDisp_Reg(EBP,SAVED_JAVA_FP_OFFSET,S0);
  VM_ProcessorLocalState.emitMoveRegToField(asm,VM_Entrypoints.framePointerField.getOffset(),EBP);
  asm.emitNOP();
}

Fixed version (ground truth):
/** 
 * Handle the C to Java transition:  JNI methods in VM_JNIFunctions.java. <pre> NOTE: -We need PR to access Java environment; we can get it from the  JNIEnv* (which is an interior pointer to the VM_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       |                   |arg 0       | ESP ->  |return addr |                   |return addr | |            |           EBP ->  |saved FP    | |            |                   |methodID    | normal MethodID for JNI function |            |                   |saved JavaFP| offset to preceeding java frame |            |                   |saved edi   | to be used for JTOC |            |                   |  "   ebx   | to be used for nonvolatile |            |                   |  "   ecx   | to be used for scrach |            |                   |  "   esi   | to be used for PR |            |                   |arg 0       | copied in reverse order |            |                   |  ...       | |            |           ESP ->  |arg n-1     | |            |                   |            | normally compiled Java code continue |            |                   |            | |            |                   |            | |            |                   |            | low memory                        low memory </pre>
 */
public static void generateGlueCodeForJNIMethod(VM_Assembler asm,VM_NormalMethod method,int methodID){
  asm.emitPUSH_Reg(EBP);
  asm.emitMOV_Reg_Reg(EBP,SP);
  asm.emitPUSH_Imm(methodID);
  asm.emitSUB_Reg_Imm(SP,STACKFRAME_HEADER_SIZE - 2 * WORDSIZE);
  asm.emitPUSH_Reg(JTOC);
  asm.emitPUSH_Reg(EBX);
  asm.emitPUSH_Reg(S0);
  VM_ProcessorLocalState.emitPushProcessor(asm);
  asm.emitSUB_RegDisp_Imm(EBP,(2 * WORDSIZE),VM_Entrypoints.JNIExternalFunctionsField.getOffset());
  VM_TypeReference[] types=method.getParameterTypes();
  int numArguments=types.length;
  int argOffset=2;
  for (int i=0; i < numArguments; i++) {
    if (types[i].isLongType() || types[i].isDoubleType()) {
      asm.emitMOV_Reg_RegDisp(EBX,EBP,((argOffset + 1) * WORDSIZE));
      asm.emitPUSH_Reg(EBX);
      asm.emitMOV_Reg_RegDisp(EBX,EBP,(argOffset * WORDSIZE));
      asm.emitPUSH_Reg(EBX);
      argOffset+=2;
    }
 else {
      asm.emitMOV_Reg_RegDisp(EBX,EBP,(argOffset * WORDSIZE));
      asm.emitPUSH_Reg(EBX);
      argOffset++;
    }
  }
  int retryLabel=asm.getMachineCodeIndex();
  asm.emitMOV_Reg_RegDisp(EBX,EBP,(2 * WORDSIZE));
  VM_ProcessorLocalState.emitSetProcessor(asm,EBX,VM_Entrypoints.JNIEnvSavedPRField.getOffset());
  VM_ProcessorLocalState.emitMoveFieldToReg(asm,JTOC,VM_Entrypoints.jtocField.getOffset());
  VM_ProcessorLocalState.emitMoveFieldToReg(asm,T0,VM_Entrypoints.vpStatusField.getOffset());
  asm.emitCMP_Reg_Imm(T0,VM_Processor.IN_NATIVE);
  VM_ForwardReference fr=asm.forwardJcc(asm.EQ);
  asm.emitMOV_Reg_RegDisp(T0,JTOC,VM_Entrypoints.the_boot_recordField.getOffset());
  asm.emitCALL_RegDisp(T0,VM_Entrypoints.sysVirtualProcessorYieldIPField.getOffset());
  asm.emitJMP_Imm(retryLabel);
  fr.resolve(asm);
  asm.emitMOV_Reg_Imm(T1,VM_Processor.IN_JAVA);
  VM_ProcessorLocalState.emitCompareAndExchangeField(asm,VM_Entrypoints.vpStatusField.getOffset(),T1);
  asm.emitJCC_Cond_Imm(asm.NE,retryLabel);
  int numLocalVariables=method.getLocalWords() - method.getParameterWords();
  asm.emitSUB_Reg_Imm(SP,(numLocalVariables << LG_WORDSIZE));
  asm.emitMOV_Reg_RegDisp(S0,EBX,VM_Entrypoints.JNITopJavaFPField.getOffset());
  asm.emitSUB_Reg_Reg(S0,EBP);
  asm.emitMOV_RegDisp_Reg(EBP,SAVED_JAVA_FP_OFFSET,S0);
  VM_ProcessorLocalState.emitMoveRegToField(asm,VM_Entrypoints.framePointerField.getOffset(),EBP);
  asm.emitNOP();
}