diff --git a/runtime/codert_vm/jswalk.c b/runtime/codert_vm/jswalk.c index efbfe38f71e..a99f1d34340 100644 --- a/runtime/codert_vm/jswalk.c +++ b/runtime/codert_vm/jswalk.c @@ -172,6 +172,9 @@ UDATA jitWalkStackFrames(J9StackWalkState *walkState) walkState->dropToCurrentFrame = jitDropToCurrentFrame; while ((walkState->jitInfo = jitGetExceptionTable(walkState)) != NULL) { +#if defined(J9MAPCACHE_DEBUG) + memset(&walkState->romMethodInfo, 0, sizeof(walkState->romMethodInfo)); +#endif /* J9MAPCACHE_DEBUG */ walkState->stackMap = NULL; walkState->inlineMap = NULL; walkState->bp = walkState->unwindSP + getJitTotalFrameSize(walkState->jitInfo); @@ -212,6 +215,9 @@ UDATA jitWalkStackFrames(J9StackWalkState *walkState) lswRecord(walkState, LSW_TYPE_METHOD, walkState->method); lswRecord(walkState, LSW_TYPE_JIT_FRAME_INFO, walkState); #endif + //initializeBasicROMMethodInfo(walkState, J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method)); + getROMMethodInfoForBytecodePC(walkState, J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method), walkState->bytecodePCOffset); + if ((rc = walkFrame(walkState)) != J9_STACKWALK_KEEP_ITERATING) { return rc; } @@ -250,6 +256,8 @@ UDATA jitWalkStackFrames(J9StackWalkState *walkState) #ifdef J9VM_INTERP_LINEAR_STACKWALK_TRACING lswRecord(walkState, LSW_TYPE_JIT_FRAME_INFO, walkState); #endif + //initializeBasicROMMethodInfo(walkState, J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method)); + getROMMethodInfoForBytecodePC(walkState, J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method), walkState->bytecodePCOffset); if ((rc = walkFrame(walkState)) != J9_STACKWALK_KEEP_ITERATING) { return rc; } @@ -1977,6 +1985,10 @@ jitWalkOSRFrame(J9StackWalkState *walkState, J9OSRFrame *osrFrame) UDATA *localSlots = ((UDATA*)(osrFrame + 1)) + maxStack; UDATA *nextFrame = localSlots + numberOfLocals; J9MonitorEnterRecord *enterRecord = osrFrame->monitorEnterRecords; + J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method); + + //initializeBasicROMMethodInfo(walkState, romMethod); + getROMMethodInfoForOSRFrame(walkState, osrFrame); #ifdef J9VM_INTERP_STACKWALK_TRACING { @@ -1987,6 +1999,7 @@ jitWalkOSRFrame(J9StackWalkState *walkState, J9OSRFrame *osrFrame) walkState->method = stateMethod; } #endif + walkBytecodeFrameSlots(walkState, method, offsetPC, localSlots - 1, pendingStackHeight, nextFrame - 1, numberOfLocals, TRUE); diff --git a/runtime/oti/j9modifiers_api.h b/runtime/oti/j9modifiers_api.h index 086af962ed0..01042173b34 100644 --- a/runtime/oti/j9modifiers_api.h +++ b/runtime/oti/j9modifiers_api.h @@ -116,8 +116,9 @@ /* Composite Flag checks */ #define J9ROMCLASS_IS_PRIMITIVE_OR_ARRAY(romClass) _J9ROMCLASS_SUNMODIFIER_IS_ANY_SET((romClass), J9AccClassArray | J9AccClassInternalPrimitiveType) -#define J9ROMMETHOD_IS_NON_EMPTY_OBJECT_CONSTRUCTOR(romMethod) \ - ((((romMethod)->modifiers) & (J9AccMethodObjectConstructor | J9AccEmptyMethod)) == J9AccMethodObjectConstructor) +#define J9ROMMETHOD_MODIFIERS_IS_NON_EMPTY_OBJECT_CONSTRUCTOR(modifiers) \ + (((modifiers) & (J9AccMethodObjectConstructor | J9AccEmptyMethod)) == J9AccMethodObjectConstructor) +#define J9ROMMETHOD_IS_NON_EMPTY_OBJECT_CONSTRUCTOR(romMethod) J9ROMMETHOD_MODIFIERS_IS_NON_EMPTY_OBJECT_CONSTRUCTOR((romMethod)->modifiers) /* Class instances are allocated via the new bytecode */ #define J9ROMCLASS_ALLOCATES_VIA_NEW(romClass) \ diff --git a/runtime/oti/j9nonbuilder.h b/runtime/oti/j9nonbuilder.h index 7acbb833c4b..be5f1337c91 100644 --- a/runtime/oti/j9nonbuilder.h +++ b/runtime/oti/j9nonbuilder.h @@ -1147,12 +1147,32 @@ typedef struct J9CudaGlobals { jmethodID runnable_run; } J9CudaGlobals; -#define J9_MAP_CACHE_SLOTS 2 - -typedef struct J9MapCacheEntry { +/* Cache slot sizes must all be multiples of 2 */ +#define J9_STACKMAP_CACHE_SLOTS 2 +#define J9_LOCALMAP_CACHE_SLOTS 2 +#define J9_ARGBITS_CACHE_SLOTS 2 + +/* Flag values for J9ROMMethodInfo */ +#define J9MAPCACHE_STACKMAP_CACHED 1 +#define J9MAPCACHE_LOCALMAP_CACHED 2 +#define J9MAPCACHE_ARGBITS_CACHED 4 +#define J9MAPCACHE_METHOD_IS_CONSTRUCTOR 8 +#define J9MAPCACHE_VALID 128 + +/* J9ROMMethodInfo must be a multiple of 8 bytes in size */ +typedef struct J9ROMMethodInfo { void *key; - U_32 bits[J9_MAP_CACHE_SLOTS]; -} J9MapCacheEntry; + U_32 stackmap[J9_STACKMAP_CACHE_SLOTS]; + U_32 localmap[J9_ARGBITS_CACHE_SLOTS]; + U_32 argbits[J9_ARGBITS_CACHE_SLOTS]; + U_32 modifiers; + U_16 tempCount; + U_8 argCount; + U_8 flags; +#if !defined(J9VM_ENV_DATA64) + U_32 padTo64; +#endif /* !defined(J9VM_ENV_DATA64) */ +} J9ROMMethodInfo; #if defined(J9VM_OPT_SHARED_CLASSES) @@ -2824,6 +2844,7 @@ typedef struct J9StackWalkState { void* stackMap; void* inlineMap; UDATA loopBreaker; + J9ROMMethodInfo romMethodInfo; /* 64-bit aligned */ /* The size of J9StackWalkState must be a multiple of 8 because it is inlined into * J9VMThread where alignment assumotions are being made. */ @@ -3756,9 +3777,7 @@ typedef struct J9ClassLoader { UDATA initClassPathEntryCount; UDATA asyncGetCallTraceUsed; omrthread_monitor_t mapCacheMutex; - struct J9HashTable* localmapCache; - struct J9HashTable* argsbitsCache; - struct J9HashTable* stackmapCache; + struct J9HashTable* romMethodInfoCache; #if defined(J9VM_OPT_JFR) J9HashTable *typeIDs; #endif /* defined(J9VM_OPT_JFR) */ diff --git a/runtime/oti/stackmap_api.h b/runtime/oti/stackmap_api.h index e242adb89e3..c4ef8a37fe5 100644 --- a/runtime/oti/stackmap_api.h +++ b/runtime/oti/stackmap_api.h @@ -196,30 +196,40 @@ j9stackmap_StackBitsForPC(J9PortLibrary * portLib, UDATA pc, J9ROMClass * romCla UDATA * (* getBuffer) (void * userData), void (* releaseBuffer) (void * userData)); +/* ---------------- mapcache.cpp ---------------- */ -/* ------------------- mapcache.cpp ----------------- */ +/** +* @brief +* @param walkState +* @param romMethod +*/ +void +initializeBasicROMMethodInfo(J9StackWalkState *walkState, J9ROMMethod *romMethod); -/* These are cache wrapper functions with the same parameters as the j9localmap_ versions, - * with VM and J9ClassLoader added on the end. +/** + * @brief + * @param walkState + * @param romMethod */ +void +getROMMethodInfoForROMMethod(J9StackWalkState *walkState, J9ROMMethod *romMethod); -IDATA -j9cached_StackBitsForPC(UDATA pc, J9ROMClass * romClass, J9ROMMethod * romMethod, - U_32 * resultArrayBase, UDATA resultArraySize, - void * userData, - UDATA * (* getBuffer) (void * userData), - void (* releaseBuffer) (void * userData), - J9JavaVM *vm, J9ClassLoader *classLoader); - +/** + * @brief + * @param walkState + * @param romMethod + * @param pc + */ void -j9cached_ArgBitsForPC0(J9ROMClass *romClass, J9ROMMethod *romMethod, U_32 *resultArrayBase, J9JavaVM *vm, J9ClassLoader *classLoader); +getROMMethodInfoForBytecodePC(J9StackWalkState *walkState, J9ROMMethod *romMethod, UDATA pc); -IDATA -j9cached_LocalBitsForPC(J9ROMClass * romClass, J9ROMMethod * romMethod, UDATA pc, U_32 * resultArrayBase, - void * userData, - UDATA * (* getBuffer) (void * userData), - void (* releaseBuffer) (void * userData), - J9JavaVM *vm, J9ClassLoader * classLoader); +/** + * @brief + * @param walkState + * @param osrFrame + */ +void +getROMMethodInfoForOSRFrame(J9StackWalkState *walkState, J9OSRFrame *osrFrame); #ifdef __cplusplus } diff --git a/runtime/stackmap/mapcache.cpp b/runtime/stackmap/mapcache.cpp index bdc312bfec8..2693fe5ba70 100644 --- a/runtime/stackmap/mapcache.cpp +++ b/runtime/stackmap/mapcache.cpp @@ -22,183 +22,261 @@ #include "rommeth.h" #include "stackmap_api.h" - extern "C" { -/** - * @brief Map cache hash function - * @param key J9MapCacheEntry pointer - * @param userData not used - * @return hash value - */ -static UDATA -localMapHashFn(void *key, void *userData) +void +initializeBasicROMMethodInfo(J9StackWalkState *walkState, J9ROMMethod *romMethod) { - J9MapCacheEntry *entry = (J9MapCacheEntry*)key; + J9ROMMethodInfo *romMethodInfo = &walkState->romMethodInfo; + memset(romMethodInfo, 0, sizeof(*romMethodInfo)); + romMethodInfo->argCount = romMethod->argCount; + romMethodInfo->tempCount = romMethod->tempCount; + romMethodInfo->modifiers = romMethod->modifiers; +#if defined(J9MAPCACHE_DEBUG) + romMethodInfo->flags = J9MAPCACHE_VALID; +#endif /* J9MAPCACHE_DEBUG */ + if (!(romMethod->modifiers & J9AccStatic)) { + if (J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod))[0] == '<') { + romMethodInfo->flags |= J9MAPCACHE_METHOD_IS_CONSTRUCTOR; + } + } +} +static UDATA +romMethodInfoHashFn(void *key, void *userData) +{ + J9ROMMethodInfo *entry = (J9ROMMethodInfo *)key; return (UDATA)entry->key; } -/** - * @brief Map cache comparator function - * @param leftKey J9MapCacheEntry pointer - * @param rightKey J9MapCacheEntry pointer - * @param userData not used - * @return 0 if comparision fails, non-zero if succeess - */ static UDATA -localMapHashEqualFn(void *leftKey, void *rightKey, void *userData) +romMethodInfoEqualFn(void *leftKey, void *rightKey, void *userData) { - J9MapCacheEntry *leftEntry = (J9MapCacheEntry*)leftKey; - J9MapCacheEntry *rightEntry = (J9MapCacheEntry*)rightKey; - - return (leftEntry->key == rightEntry->key); + J9ROMMethodInfo *left = (J9ROMMethodInfo *)leftKey; + J9ROMMethodInfo *right = (J9ROMMethodInfo *)rightKey; + return (left->key == right->key); } -/** -* @brief Check the given cache for the key. If found, populate the resultArray. -* @param vm the J9JavaVM -* @param classLoader the J9ClassLoader -* @param key the cache key -* @param mapCache the cache to search -* @param resultArrayBase the result array -* @param mapWords the numhber of U_32 in the result array -* @return true on cache hit, false on miss -*/ static bool -checkCache(J9JavaVM *vm, J9ClassLoader *classLoader, void *key, J9HashTable *mapCache, U_32 *resultArrayBase, UDATA mapWords) +checkROMMethodInfoCache(J9ClassLoader *classLoader, void *key, J9ROMMethodInfo *outInfo) { bool found = false; omrthread_monitor_t mapCacheMutex = classLoader->mapCacheMutex; - /* If the mapCacheMutex exists, the caching feature is enabled */ if (NULL != mapCacheMutex) { - if (mapWords <= J9_MAP_CACHE_SLOTS) { - omrthread_monitor_enter(mapCacheMutex); - - /* If the cache exists, check it for this key */ - if (NULL != mapCache) { - J9MapCacheEntry exemplar = { 0 }; - exemplar.key = key; - J9MapCacheEntry *entry = (J9MapCacheEntry*)hashTableFind(mapCache, &exemplar); - - if (NULL != entry) { - memcpy(resultArrayBase, entry->bits, sizeof(U_32) * mapWords); - found = true; - } - } + omrthread_monitor_enter(mapCacheMutex); - omrthread_monitor_exit(mapCacheMutex); + J9HashTable *cache = classLoader->romMethodInfoCache; + if (NULL != cache) { + J9ROMMethodInfo exemplar = {0}; + exemplar.key = key; + J9ROMMethodInfo *entry = (J9ROMMethodInfo *)hashTableFind(cache, &exemplar); + if (NULL != entry) { + *outInfo = *entry; + found = true; + } } + + omrthread_monitor_exit(mapCacheMutex); } return found; } -/** -* @brief Cache a result in the given cache for the key. -* @param vm the J9JavaVM -* @param classLoader the J9ClassLoader -* @param key the cache key -* @param cacheSlot pointer to the slot holding the cache pointer -* @param resultArrayBase the result array -* @param mapWords the numhber of U_32 in the result array -*/ static void -updateCache(J9JavaVM *vm, J9ClassLoader *classLoader, void *key, J9HashTable **cacheSlot, U_32 *resultArrayBase, UDATA mapWords) +updateROMMethodInfoCache(J9JavaVM *vm, J9ClassLoader *classLoader, J9ROMMethodInfo *info) { omrthread_monitor_t mapCacheMutex = classLoader->mapCacheMutex; + if (NULL == mapCacheMutex) { + return; /* caching disabled */ + } - /* If the mapCacheMutex exists, the caching feature is enabled */ - if (NULL != mapCacheMutex) { - if (mapWords <= J9_MAP_CACHE_SLOTS) { - omrthread_monitor_enter(mapCacheMutex); - - /* Create the cache if necessary - failure is non-fatal */ - J9HashTable *mapCache = *cacheSlot; - if (NULL == mapCache) { - mapCache = hashTableNew(OMRPORT_FROM_J9PORT(vm->portLibrary), - J9_GET_CALLSITE(), - 0, - sizeof(J9MapCacheEntry), - sizeof(J9MapCacheEntry *), - 0, - J9MEM_CATEGORY_VM, - localMapHashFn, - localMapHashEqualFn, - NULL, - NULL); - *cacheSlot = mapCache; - } + omrthread_monitor_enter(mapCacheMutex); - /* If the cache exists, attempt to add and entry for this map - failure is non-fatal */ - if (NULL != mapCache) { - J9MapCacheEntry entry = { 0 }; - entry.key = key; - memcpy(entry.bits, resultArrayBase, sizeof(U_32) * mapWords); - hashTableAdd(mapCache, &entry); - } + J9HashTable *cache = classLoader->romMethodInfoCache; + if (NULL == cache) { + /* Create the cache if it doesn't exist */ + cache = hashTableNew( + OMRPORT_FROM_J9PORT(vm->portLibrary), + J9_GET_CALLSITE(), + 0, + sizeof(J9ROMMethodInfo), + sizeof(J9ROMMethodInfo *), + 0, + J9MEM_CATEGORY_VM, + romMethodInfoHashFn, + romMethodInfoEqualFn, + NULL, + NULL); + classLoader->romMethodInfoCache = cache; + } - omrthread_monitor_exit(mapCacheMutex); - } + if (NULL != cache) { + PORT_ACCESS_FROM_JAVAVM(vm); + J9ROMMethodInfo *copy = (J9ROMMethodInfo *) j9mem_allocate_memory(sizeof(J9ROMMethodInfo), J9MEM_CATEGORY_VM); + *copy = *info; + hashTableAdd(cache, copy); } + + omrthread_monitor_exit(mapCacheMutex); } -IDATA -j9cached_StackBitsForPC(UDATA pc, J9ROMClass * romClass, J9ROMMethod * romMethod, - U_32 * resultArrayBase, UDATA resultArraySize, - void * userData, - UDATA * (* getBuffer) (void * userData), - void (* releaseBuffer) (void * userData), - J9JavaVM *vm, J9ClassLoader *classLoader) +static void +populateROMMethodInfo(J9StackWalkState *walkState, J9ROMMethod *romMethod, void *key, UDATA pc, bool computeStackAndLocals, UDATA pendingCount, UDATA numberOfLocals) { - UDATA mapWords = (resultArraySize + 31) >> 5; - void *bytecodePC = (void*)(J9_BYTECODE_START_FROM_ROM_METHOD(romMethod) + pc); - IDATA rc = 0; - - if (!checkCache(vm, classLoader, bytecodePC, classLoader->stackmapCache, resultArrayBase, mapWords)) { - /* Cache miss - perform the map and attempt to cache the result if successful */ - rc = j9stackmap_StackBitsForPC(vm->portLibrary, pc, romClass, romMethod, - resultArrayBase, resultArraySize, userData, getBuffer, releaseBuffer); - if (0 == rc) { - updateCache(vm, classLoader, bytecodePC, &classLoader->stackmapCache, resultArrayBase, mapWords); - } + J9Method *method = walkState->method; + J9ClassLoader *classLoader = J9_CLASS_FROM_METHOD(method)->classLoader; + J9JavaVM *vm = walkState->javaVM; + + J9ROMMethodInfo newInfo = {0}; + newInfo.key = key; + J9ROMClass *romClass = J9_CLASS_FROM_METHOD(method)->romClass; + + /* Always compute argument bits */ + j9localmap_ArgBitsForPC0(romClass, romMethod, newInfo.argbits); + if (computeStackAndLocals) { + /* Compute stack map for this PC */ + j9stackmap_StackBitsForPC( + vm->portLibrary, + pc, + romClass, + romMethod, + newInfo.stackmap, + J9_STACKMAP_CACHE_SLOTS << 5, + NULL, + NULL, + NULL); + + /* Compute local variable map for this PC */ + + vm->localMapFunction( + vm->portLibrary, + romClass, + romMethod, + pc, + newInfo.localmap, + NULL, + NULL, + NULL); + } + + /* Copy metadata */ + newInfo.modifiers = romMethod->modifiers; + newInfo.argCount = J9_ARG_COUNT_FROM_ROM_METHOD(romMethod); + newInfo.tempCount = J9_TEMP_COUNT_FROM_ROM_METHOD(romMethod); + + /* Insert into cache */ + //updateROMMethodInfoCache(vm, classLoader, &newInfo); + PORT_ACCESS_FROM_JAVAVM(vm); + J9ROMMethodInfo *stored = (J9ROMMethodInfo *) j9mem_allocate_memory(sizeof(J9ROMMethodInfo), J9MEM_CATEGORY_VM); + if (NULL == stored) { + walkState->romMethodInfo = newInfo; + } else { + *stored = newInfo; + updateROMMethodInfoCache(vm, classLoader, stored); + walkState->romMethodInfo = *stored; } - return rc; +} + +static UDATA +computePendingCountForBytecode(J9ROMMethod *romMethod) +{ + UDATA pendingCount = 0; + + UDATA argCount = romMethod->argCount; + UDATA tempCount = romMethod->tempCount; + + pendingCount = argCount + tempCount; + + UDATA modifiers = romMethod->modifiers; + + if (modifiers & J9AccSynchronized) { + /* Add monitor slot for synchronized methods */ + pendingCount += 1; + } else if ((modifiers & (J9AccMethodObjectConstructor | J9AccEmptyMethod)) == J9AccMethodObjectConstructor) { + /* Add extra receiver temp for non-empty Object. */ + pendingCount += 1; + } + + return pendingCount; } void -j9cached_ArgBitsForPC0(J9ROMClass *romClass, J9ROMMethod *romMethod, U_32 *resultArrayBase, J9JavaVM *vm, J9ClassLoader *classLoader) +getROMMethodInfoForROMMethod(J9StackWalkState *walkState, J9ROMMethod *romMethod) { - UDATA mapWords = (J9_ARG_COUNT_FROM_ROM_METHOD(romMethod) + 31) >> 5; + J9Method *method = walkState->method; + J9ClassLoader *classLoader = J9_CLASS_FROM_METHOD(method)->classLoader; + if (NULL == walkState->method || walkState->pc == NULL) { + return; // avoid dereference + } + void *key = (void *)romMethod; + J9ROMMethodInfo tmp = {0}; - if (!checkCache(vm, classLoader, (void*)romMethod, classLoader->argsbitsCache, resultArrayBase, mapWords)) { - /* Cache miss - perform the map and attempt to cache the result */ - j9localmap_ArgBitsForPC0(romClass, romMethod, resultArrayBase); - updateCache(vm, classLoader, (void*)romMethod, &classLoader->argsbitsCache, resultArrayBase, mapWords); + /* Check cache first */ + if (!checkROMMethodInfoCache(classLoader, key, &tmp)) { + /* Cache miss or not populated */ + initializeBasicROMMethodInfo(walkState, romMethod); + populateROMMethodInfo(walkState, romMethod, key, 0, false, 0, 0); + //populateROMMethodInfo(walkState, romMethod, key, 0, false); + } else { + /* Cache hit */ + walkState->romMethodInfo = tmp; } } -IDATA -j9cached_LocalBitsForPC(J9ROMClass * romClass, J9ROMMethod * romMethod, UDATA pc, U_32 * resultArrayBase, - void * userData, - UDATA * (* getBuffer) (void * userData), - void (* releaseBuffer) (void * userData), - J9JavaVM *vm, J9ClassLoader * classLoader) +/* Bytecode PC: compute argbits + stackmap + localmap */ +void +getROMMethodInfoForBytecodePC(J9StackWalkState *walkState, J9ROMMethod *romMethod, UDATA pc) { - IDATA rc = 0; - void *bytecodePC = (void*)(J9_BYTECODE_START_FROM_ROM_METHOD(romMethod) + pc); - UDATA mapWords = (UDATA) ((J9_TEMP_COUNT_FROM_ROM_METHOD(romMethod) + J9_ARG_COUNT_FROM_ROM_METHOD(romMethod) + 31) >> 5); - - if (!checkCache(vm, classLoader, bytecodePC, classLoader->localmapCache, resultArrayBase, mapWords)) { - /* Cache miss - perform the map and attempt to cache the result if successful */ - rc = vm->localMapFunction(vm->portLibrary, romClass, romMethod, pc, resultArrayBase, userData, getBuffer, releaseBuffer); - if (0 == rc) { - updateCache(vm, classLoader, bytecodePC, &classLoader->localmapCache, resultArrayBase, mapWords); - } + if (pc <= J9SF_MAX_SPECIAL_FRAME_TYPE || pc >= (UDATA)J9_BYTECODE_SIZE_FROM_ROM_METHOD(romMethod)) { + initializeBasicROMMethodInfo(walkState, romMethod); + return; + } + + J9Method *method = walkState->method; + J9ClassLoader *classLoader = J9_CLASS_FROM_METHOD(method)->classLoader; + if (NULL == walkState->method || walkState->pc == NULL) { + return; // avoid dereference + } + + void *key = (void *)( (uintptr_t)J9_BYTECODE_START_FROM_ROM_METHOD(romMethod) + (uintptr_t)pc ); + J9ROMMethodInfo tmp = {0}; + + /* Check cache first */ + if (!checkROMMethodInfoCache(classLoader, key, &tmp)) { + /* Cache miss or not populated */ + initializeBasicROMMethodInfo(walkState, romMethod); + UDATA pendingCount = computePendingCountForBytecode(romMethod); + UDATA numberOfLocals = romMethod->tempCount + romMethod->argCount; + populateROMMethodInfo(walkState, romMethod, key, pc, true, pendingCount, numberOfLocals); + //populateROMMethodInfo(walkState, romMethod, key, pc, true); + } else { + /* Cache hit */ + walkState->romMethodInfo = tmp; } +} + +void +getROMMethodInfoForOSRFrame(J9StackWalkState *walkState, J9OSRFrame *osrFrame) +{ + J9Method *method = osrFrame->method; + J9ClassLoader *classLoader = J9_CLASS_FROM_METHOD(method)->classLoader; + J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method); + + /* Use the ROMMethod pointer plus bytecode offset as key */ + void *key = (void *)((uintptr_t)J9_BYTECODE_START_FROM_ROM_METHOD(romMethod) + (uintptr_t)osrFrame->bytecodePCOffset); + J9ROMMethodInfo tmp = {0}; - return rc; + /* Check the cache first */ + if (!checkROMMethodInfoCache(classLoader, key, &tmp)) { + /* Cache miss or not populated */ + initializeBasicROMMethodInfo(walkState, romMethod); + populateROMMethodInfo(walkState, romMethod, key, osrFrame->bytecodePCOffset, true, osrFrame->pendingStackHeight, osrFrame->numberOfLocals); + //populateROMMethodInfo(walkState, romMethod, key, osrFrame->bytecodePCOffset,true); + } else { + /* Cache hit */ + walkState->romMethodInfo = tmp; + } } } /* extern "C" */ diff --git a/runtime/vm/classallocation.c b/runtime/vm/classallocation.c index 0d61b465379..da7ec7c5e38 100644 --- a/runtime/vm/classallocation.c +++ b/runtime/vm/classallocation.c @@ -67,17 +67,9 @@ U_32 classPropagationTable[CLASS_PROPAGATION_TABLE_SIZE] = { void freeMapCaches(J9ClassLoader *classLoader) { - if (NULL != classLoader->localmapCache) { - hashTableFree(classLoader->localmapCache); - classLoader->localmapCache = NULL; - } - if (NULL != classLoader->argsbitsCache) { - hashTableFree(classLoader->argsbitsCache); - classLoader->argsbitsCache = NULL; - } - if (NULL != classLoader->stackmapCache) { - hashTableFree(classLoader->stackmapCache); - classLoader->stackmapCache = NULL; + if (NULL != classLoader->romMethodInfoCache) { + hashTableFree(classLoader->romMethodInfoCache); + classLoader->romMethodInfoCache = NULL; } } diff --git a/runtime/vm/swalk.c b/runtime/vm/swalk.c index f29d5025dea..6724cd0e91a 100644 --- a/runtime/vm/swalk.c +++ b/runtime/vm/swalk.c @@ -55,6 +55,13 @@ #include +#if defined(J9MAPCACHE_DEBUG) +#define ENSURE_ROM_METHOD_INFO_VALID(romMethodInfo) \ + if (J9_ARE_NO_BITS_SET(romMethodInfo->flags, J9MAPCACHE_VALID)) *(UDATA*)-1=-1 +#else /* J9MAPCACHE_DEBUG */ +#define ENSURE_ROM_METHOD_INFO_VALID(romMethodInfo) +#endif /* J9MAPCACHE_DEBUG */ + #if (defined(J9VM_INTERP_STACKWALK_TRACING)) static void printFrameType (J9StackWalkState * walkState, char * frameType); @@ -309,6 +316,11 @@ UDATA walkStackFrames(J9VMThread *currentThread, J9StackWalkState *walkState) walkState->outgoingArgCount = walkState->argCount; walkState->bytecodePCOffset = -1; +#if defined(J9MAPCACHE_DEBUG) + memset(&walkState->romMethodInfo, 0, sizeof(walkState->romMethodInfo)); +#endif /* J9MAPCACHE_DEBUG */ + + #ifdef J9VM_INTERP_LINEAR_STACKWALK_TRACING lswFrameNew(vm, walkState, (UDATA)walkState->pc); #endif @@ -489,16 +501,14 @@ UDATA walkFrame(J9StackWalkState * walkState) } if (walkState->flags & J9_STACKWALK_HIDE_EXCEPTION_FRAMES) { - J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method); - - if (!(romMethod->modifiers & J9AccStatic)) { - if (J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod))[0] == '<') { - if (*walkState->arg0EA == (UDATA) walkState->restartException) { - return J9_STACKWALK_KEEP_ITERATING; - } + J9ROMMethodInfo *romMethodInfo = &walkState->romMethodInfo; + ENSURE_ROM_METHOD_INFO_VALID(romMethodInfo); + if (J9_ARE_ANY_BITS_SET(romMethodInfo->flags, J9MAPCACHE_METHOD_IS_CONSTRUCTOR)) { + if (*walkState->arg0EA == (UDATA) walkState->restartException) { + return J9_STACKWALK_KEEP_ITERATING; } - walkState->flags &= ~J9_STACKWALK_HIDE_EXCEPTION_FRAMES; } + walkState->flags &= ~J9_STACKWALK_HIDE_EXCEPTION_FRAMES; } } @@ -709,6 +719,11 @@ walkMethodFrame(J9StackWalkState * walkState) walkState->frameFlags = methodFrame->specialFrameFlags; MARK_SLOT_AS_OBJECT(walkState, (j9object_t*) &(methodFrame->specialFrameFlags)); walkState->method = methodFrame->method; + if (NULL != walkState->method) { + J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method); + getROMMethodInfoForROMMethod(walkState, romMethod); + //initializeBasicROMMethodInfo(walkState, J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method)); + } walkState->unwindSP = (UDATA *) methodFrame; #ifdef J9VM_INTERP_LINEAR_STACKWALK_TRACING @@ -745,22 +760,32 @@ walkMethodFrame(J9StackWalkState * walkState) } if (walkState->method) { J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method); + J9ROMMethodInfo *romMethodInfo = &walkState->romMethodInfo; + + //initializeBasicROMMethodInfo(walkState, romMethod); + getROMMethodInfoForROMMethod(walkState, romMethod); walkState->constantPool = UNTAGGED_METHOD_CP(walkState->method); - walkState->argCount = J9_ARG_COUNT_FROM_ROM_METHOD(romMethod); + walkState->argCount = romMethodInfo->argCount; if (walkState->flags & J9_STACKWALK_ITERATE_O_SLOTS) { WALK_METHOD_CLASS(walkState); if (walkState->argCount) { /* Max size as argCount always <= 255 */ - U_32 result[8]; + U_32 inlineResult[8]; + U_32 *result = inlineResult; J9Class *methodClass = UNTAGGED_METHOD_CP(walkState->method)->ramClass; #ifdef J9VM_INTERP_STACKWALK_TRACING swPrintf(walkState, 4, "\tUsing signature mapper\n"); #endif - j9cached_ArgBitsForPC0(methodClass->romClass, romMethod, result, walkState->javaVM, methodClass->classLoader); + + if (J9_ARE_ANY_BITS_SET(romMethodInfo->flags, J9MAPCACHE_ARGBITS_CACHED)) { + result = romMethodInfo->argbits; + } else { + j9localmap_ArgBitsForPC0(methodClass->romClass, romMethod, result); + } #ifdef J9VM_INTERP_STACKWALK_TRACING swPrintf(walkState, 4, "\tArguments starting at %p for %d slots\n", walkState->arg0EA, walkState->argCount); @@ -812,7 +837,7 @@ walkMethodTypeFrame(J9StackWalkState * walkState) MARK_SLOT_AS_OBJECT(walkState, (j9object_t*) &(methodTypeFrame->specialFrameFlags)); MARK_SLOT_AS_OBJECT(walkState, (j9object_t*) &(methodTypeFrame->argStackSlots)); MARK_SLOT_AS_OBJECT(walkState, (j9object_t*) &(methodTypeFrame->descriptionIntCount)); - walkState->method = NULL; + NULL; walkState->unwindSP = (UDATA *) methodTypeFrame; #ifdef J9VM_INTERP_LINEAR_STACKWALK_TRACING @@ -879,21 +904,20 @@ walkBytecodeFrameSlots(J9StackWalkState *walkState, J9Method *method, UDATA offs { J9JavaVM *vm = walkState->javaVM; PORT_ACCESS_FROM_JAVAVM(vm); + J9ROMMethodInfo *romMethodInfo = &walkState->romMethodInfo; UDATA *bp = localBase - numberOfLocals; - J9Class *ramClass = J9_CLASS_FROM_METHOD(method); - J9ROMClass *romClass = ramClass->romClass; - J9ROMMethod *romMethod = getOriginalROMMethod(method); - U_32 smallResult = 0; - U_32 *result = &smallResult; U_32 *globalBuffer = NULL; UDATA numberOfMappedLocals = numberOfLocals; + U_32 modifiers = romMethodInfo->modifiers; + U_32 flags = romMethodInfo->flags; + + ENSURE_ROM_METHOD_INFO_VALID(romMethodInfo); #ifdef J9VM_INTERP_STACKWALK_TRACING swPrintf(walkState, 3, "\tBytecode index = %d\n", offsetPC); #endif - - if (romMethod->modifiers & J9AccSynchronized) { + if (modifiers & J9AccSynchronized) { #ifdef J9VM_INTERP_STACKWALK_TRACING swPrintf(walkState, 4, "\tSync object for synchronized method\n"); #endif @@ -901,7 +925,7 @@ walkBytecodeFrameSlots(J9StackWalkState *walkState, J9Method *method, UDATA offs walkState->slotIndex = -1; WALK_NAMED_O_SLOT((j9object_t*) (bp + 1), "Sync O-Slot"); numberOfMappedLocals -= 1; - } else if (J9ROMMETHOD_IS_NON_EMPTY_OBJECT_CONSTRUCTOR(romMethod)) { + } else if (J9ROMMETHOD_MODIFIERS_IS_NON_EMPTY_OBJECT_CONSTRUCTOR(modifiers)) { /* Non-empty java.lang.Object. has one hidden temp to hold a copy of the receiver */ #ifdef J9VM_INTERP_STACKWALK_TRACING swPrintf(walkState, 4, "\tReceiver object for java.lang.Object.\n"); @@ -912,40 +936,57 @@ walkBytecodeFrameSlots(J9StackWalkState *walkState, J9Method *method, UDATA offs numberOfMappedLocals -= 1; } - if ((numberOfMappedLocals > 32) || (pendingStackHeight > 32)) { - UDATA maxCount = (numberOfMappedLocals > pendingStackHeight) ? numberOfMappedLocals : pendingStackHeight; - result = j9mem_allocate_memory(((maxCount + 31) >> 5) * sizeof(U_32), OMRMEM_CATEGORY_VM); - if (NULL == result) { - globalBuffer = j9mapmemory_GetResultsBuffer(vm); - result = globalBuffer; + { + J9ROMClass *romClass = J9_CLASS_FROM_METHOD(method)->romClass; + J9ROMMethod *romMethod = getOriginalROMMethod(method); + U_32 smallResult = 0; + U_32 *result = &smallResult; + BOOLEAN freeBuffer = FALSE; + + if ((numberOfMappedLocals > 32) || (pendingStackHeight > 32)) { + UDATA maxCount = (numberOfMappedLocals > pendingStackHeight) ? numberOfMappedLocals : pendingStackHeight; + result = j9mem_allocate_memory(((maxCount + 31) >> 5) * sizeof(U_32), OMRMEM_CATEGORY_VM); + if (NULL == result) { + globalBuffer = j9mapmemory_GetResultsBuffer(vm); + result = globalBuffer; + } + freeBuffer = TRUE; } - } - if (0 != numberOfMappedLocals) { - getLocalsMap(walkState, romClass, romMethod, offsetPC, result, numberOfMappedLocals, alwaysLocalMap); + if (0 != numberOfMappedLocals) { + if (J9_ARE_ANY_BITS_SET(flags, J9MAPCACHE_LOCALMAP_CACHED)) { + result = romMethodInfo->localmap; + } else { + getLocalsMap(walkState, romClass, romMethod, offsetPC, result, numberOfMappedLocals, alwaysLocalMap); + } #ifdef J9VM_INTERP_STACKWALK_TRACING - swPrintf(walkState, 4, "\tLocals starting at %p for %d slots\n", localBase, numberOfMappedLocals); + swPrintf(walkState, 4, "\tLocals starting at %p for %d slots\n", localBase, numberOfMappedLocals); #endif - walkState->slotType = J9_STACKWALK_SLOT_TYPE_METHOD_LOCAL; - walkState->slotIndex = 0; - walkDescribedPushes(walkState, localBase, numberOfMappedLocals, result, romMethod->argCount); - } + walkState->slotType = J9_STACKWALK_SLOT_TYPE_METHOD_LOCAL; + walkState->slotIndex = 0; + walkDescribedPushes(walkState, localBase, numberOfMappedLocals, result, romMethodInfo->argCount); + } - if (0 != pendingStackHeight) { - getStackMap(walkState, romClass, romMethod, offsetPC, pendingStackHeight, result); + if (0 != pendingStackHeight) { + if (J9_ARE_ANY_BITS_SET(flags, J9MAPCACHE_STACKMAP_CACHED)) { + result = romMethodInfo->stackmap; + } else { + getStackMap(walkState, romClass, romMethod, offsetPC, pendingStackHeight, result); + } #ifdef J9VM_INTERP_STACKWALK_TRACING - swPrintf(walkState, 4, "\tPending stack starting at %p for %d slots\n", pendingBase, pendingStackHeight); + swPrintf(walkState, 4, "\tPending stack starting at %p for %d slots\n", pendingBase, pendingStackHeight); #endif - walkState->slotType = J9_STACKWALK_SLOT_TYPE_PENDING; - walkState->slotIndex = 0; - walkDescribedPushes(walkState, pendingBase, pendingStackHeight, result, 0); - } + walkState->slotType = J9_STACKWALK_SLOT_TYPE_PENDING; + walkState->slotIndex = 0; + walkDescribedPushes(walkState, pendingBase, pendingStackHeight, result, 0); + } - if (result != &smallResult) { - if (NULL == globalBuffer) { - j9mem_free_memory(result); - } else { - j9mapmemory_ReleaseResultsBuffer(vm); + if (freeBuffer) { + if (NULL == globalBuffer) { + j9mem_free_memory(result); + } else { + j9mapmemory_ReleaseResultsBuffer(vm); + } } } } @@ -985,7 +1026,11 @@ walkBytecodeFrame(J9StackWalkState * walkState) #endif /* defined(J9VM_OPT_METHOD_HANDLE) */ UDATA argTempCount = 0; J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method); + J9ROMMethodInfo *romMethodInfo = &walkState->romMethodInfo; + //initializeBasicROMMethodInfo(walkState, romMethod); + UDATA pcOffset = walkState->pc - J9_BYTECODE_START_FROM_RAM_METHOD(walkState->method); + getROMMethodInfoForBytecodePC(walkState, romMethod, pcOffset); walkState->constantPool = UNTAGGED_METHOD_CP(walkState->method); #if defined(J9VM_OPT_METHOD_HANDLE) @@ -999,16 +1044,16 @@ walkBytecodeFrame(J9StackWalkState * walkState) walkState->bytecodePCOffset = walkState->pc - (U_8 *) J9_BYTECODE_START_FROM_RAM_METHOD(walkState->method); #endif /* defined(J9VM_OPT_METHOD_HANDLE) */ - walkState->argCount = J9_ARG_COUNT_FROM_ROM_METHOD(romMethod); - argTempCount = J9_TEMP_COUNT_FROM_ROM_METHOD(romMethod) + walkState->argCount; + walkState->argCount = romMethodInfo->argCount; + argTempCount = romMethodInfo->tempCount + walkState->argCount; walkState->bp = walkState->arg0EA - argTempCount; - if (romMethod->modifiers & J9AccSynchronized) { + if (romMethodInfo->modifiers & J9AccSynchronized) { #ifdef J9VM_INTERP_LINEAR_STACKWALK_TRACING lswRecordSlot(walkState, walkState->bp, LSW_TYPE_O_SLOT, "Sync Object"); #endif argTempCount += 1; walkState->bp -= 1; - } else if (J9ROMMETHOD_IS_NON_EMPTY_OBJECT_CONSTRUCTOR(romMethod)) { + } else if (((romMethodInfo->modifiers) & (J9AccMethodObjectConstructor | J9AccEmptyMethod)) == J9AccMethodObjectConstructor) { /* Non-empty java.lang.Object. has one hidden temp to hold a copy of the receiver */ #ifdef J9VM_INTERP_LINEAR_STACKWALK_TRACING lswRecordSlot(walkState, walkState->bp, LSW_TYPE_O_SLOT, "Receiver Object"); @@ -1035,8 +1080,8 @@ walkBytecodeFrame(J9StackWalkState * walkState) if (walkState->flags & J9_STACKWALK_ITERATE_O_SLOTS) { WALK_METHOD_CLASS(walkState); - walkBytecodeFrameSlots(walkState, walkState->method, walkState->bytecodePCOffset, - walkState->unwindSP - 1, walkState->unwindSP - walkState->walkSP, + walkBytecodeFrameSlots(walkState, walkState->method, + walkState->bytecodePCOffset, walkState->unwindSP - 1, walkState->unwindSP - walkState->walkSP, walkState->arg0EA, argTempCount, FALSE); } } @@ -1190,6 +1235,11 @@ static void walkJITJNICalloutFrame(J9StackWalkState * walkState) walkState->frameFlags = methodFrame->specialFrameFlags; MARK_SLOT_AS_OBJECT(walkState, (j9object_t*) &(methodFrame->specialFrameFlags)); walkState->method = methodFrame->method; + if (NULL != walkState->method) { + J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method); + getROMMethodInfoForROMMethod(walkState, romMethod); + //initializeBasicROMMethodInfo(walkState, J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method)); + } walkState->constantPool = UNTAGGED_METHOD_CP(walkState->method); #ifdef J9VM_INTERP_STACKWALK_TRACING printFrameType(walkState, "JIT JNI call-out"); @@ -1500,8 +1550,11 @@ static void getLocalsMap(J9StackWalkState * walkState, J9ROMClass * romClass, J9ROMMethod * romMethod, UDATA offsetPC, U_32 * result, UDATA argTempCount, UDATA alwaysLocalMap) { PORT_ACCESS_FROM_WALKSTATE(walkState); - IDATA errorCode; J9JavaVM *vm = walkState->walkThread->javaVM; + J9ROMMethodInfo *romMethodInfo = &walkState->romMethodInfo; + UDATA copySize = ((argTempCount + 31) / 32) * sizeof(U_32); + + ENSURE_ROM_METHOD_INFO_VALID(romMethodInfo); if (!alwaysLocalMap) { /* Detect method entry vs simply executing at PC 0. If the bytecode frame is invisible (method monitor enter or @@ -1520,9 +1573,16 @@ getLocalsMap(J9StackWalkState * walkState, J9ROMClass * romClass, J9ROMMethod * #endif /* j9localmap_ArgBitsForPC0 only deals with args, so zero out the result array to make sure the temps are non-object */ + memset(result, 0, copySize); + if (J9_ARE_ANY_BITS_SET(romMethodInfo->flags, J9MAPCACHE_ARGBITS_CACHED)) { + if (copySize > sizeof(romMethodInfo->argbits)) { + copySize = sizeof(romMethodInfo->argbits); + } + memcpy(result, romMethodInfo->argbits, copySize); + } else { + j9localmap_ArgBitsForPC0(romClass, romMethod, result); + } - memset(result, 0, ((argTempCount + 31) / 32) * sizeof(U_32)); - j9cached_ArgBitsForPC0(romClass, romMethod, result, walkState->javaVM, UNTAGGED_METHOD_CP(walkState->method)->ramClass->classLoader); return; } } @@ -1530,17 +1590,22 @@ getLocalsMap(J9StackWalkState * walkState, J9ROMClass * romClass, J9ROMMethod * #ifdef J9VM_INTERP_STACKWALK_TRACING swPrintf(walkState, 4, "\tUsing local mapper\n"); #endif - errorCode = j9cached_LocalBitsForPC(romClass, romMethod, offsetPC, result, vm, j9mapmemory_GetBuffer, j9mapmemory_ReleaseBuffer, vm, J9_CLASS_FROM_METHOD(walkState->method)->classLoader); - if (errorCode < 0) { - if (J9_ARE_NO_BITS_SET(walkState->flags, J9_STACKWALK_NO_ERROR_REPORT)) { - /* Local map failed, result = %p - aborting VM - needs new message TBD */ - j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_VM_STACK_MAP_FAILED, errorCode); + if (J9_ARE_ANY_BITS_SET(romMethodInfo->flags, J9MAPCACHE_LOCALMAP_CACHED)) { + memcpy(result, romMethodInfo->localmap, copySize); + } else { + IDATA errorCode = vm->localMapFunction(vm->portLibrary, romClass, romMethod, offsetPC, result, vm, j9mapmemory_GetBuffer, j9mapmemory_ReleaseBuffer); + + if (errorCode < 0) { + if (J9_ARE_NO_BITS_SET(walkState->flags, J9_STACKWALK_NO_ERROR_REPORT)) { + /* Local map failed, result = %p - aborting VM - needs new message TBD */ + j9nls_printf(PORTLIB, J9NLS_ERROR, J9NLS_VM_STACK_MAP_FAILED, errorCode); #if defined(J9VM_INTERP_STACKWALK_TRACING) - Assert_VRB_stackMapFailed(); + Assert_VRB_stackMapFailed(); #else /* J9VM_INTERP_STACKWALK_TRACING */ - Assert_VM_stackMapFailed(); + Assert_VM_stackMapFailed(); #endif /* J9VM_INTERP_STACKWALK_TRACING */ + } } } @@ -1554,7 +1619,7 @@ getStackMap(J9StackWalkState * walkState, J9ROMClass * romClass, J9ROMMethod * r PORT_ACCESS_FROM_WALKSTATE(walkState); IDATA errorCode; - errorCode = j9cached_StackBitsForPC(offsetPC, romClass, romMethod, result, pushCount, walkState->javaVM, j9mapmemory_GetBuffer, j9mapmemory_ReleaseBuffer, walkState->javaVM, UNTAGGED_METHOD_CP(walkState->method)->ramClass->classLoader); + errorCode = j9stackmap_StackBitsForPC(PORTLIB, offsetPC, romClass, romMethod, result, pushCount, walkState->javaVM, j9mapmemory_GetBuffer, j9mapmemory_ReleaseBuffer); if (errorCode < 0) { if (J9_ARE_NO_BITS_SET(walkState->flags, J9_STACKWALK_NO_ERROR_REPORT)) { /* Local map failed, result = %p - aborting VM */