@@ -2326,13 +2326,6 @@ void jitDiscardPendingCompilationsOfNatives(J9VMThread *vmThread, J9Class *clazz
2326
2326
compInfo->releaseCompilationLock ();
2327
2327
}
2328
2328
2329
- static bool classesAreRedefinedInPlace ()
2330
- {
2331
- if (TR::Options::getCmdLineOptions ()->getOption (TR_EnableHCR))
2332
- return true ;
2333
- else return false ;
2334
- }
2335
-
2336
2329
static bool methodsAreRedefinedInPlace ()
2337
2330
{
2338
2331
// NOTE: making this return "true" will require careful thought.
@@ -2343,8 +2336,78 @@ static bool methodsAreRedefinedInPlace()
2343
2336
return false ;
2344
2337
}
2345
2338
2346
- // Hack markers
2347
- #define VM_PASSES_SAME_CLASS_TWICE 1
2339
+ namespace { // file-local
2340
+
2341
+ /* *
2342
+ * \brief A pair of corresponding classes related by redefinition,
2343
+ * distinguished from each other in two ways: old/new and fresh/stale.
2344
+ *
2345
+ * NOTE: Neither set of terminology, i.e. neither old/new nor fresh/stale as
2346
+ * used here, is necessarily consistent with terminology elsewhere in the VM.
2347
+ */
2348
+ struct ElaboratedClassPair
2349
+ {
2350
+ /* *
2351
+ * \brief The original class that existed before HCR.
2352
+ *
2353
+ * This is always different from newClass.
2354
+ */
2355
+ TR_OpaqueClassBlock *oldClass;
2356
+
2357
+ /* *
2358
+ * \brief The class that was created in order to carry out HCR.
2359
+ *
2360
+ * This is always different from oldClass.
2361
+ */
2362
+ TR_OpaqueClassBlock *newClass;
2363
+
2364
+ /* *
2365
+ * \brief The class whose methods have the old bytecode.
2366
+ *
2367
+ * This is always different from freshClass. It is equal to newClass if the
2368
+ * class has been redefined in-place, and oldClass otherwise.
2369
+ */
2370
+ TR_OpaqueClassBlock *staleClass;
2371
+
2372
+ /* *
2373
+ * \brief The class whose methods have the new bytecode.
2374
+ *
2375
+ * This is always different from staleClass. It is equal to oldClass if the
2376
+ * class has been redefined in-place, and newClass otherwise.
2377
+ */
2378
+ TR_OpaqueClassBlock *freshClass;
2379
+ };
2380
+
2381
+ void setElaboratedClassPair (ElaboratedClassPair *ecp, J9JITRedefinedClass *classPair)
2382
+ {
2383
+ // The VM tells us the old J9Class and the fresh one (which here it calls "new").
2384
+ J9Class *oldJ9Class = classPair->oldClass ;
2385
+ J9Class *freshJ9Class = classPair->newClass ;
2386
+ J9Class *staleJ9Class = freshJ9Class->replacedClass ;
2387
+
2388
+ ecp->oldClass = TR::Compiler->cls .convertClassPtrToClassOffset (oldJ9Class);
2389
+ ecp->freshClass = TR::Compiler->cls .convertClassPtrToClassOffset (freshJ9Class);
2390
+ ecp->staleClass = TR::Compiler->cls .convertClassPtrToClassOffset (staleJ9Class);
2391
+
2392
+ TR_ASSERT_FATAL (
2393
+ ecp->freshClass != ecp->staleClass ,
2394
+ " fresh and stale classes are the same: %p" ,
2395
+ ecp->freshClass );
2396
+
2397
+ TR_ASSERT_FATAL (
2398
+ ecp->oldClass == ecp->freshClass || ecp->oldClass == ecp->staleClass ,
2399
+ " oldClass %p matches neither freshClass %p nor staleClass %p" ,
2400
+ ecp->oldClass ,
2401
+ ecp->freshClass ,
2402
+ ecp->staleClass );
2403
+
2404
+ // Don't try to predict whether classes should be redefined in-place.
2405
+ // Instead just check whether this one was in fact redefined in-place.
2406
+ ecp->newClass =
2407
+ ecp->oldClass == ecp->freshClass ? ecp->staleClass : ecp->freshClass ;
2408
+ }
2409
+
2410
+ } // anonymous namespace
2348
2411
2349
2412
#if (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64))
2350
2413
void jitClassesRedefined (J9VMThread * currentThread, UDATA classCount, J9JITRedefinedClass *classList, UDATA extensionsUsed)
@@ -2366,23 +2429,19 @@ void jitClassesRedefined(J9VMThread * currentThread, UDATA classCount, J9JITRede
2366
2429
2367
2430
TR_RuntimeAssumptionTable * rat = compInfo->getPersistentInfo ()->getRuntimeAssumptionTable ();
2368
2431
2369
- TR_OpaqueClassBlock *oldClass, *newClass;
2370
- J9Method *oldMethod, *newMethod;
2432
+ ElaboratedClassPair elaboratedPair = {};
2371
2433
2372
- // A few definitions. In the jit's terminology:
2373
- // The "stale method" is the one that points at the old bytecodes from before the hot swap.
2374
- // The "stale class" is the one that points at the stale methods.
2375
- // The "old class" is the j9class struct that existed before the hot swap.
2376
- // The "new class" is the one created in response to the hot swap.
2377
- //
2378
- // NOTE: THIS MAY NOT MATCH THE VM'S TERMINOLOGY!
2379
- //
2380
- // Here we define various aliases so we can freely use the terminology we want.
2381
- //
2382
- TR_OpaqueClassBlock *&freshClass = classesAreRedefinedInPlace ()? oldClass : newClass;
2383
- TR_OpaqueClassBlock *&staleClass = classesAreRedefinedInPlace ()? newClass : oldClass;
2384
- J9Method *&freshMethod = methodsAreRedefinedInPlace ()? oldMethod : newMethod;
2385
- J9Method *&staleMethod = methodsAreRedefinedInPlace ()? newMethod : oldMethod;
2434
+ // Local aliases to avoid elaboratedPair.someClass everywhere.
2435
+ // These will reflect changes to elaboratedPair.
2436
+ TR_OpaqueClassBlock * const &oldClass = elaboratedPair.oldClass ;
2437
+ TR_OpaqueClassBlock * const &newClass = elaboratedPair.newClass ;
2438
+ TR_OpaqueClassBlock * const &staleClass = elaboratedPair.staleClass ;
2439
+ TR_OpaqueClassBlock * const &freshClass = elaboratedPair.freshClass ;
2440
+
2441
+ // Here old/new and stale/fresh have the same meaning as in ElaboratedClassPair.
2442
+ J9Method *oldMethod, *newMethod;
2443
+ J9Method *&freshMethod = methodsAreRedefinedInPlace () ? oldMethod : newMethod;
2444
+ J9Method *&staleMethod = methodsAreRedefinedInPlace () ? newMethod : oldMethod;
2386
2445
2387
2446
int methodCount;
2388
2447
J9JITMethodEquivalence *methodList;
@@ -2398,11 +2457,7 @@ void jitClassesRedefined(J9VMThread * currentThread, UDATA classCount, J9JITRede
2398
2457
{
2399
2458
for (i = 0 ; i < classCount; i++)
2400
2459
{
2401
- freshClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset (classPair->newClass );
2402
- if (VM_PASSES_SAME_CLASS_TWICE)
2403
- staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset (((J9Class*)freshClass)->replacedClass );
2404
- else
2405
- staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset (classPair->oldClass );
2460
+ setElaboratedClassPair (&elaboratedPair, classPair); // affects oldClass, etc.
2406
2461
methodCount = classPair->methodCount ;
2407
2462
methodList = classPair->methodList ;
2408
2463
@@ -2495,11 +2550,8 @@ void jitClassesRedefined(J9VMThread * currentThread, UDATA classCount, J9JITRede
2495
2550
deserializer->invalidateClass (currentThread, classPair->oldClass );
2496
2551
}
2497
2552
#endif
2498
- freshClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset (classPair->newClass );
2499
- if (VM_PASSES_SAME_CLASS_TWICE)
2500
- staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset (((J9Class*)freshClass)->replacedClass );
2501
- else
2502
- staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset (classPair->oldClass );
2553
+
2554
+ setElaboratedClassPair (&elaboratedPair, classPair); // affects oldClass, etc.
2503
2555
methodCount = classPair->methodCount ;
2504
2556
methodList = classPair->methodList ;
2505
2557
0 commit comments