2222
2323#include " rommeth.h"
2424#include " stackmap_api.h"
25-
2625extern " C" {
2726
2827void
@@ -43,11 +42,228 @@ initializeBasicROMMethodInfo(J9StackWalkState *walkState, J9ROMMethod *romMethod
4342 }
4443}
4544
45+ static UDATA
46+ romMethodInfoHashFn (void *key, void *userData)
47+ {
48+ J9ROMMethodInfo *entry = (J9ROMMethodInfo *)key;
49+ return (UDATA)entry->key ;
50+ }
51+
52+ static UDATA
53+ romMethodInfoEqualFn (void *leftKey, void *rightKey, void *userData)
54+ {
55+ J9ROMMethodInfo *left = (J9ROMMethodInfo *)leftKey;
56+ J9ROMMethodInfo *right = (J9ROMMethodInfo *)rightKey;
57+ return (left->key == right->key );
58+ }
59+
60+ static bool
61+ checkROMMethodInfoCache (J9ClassLoader *classLoader, void *key, J9ROMMethodInfo *outInfo)
62+ {
63+ bool found = false ;
64+ omrthread_monitor_t mapCacheMutex = classLoader->mapCacheMutex ;
65+
66+ if (NULL != mapCacheMutex) {
67+ omrthread_monitor_enter (mapCacheMutex);
68+
69+ J9HashTable *cache = classLoader->romMethodInfoCache ;
70+ if (NULL != cache) {
71+ J9ROMMethodInfo exemplar = {0 };
72+ exemplar.key = key;
73+ J9ROMMethodInfo *entry = (J9ROMMethodInfo *)hashTableFind (cache, &exemplar);
74+ if (NULL != entry) {
75+ *outInfo = *entry; /* Copy struct */
76+ found = true ;
77+ }
78+ }
79+
80+ omrthread_monitor_exit (mapCacheMutex);
81+ }
82+
83+ return found;
84+ }
85+
86+ static void
87+ updateROMMethodInfoCache (J9JavaVM *vm, J9ClassLoader *classLoader, J9ROMMethodInfo *info)
88+ {
89+ omrthread_monitor_t mapCacheMutex = classLoader->mapCacheMutex ;
90+ if (NULL == mapCacheMutex) {
91+ return ; /* caching disabled */
92+ }
93+
94+ omrthread_monitor_enter (mapCacheMutex);
95+
96+ J9HashTable *cache = classLoader->romMethodInfoCache ;
97+ if (NULL == cache) {
98+ cache = hashTableNew (
99+ OMRPORT_FROM_J9PORT (vm->portLibrary ),
100+ J9_GET_CALLSITE (),
101+ 0 ,
102+ sizeof (J9ROMMethodInfo),
103+ sizeof (J9ROMMethodInfo *),
104+ 0 ,
105+ J9MEM_CATEGORY_VM,
106+ romMethodInfoHashFn,
107+ romMethodInfoEqualFn,
108+ NULL ,
109+ NULL );
110+ classLoader->romMethodInfoCache = cache;
111+ }
112+
113+ if (NULL != cache) {
114+ hashTableAdd (cache, info);
115+ }
116+
117+ omrthread_monitor_exit (mapCacheMutex);
118+ }
119+
46120void
47121populateROMMethodInfo (J9StackWalkState *walkState, J9ROMMethod *romMethod, void *key)
48122{
49123 initializeBasicROMMethodInfo (walkState, romMethod);
124+
125+ J9Method *method = walkState->method ;
126+ J9ClassLoader *classLoader = J9_CLASS_FROM_METHOD (method)->classLoader ;
127+ J9JavaVM *vm = walkState->javaVM ;
128+
129+ UDATA codeSize = (UDATA)J9_BYTECODE_SIZE_FROM_ROM_METHOD (romMethod);
130+ void *bytecodeStart = (void *)J9_BYTECODE_START_FROM_ROM_METHOD (romMethod);
131+
132+ bool isMethodCase = (key == (void *)romMethod);
133+ UDATA pc = 0 ;
134+
135+ if (!isMethodCase) {
136+ // Compute PC only if key points into bytecode range
137+ if ((uintptr_t )key >= (uintptr_t )bytecodeStart &&
138+ (uintptr_t )key < (uintptr_t )bytecodeStart + codeSize) {
139+ pc = (UDATA)((uintptr_t )key - (uintptr_t )bytecodeStart);
140+ }
141+ }
142+
143+ J9ROMClass *romClass = J9_CLASS_FROM_METHOD (method)->romClass ;
144+ J9ROMMethodInfo newInfo = {0 };
145+ newInfo.key = key;
146+
147+ // Always compute argbits
148+ j9localmap_ArgBitsForPC0 (romClass, romMethod, newInfo.argbits );
149+
150+ if (!isMethodCase && pc < codeSize) {
151+ // Stack map
152+ j9stackmap_StackBitsForPC (
153+ vm->portLibrary ,
154+ pc,
155+ romClass,
156+ romMethod,
157+ newInfo.stackmap ,
158+ J9_STACKMAP_CACHE_SLOTS << 5 ,
159+ NULL , NULL , NULL );
160+
161+ // Local map
162+ vm->localMapFunction (
163+ vm->portLibrary ,
164+ romClass,
165+ romMethod,
166+ pc,
167+ newInfo.localmap ,
168+ NULL , NULL , NULL );
169+ }
170+
171+ // Copy metadata
172+ newInfo.modifiers = romMethod->modifiers ;
173+ newInfo.argCount = J9_ARG_COUNT_FROM_ROM_METHOD (romMethod);
174+ newInfo.tempCount = J9_TEMP_COUNT_FROM_ROM_METHOD (romMethod);
175+
176+ // Insert into cache
177+ updateROMMethodInfoCache (vm, classLoader, &newInfo);
178+
179+ // Reflect it into the current walkState
180+ walkState->romMethodInfo = newInfo;
181+ }
182+
50183#if 0
184+
185+ void
186+ populateROMMethodInfo(J9StackWalkState *walkState, J9ROMMethod *romMethod, void *key)
187+ {
188+ initializeBasicROMMethodInfo(walkState, romMethod);
189+
190+ J9Method *method = walkState->method;
191+ J9ClassLoader *classLoader = J9_CLASS_FROM_METHOD(method)->classLoader;
192+ J9JavaVM *vm = walkState->javaVM;
193+ J9ROMMethodInfo cachedInfo = {0};
194+
195+ /* Try to find in cache first */
196+ bool found = checkROMMethodInfoCache(classLoader, key, &cachedInfo);
197+ if (found) {
198+ walkState->romMethodInfo = cachedInfo;
199+ return;
200+ }
201+
202+ /* Cache miss — build new info */
203+ J9ROMMethodInfo newInfo = {0};
204+ newInfo.key = key;
205+
206+ bool isMethodCase = (key == (void *)romMethod);
207+ J9ROMClass *romClass = J9_CLASS_FROM_METHOD(method)->romClass;
208+
209+ /* Always compute argbits */
210+ {
211+ UDATA argWords = (J9_ARG_COUNT_FROM_ROM_METHOD(romMethod) + 31) >> 5;
212+ if (argWords > J9_ARGBITS_CACHE_SLOTS) {
213+ argWords = J9_ARGBITS_CACHE_SLOTS;
214+ }
215+ j9localmap_ArgBitsForPC0(romClass, romMethod, newInfo.argbits);
216+ }
217+
218+ if (!isMethodCase) {
219+ /* PC case: compute stack and local maps */
220+ UDATA pc = (UDATA)((UDATA)key - (UDATA)J9_BYTECODE_START_FROM_ROM_METHOD(romMethod));
221+ /* Stack map */
222+ UDATA stackWords = (J9_STACKMAP_CACHE_SLOTS);
223+ if (stackWords > J9_STACKMAP_CACHE_SLOTS) {
224+ stackWords = J9_STACKMAP_CACHE_SLOTS;
225+ }
226+ j9stackmap_StackBitsForPC(
227+ vm->portLibrary,
228+ pc,
229+ romClass,
230+ romMethod,
231+ newInfo.stackmap,
232+ stackWords << 5,
233+ NULL, NULL, NULL);
234+
235+ /* Local map */
236+ UDATA localWords = (J9_TEMP_COUNT_FROM_ROM_METHOD(romMethod) +
237+ J9_ARG_COUNT_FROM_ROM_METHOD(romMethod) + 31) >> 5;
238+ if (localWords > J9_ARGBITS_CACHE_SLOTS) {
239+ localWords = J9_ARGBITS_CACHE_SLOTS;
240+ }
241+ vm->localMapFunction(
242+ vm->portLibrary,
243+ romClass,
244+ romMethod,
245+ pc,
246+ newInfo.localmap,
247+ NULL, NULL, NULL);
248+ }
249+
250+ /* Copy metadata */
251+ newInfo.modifiers = romMethod->modifiers;
252+ newInfo.argCount = J9_ARG_COUNT_FROM_ROM_METHOD(romMethod);
253+ newInfo.tempCount = J9_TEMP_COUNT_FROM_ROM_METHOD(romMethod);
254+
255+ /* Insert into cache */
256+ updateROMMethodInfoCache(vm, classLoader, &newInfo);
257+
258+ /* Reflect it into the current walkState */
259+ walkState->romMethodInfo = newInfo;
260+ }
261+
262+ void
263+ populateROMMethodInfo(J9StackWalkState *walkState, J9ROMMethod *romMethod, void *key)
264+ {
265+ initializeBasicROMMethodInfo(walkState, romMethod);
266+
51267 bool found = false;
52268 J9Method *method = walkState->method;
53269 J9ClassLoader *classLoader = J9_CLASS_FROM_METHOD(method)->classLoader;
@@ -74,10 +290,8 @@ populateROMMethodInfo(J9StackWalkState *walkState, J9ROMMethod *romMethod, void
74290
75291 omrthread_monitor_exit(mapCacheMutex);
76292 }
77- #endif
78293}
79294
80- #if 0
81295
82296/**
83297 * @brief Map cache hash function
0 commit comments