jit_common.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,132 行 · 第 1/5 页
C
2,132 行
DECACHE_TOS(); if (CVMframeIsCompiled(frame)) { goto returnToCompiled; } else { DECACHE_FRAME(); return CVM_COMPILED_RETURN; } } else { int invokerId; topOfStack -= CVMmbArgsSize(mb);new_mb: invokerId = CVMmbInvokerIdx(mb); CVMassert(frameSanity(frame,topOfStack)); if (invokerId < CVM_INVOKE_CNI_METHOD) { /* This means that invokerId == CVM_INVOKE_JAVA_METHOD or CVM_INVOKE_JAVA_SYNC_METHOD: */ CVMInt32 cost; CVMInt32 oldCost; /* Java method */ if (CVMmbIsCompiled(mb)) { CVMCompiledMethodDescriptor *cmd = CVMmbCmd(mb); CVMObjectICell* receiverObjICell; CVMFrame *prev = frame; CVMBool needExpand = CVM_FALSE; CVMassert(frameSanity(frame,topOfStack)); /* If we get here, then we're about to call a compiled method from an interpreted, or a transition method. JNI methods would have to go through a transition method to call any method. Hence the caller cannot be a JNI method. If the caller is an interpreted method, then we would want to increment its invokeCost because this transition makes the caller more desirable for compilation. If the caller is a transition method, then the mb might be abstract, in which case we can't make any adjustment to invokeCost. */ if (!CVMframeIsTransition(frame)) { CVMMethodBlock* callerMb = frame->mb; oldCost = CVMmbInvokeCost(callerMb); cost = oldCost - CVMglobals.jit.mixedTransitionCost; if (cost < 0) { cost = 0; } if (cost != oldCost){ CVMmbInvokeCostSet(callerMb, cost); } } if (CVMmbIs(mb, STATIC)) { CVMClassBlock* cb = CVMmbClassBlock(mb); receiverObjICell = CVMcbJavaInstance(cb); } else { receiverObjICell = &topOfStack[0].ref; } CVMassert(frameSanity(frame,topOfStack)); /* * Make sure we don't decompile this method if we become * gcSafe during the call to CVMpushFrame(). */ CVMassert(ee->invokeMb == NULL); ee->invokeMb = mb; CVMpushFrame(ee, &ee->interpreterStack, frame, topOfStack, CVMcmdCapacity(cmd), CVMcmdMaxLocals(cmd), CVM_FRAMETYPE_COMPILED, mb, CVM_FALSE, /* action if pushFrame fails */ { /* CVMpushFrame() set 'frame' to NULL. So, do the sanity check on the re-cache value of the currentFrame on the stack instead: */ CVMassert(frameSanity(CACHE_FRAME(),topOfStack)); ee->invokeMb = NULL; return CVM_COMPILED_EXCEPTION; }, /* action to take if stack expansion occurred */ { TRACE(("pushing JavaFrame caused stack expansion\n")); needExpand = CVM_TRUE; }); CVMassert(frameSanity(prev, topOfStack)); /* Use the interpreter -> compiled entry point */ CVMcompiledFramePC(frame) = CVMcmdStartPCFromInterpreted(cmd); CVM_RESET_COMPILED_TOS(frame->topOfStack, frame); TRACE_METHOD_CALL(frame, CVM_FALSE);#if 0 /* Force GC for testing purposes. */ CVMD_gcSafeExec(ee, { CVMgcRunGC(ee); });#endif if (CVMmbIs(mb, SYNCHRONIZED)) {#ifdef CVM_JVMTI /* No events during this delicate phase of creating * a frame */ CVMBool jvmtiEvents = CVMjvmtiDebugEventsEnabled(ee); CVMjvmtiDebugEventsEnabled(ee) = CVM_FALSE;#endif /* The method is sync, so lock the object. */ /* %comment l002 */ if (!CVMfastTryLock(ee, CVMID_icellDirect(ee, receiverObjICell))) { if (!CVMobjectLock(ee, receiverObjICell)) { CVMthrowOutOfMemoryError(ee, NULL); CVMassert(frameSanity(frame, topOfStack)); ee->invokeMb = NULL;#ifdef CVM_JVMTI CVMjvmtiDebugEventsEnabled(ee) = jvmtiEvents;#endif return CVM_COMPILED_EXCEPTION; } } CVMID_icellAssignDirect(ee, &CVMframeReceiverObj(frame, Compiled), receiverObjICell);#ifdef CVM_JVMTI CVMjvmtiDebugEventsEnabled(ee) = jvmtiEvents;#endif } DECACHE_FRAME(); if (needExpand) {#ifdef CVM_DEBUG_ASSERTS CVMStackVal32* space =#endif CVMexpandStack(ee, &ee->interpreterStack, CVMcmdCapacity(cmd), CVM_TRUE, CVM_FALSE); CVMassert((CVMFrame*)&space[CVMcmdMaxLocals(cmd)] == frame); /* Since the stack expanded, we need to set locals * to the new frame minus the number of locals. * Also, we need to copy the arguments, which * topOfStack points to, to the new locals area. */ memcpy((CVMSlotVal32*)frame - CVMcmdMaxLocals(cmd), topOfStack, CVMmbArgsSize(mb) * sizeof(CVMSlotVal32)); } /* * GC-safety stage 2: Update caller frame's topOfStack to * exclude the arguments. Once we update our new frame * state, the callee frame's stackmap will cover the arguments * as incoming locals. */ prev->topOfStack = topOfStack; CVMassert(frameSanity(prev, topOfStack)); CVMassert(frame->mb == mb); ee->invokeMb = NULL; /* Invoke the compiled method */ if ((CVMUint8*)cmd >= CVMglobals.jit.codeCacheDecompileStart#ifdef CVM_AOT && !((CVMUint8*)cmd >= CVMglobals.jit.codeCacheAOTStart && (CVMUint8*)cmd < CVMglobals.jit.codeCacheAOTEnd)#endif ) { CVMcmdEntryCount(cmd)++; } mb = CVMinvokeCompiled(ee, CVMgetCompiledFrame(frame)); frame = CACHE_FRAME(); CACHE_TOS(); goto check_mb; } /* * If we get here, then we're about to call an interpreted method * from a compiled method. Hence, we increment the invokeCost on * the callee because this transition makes the callee more * desirable for compilation. * * NOTE: we add in interpreterTransitionCost because this * value will also be subtracted when the interpreter loop * does this invocation for us and we only want to count * this invocation is a mixed one, not both a mixed one * and an interpreted-to-interpreted one. */ oldCost = CVMmbInvokeCost(mb); cost = oldCost - CVMglobals.jit.mixedTransitionCost; cost += CVMglobals.jit.interpreterTransitionCost; if (cost < 0) { cost = 0; } if (cost != oldCost){ CVMmbInvokeCostSet(mb, cost); } *mb_p = mb; CVMassert(frameSanity(frame,topOfStack)); return CVM_COMPILED_NEW_MB; } else if (invokerId < CVM_INVOKE_JNI_METHOD) { /* This means that invokerId == CVM_INVOKE_CNI_METHOD: */ /* CNI */ CVMStack *stack = &ee->interpreterStack; CNINativeMethod *f = (CNINativeMethod *)CVMmbNativeCode(mb); CNIResultCode ret; TRACE_FRAMELESS_METHOD_CALL(frame, mb, CVM_FALSE); ret = (*f)(ee, topOfStack, &mb); TRACE_FRAMELESS_METHOD_RETURN(mb, frame); if ((int)ret >= 0) { topOfStack += (int)ret; DECACHE_TOS(); CVMassert(frame == stack->currentFrame); (void)stack; goto returnToCompiled; } else if (ret == CNI_NEW_TRANSITION_FRAME) { CVMassert(frameSanity(frame,topOfStack)); /* pop invoker's arguments. Must be done * before CACHE_FRAME() */ DECACHE_TOS(); /* get the transition frame. */ frame = CACHE_FRAME(); CVMassert(frameSanity(frame, frame->topOfStack)); return CVM_COMPILED_NEW_TRANSITION; } else if (ret == CNI_NEW_MB) { CVMassert(frame == stack->currentFrame); (void)stack; CVMassert(frameSanity(frame,topOfStack)); DECACHE_TOS(); frame->topOfStack += CVMmbArgsSize(mb); CVMassert(frameSanity(frame, frame->topOfStack)); goto new_mb; } else if (ret == CNI_EXCEPTION) { CVMassert(frame == stack->currentFrame); (void)stack; CVMassert(frameSanity(frame, frame->topOfStack)); return CVM_COMPILED_EXCEPTION; } else { CVMdebugPrintf(("Bad CNI result code")); CVMassert(CVM_FALSE); } } else if (invokerId < CVM_INVOKE_ABSTRACT_METHOD) { /* This means that invokerId == CVM_INVOKE_JNI_METHOD or CVM_INVOKE_JNI_SYNC_METHOD: */ /* JNI */ CVMBool ok; TRACE_METHOD_CALL(frame, CVM_FALSE); ok = CVMinvokeJNIHelper(ee, mb); TRACE_METHOD_RETURN(frame); if (ok) { goto returnToCompiled; } else { CVMassert(frameSanity(frame, frame->topOfStack)); return CVM_COMPILED_EXCEPTION; } } else if (invokerId == CVM_INVOKE_ABSTRACT_METHOD) { CVMthrowAbstractMethodError(ee, "%C.%M", CVMmbClassBlock(mb), mb); return CVM_COMPILED_EXCEPTION;#ifdef CVM_CLASSLOADING } else if (invokerId == CVM_INVOKE_NONPUBLIC_MIRANDA_METHOD) { /* It's a miranda method created to deal with a non-public method with the same name as an interface method: */ CVMthrowIllegalAccessError(ee, "access non-public method %C.%M through an interface", CVMmbClassBlock(mb), CVMmbMirandaInterfaceMb(mb)); return CVM_COMPILED_EXCEPTION; } else if (invokerId == CVM_INVOKE_MISSINGINTERFACE_MIRANDA_METHOD) { /* It's a miranda method created to deal with a missing interface method: */ CVMthrowAbstractMethodError(ee, "%C.%M", CVMmbClassBlock(mb), mb); return CVM_COMPILED_EXCEPTION; } else if (invokerId == CVM_INVOKE_LAZY_JNI_METHOD) { /* * It's a native method of a dynamically loaded class. * We still need to lookup the native code. */ CVMBool result; *mb_p = mb; CVMD_gcSafeExec(ee, { result = CVMlookupNativeMethodCode(ee, mb); }); if (!result) { return CVM_COMPILED_EXCEPTION; } else { /* * CVMlookupNativeMethod() stored the pointer to the * native method and also changed the invoker index, so * just branch to new_mb and the correct native * invoker will be used. */ goto new_mb; }#endif } else { CVMdebugPrintf(("ERROR: Method %C.%M(), invokerID = %d\n", CVMmbClassBlock(mb), mb, invokerId)); CVMassert(CVM_FALSE); return CVM_COMPILED_EXCEPTION; } } CVMassert(CVM_FALSE); /* unreachable */returnToCompiled: CVMassert(frameSanity(frame, topOfStack)); /* Return to the compiled method */ mb = CVMreturnToCompiled(ee, CVMgetCompiledFrame(frame), NULL); frame = CACHE_FRAME(); CACHE_TOS(); goto check_mb;}CVMCompiledResultCodeCVMreturnToCompiledHelper(CVMExecEnv *ee, CVMFrame *frame, CVMMethodBlock **mb_p, CVMObject* exceptionObject){ CVMCompiledResultCode resCode; CVMCompiledFrame *cframe = CVMgetCompiledFrame(frame); *mb_p = CVMreturnToCompiled(ee, cframe, exceptionObject); frame = CACHE_FRAME(); resCode = CVMinvokeCompiledHelper(ee, frame, mb_p); frame = CACHE_FRAME(); CVMassert(resCode == CVM_COMPILED_EXCEPTION || frameSanity(frame, frame->topOfStack)); return resCode;}/* Purpose: Do On-Stack replacement of an interpreted stack frame with a compiled stack frame and continue executing the method using its compiled form at the location indicated by the specified bytecode PC. */CVMCompiledResultCodeCVMinvokeOSRCompiledHelper(CVMExecEnv *ee, CVMFrame *frame, CVMMethodBlock **mb_p, CVMUint8 *pc){ CVMStack *stack = &ee->interpreterStack; CVMCompiledResultCode resCode; CVMMethodBlock *mb = *mb_p; CVMObjectICell *receiverObjICell; CVMJavaMethodDescriptor *jmd; CVMCompiledMethodDescriptor *cmd; CVMFrame *oldFrame = frame; CVMBool needExpand = CVM_FALSE; CVMassert(CVMmbIsCompiled(mb)); jmd = CVMmbJmd(mb); cmd = CVMmbCmd(mb); /* * Make sure we don't decompile this method if we become * gcSafe during the call to CVMreplaceFrame(). */ CVMassert(ee->invokeMb == NULL); ee->invokeMb = mb; /* Save off the receiverObject: */ receiverObjICell = CVMsyncICell(ee); CVMassert(CVMID_icellIsNull(receiverObjICell)); CVMID_icellAssignDirect(ee, receiverObjICell, &CVMframeReceiverObj(frame, Java)); /* Convert the Java frame into a Compiled frame: */ CVMreplaceFrame(ee, stack, frame, sizeof(CVMJavaFrame) - sizeof(CVMSlotVal32), CVMjmdMaxLocals(jmd), CVMcmdCapacity(cmd), CVMcmdMaxLocals(cmd), CVM_FRAMETYPE_COMPILED, mb, CVM_FALSE, /* action if replaceFrame fails */ { /* We should never fail because we have already verified that the replacement frame will fit before we actually do the replacement. */ CVMassert(CVM_FALSE); }, /* action to take if stack expansion occurred */ { TRACE(("replacing JavaFrame caused stack expansion\n")); needExpand = CVM_TRUE; }); /* NOTE: We cannot become GC safe after CVMreplaceFrame() until we finish replacing the frame below: */ /* If the stack was expanded, then we need to copy the locals to new frame in the new stack chunk: */ if (needExpand) { CVMUint16 oldNumberOfLocals = CVMjmdMaxLocals(jmd); CVMSlotVal32 *oldFrameStart; CVMStackChunk *prevChunk; oldFrameStart = (CVMSlotVal32*)oldFrame - oldNumberOfLocals; memcpy((CVMSlotVal32*)frame - CVMcmdMaxLocals(cmd), oldFrameStart, oldNumberOfLocals * sizeof(CVMSlotVal32)); /* We're here because we have expanded the stack in order to install the replacement frame. However, the oldFrame may be the only frame in the previous chunk. In that case, since the oldFrame is no longer in use, we need to delete that chunk. */ prevChunk = CVMstackGetCurrentChunk(stack)->prev;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?