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 + -
显示快捷键?