jitcompile.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,252 行 · 第 1/3 页

C
1,252
字号
    CVMassert(offsetof(CVMJITUnaryOp, operand) ==	      offsetof(CVMJITGenericSubNode, firstOperand));}#endifstatic voidbackOff(CVMMethodBlock* mb, CVMUint32 newInvokeCost){    /* Try again later. */    CVMUint32 oldInvokeCost = CVMmbInvokeCost(mb);    if (newInvokeCost > CVMJIT_MAX_INVOKE_COST) {	newInvokeCost = CVMJIT_MAX_INVOKE_COST;    }    if (newInvokeCost > oldInvokeCost) {	CVMmbInvokeCostSet(mb, newInvokeCost);    }}/* * Entry point to compiler */CVMJITReturnValueCVMJITcompileMethod(CVMExecEnv *ee, CVMMethodBlock* mb){    CVMJITCompilationContext con;    CVMJITReturnValue retVal;    volatile CVMBool needDestroyContext = CVM_FALSE;    volatile int extraCodeExpansion = 0;    volatile int extraStackmapSpace = 0;    volatile int maxAllowedInliningDepth = CVMglobals.jit.maxAllowedInliningDepth;    /* Cache the ee's noOSRSkip & noOSRStackAdjust in case we recurse into the       interpreter while compiling: */    CVMInt32 noOSRSkip = ee->noOSRSkip;    CVMInt8  noOSRStackAdjust = ee->noOSRStackAdjust;#ifdef CVM_JIT_COLLECT_STATS    CVMInt64 startTime;    CVMInt64 endTime;#endif#ifdef CVM_JIT_ESTIMATE_COMPILATION_SPEED    static CVMInt32 measuredCycle;    static CVMInt64 measuredStartTime;#endif    CVMtraceJITAny(("JS: ATTEMPTING TO COMPILE %C.%M\n",		    CVMmbClassBlock(mb), mb));    CVMassert(CVMD_isgcSafe(ee));    /*     * Check if this thread has been prohibited from doing compilations     * in order to avoid a deadlock with the jitLock.     */    if (ee->noCompilations) {	return CVMJIT_CANNOT_COMPILE_NOW;    }    CVMJITstatsExec({ startTime = CVMtimeMillis(); });    /* One compilation at a time. Lock others out. */    CVMsysMutexLock(ee, &CVMglobals.jitLock);    /*     * Recursive entry into compiler should not happen!     */    CVMassert(!CVMglobals.jit.compiling);    CVMglobals.jit.compiling = CVM_TRUE;#ifdef CVM_JIT_ESTIMATE_COMPILATION_SPEED    measuredCycle = CVMglobals.jit.doCSpeedMeasurement ?        CVMJIT_NUMBER_OF_COMPILATION_PASS_MEASUREMENT_REPETITIONS : 1;    measuredStartTime = CVMtimeMillis();#endif    CVMglobals.jit.compilationAttempts++;#ifdef CVM_JIT_DEBUG    CVMJITdebugInitCompilation(ee, mb);#endif#ifdef CVM_AOT    /* AOT requires ROMization. If we are doing AOT compilation,     * we better make sure the method is a ROMized method.     */    if (CVMglobals.jit.isPrecompiling) {        if (!CVMcbIsInROM(CVMmbClassBlock(mb))) {	    CVMconsolePrintf("CANNOT AOT NON-ROMIZED %C.%M\n",                              CVMmbClassBlock(mb), mb);            CVMglobals.jit.aotCompileFailed = CVM_TRUE;            retVal = CVMJIT_SUCCESS;            goto done;        }    }#endif#ifdef CVM_JVMTI    if (CVMjvmtiIsInDebugMode()) {	retVal = CVMJIT_CANNOT_COMPILE;	CVMJITsetErrorMessage(&con, "Debugger connected");	goto done;    }#endif    /* Check if mb is not compilable */    if (isBadMethod(ee, mb)) {	retVal = CVMJIT_CANNOT_COMPILE;	CVMJITsetErrorMessage(&con, "Method already marked as not compilable");	goto done;    }    /* Make sure the method isn't already compiled. */    if (CVMmbIsCompiled(mb)) {        CVMtraceJITStatus(("JS: ALREADY COMPILED %C.%M\n",			   CVMmbClassBlock(mb), mb));	retVal = CVMJIT_SUCCESS;	goto done;    }    CVMtraceJITAny(("JS: COMPILING %C.%M\n", CVMmbClassBlock(mb), mb)); retry:    if (!CVMJITinitializeContext(&con, mb, ee, maxAllowedInliningDepth)) {	CVMJITsetErrorMessage(&con,			      "Could not initialize compilation context");	retVal = CVMJIT_OUT_OF_MEMORY;	goto done;    }    needDestroyContext = CVM_TRUE;    if (setjmp(con.errorHandlerContext) == 0) {	CVMJITinitializeCompilation(&con);		CVMJITcompileBytecodeToIR(&con);	/* Sanity check capacity */	CVMassert(con.capacity >= CVMjmdCapacity(con.jmd));	/* Sanity check code length */	CVMassert(con.codeLength >= CVMjmdCodeLength(con.jmd));	CVMJITcompileOptimizeIR(&con);	con.extraCodeExpansion = extraCodeExpansion;	con.extraStackmapSpace = extraStackmapSpace;	CVMJITcompileGenerateCode(&con);	CVMJITwriteStackmaps(&con);#ifdef CVM_JIT_PATCHED_METHOD_INVOCATIONS	if (con.callees != NULL && (CVMUint32)con.callees[0] != 0) {	    /* Make room for the callee table. It will be after the stackmaps,	       which are located after the generated code. */	    CVMUint32 numCallees = (CVMUint32)con.callees[0];	    /* On platforms with variably sized instructions, such as x86,	       need to pad the codebuffer before the start of callee table. */	    CVMMethodBlock** callees = (CVMMethodBlock**)		(((CVMAddr)CVMJITcbufGetPhysicalPC(&con) +		  sizeof(CVMAddr) - 1) &		 ~(sizeof(CVMAddr) - 1));            CVMassert(CVMglobals.jit.pmiEnabled);	    CVMJITcbufGetPhysicalPC(&con) =		(CVMUint8*)&callees[numCallees + 1];	    if (CVMJITcbufGetPhysicalPC(&con) >= con.codeBufEnd) {		/* Fail to compile. We will retry with a larger buffer */		CVMJITerror(&con, CODEBUFFER_TOO_SMALL,			    "Estimated code buffer too small");	    }	    memcpy(callees, con.callees,		   (numCallees + 1) * sizeof(CVMMethodBlock*));	    con.callees = callees;	} else {	    con.callees = NULL;	}#endif#ifdef CVM_JIT_ESTIMATE_COMPILATION_SPEED        if (--measuredCycle != 0) {            CVMJITerror(&con, RETRY, "Retry to measure compilation time");        }#endif        /* By now, we know exactly the number of the maximum Temp words         * (maxTempWords) of the compiled method. Before we go         * any further, make sure it doesn't exceed 255 (0xFF) limit.         */        if (con.maxTempWords > 0xFF) {            CVMJITerror(&con, CANNOT_COMPILE,                        "Too many temp words (> 255)");        }	/* No more errors allowed after this point */	{	    CVMUint8 *startPC = con.codeEntry;	    CVMCompiledMethodDescriptor *cmd =		((CVMCompiledMethodDescriptor *)startPC) - 1;	    CVMassert(con.mapPcNodeCount == 0 ||		con.pcMapTable->numEntries == con.mapPcNodeCount);	    CVMJITcbufSetCmd(con.codeBufAddr, cmd);#ifdef CVM_DEBUG_ASSERTS	    cmd->magic = CVMJIT_CMD_MAGIC;#endif	    CVMcmdSpillSize(cmd) = con.maxTempWords;	    CVMcmdCapacity(cmd) = con.capacity + CVMcmdSpillSize(cmd);	    CVMcmdMaxLocals(cmd) = con.numberLocalWords;	    CVMassert(CVMcmdStartPC(cmd) == con.codeEntry);	    {		CVMUint8 *interpStartPC = startPC + con.intToCompOffset;		cmd->startPCFromInterpretedOffsetX =		            interpStartPC - (CVMUint8 *)cmd;		CVMassert(CVMcmdStartPCFromInterpreted(cmd) ==		    interpStartPC);	    }	    /* We allocate memory in the code cache for other data, not	       just the compiled code.  These regions are:	       PC map table, inlining info, gc patches, stackmaps,	       and callee table. */	       	    /* Fill in the offsets for reaching our memory regions	       from the cmd */	    cmd->codeBufOffsetX =		(CVMUint16 *)con.codeBufAddr - (CVMUint16 *)cmd;	    CVMassert(CVMcmdCodeBufAddr(cmd) == con.codeBufAddr);	    cmd->pcMapTableOffsetX =		(CVMUint16 *)con.pcMapTable - (CVMUint16 *)cmd;	    CVMassert(CVMcmdCompiledPcMapTable(cmd) == con.pcMapTable);	    if (con.stackmaps != NULL) {		cmd->stackMapsOffsetX =		    (CVMUint16 *)con.stackmaps - (CVMUint16 *)cmd;	    } else {		cmd->stackMapsOffsetX = 0;	    }	    CVMassert(CVMcmdStackMaps(cmd) == con.stackmaps);	    if (con.inliningInfo != NULL) {		cmd->inliningInfoOffsetX =		    (CVMUint16 *)con.inliningInfo - (CVMUint16 *)cmd;	    } else {		cmd->inliningInfoOffsetX = 0;	    }	    CVMassert(CVMcmdInliningInfo(cmd) == con.inliningInfo);#ifdef CVM_JIT_PATCHED_METHOD_INVOCATIONS	    if (con.callees != NULL) {                CVMassert(CVMglobals.jit.pmiEnabled);	    	cmd->calleesOffsetX =		    (CVMUint32*)con.callees - (CVMUint32 *)cmd;	    } else {	    	cmd->calleesOffsetX = 0;	    }		    	    CVMassert(CVMcmdCallees(cmd) == con.callees);#endif#ifdef CVMJIT_PATCH_BASED_GC_CHECKS	    {	        if (con.gcCheckPcs != NULL) {		    cmd->gcCheckPCsOffsetX =		        (CVMUint16 *)con.gcCheckPcs - (CVMUint16 *)cmd;	        } else {		    cmd->gcCheckPCsOffsetX = 0;	        }	        CVMassert(CVMcmdGCCheckPCs(cmd) == con.gcCheckPcs);            }#endif#ifdef CVMCPU_HAS_CP_REG	    {		CVMUint8 *cp =		    CVMJITcbufLogicalToPhysical(&con, con.target.cpLogicalPC);		cmd->cpBaseRegOffsetX =		    (CVMUint16 *)cp - (CVMUint16 *)cmd;		CVMassert(CVMcmdCPBaseReg(cmd) == cp);	    }#endif	    CVMcmdMb(cmd) = mb;	    /* make sure we survive at least one gc */	    CVMcmdEntryCount(cmd) = 0x2;	    /*	     * Make sure the cost is properly counted down.	     * A simplifying assumption in a couple of other spots.	     * Note how this is reset in the case of decompilation.	     */	    CVMmbInvokeCostSet(mb, 0);	    /*	     * We must add the entry to the code cache and set startPC	     * atomically. The main thing we need to avoid is having	     * aging happening after the method is added to the code cache,	     * but before startPC is set. Since aging code will grab	     * the jitLock first, we are safe, since we own jitLock	     * for the duration of compilation	     */	    CVMassert(CVMsysMutexIAmOwner(con.ee, &CVMglobals.jitLock));	    {		/*		 * The following will also make CVMmbIsCompiled() start		 * to return TRUE. We must do this last.		 */		CVMassert (!CVMmbIsCompiled(mb));		CVMmbStartPC(mb) = startPC;		CVMmbJitInvoker(mb) = startPC;		/*		 * We need to commit the code buffer while in the lock to		 * protect from races with decompilation.		 */		CVMJITcbufCommit(&con);#ifdef CVM_JIT_PATCHED_METHOD_INVOCATIONS		/* If any compiled method calls this method, patch the call		 * to be a direct call to this compiled method.		 */		CVMJITPMIpatchCallsToMethod(mb, CVMJITPMI_PATCHSTATE_COMPILED);#endif	    }	    /* IAI-07: Notify JVMPI of compilation. */#ifdef CVM_JVMPI	    if (CVMjvmpiEventCompiledMethodLoadIsEnabled()) {		CVMjvmpiPostCompiledMethodLoadEvent(ee, mb);	    }#endif	    /* IAI-07: Notify JVMTI of compilation. */#ifdef CVM_JVMTI	    if (CVMjvmtiShouldPostCompiledMethodLoad()) {		CVMjvmtiPostCompiledMethodLoadEvent(ee, mb);	    }#endif	    CVMtraceJITStatus(("JS: COMPILED: size=%d startPC=0x%x %C.%M\n",			       CVMcmdCodeBufSize(cmd), startPC,			       CVMmbClassBlock(mb), mb));#ifdef CVM_JIT_PATCHED_METHOD_INVOCATIONS	    CVMtraceJITPatchedInvokesExec({	        CVMJITPMIdumpMethodCalleeInfo(con.mb, CVM_FALSE);	    });#endif            CVMJITstatsExec({                endTime = CVMtimeMillis();                CVMJITstatsRecordSetCount(&con, CVMJIT_STATS_COMPILATION_TIME,                    CVMlong2Int(CVMlongSub(endTime, startTime)));            });            /* Update the per compilation cycle and global statistics: */#ifdef CVM_JIT_ESTIMATE_COMPILATION_SPEED            if (CVMglobals.jit.doCSpeedMeasurement) {                CVMglobals.jit.numberOfByteCodeBytesCompiled                    += con.codeLength;                CVMglobals.jit.numberOfByteCodeBytesCompiledWithoutInlinedMethods                    += CVMjmdCodeLength(con.jmd);                CVMglobals.jit.numberOfBytesOfGeneratedCode                    += CVMcmdCodeBufSize(cmd);            }#endif            CVMJITstatsUpdateStats(&con);	    CVMtraceJITStatsExec({CVMJITstatsDump(&con);});	}    } else {	if (con.codeBufAddr != NULL) {	    CVMassert(CVMsysMutexIAmOwner(con.ee, &CVMglobals.jitLock));	    CVMJITcbufFree(con.codeBufAddr, CVM_FALSE);	}	if (con.resultCode == CVMJIT_CANNOT_COMPILE) {	    CVMglobals.jit.failedCompilationAttempts++;	    /* Mark method as bad */	    badMethod(ee, mb);	}    }     retVal = con.resultCode; done:#ifdef CVM_JIT_PATCHED_METHOD_INVOCATIONS    /* We've probably already added some patchable method invokes to       the database, so we need to remove them if compilation failed. */    if (retVal != CVMJIT_SUCCESS && needDestroyContext && con.callees != NULL){	/*	 * For each method directly called by this method, have that method	 * (the callee method) remove this method (the caller method)	 * from its entries in the patch table.	 */	CVMUint32 numCallees = (CVMUint32)con.callees[0];	CVMUint32 i;        CVMassert(CVMglobals.jit.pmiEnabled);	for (i = 1; i <= numCallees; i++) {	    CVMMethodBlock* calleeMb = con.callees[i];	    /* Remove records. */ 	    CVMJITPMIremovePatchRecords(con.mb, calleeMb,					con.codeBufAddr, con.codeBufEnd);	}    }#endif    switch (retVal) {        case CVMJIT_SUCCESS:	    break;        case CVMJIT_CANNOT_COMPILE: {	    /* Don't try again for as long as possible */	    CVMmbInvokeCostSet(mb, CVMJIT_MAX_INVOKE_COST);	    CVMtraceJITError(("JE: CANNOT COMPILE %C.%M\n",

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?