Skip to content

Commit daa9cc0

Browse files
authored
Merge pull request #20062 from tajila/pmr
(0.46.1) JIT: Detect in-place redefinition based on J9JITRedefinedClass
2 parents a9f26a2 + 82651fd commit daa9cc0

File tree

2 files changed

+87
-37
lines changed

2 files changed

+87
-37
lines changed

runtime/compiler/control/HookedByTheJit.cpp

Lines changed: 87 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,13 +2303,6 @@ void jitDiscardPendingCompilationsOfNatives(J9VMThread *vmThread, J9Class *clazz
23032303
compInfo->releaseCompilationLock();
23042304
}
23052305

2306-
static bool classesAreRedefinedInPlace()
2307-
{
2308-
if(TR::Options::getCmdLineOptions()->getOption(TR_EnableHCR))
2309-
return true;
2310-
else return false;
2311-
}
2312-
23132306
static bool methodsAreRedefinedInPlace()
23142307
{
23152308
// NOTE: making this return "true" will require careful thought.
@@ -2320,8 +2313,78 @@ static bool methodsAreRedefinedInPlace()
23202313
return false;
23212314
}
23222315

2323-
// Hack markers
2324-
#define VM_PASSES_SAME_CLASS_TWICE 1
2316+
namespace { // file-local
2317+
2318+
/**
2319+
* \brief A pair of corresponding classes related by redefinition,
2320+
* distinguished from each other in two ways: old/new and fresh/stale.
2321+
*
2322+
* NOTE: Neither set of terminology, i.e. neither old/new nor fresh/stale as
2323+
* used here, is necessarily consistent with terminology elsewhere in the VM.
2324+
*/
2325+
struct ElaboratedClassPair
2326+
{
2327+
/**
2328+
* \brief The original class that existed before HCR.
2329+
*
2330+
* This is always different from newClass.
2331+
*/
2332+
TR_OpaqueClassBlock *oldClass;
2333+
2334+
/**
2335+
* \brief The class that was created in order to carry out HCR.
2336+
*
2337+
* This is always different from oldClass.
2338+
*/
2339+
TR_OpaqueClassBlock *newClass;
2340+
2341+
/**
2342+
* \brief The class whose methods have the old bytecode.
2343+
*
2344+
* This is always different from freshClass. It is equal to newClass if the
2345+
* class has been redefined in-place, and oldClass otherwise.
2346+
*/
2347+
TR_OpaqueClassBlock *staleClass;
2348+
2349+
/**
2350+
* \brief The class whose methods have the new bytecode.
2351+
*
2352+
* This is always different from staleClass. It is equal to oldClass if the
2353+
* class has been redefined in-place, and newClass otherwise.
2354+
*/
2355+
TR_OpaqueClassBlock *freshClass;
2356+
};
2357+
2358+
void setElaboratedClassPair(ElaboratedClassPair *ecp, J9JITRedefinedClass *classPair)
2359+
{
2360+
// The VM tells us the old J9Class and the fresh one (which here it calls "new").
2361+
J9Class *oldJ9Class = classPair->oldClass;
2362+
J9Class *freshJ9Class = classPair->newClass;
2363+
J9Class *staleJ9Class = freshJ9Class->replacedClass;
2364+
2365+
ecp->oldClass = TR::Compiler->cls.convertClassPtrToClassOffset(oldJ9Class);
2366+
ecp->freshClass = TR::Compiler->cls.convertClassPtrToClassOffset(freshJ9Class);
2367+
ecp->staleClass = TR::Compiler->cls.convertClassPtrToClassOffset(staleJ9Class);
2368+
2369+
TR_ASSERT_FATAL(
2370+
ecp->freshClass != ecp->staleClass,
2371+
"fresh and stale classes are the same: %p",
2372+
ecp->freshClass);
2373+
2374+
TR_ASSERT_FATAL(
2375+
ecp->oldClass == ecp->freshClass || ecp->oldClass == ecp->staleClass,
2376+
"oldClass %p matches neither freshClass %p nor staleClass %p",
2377+
ecp->oldClass,
2378+
ecp->freshClass,
2379+
ecp->staleClass);
2380+
2381+
// Don't try to predict whether classes should be redefined in-place.
2382+
// Instead just check whether this one was in fact redefined in-place.
2383+
ecp->newClass =
2384+
ecp->oldClass == ecp->freshClass ? ecp->staleClass : ecp->freshClass;
2385+
}
2386+
2387+
} // anonymous namespace
23252388

23262389
#if (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64))
23272390
void jitClassesRedefined(J9VMThread * currentThread, UDATA classCount, J9JITRedefinedClass *classList, UDATA extensionsUsed)
@@ -2343,23 +2406,19 @@ void jitClassesRedefined(J9VMThread * currentThread, UDATA classCount, J9JITRede
23432406

23442407
TR_RuntimeAssumptionTable * rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();
23452408

2346-
TR_OpaqueClassBlock *oldClass, *newClass;
2347-
J9Method *oldMethod, *newMethod;
2409+
ElaboratedClassPair elaboratedPair = {};
23482410

2349-
// A few definitions. In the jit's terminology:
2350-
// The "stale method" is the one that points at the old bytecodes from before the hot swap.
2351-
// The "stale class" is the one that points at the stale methods.
2352-
// The "old class" is the j9class struct that existed before the hot swap.
2353-
// The "new class" is the one created in response to the hot swap.
2354-
//
2355-
// NOTE: THIS MAY NOT MATCH THE VM'S TERMINOLOGY!
2356-
//
2357-
// Here we define various aliases so we can freely use the terminology we want.
2358-
//
2359-
TR_OpaqueClassBlock *&freshClass = classesAreRedefinedInPlace()? oldClass : newClass;
2360-
TR_OpaqueClassBlock *&staleClass = classesAreRedefinedInPlace()? newClass : oldClass;
2361-
J9Method *&freshMethod = methodsAreRedefinedInPlace()? oldMethod : newMethod;
2362-
J9Method *&staleMethod = methodsAreRedefinedInPlace()? newMethod : oldMethod;
2411+
// Local aliases to avoid elaboratedPair.someClass everywhere.
2412+
// These will reflect changes to elaboratedPair.
2413+
TR_OpaqueClassBlock * const &oldClass = elaboratedPair.oldClass;
2414+
TR_OpaqueClassBlock * const &newClass = elaboratedPair.newClass;
2415+
TR_OpaqueClassBlock * const &staleClass = elaboratedPair.staleClass;
2416+
TR_OpaqueClassBlock * const &freshClass = elaboratedPair.freshClass;
2417+
2418+
// Here old/new and stale/fresh have the same meaning as in ElaboratedClassPair.
2419+
J9Method *oldMethod, *newMethod;
2420+
J9Method *&freshMethod = methodsAreRedefinedInPlace() ? oldMethod : newMethod;
2421+
J9Method *&staleMethod = methodsAreRedefinedInPlace() ? newMethod : oldMethod;
23632422

23642423
int methodCount;
23652424
J9JITMethodEquivalence *methodList;
@@ -2375,11 +2434,7 @@ void jitClassesRedefined(J9VMThread * currentThread, UDATA classCount, J9JITRede
23752434
{
23762435
for (i = 0; i < classCount; i++)
23772436
{
2378-
freshClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(classPair->newClass);
2379-
if (VM_PASSES_SAME_CLASS_TWICE)
2380-
staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(((J9Class*)freshClass)->replacedClass);
2381-
else
2382-
staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(classPair->oldClass);
2437+
setElaboratedClassPair(&elaboratedPair, classPair); // affects oldClass, etc.
23832438
methodCount = classPair->methodCount;
23842439
methodList = classPair->methodList;
23852440

@@ -2472,11 +2527,8 @@ void jitClassesRedefined(J9VMThread * currentThread, UDATA classCount, J9JITRede
24722527
deserializer->invalidateClass(currentThread, classPair->oldClass);
24732528
}
24742529
#endif
2475-
freshClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(classPair->newClass);
2476-
if (VM_PASSES_SAME_CLASS_TWICE)
2477-
staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(((J9Class*)freshClass)->replacedClass);
2478-
else
2479-
staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(classPair->oldClass);
2530+
2531+
setElaboratedClassPair(&elaboratedPair, classPair); // affects oldClass, etc.
24802532
methodCount = classPair->methodCount;
24812533
methodList = classPair->methodList;
24822534

test/functional/JavaAgentTest/playlist.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,6 @@
308308
<variation>Mode107</variation>
309309
</variations>
310310
<command>$(JAVA_COMMAND) $(JVM_OPTIONS) \
311-
-XX:+EnableExtendedHCR \
312311
-javaagent:$(Q)$(TEST_RESROOT)$(D)javaagenttest.jar$(Q) \
313312
-cp $(Q)$(RESOURCES_DIR)$(P)$(TESTNG)$(P)$(LIB_DIR)$(D)asm-all.jar$(Q) \
314313
org.testng.TestNG -d $(REPORTDIR) $(Q)$(TEST_RESROOT)$(D)testng.xml$(Q) -testnames RefreshGCCache_NoBCI_Test \
@@ -362,7 +361,6 @@
362361
<variation>Mode107</variation>
363362
</variations>
364363
<command>$(JAVA_COMMAND) $(JVM_OPTIONS) \
365-
-XX:+EnableExtendedHCR \
366364
-javaagent:$(Q)$(TEST_RESROOT)$(D)javaagenttest.jar$(Q) \
367365
-cp $(Q)$(RESOURCES_DIR)$(P)$(TESTNG)$(P)$(LIB_DIR)$(D)asm-all.jar$(Q) \
368366
org.testng.TestNG -d $(REPORTDIR) $(Q)$(TEST_RESROOT)$(D)testng.xml$(Q) -testnames RefreshGCCache_FastHCR_Test \

0 commit comments

Comments
 (0)