stackmaps.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,928 行 · 第 1/5 页
C
1,928 行
state[v] = '\0'; CVMtraceStackmaps(("Variables %s\n", state)); for (v = 0; v < topOfStack; v++) { state[v] = CVMstackmapCtsToChar(stackState[v]); } state[v] = '\0'; CVMtraceStackmaps(("Stack %s\n", state)); CVMtraceStackmaps(("Top of stack %d\n", topOfStack));}/* * Print the entry state of a basic block in human-readable form */static voidCVMstackmapPrintBBState(CVMStackmapContext* con, CVMBasicBlock* bb){ CVMstackmapPrintState(con, bb->topOfStack, bb->varState, bb->stackState);}#endif/* * Is the field reference of the non-quick field access bytecode at 'pc' * a reference or a value.from quicken.c.... */static voidCVMstackmapFieldKind(CVMStackmapContext* con, CVMUint8* pc, CVMBool* isRef, CVMBool* isDoubleword){ CVMUint32 cpIdx = CVMgetUint16(pc+1); CVMFieldTypeID fbTid;#ifdef CVM_DEBUG_ASSERTS { CVMOpcode instr = (CVMOpcode)*pc;#ifdef CVM_JVMTI if (instr == opc_breakpoint) { /* Must get the original byte-code: */ instr = CVMjvmtiGetBreakpointOpcode(con->ee, pc, CVM_FALSE); }#endif CVMassert(instr == opc_getfield || instr == opc_getstatic || instr == opc_putfield || instr == opc_putstatic || instr == opc_putfield_quick_w || instr == opc_getfield_quick_w); }#endif /* * Get the typeID of the field at cpIdx. */#ifdef CVM_CLASSLOADING if (CVMcpIsResolved(con->cp, cpIdx)) { resolved:#endif fbTid = CVMfbNameAndTypeID(CVMcpGetFb(con->cp, cpIdx));#ifdef CVM_CLASSLOADING } else { CVMcpLock(con->ee); if (CVMcpIsResolved(con->cp, cpIdx)) { CVMcpUnlock(con->ee); goto resolved; } else { CVMUint16 typeIDIdx = CVMcpGetMemberRefTypeIDIdx(con->cp, cpIdx); fbTid = CVMcpGetFieldTypeID(con->cp, typeIDIdx); CVMcpUnlock(con->ee);#endif /* CVM_CLASSLOADING */ } } *isRef = CVMtypeidFieldIsRef(fbTid); *isDoubleword = CVMtypeidFieldIsDoubleword(fbTid);}/* * Handle method invocation given a methodblock */static CVMInt32CVMstackmapHandleMethod(CVMStackmapContext* con, CVMCellTypeState* stack, CVMInt32 topOfStack, CVMBool isStatic, CVMMethodBlock* mb){ topOfStack -= CVMmbArgsSize(mb); if (isStatic != CVMmbIs(mb, STATIC)) { /* * There has been an illegal method call that has confused * the stackmap generator. See bug #4381392. The method's * argsize is off by one because the invoker and invokee do * no agree on whether or not the method is static, and thus * whether or not there is a "this" argument. If the invoker * thinks the method should be static, then we need to "undo" * the popping of the "this" argument. If the invoker thinks * the method is not static, then we need to pop the "this" * argument because it was not accounted for in CVMmbArgsSize(mb). */ topOfStack += (isStatic ? 1 : -1); } switch(CVMtypeidGetReturnType(CVMmbNameAndTypeID(mb))) { case CVM_TYPEID_VOID: break; case CVM_TYPEID_OBJ: stack[topOfStack++] = CVMctsRef; break; case CVM_TYPEID_LONG: case CVM_TYPEID_DOUBLE: stack[topOfStack++] = CVMctsVal; stack[topOfStack++] = CVMctsVal; break; default: stack[topOfStack++] = CVMctsVal; } return topOfStack;}/* * Handle method invocation given a pc pointing to an invocation */static CVMInt32CVMstackmapHandleMethodRefFromCode(CVMStackmapContext* con, CVMCellTypeState* stack, CVMInt32 topOfStack, CVMUint8* pc, CVMBool isStatic){ CVMUint32 cpIdx;#ifdef CVM_JVMTI CVMassert(CVMbcAttr(*pc, INVOCATION) || (((CVMOpcode)*pc == opc_breakpoint) && CVMbcAttr(CVMjvmtiGetBreakpointOpcode(con->ee, pc, CVM_FALSE), INVOCATION)));#else CVMassert(CVMbcAttr(*pc, INVOCATION));#endif cpIdx = CVMgetUint16(pc+1); /* * The entry may not be resolved already, in which case we have * to deal with an CVMMethodTypeID instead of an CVMMethodBlock. */#ifdef CVM_CLASSLOADING if (CVMcpIsResolved(con->cp, cpIdx)) { resolved:#endif return CVMstackmapHandleMethod(con, stack, topOfStack, isStatic, CVMcpGetMb(con->cp, cpIdx));#ifdef CVM_CLASSLOADING } else { CVMcpLock(con->ee); if (CVMcpIsResolved(con->cp, cpIdx)) { CVMcpUnlock(con->ee); goto resolved; } else { CVMUint16 typeIDIdx = CVMcpGetMemberRefTypeIDIdx(con->cp, cpIdx); CVMMethodTypeID methodTypeID = CVMcpGetMethodTypeID(con->cp, typeIDIdx); CVMcpUnlock(con->ee); /* adjust the stack by the number of arguments.*/ topOfStack -= (isStatic ? 0 : 1); /* handle "this" argument */ topOfStack -= CVMtypeidGetArgsSize(methodTypeID); /* set the return type */ switch(CVMtypeidGetReturnType(methodTypeID)) { case CVM_TYPEID_VOID: break; case CVM_TYPEID_OBJ: stack[topOfStack++] = CVMctsRef; break; case CVM_TYPEID_LONG: case CVM_TYPEID_DOUBLE: stack[topOfStack++] = CVMctsVal; stack[topOfStack++] = CVMctsVal; break; default: stack[topOfStack++] = CVMctsVal; } return topOfStack; } }#endif /* CVM_CLASSLOADING */}static CVMInt32CVMstackmapLocalStore(CVMStackmapContext* con, CVMUint32 varNo, CVMInt32 topOfStack, CVMCellTypeState* stack, CVMCellTypeState* vars){ CVMassert(topOfStack >= 1); CVMassert(stack[topOfStack - 1] == CVMctsVal); vars[varNo] = stack[topOfStack - 1]; topOfStack--; return topOfStack;}static CVMInt32CVMstackmapLocalAStore(CVMStackmapContext* con, CVMUint32 varNo, CVMInt32 topOfStack, CVMCellTypeState* stack, CVMCellTypeState* vars){ CVMassert(topOfStack >= 1); CVMassert((stack[topOfStack - 1] == CVMctsRef) || (CVMctsGetFlags(stack[topOfStack - 1]) == CVMctsPC)); vars[varNo] = stack[topOfStack - 1]; topOfStack--; return topOfStack;}static CVMInt32CVMstackmapLocalDStore(CVMStackmapContext* con, CVMUint32 varNo, CVMInt32 topOfStack, CVMCellTypeState* stack, CVMCellTypeState* vars){ CVMassert(topOfStack >= 2); CVMassert(stack[topOfStack - 1] == CVMctsVal); CVMassert(stack[topOfStack - 2] == CVMctsVal); vars[(varNo)] = stack[topOfStack - 2]; vars[(varNo) + 1] = stack[topOfStack - 1]; topOfStack -= 2; return topOfStack;}static CVMInt32CVMstackmapLocalLoad(CVMStackmapContext* con, CVMUint32 varNo, CVMInt32 topOfStack, CVMCellTypeState* stack, CVMCellTypeState* vars){ CVMassert(topOfStack < con->maxStack); /* * We don't care if we encounter a conflict here. We are only * worried about using a conflict as a ref, which is handled in * CVMstackmapLocalALoad(). */ stack[topOfStack++] = CVMctsVal; return topOfStack;}static CVMInt32CVMstackmapLocalALoad(CVMStackmapContext* con, CVMUint8* pc, CVMUint32 varNo, CVMInt32 topOfStack, CVMCellTypeState* stack, CVMCellTypeState* vars){ CVMCellTypeState theVar = vars[varNo]; CVMassert(topOfStack < con->maxStack); if (theVar != CVMctsRef) { /* * Conflicts had better not occur unless we have pre-determined * that they are possible. */ CVMassert(con->mayNeedRewriting); if (CVMctsIsUninit(theVar)) { CVMtraceStackmaps(("ALOAD(%d) at relPC=%d: " "Ref-uninit conflict (%C.%M)\n", varNo, pc - con->code, con->cb, con->mb)); /* * Record the use of this conflict, along with its type. We'll * check this use during map generation. */ if (con->refVarsToInitialize[varNo] == 0) { /* * We have not made a record of this variable yet */ con->refVarsToInitialize[varNo] = theVar; con->numRefVarsToInitialize++; } } else if (CVMctsIsPC(theVar)) { CVMtraceStackmaps(("ALOAD(%d) at relPC=%d: " "Ref-pc conflict (%C.%M)\n", varNo, pc - con->code, con->cb, con->mb)); con->nRefPCConflicts++; remapConflictVarno(con, varNo); } else { CVMassert(CVMctsIsVal(theVar)); CVMtraceStackmaps(("ALOAD(%d) at relPC=%d: " "Ref-val conflict (%C.%M)\n", varNo, pc - con->code, con->cb, con->mb)); con->nRefValConflicts++; remapConflictVarno(con, varNo); } } stack[topOfStack++] = CVMctsRef; return topOfStack;}static CVMInt32CVMstackmapLocalDLoad(CVMStackmapContext* con, CVMUint32 varNo, CVMInt32 topOfStack, CVMCellTypeState* stack, CVMCellTypeState* vars){ CVMassert(topOfStack - 1 < con->maxStack); /* * We don't care if we encounter a conflict here. We are only * worried about using a conflict as a ref, which is handled in * CVMstackmapLocalALoad(). */ stack[topOfStack++] = CVMctsVal; stack[topOfStack++] = CVMctsVal; return topOfStack;}/* * Interpret one opcode. Return updated topOfStack. Don't do anything * for opcodes that don't affect state (variables, stack). */static CVMInt32CVMstackmapInterpretOne(CVMStackmapContext* con, CVMUint8* pc, CVMCellTypeState* vars, CVMCellTypeState* stack, CVMInt32 topOfStack){ CVMOpcode instr = (CVMOpcode)*pc; CVMassert(topOfStack >= 0);#ifdef CVM_JVMTI /* Just in case we have to re-do the instruction due to a breakpoint */ interpretInstr:#endif switch(instr) { case opc_nop: case opc_goto: case opc_goto_w: case opc_iinc: case opc_return: case opc_ret: /* hairy ret handling outside of here */ /* nothing */ break; case opc_iload: case opc_fload: topOfStack = CVMstackmapLocalLoad(con, pc[1], topOfStack, stack, vars); break; case opc_lload: case opc_dload: topOfStack = CVMstackmapLocalDLoad(con, pc[1], topOfStack, stack, vars); break; case opc_aload: topOfStack = CVMstackmapLocalALoad(con, pc, pc[1], topOfStack, stack, vars); break; case opc_iload_0: case opc_fload_0: topOfStack = CVMstackmapLocalLoad(con, 0, topOfStack, stack, vars); break; case opc_iload_1: case opc_fload_1: topOfStack = CVMstackmapLocalLoad(con, 1, topOfStack, stack, vars); break; case opc_iload_2: case opc_fload_2: topOfStack = CVMstackmapLocalLoad(con, 2, topOfStack, stack, vars); break; case opc_iload_3: case opc_fload_3: topOfStack = CVMstackmapLocalLoad(con, 3, topOfStack, stack, vars); break; case opc_lload_0: case opc_dload_0: topOfStack = CVMstackmapLocalDLoad(con, 0, topOfStack, stack, vars); break; case opc_lload_1: case opc_dload_1: topOfStack = CVMstackmapLocalDLoad(con, 1, topOfStack, stack, vars); break; case opc_lload_2: case opc_dload_2: topOfStack = CVMstackmapLocalDLoad(con, 2, topOfStack, stack, vars); break; case opc_lload_3: case opc_dload_3: topOfStack = CVMstackmapLocalDLoad(con, 3, topOfStack, stack, vars); break; case opc_aload_0: topOfStack = C
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?