Skip to content

Commit 47042a0

Browse files
authored
Merge pull request #20195 from theresa-m/findclass_cache_48
(0.48) Cache rom to ram mappings for exception backtrace
2 parents ff860c5 + 00eea85 commit 47042a0

File tree

6 files changed

+165
-9
lines changed

6 files changed

+165
-9
lines changed

runtime/nls/shrc/j9shr.nls

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6943,3 +6943,17 @@ J9NLS_SHRC_CM_PRINTSTATS_PAGESIZEE.explanation=NOTAG
69436943
J9NLS_SHRC_CM_PRINTSTATS_PAGESIZEE.system_action=
69446944
J9NLS_SHRC_CM_PRINTSTATS_PAGESIZEE.user_response=
69456945
# END NON-TRANSLATABLE
6946+
6947+
J9NLS_SHRC_SHRINIT_FAILURE_CREATE_ROMTORAMHASHTABLE=Cannot allocate ROM to RAM class hash table in shrinit
6948+
# START NON-TRANSLATABLE
6949+
J9NLS_SHRC_SHRINIT_FAILURE_CREATE_ROMTORAMHASHTABLE.explanation=The system is unable to obtain sufficient native memory to allocate internal data structures.
6950+
J9NLS_SHRC_SHRINIT_FAILURE_CREATE_ROMTORAMHASHTABLE.system_action=The JVM terminates, unless you have specified the nonfatal option with "-Xshareclasses:nonfatal", in which case the JVM attempts to start up without using Shared Classes.
6951+
J9NLS_SHRC_SHRINIT_FAILURE_CREATE_ROMTORAMHASHTABLE.user_response=System is running low on memory resource for the JVM to start up properly. Check system memory configuration. If the situation persists, contact your service representative.
6952+
# END NON-TRANSLATABLE
6953+
6954+
J9NLS_SHRC_SHRINIT_FAILURE_CREATE_ROMTORAMMUTEX=Cannot allocate ROM to RAM class mutex in shrinit
6955+
# START NON-TRANSLATABLE
6956+
J9NLS_SHRC_SHRINIT_FAILURE_CREATE_ROMTORAMMUTEX.explanation=The system is unable to obtain sufficient native memory to allocate internal data structures.
6957+
J9NLS_SHRC_SHRINIT_FAILURE_CREATE_ROMTORAMMUTEX.system_action=The JVM terminates, unless you have specified the nonfatal option with "-Xshareclasses:nonfatal", in which case the JVM attempts to start up without using Shared Classes.
6958+
J9NLS_SHRC_SHRINIT_FAILURE_CREATE_ROMTORAMMUTEX.user_response=System is running low on memory resource for the JVM to start up properly. Check system memory configuration. If the situation persists, contact your service representative.
6959+
# END NON-TRANSLATABLE

runtime/oti/j9nonbuilder.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,11 @@ typedef struct J9SharedClassConfig {
14151415
const char* cacheName;
14161416
I_8 layer;
14171417
U_64 readOnlyCacheRuntimeFlags;
1418+
/* This table is a cache for exceptiondescribe.c:findJ9ClassForROMClass
1419+
* and does not contain mappings for every romClass to ramClass.
1420+
*/
1421+
struct J9HashTable *romToRamHashTable;
1422+
omrthread_rwmutex_t romToRamHashTableMutex;
14181423
} J9SharedClassConfig;
14191424

14201425
typedef struct J9SharedClassPreinitConfig {

runtime/shared_common/include/SCQueryFunctions.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,18 @@ j9shr_Query_PopulatePreinitConfigDefaults(J9JavaVM *vm, J9SharedClassPreinitConf
130130
}
131131
#endif
132132

133+
typedef struct RomToRamEntry {
134+
J9Class *ramClass;
135+
} RomToRamEntry;
136+
137+
typedef struct RomToRamQueryEntry {
138+
/* J9ROMClass address | ROM_TO_RAM_QUERY_TAG */
139+
J9ROMClass *romClass;
140+
} RomToRamQueryEntry;
141+
142+
/* Used to tell RomToRamQueryEntry apart from RomToRamEntry. */
143+
#define ROM_TO_RAM_QUERY_TAG 0x1
144+
133145
#ifdef __cplusplus
134146
}/*extern "C"*/
135147
#endif

runtime/shared_common/shrinit.cpp

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ extern "C" {
6868
#include "simplepool_api.h"
6969
#include "SCStringInternHelpers.h"
7070
#include <string.h>
71+
#include "SCQueryFunctions.h"
7172
#include "util_api.h"
7273
}
7374

@@ -412,6 +413,12 @@ static char* generateStartupHintsKey(J9JavaVM *vm);
412413
static void fetchStartupHintsFromSharedCache(J9VMThread* vmThread);
413414
static void findExistingCacheLayerNumbers(J9JavaVM* vm, const char* ctrlDirName, const char* cacheName, U_64 runtimeFlags, I_8 *maxLayerNo);
414415
static IDATA sysinfoGetUserNameHelper(J9JavaVM *vm, UDATA verboseFlags, char *buffer, UDATA length);
416+
static UDATA romToRamGetRomAddress(void *item);
417+
static UDATA romToRamHashFn(void *item, void *userData);
418+
static UDATA romToRamEqualFn(void *left, void *right, void *userData);
419+
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
420+
static void romToRamRemoveEntry(J9HookInterface **hookInterface, UDATA eventNum, void *voidData, void *userData);
421+
#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */
415422

416423
typedef struct J9SharedVerifyStringTable {
417424
void *romClassAreaStart;
@@ -3183,6 +3190,49 @@ j9shr_isBCIEnabled(J9JavaVM *vm)
31833190
return (0 != (vm->sharedClassConfig->runtimeFlags & J9SHR_RUNTIMEFLAG_ENABLE_BCI));
31843191
}
31853192

3193+
static UDATA
3194+
romToRamGetRomAddress(void *item)
3195+
{
3196+
RomToRamQueryEntry *queryEntry = (RomToRamQueryEntry *)item;
3197+
UDATA romAddress = (UDATA)(queryEntry->romClass);
3198+
if (J9_ARE_ALL_BITS_SET(romAddress, ROM_TO_RAM_QUERY_TAG)) {
3199+
return romAddress & ~ROM_TO_RAM_QUERY_TAG;
3200+
} else {
3201+
RomToRamEntry *entry = (RomToRamEntry *)item;
3202+
return (UDATA)(entry->ramClass->romClass);
3203+
}
3204+
}
3205+
3206+
/* THREADING: Must be protected by J9SharedClassConfig.romToRamHashTableMutex */
3207+
static UDATA
3208+
romToRamHashFn(void *item, void *userData)
3209+
{
3210+
return romToRamGetRomAddress(item);
3211+
}
3212+
3213+
/* THREADING: Must be protected by J9SharedClassConfig.romToRamHashTableMutex */
3214+
static UDATA
3215+
romToRamEqualFn(void *left, void *right, void *userData)
3216+
{
3217+
return (romToRamGetRomAddress(left) == romToRamGetRomAddress(right));
3218+
}
3219+
3220+
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
3221+
static void
3222+
romToRamRemoveEntry(J9HookInterface **hookInterface, UDATA eventNum, void *voidData, void *userData)
3223+
{
3224+
J9VMClassesUnloadEvent *data = (J9VMClassesUnloadEvent *)voidData;
3225+
J9SharedClassConfig *config = data->currentThread->javaVM->sharedClassConfig;
3226+
omrthread_rwmutex_enter_write(config->romToRamHashTableMutex);
3227+
for (J9Class *ramClass = data->classesToUnload; ramClass; ramClass = ramClass->gcLink) {
3228+
RomToRamEntry entry;
3229+
entry.ramClass = ramClass;
3230+
hashTableRemove(config->romToRamHashTable, &entry);
3231+
}
3232+
omrthread_rwmutex_exit_write(config->romToRamHashTableMutex);
3233+
}
3234+
#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */
3235+
31863236
/**
31873237
* JVM Initialisation processing for shared classes
31883238
*
@@ -3207,7 +3257,7 @@ j9shr_init(J9JavaVM *vm, UDATA loadFlags, UDATA* nonfatal)
32073257
U_64 runtimeFlags = vm->sharedCacheAPI->runtimeFlags;
32083258
UDATA verboseFlags = vm->sharedCacheAPI->verboseFlags;
32093259
UDATA printStatsOptions = vm->sharedCacheAPI->printStatsOptions;
3210-
J9HookInterface** hook = vm->internalVMFunctions->getVMHookInterface(vm);
3260+
J9HookInterface** vmHooks = vm->internalVMFunctions->getVMHookInterface(vm);
32113261
UDATA parseResult = vm->sharedCacheAPI->parseResult;
32123262
IDATA rc, rcStartup = 0;
32133263
const char* cacheName = vm->sharedCacheAPI->cacheName;
@@ -3515,6 +3565,24 @@ j9shr_init(J9JavaVM *vm, UDATA loadFlags, UDATA* nonfatal)
35153565
config->jclURLCache = NULL;
35163566
config->jclURLHashTable = NULL;
35173567
config->jclUTF8HashTable = NULL;
3568+
if (J9_ARE_ALL_BITS_SET(runtimeFlags, J9SHR_RUNTIMEFLAG_ENABLE_CACHE_NON_BOOT_CLASSES)) {
3569+
if (omrthread_rwmutex_init(&(config->romToRamHashTableMutex), 0, "romToRamHashTable mutex")) {
3570+
SHRINIT_ERR_TRACE(verboseFlags, J9NLS_SHRC_SHRINIT_FAILURE_CREATE_ROMTORAMMUTEX);
3571+
goto _error;
3572+
}
3573+
omrthread_rwmutex_enter_write(config->romToRamHashTableMutex);
3574+
config->romToRamHashTable = hashTableNew(OMRPORT_FROM_J9PORT(vm->portLibrary),
3575+
J9_GET_CALLSITE(), 0, sizeof(RomToRamEntry), sizeof(char *), 0,
3576+
J9MEM_CATEGORY_CLASSES, romToRamHashFn, romToRamEqualFn, NULL, NULL);
3577+
if (NULL == config->romToRamHashTable) {
3578+
omrthread_rwmutex_exit_write(config->romToRamHashTableMutex);
3579+
omrthread_rwmutex_destroy(config->romToRamHashTableMutex);
3580+
SHRINIT_ERR_TRACE(verboseFlags, J9NLS_SHRC_SHRINIT_FAILURE_CREATE_ROMTORAMHASHTABLE);
3581+
goto _error;
3582+
}
3583+
omrthread_rwmutex_exit_write(config->romToRamHashTableMutex);
3584+
}
3585+
35183586
config->jclJ9ClassPathEntryPool = pool_new(sizeof(struct J9ClassPathEntry), 0, 0, 0, J9_GET_CALLSITE(), J9MEM_CATEGORY_CLASSES, POOL_FOR_PORT(vm->portLibrary));
35193587
if (!(config->jclJ9ClassPathEntryPool)) {
35203588
SHRINIT_ERR_TRACE(verboseFlags, J9NLS_SHRC_SHRINIT_FAILURE_CREATE_POOL);
@@ -3556,7 +3624,7 @@ j9shr_init(J9JavaVM *vm, UDATA loadFlags, UDATA* nonfatal)
35563624
}
35573625

35583626
/* Register hooks */
3559-
(*hook)->J9HookRegisterWithCallSite(hook, J9HOOK_VM_FIND_LOCALLY_DEFINED_CLASS, hookFindSharedClass, OMR_GET_CALLSITE(), NULL);
3627+
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_FIND_LOCALLY_DEFINED_CLASS, hookFindSharedClass, OMR_GET_CALLSITE(), NULL);
35603628

35613629
/* We don't need the string table when running with -Xshareclasses:print<XXXX>Stats.
35623630
* This is because the JVM is terminated, after displaying the requested information.
@@ -3710,10 +3778,13 @@ j9shr_init(J9JavaVM *vm, UDATA loadFlags, UDATA* nonfatal)
37103778
}
37113779

37123780
if (0 != (runtimeFlags & J9SHR_RUNTIMEFLAG_ADD_TEST_JITHINT)) {
3713-
J9HookInterface** hook = vm->internalVMFunctions->getVMHookInterface(vm);
3714-
(*hook)->J9HookRegisterWithCallSite(hook, J9HOOK_VM_FIND_LOCALLY_DEFINED_CLASS, addTestJitHint, OMR_GET_CALLSITE(), NULL);
3781+
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_FIND_LOCALLY_DEFINED_CLASS, addTestJitHint, OMR_GET_CALLSITE(), NULL);
37153782
}
3716-
3783+
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
3784+
if (NULL != vm->sharedClassConfig->romToRamHashTable) {
3785+
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASSES_UNLOAD, romToRamRemoveEntry, OMR_GET_CALLSITE(), NULL);
3786+
}
3787+
#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */
37173788
if (doPrintStats) {
37183789
if (j9shr_print_stats(vm, parseResult, runtimeFlags, printStatsOptions) != -1) {
37193790
*nonfatal = 0; /* Nonfatal should be ignored for stats utilities */
@@ -4137,6 +4208,11 @@ j9shr_guaranteed_exit(J9JavaVM *vm, BOOLEAN exitForDebug)
41374208
*/
41384209
J9HookInterface** hook = vm->internalVMFunctions->getVMHookInterface(vm);
41394210
(*hook)->J9HookUnregister(hook, J9HOOK_VM_FIND_LOCALLY_DEFINED_CLASS, hookFindSharedClass, NULL);
4211+
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
4212+
if (NULL != vm->sharedClassConfig->romToRamHashTable) {
4213+
(*hook)->J9HookUnregister(hook, J9HOOK_VM_CLASSES_UNLOAD, romToRamRemoveEntry, NULL);
4214+
}
4215+
#endif /* defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) */
41404216
J9HookInterface **shcHooks;
41414217
shcHooks = zip_getVMZipCachePoolHookInterface((J9ZipCachePool *)vm->zipCachePool);
41424218
(*shcHooks)->J9HookUnregister(shcHooks, J9HOOK_VM_ZIP_LOAD, j9shr_hookZipLoadEvent, NULL);
@@ -4207,6 +4283,8 @@ j9shr_shutdown(J9JavaVM *vm)
42074283
J9SharedStringFarm* jclStringFarm = config->jclStringFarm;
42084284
J9HashTable* urlHashTable = config->jclURLHashTable;
42094285
J9HashTable* utfHashTable = config->jclUTF8HashTable;
4286+
J9HashTable *romToRamHashTable = config->romToRamHashTable;
4287+
omrthread_rwmutex_t romToRamHashTableMutex = config->romToRamHashTableMutex;
42104288
J9VMThread* currentThread = vm->internalVMFunctions->currentVMThread(vm);
42114289

42124290
/* Free all of the cached ClasspathItems */
@@ -4251,6 +4329,16 @@ j9shr_shutdown(J9JavaVM *vm)
42514329
if (utfHashTable) {
42524330
hashTableFree(utfHashTable);
42534331
}
4332+
if (NULL != romToRamHashTable) {
4333+
omrthread_rwmutex_enter_write(romToRamHashTableMutex);
4334+
config->romToRamHashTable = NULL;
4335+
config->romToRamHashTableMutex = NULL;
4336+
if (romToRamHashTable) {
4337+
hashTableFree(romToRamHashTable);
4338+
}
4339+
omrthread_rwmutex_exit_write(romToRamHashTableMutex);
4340+
omrthread_rwmutex_destroy(romToRamHashTableMutex);
4341+
}
42544342

42554343
/* Kill the string farm */
42564344

runtime/util/hshelp.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "j2sever.h"
4747
#include "vrfytbl.h"
4848
#include "bytecodewalk.h"
49+
#include "../shared_common/include/SCQueryFunctions.h"
4950

5051
/* Static J9ITable used as a non-NULL iTable cache value by classes that don't implement any interfaces */
5152
const J9ITable invalidITable = { (J9Class *) (UDATA) 0xDEADBEEF, 0, (J9ITable *) NULL };
@@ -2641,6 +2642,13 @@ recreateRAMClasses(J9VMThread * currentThread, J9HashTable * classHashTable, J9H
26412642
/* Delete original class from defining loader's class table */
26422643
if (!fastHCR) {
26432644
vmFuncs->hashClassTableDelete(classLoader, J9UTF8_DATA(className), J9UTF8_LENGTH(className));
2645+
if ((NULL != vm->sharedClassConfig) && (NULL != vm->sharedClassConfig->romToRamHashTable)) {
2646+
omrthread_rwmutex_enter_write(vm->sharedClassConfig->romToRamHashTableMutex);
2647+
RomToRamEntry entry;
2648+
entry.ramClass = originalRAMClass;
2649+
hashTableRemove(vm->sharedClassConfig->romToRamHashTable, &entry);
2650+
omrthread_rwmutex_exit_write(vm->sharedClassConfig->romToRamHashTableMutex);
2651+
}
26442652
}
26452653

26462654
/* Create new RAM class */

runtime/vm/exceptiondescribe.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,12 +234,33 @@ findJ9ClassForROMClass(J9VMThread *vmThread, J9ROMClass *romClass, J9ClassLoader
234234
{
235235
J9UTF8 const *utfClassName = J9ROMCLASS_CLASSNAME(romClass);
236236
J9JavaVM *vm = vmThread->javaVM;
237+
J9SharedClassConfig *config = vm->sharedClassConfig;
237238
J9Class* ret = NULL;
238-
if (j9shr_Query_IsAddressInCache(vm, romClass, romClass->romSize)) {
239+
240+
if (_J9ROMCLASS_J9MODIFIER_IS_SET(romClass, J9AccClassAnonClass)) {
241+
/* Anonymous classes are not allowed in any class loader hash table. */
242+
return NULL;
243+
}
244+
245+
if (j9shr_Query_IsAddressInCache(vm, romClass, romClass->romSize)
246+
&& (NULL != config->romToRamHashTable)
247+
) {
239248
J9ClassLoaderWalkState walkState;
240249
J9ClassLoader* classLoader = NULL;
241250
BOOLEAN fastMode = J9_ARE_ALL_BITS_SET(vm->extendedRuntimeFlags, J9_EXTENDED_RUNTIME_FAST_CLASS_HASH_TABLE);
242251
J9Class* ramClass = NULL;
252+
RomToRamEntry *resultEntry;
253+
RomToRamQueryEntry searchEntry;
254+
searchEntry.romClass = (J9ROMClass *)((UDATA)romClass | ROM_TO_RAM_QUERY_TAG);
255+
256+
omrthread_rwmutex_enter_read(config->romToRamHashTableMutex);
257+
resultEntry = hashTableFind(config->romToRamHashTable, &searchEntry);
258+
omrthread_rwmutex_exit_read(config->romToRamHashTableMutex);
259+
if (NULL != resultEntry) {
260+
ret = resultEntry->ramClass;
261+
goto done;
262+
}
263+
243264
if (!fastMode) {
244265
omrthread_monitor_enter(vm->classTableMutex);
245266
}
@@ -259,7 +280,7 @@ findJ9ClassForROMClass(J9VMThread *vmThread, J9ROMClass *romClass, J9ClassLoader
259280
if (!fastMode) {
260281
omrthread_monitor_exit(vm->classTableMutex);
261282
}
262-
goto done;
283+
goto cacheresult;
263284
}
264285

265286
ramClass = hashClassTableAt(vm->extensionClassLoader, J9UTF8_DATA(utfClassName), J9UTF8_LENGTH(utfClassName));
@@ -271,7 +292,7 @@ findJ9ClassForROMClass(J9VMThread *vmThread, J9ROMClass *romClass, J9ClassLoader
271292
if (!fastMode) {
272293
omrthread_monitor_exit(vm->classTableMutex);
273294
}
274-
goto done;
295+
goto cacheresult;
275296
}
276297

277298
ramClass = hashClassTableAt(vm->applicationClassLoader, J9UTF8_DATA(utfClassName), J9UTF8_LENGTH(utfClassName));
@@ -283,7 +304,7 @@ findJ9ClassForROMClass(J9VMThread *vmThread, J9ROMClass *romClass, J9ClassLoader
283304
if (!fastMode) {
284305
omrthread_monitor_exit(vm->classTableMutex);
285306
}
286-
goto done;
307+
goto cacheresult;
287308
}
288309

289310
classLoader = vm->internalVMFunctions->allClassLoadersStartDo(&walkState, vm, 0);
@@ -307,6 +328,14 @@ findJ9ClassForROMClass(J9VMThread *vmThread, J9ROMClass *romClass, J9ClassLoader
307328
if (!fastMode) {
308329
omrthread_monitor_exit(vm->classTableMutex);
309330
}
331+
cacheresult:
332+
if (NULL != ret) {
333+
RomToRamEntry newEntry;
334+
newEntry.ramClass = ret;
335+
omrthread_rwmutex_enter_write(config->romToRamHashTableMutex);
336+
hashTableAdd(config->romToRamHashTable, &newEntry);
337+
omrthread_rwmutex_exit_write(config->romToRamHashTableMutex);
338+
}
310339
} else {
311340
ret = peekClassHashTable(vmThread, *resultClassLoader, J9UTF8_DATA(utfClassName), J9UTF8_LENGTH(utfClassName));
312341
}

0 commit comments

Comments
 (0)