jit_common.c

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

C
2,132
字号
#ifdef CVM_MTASK/* * Re-initialize the JIT state after a client JVM instance * has been created. */CVMBoolCVMjitReinitialize(CVMExecEnv* ee, const char* subOptionsString){    CVMJITGlobalState* jgs = &CVMglobals.jit;    /* Remember those values we don't want overridden */    CVMUint32 currentCodeCacheSize = jgs->codeCacheSize;        CVMassert(!jgs->compiling);        if (!CVMinitParsedSubOptions(&jgs->parsedSubOptions, subOptionsString)) {	return CVM_FALSE;    }    if (!CVMprocessSubOptions(knownJitSubOptions, "-Xjit",			      &jgs->parsedSubOptions)) {	CVMjitPrintUsage();	return CVM_FALSE;    }    /* Re-set codeCacheSize to what it was. That way, any overrides       are ignored */    jgs->codeCacheSize = currentCodeCacheSize;    handleDoPrivileged();    free(jgs->inliningThresholds);    if (!CVMjitPolicyInit(ee, jgs)) {        return CVM_FALSE;    }    if (!CVMjitSetInliningThresholds(ee, jgs)) {        return CVM_FALSE;    }    /* Forget any collected stats if any */    CVMJITstatsDestroyGlobalStats(&jgs->globalStats);    /* And re-initialize if necessary */    if (!CVMJITstatsInitGlobalStats(&jgs->globalStats)) {        return CVM_FALSE;    }        if (!CVMJITcodeCacheInitOptions(jgs)) {        return CVM_FALSE;    }    #ifdef CVM_DEBUG    CVMjitDumpSysInfo();#endif    return CVM_TRUE;}#endif#if defined(CVM_DEBUG) || defined(CVM_INSPECTOR)/* Dumps info about the configuration of the JIT. */void CVMjitDumpSysInfo(){    CVMconsolePrintf("JIT Configuration:\n");    CVMprintSubOptionValues(knownJitSubOptions);}#endif /* CVM_DEBUG || CVM_INSPECTOR */#if defined(CVM_AOT) && !defined(CVM_MTASK)/* * CVMjitCompileAOTCode() is called during VM startup. If there is * no existing AOT code, compile all the methods on  * CVMglobals.jit.aotMethodList. The compiled methods will be save  * as the AOT code. */CVMBoolCVMjitCompileAOTCode(CVMExecEnv* ee){    CVMJITGlobalState* jgs = &CVMglobals.jit;    JNIEnv* env = CVMexecEnv2JniEnv(ee);    jstring jmlist;    CVMassert(!jgs->aotCompileFailed);    if (!jgs->aotEnabled) {        return CVM_TRUE;    }    if (jgs->codeCacheAOTCodeExist) {        return CVMJITinitializeAOTCode();    } else {          CVMassert(jgs->isPrecompiling == CVM_TRUE);        CVMassert(jgs->aotMethodList != NULL);        jmlist = (*env)->NewStringUTF(env, jgs->aotMethodList);        if ((*env)->ExceptionOccurred(env)) {            return CVM_FALSE;        }        CVMjniCallStaticVoidMethod(env,            CVMcbJavaInstance(CVMsystemClass(sun_misc_Warmup)),            CVMglobals.sun_misc_Warmup_runit, NULL, jmlist);        if (jgs->aotCompileFailed) {	    return CVM_FALSE;	}        return CVM_TRUE;    }}#endif#ifdef CVMJIT_SIMPLE_SYNC_METHODS/* * Simple Sync Method Names * * Array of method names that have simple synchronization requirements * and should be remapped to "Simple Sync" versions. This array provides * the symbolic mappings, and is processed to produce the mb->mb mappings * stored in jgs->simpleSyncMBs[]. */typedef struct {    CVMClassBlock* cb;    const char* methodName;    const char* methodSig;    const char* simpleSyncMethodName; /* uses methodSig as the signature */    const CVMUint16 jitFlags; /* extra mb->jitFlagsx flags to set */} CVMJITSimpleSyncMethodName;static const CVMJITSimpleSyncMethodName CVMJITsimpleSyncMethodNames[] = {    {	/* java.util.Random.next(I)I */	CVMsystemClass(java_util_Random),	"next", "(I)I",	"nextSimpleSync",        0    },    {	/* java.util.Hashtable.size()I */	CVMsystemClass(java_util_Hashtable),	"size", "()I",	"sizeSimpleSync",        0    },    {	/* java.util.Hashtable.isEmpty()Z */	CVMsystemClass(java_util_Hashtable),	"isEmpty", "()Z",	"isEmptySimpleSync",        0    },    {	/* java.lang.String.<init>(Ljava.lang.StringBuffer;) */	CVMsystemClass(java_lang_String),	"<init>", "(Ljava/lang/StringBuffer;)V",	"initSimpleSync",	/* calls other simple methods, which must be inlined */	CVMJIT_NEEDS_TO_INLINE    },    {	/* java.lang.StringBuffer.length()I */	CVMsystemClass(java_lang_StringBuffer),	"length", "()I",	"lengthSimpleSync",        0    },    {	/* java.lang.StringBuffer.capacity()I */	CVMsystemClass(java_lang_StringBuffer),	"capacity", "()I",	"capacitySimpleSync",        0    },    {	/* java.lang.StringBuffer.charAt(I)C */	CVMsystemClass(java_lang_StringBuffer),	"charAt", "(I)C",	"charAtSimpleSync",        0    },    {	/* java.lang.StringBuffer.append(C)Ljava/lang/StringBuffer; */	CVMsystemClass(java_lang_StringBuffer),	"append", "(C)Ljava/lang/StringBuffer;",	"appendSimpleSync",        0    },    {	/* java.util.Vector.capacity()I */	CVMsystemClass(java_util_Vector),	"capacity", "()I",	"capacitySimpleSync",        0    },    {	/* java.util.Vector.size()I */	CVMsystemClass(java_util_Vector),	"size", "()I",	"sizeSimpleSync",        0    },    {	/* java.util.Vector.isEmpty()Z */	CVMsystemClass(java_util_Vector),	"isEmpty", "()Z",	"isEmptySimpleSync",        0    },    {	/* java.util.Vector.elementAt(I)Ljava/lang/Object; */	CVMsystemClass(java_util_Vector),	"elementAt", "(I)Ljava/lang/Object;",	"elementAtSimpleSync",	/* calls get0, which really does the simple sync work */	CVMJIT_NEEDS_TO_INLINE    },    {	/* java.util.Vector.firstElement()Ljava/lang/Object; */	CVMsystemClass(java_util_Vector),	"firstElement", "()Ljava/lang/Object;",	"firstElementSimpleSync",	/* calls get0, which really does the simple sync work */	CVMJIT_NEEDS_TO_INLINE    },    {	/* java.util.Vector.lastElement()Ljava/lang/Object; */	CVMsystemClass(java_util_Vector),	"lastElement", "()Ljava/lang/Object;",	"lastElementSimpleSync",        0    },    {	/* java.util.Vector.setElementAt(Ljava/lang/Object;I)V */	CVMsystemClass(java_util_Vector),	"setElementAt", "(Ljava/lang/Object;I)V",	"setElementAtSimpleSync",	/* calls set0, which really does the simple sync work */	CVMJIT_NEEDS_TO_INLINE    },    {	/* java.util.Vector.addElement(Ljava/lang/Object;)V */	CVMsystemClass(java_util_Vector),	"addElement", "(Ljava/lang/Object;)V",	"addElementSimpleSync",        0    },    {	/* java.util.Vector.get(I)Ljava/lang/Object; */	CVMsystemClass(java_util_Vector),	"get", "(I)Ljava/lang/Object;",	"getSimpleSync",	/* calls get0, which really does the simple sync work */	CVMJIT_NEEDS_TO_INLINE    },    {	/* java.util.Vector.set(ILjava/lang/Object;)Ljava/lang/Object; */	CVMsystemClass(java_util_Vector),	"set", "(ILjava/lang/Object;)Ljava/lang/Object;",	"setSimpleSync",	/* calls set0, which really does the simple sync work */	CVMJIT_NEEDS_TO_INLINE    },    {	/* java.util.Vector$1.nextElement()Ljava/lang/Object; */	CVMsystemClass(java_util_Vector_1),	"nextElement", "()Ljava/lang/Object;",	"nextElementSimpleSync",        0    },};#define CVM_JIT_NUM_SIMPLESYNC_METHODS  \    (sizeof(CVMJITsimpleSyncMethodNames) / sizeof(CVMJITSimpleSyncMethodName))static CVMBoolCVMJITsimpleSyncInit(CVMExecEnv* ee, CVMJITGlobalState* jgs){    int i;    CVMMethodTypeID methodTypeID;     CVMMethodBlock* mb;    /* These method are always inlinable. They are called by the     * simple sync methods, but are actually the ones that really     * do the simple sync work. For example:     *     * private Object setSimpleSync(int index, Object element) {     *	   return set0(index, element);     * }     *     * We want to be agressive about inlining them.     */    methodTypeID = CVMtypeidLookupMethodIDFromNameAndSig(	ee, "get0", "(IZ)Ljava/lang/Object;");    mb = CVMclassGetMethodBlock(       	CVMsystemClass(java_util_Vector), methodTypeID, CVM_FALSE);    CVMassert(mb != NULL);    CVMmbCompileFlags(mb) |= CVMJIT_ALWAYS_INLINABLE;    methodTypeID = CVMtypeidLookupMethodIDFromNameAndSig(	ee, "set0", "(ILjava/lang/Object;)Ljava/lang/Object;");    mb = CVMclassGetMethodBlock(       	CVMsystemClass(java_util_Vector), methodTypeID, CVM_FALSE);    CVMassert(mb != NULL);    CVMmbCompileFlags(mb) |= CVMJIT_ALWAYS_INLINABLE;    /*     * allocate jgs->simpleSyncMBs[]     */    jgs->numSimpleSyncMBs = CVM_JIT_NUM_SIMPLESYNC_METHODS;    jgs->simpleSyncMBs = (void*)	malloc(sizeof(jgs->simpleSyncMBs[0]) * CVM_JIT_NUM_SIMPLESYNC_METHODS);    if (jgs->simpleSyncMBs == NULL) {	return CVM_FALSE;    }    /*     * initialize jgs->simpleSyncMBs based on the info in     * CVMJITsimpleSyncMethodNames[]     */    for (i = 0; i < CVM_JIT_NUM_SIMPLESYNC_METHODS; i++) {	/* lookup originalMB */	methodTypeID = CVMtypeidLookupMethodIDFromNameAndSig(	    ee, 	    CVMJITsimpleSyncMethodNames[i].methodName, 	    CVMJITsimpleSyncMethodNames[i].methodSig);	mb = CVMclassGetMethodBlock(            CVMJITsimpleSyncMethodNames[i].cb, methodTypeID, CVM_FALSE);#if 0	CVMconsolePrintf("%C.%!M\n",			 CVMJITsimpleSyncMethodNames[i].cb,			 methodTypeID);#endif	CVMassert(mb != NULL);	jgs->simpleSyncMBs[i].originalMB = mb;	/* lookup simpleSyncMB */	methodTypeID = CVMtypeidLookupMethodIDFromNameAndSig(	    ee, 	    CVMJITsimpleSyncMethodNames[i].simpleSyncMethodName, 	    CVMJITsimpleSyncMethodNames[i].methodSig);	mb = CVMclassGetMethodBlock(            CVMJITsimpleSyncMethodNames[i].cb, methodTypeID,  CVM_FALSE);	CVMassert(mb != NULL);	jgs->simpleSyncMBs[i].simpleSyncMB = mb;	/* these methods are always inlinable */	CVMmbCompileFlags(mb) |= CVMJIT_ALWAYS_INLINABLE;	/* Possibly set CVMJIT_NEEDS_TO_INLINE flag */	CVMmbCompileFlags(mb) |= CVMJITsimpleSyncMethodNames[i].jitFlags;    }    return CVM_TRUE;}static voidCVMJITsimpleSyncDestroy(CVMJITGlobalState* jgs){    free(jgs->simpleSyncMBs);    jgs->simpleSyncMBs = NULL;}#endif /* CVMJIT_SIMPLE_SYNC_METHODS */#ifdef CVM_JIT_PATCHED_METHOD_INVOCATIONS/********************************************************************  PMI - Patched Method Invocations support.   Support for the patch table used to support direct method invocations.  The patch table is used to track which code cache locations have direct  calls so they can be patched as methods get compiled/decompiled or  overridden for the first time. It has two main components:   -A hash table used to lookup mb's that have direct method calls to them.    This is referred to as the "Callee Table".   -An array that contains codecache offsets of instructions that make    direct method calls. This is referred to as the "Caller Table".  The Caller Table is indexed by the entries in the Callee Table. Each  Caller Table entry forms a linked list of entries. When an mb changes  state, it looks itself up in the Callee Table. If it finds an entry  for itself, then it knows there are direct method calls to it that  need to be patched. The location of these calls are discovered by  following the link (actually an array index) in the Callee Table  entry to the first entry for the method in the Caller Table. From  there each Caller Table method has a link (index) to the next entry  for the method. This is how a method finds all code cache locations  that need to be patched.  Details for the Callee Table and Caller Table are below:*//*  CALLEE TABLE - Hash table for tracking callee records.  Callee records (CVMJITPMICalleeRecords) are used to find all direct  method calls to a given callee. For tracking CVMJITPMICalleeRecords,  we use a hash table with open addressing and a double hashing  (secondary hash used when there is a collision). The secondary hash  value is a small prime number indexed out of the prime number table  below. We use a table size that is relatively prime to the secondary  hash (no factors common to any of the secondary hash primes). This  guarantees that all entries will be traversed and we will get a good  dispersal of entries in the table.  The reason for using this type of hash table is that it strikes a  good balance between minimal space and minimal lookup times. A  simple array would use the least amount of space, but would result  in either very slow lookups, or require extra space in each mb to  map each mb to an entry (even ones with no patched calls to  them). Any other type of data structure would waste space with link  pointers.  Since entries can be deleted, they need to be specially tagged so the  search does not end when a deleted entry is found. If callerMb == NULL,  this indicates an empty entry. If callerMb == 1, this indicates a  deleted entry.  The hash table grows if it gets too full, including counting  entries marked as deleted. CVMJITPMI_CALLEETABLE_MAX_PERCENT_FULL  determines when the table grows. Deleted entries are purged during  this process.  Each entry in the callee hash table is a CVMJITPMICalleeRecord,  which contains indices for the first and last caller entrie

⌨️ 快捷键说明

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