Skip to content

Commit

Permalink
Merge pull request eclipse-openj9#15 from cathyzhyi/monitor-api-valha…
Browse files Browse the repository at this point in the history
…lla-sandbox

Update monitor elimination to use new monitor API
  • Loading branch information
Charlmzz authored Mar 26, 2020
2 parents 72ad247 + f3a4527 commit 619b5ea
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 75 deletions.
13 changes: 10 additions & 3 deletions runtime/compiler/optimizer/MonitorElimination.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2019 IBM Corp. and others
* Copyright (c) 2000, 2020 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -1566,10 +1566,17 @@ void TR::MonitorElimination::transformMonitorsIntoTMRegions()
TR::Node *monitorObject = TR::Node::copy(monitor->getMonitorNode()->getFirstChild());
monitorObject->setReferenceCount(0);
TR::Node *tstartNode = TR::Node::createWithRoomForFive(TR::tstart, persistentFailNode, transientFailNode,fallThroughNode,monitorObject);
#ifdef OLD_MONITOR_API
if(monitor->getMonitorNode()->hasMonitorClassInNode())
tstartNode->setMonitorClassInNode(monitor->getMonitorNode()->getMonitorClassInNode());
tstartNode->setMonitorClassInNode(monitor->getMonitorNode()->getMonitorClassInNode());
else
tstartNode->setMonitorClassInNode(NULL);
tstartNode->setMonitorClassInNode(NULL);
#else
if(monitor->getMonitorNode()->hasMonitorInfoInNode())
tstartNode->setMonitorInfoInNode(monitor->getMonitorNode()->getMonitorInfoInNode());
else
tstartNode->setMonitorInfoInNode(NULL);
#endif
tstartNode->setSymbolReference(comp()->getSymRefTab()->findOrCreateTransactionEntrySymbolRef(comp()->getMethodSymbol()));
TR::TreeTop *tstarttt = TR::TreeTop::create(comp(),tstartNode,NULL,NULL);

Expand Down
87 changes: 27 additions & 60 deletions runtime/compiler/x/codegen/J9TreeEvaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,17 +132,14 @@ inline void generateLoadJ9Class(TR::Node* node, TR::Register* j9class, TR::Regis
switch (opValue)
{
case TR::checkcastAndNULLCHK:
case TR::monent:
case TR::monexit:
needsNULLCHK = true;
break;
case TR::icall: // TR_checkAssignable
return; // j9class register already holds j9class
case TR::checkcast:
case TR::instanceof:
break;
default:
TR_ASSERT(false, "Unexpected opCode for generateLoadJ9Class %s.", node->getOpCode().getName());
TR_ASSERT(opValue == TR::checkcast ||
opValue == TR::instanceof,
"Unexpected opCode for generateLoadJ9Class %s.", node->getOpCode().getName());
break;
}
}
Expand Down Expand Up @@ -1871,7 +1868,7 @@ TR::Register *J9::X86::TreeEvaluator::evaluateNULLCHKWithPossibleResolve(
{
needExplicitCheck = false;
TR::MemoryReference *memRef = NULL;
if (TR::Compiler->om.compressedReferenceShift() > 0
if (TR::Compiler->om.compressedReferenceShift() > 0
&& firstChild->getType() == TR::Address
&& firstChild->getOpCode().hasSymbolReference()
&& firstChild->getSymbol()->isCollectedReference())
Expand Down Expand Up @@ -4511,31 +4508,6 @@ void J9::X86::TreeEvaluator::transactionalMemoryJITMonitorEntry(TR::Node
cg->stopUsingRegister(counterReg);
}

TR_YesNoMaybe static isMonitorValueType(TR::Node *node, TR::CodeGenerator *cg)
{
J9Class * monitorClass = (J9Class *) cg->getMonClass(node);
return monitorClass == NULL? TR_maybe: (J9_IS_J9CLASS_VALUETYPE(monitorClass) ? TR_yes: TR_no);
}

void
J9::X86::TreeEvaluator::monitorEnterOrExitForValueTypeClass(
TR::Node *node,
TR::LabelSymbol *snippetLabel,
TR::CodeGenerator *cg)
{
if (isMonitorValueType(node, cg) != TR_maybe)
return;
TR::Register *objectReg = cg->evaluate(node->getFirstChild());
auto j9classReg = cg->allocateRegister();
generateLoadJ9Class(node, j9classReg, objectReg, cg);
TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe());
auto classFlagsMR = generateX86MemoryReference(j9classReg, (uintptr_t)(fej9->getOffsetOfClassFlags()), cg);
static_assert((uint32_t) J9ClassIsValueType < USHRT_MAX);
//test [j9classReg.classFlags], J9ClassIsValueType
generateMemImmInstruction(TEST2MemImm2, node, classFlagsMR, J9ClassIsValueType, cg);
generateLabelInstruction(JNE4, node, snippetLabel, cg);
}

TR::Register *
J9::X86::TreeEvaluator::VMmonentEvaluator(
TR::Node *node,
Expand All @@ -4546,22 +4518,20 @@ J9::X86::TreeEvaluator::VMmonentEvaluator(
// appropriate excepting instruction we must make sure to reset the
// excepting instruction since our children may have set it.
//
TR::Compilation *comp = cg->comp();
TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe());
static const char *noInline = feGetEnv("TR_NoInlineMonitor");
static const char *firstMonEnt = feGetEnv("TR_FirstMonEnt");
static int32_t monEntCount = 0;
static const char *firstMonEnt = feGetEnv("TR_FirstMonEnt");
static const char *doCmpFirst = feGetEnv("TR_AddCMPBeforeCMPXCHG");
bool reservingLock = false;
bool normalLockPreservingReservation = false;
bool dummyMethodMonitor = false;

static const char *doCmpFirst = feGetEnv("TR_AddCMPBeforeCMPXCHG");
TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe());
TR::Compilation *comp = cg->comp();

int lwOffset = fej9->getByteOffsetToLockword((TR_OpaqueClassBlock *) cg->getMonClass(node));
if (comp->getOption(TR_MimicInterpreterFrameShape) ||
(comp->getOption(TR_FullSpeedDebug) && node->isSyncMethodMonitor()) ||
noInline ||
TR::Compiler->om.areValueTypesEnabled() && isMonitorValueType(node, cg) == TR_yes ||
comp->getOption(TR_DisableInlineMonEnt) ||
(firstMonEnt && (*firstMonEnt-'0') > monEntCount++))
{
Expand Down Expand Up @@ -4626,8 +4596,6 @@ J9::X86::TreeEvaluator::VMmonentEvaluator(
TR::SymbolReference *originalNodeSymRef = NULL;

TR::Node *helperCallNode = node;
if (TR::Compiler->om.areValueTypesEnabled())
monitorEnterOrExitForValueTypeClass(node, snippetLabel, cg);
if (comp->getOption(TR_ReservingLocks))
{
// About to change the node's symref... store the original.
Expand Down Expand Up @@ -5156,10 +5124,8 @@ void J9::X86::TreeEvaluator::generateValueTracingCode(
generateMemRegInstruction(SMemReg(), node, generateX86MemoryReference(vmThreadReg, vmThreadCursor, cg), scratchReg, cg);
}

TR::Register
*J9::X86::TreeEvaluator::VMmonexitEvaluator(
TR::Node *node,
TR::CodeGenerator *cg)
TR::Register *J9::X86::TreeEvaluator::VMmonexitEvaluator(TR::Node *node,
TR::CodeGenerator *cg)
{
// If there is a NULLCHK above this node it will be expecting us to set
// up the excepting instruction. If we are not going to inline an
Expand All @@ -5169,17 +5135,16 @@ TR::Register
TR::Compilation *comp = cg->comp();
TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe());
static const char *noInline = feGetEnv("TR_NoInlineMonitor");
static const char *firstMonExit = feGetEnv("TR_FirstMonExit");
static int32_t monExitCount = 0;
static const char *firstMonExit = feGetEnv("TR_FirstMonExit");
bool reservingLock = false;
bool normalLockPreservingReservation = false;
bool dummyMethodMonitor = false;
bool gen64BitInstr = cg->comp()->target().is64Bit() && !fej9->generateCompressedLockWord();
int lwOffset = fej9->getByteOffsetToLockword((TR_OpaqueClassBlock *) cg->getMonClass(node));

int lwOffset = fej9->getByteOffsetToLockword((TR_OpaqueClassBlock *) cg->getMonClass(node));
if ((comp->getOption(TR_MimicInterpreterFrameShape) /*&& !comp->getOption(TR_EnableLiveMonitorMetadata)*/) ||
noInline ||
isMonitorValueType(node, cg) == TR_yes ||
comp->getOption(TR_DisableInlineMonExit) ||
(firstMonExit && (*firstMonExit-'0') > monExitCount++))
{
Expand Down Expand Up @@ -5227,10 +5192,7 @@ TR::Register

TR::LabelSymbol *startLabel = generateLabelSymbol(cg);
TR::LabelSymbol *fallThru = generateLabelSymbol(cg);
// Create the monitor exit snippet
TR::LabelSymbol *snippetLabel = generateLabelSymbol(cg);
if (TR::Compiler->om.areValueTypesEnabled())
monitorEnterOrExitForValueTypeClass(node, snippetLabel, cg);

#if !defined(J9VM_OPT_REAL_TIME_LOCKING_SUPPORT)
// Now that the object reference has been generated, see if this is the end
// of a small synchronized block.
Expand Down Expand Up @@ -5283,6 +5245,7 @@ TR::Register
TR::LabelSymbol *fallThruFromMonitorLookupCacheLabel = generateLabelSymbol(cg);

#if defined(J9VM_OPT_REAL_TIME_LOCKING_SUPPORT)
TR::LabelSymbol *snippetLabel = generateLabelSymbol(cg);
TR::LabelSymbol *decCountLabel = generateLabelSymbol(cg);

unlockedReg = cg->allocateRegister();
Expand Down Expand Up @@ -5380,6 +5343,10 @@ TR::Register

#else

// Create the monitor exit snippet
//
TR::LabelSymbol *snippetLabel = generateLabelSymbol(cg);

if (lwOffset <= 0)
{
generateRegImmInstruction(CMP4RegImm4, node, objectClassReg, 0, cg);
Expand Down Expand Up @@ -12696,7 +12663,7 @@ TR::Register *
J9::X86::TreeEvaluator::generateConcurrentScavengeSequence(TR::Node *node, TR::CodeGenerator *cg)
{
TR::Register* object = TR::TreeEvaluator::performHeapLoadWithReadBarrier(node, cg);

if (!node->getSymbolReference()->isUnresolved() &&
(node->getSymbolReference()->getSymbol()->getKind() == TR::Symbol::IsShadow) &&
(node->getSymbolReference()->getCPIndex() >= 0) &&
Expand Down Expand Up @@ -12745,7 +12712,7 @@ J9::X86::TreeEvaluator::irdbariEvaluator(TR::Node *node, TR::CodeGenerator *cg)
}
}

// Note: For indirect rdbar nodes, the first child (sideEffectNode) is also used by the
// Note: For indirect rdbar nodes, the first child (sideEffectNode) is also used by the
// load evaluator. The load evaluator will also evaluate+decrement it. In order to avoid double
// decrementing the node we skip doing it here and let the load evaluator do it.
return resultReg;
Expand Down Expand Up @@ -12813,7 +12780,7 @@ J9::X86::TreeEvaluator::ardbariEvaluator(TR::Node *node, TR::CodeGenerator *cg)
node->setRegister(resultReg);
}

// Note: For indirect rdbar nodes, the first child (sideEffectNode) is also used by the
// Note: For indirect rdbar nodes, the first child (sideEffectNode) is also used by the
// load evaluator. The load evaluator will also evaluate+decrement it. In order to avoid double
// decrementing the node we skip doing it here and let the load evaluator do it.
return resultReg;
Expand All @@ -12833,7 +12800,7 @@ TR::Register *J9::X86::TreeEvaluator::fwrtbarEvaluator(TR::Node *node, TR::CodeG
TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);
}

// Note: The reference count for valueReg's node is not decremented here because the
// Note: The reference count for valueReg's node is not decremented here because the
// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here
// to avoid double decrementing.
cg->decReferenceCount(sideEffectNode);
Expand All @@ -12854,7 +12821,7 @@ TR::Register *J9::X86::TreeEvaluator::fwrtbariEvaluator(TR::Node *node, TR::Code
TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);
}

// Note: The reference count for valueReg's node is not decremented here because the
// Note: The reference count for valueReg's node is not decremented here because the
// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here
// to avoid double decrementing.
cg->decReferenceCount(sideEffectNode);
Expand All @@ -12876,7 +12843,7 @@ TR::Register *J9::X86::i386::TreeEvaluator::dwrtbarEvaluator(TR::Node *node, TR:
TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);
}

// Note: The reference count for valueReg's node is not decremented here because the
// Note: The reference count for valueReg's node is not decremented here because the
// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here
// to avoid double decrementing.
cg->decReferenceCount(sideEffectNode);
Expand All @@ -12897,7 +12864,7 @@ TR::Register *J9::X86::i386::TreeEvaluator::dwrtbariEvaluator(TR::Node *node, TR
TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);
}

// Note: The reference count for valueReg's node is not decremented here because the
// Note: The reference count for valueReg's node is not decremented here because the
// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here
// to avoid double decrementing.
cg->decReferenceCount(sideEffectNode);
Expand All @@ -12920,7 +12887,7 @@ TR::Register *J9::X86::AMD64::TreeEvaluator::dwrtbarEvaluator(TR::Node *node, TR
TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);
}

// Note: The reference count for valueReg's node is not decremented here because the
// Note: The reference count for valueReg's node is not decremented here because the
// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here
// to avoid double decrementing.
cg->decReferenceCount(sideEffectNode);
Expand All @@ -12941,7 +12908,7 @@ TR::Register *J9::X86::AMD64::TreeEvaluator::dwrtbariEvaluator(TR::Node *node, T
TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);
}

// Note: The reference count for valueReg's node is not decremented here because the
// Note: The reference count for valueReg's node is not decremented here because the
// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here
// to avoid double decrementing.
cg->decReferenceCount(sideEffectNode);
Expand Down
12 changes: 0 additions & 12 deletions runtime/compiler/x/codegen/J9TreeEvaluator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,6 @@ class OMR_EXTENSIBLE TreeEvaluator: public J9::TreeEvaluator
static TR::Register *checkcastinstanceofEvaluator(TR::Node *node, TR::CodeGenerator *cg);
static void asyncGCMapCheckPatching(TR::Node *node, TR::CodeGenerator *cg, TR::LabelSymbol *snippetLabel);
static void inlineRecursiveMonitor(TR::Node *node, TR::CodeGenerator *cg, TR::LabelSymbol *startLabel, TR::LabelSymbol *snippetLabel, TR::LabelSymbol *JITMonitorEnterSnippetLabel, TR::Register *objectReg, int lwoffset, TR::LabelSymbol *snippetRestartLabel, bool reservingLock);

/*
* \brief Generates the sequence to handle the cases where the monitor object is value type
*
* Call the VM helper if it's detected at runtime that the monitor object is value type.
* The VM helper throws appropriate IllegalMonitorStateException for us.
*
* \notes
* This method only handles the cases where, at compile time, it's unknown whether the
* object is reference type or value type.
*/
static void monitorEnterOrExitForValueTypeClass(TR::Node *node, TR::LabelSymbol *snippetLabel, TR::CodeGenerator *cg);
static void transactionalMemoryJITMonitorEntry(TR::Node *node, TR::CodeGenerator *cg, TR::LabelSymbol *startLabel, TR::LabelSymbol *snippetLabel, TR::LabelSymbol *JITMonitorEnterSnippetLabel, TR::Register *objectReg, int lwoffset);
static void generateValueTracingCode(TR::Node *node, TR::Register *vmThreadReg, TR::Register *scratchReg, TR::Register *valueRegHigh, TR::Register *valueRegLow, TR::CodeGenerator *cg);
static void generateValueTracingCode(TR::Node *node, TR::Register *vmThreadReg, TR::Register *scratchReg, TR::Register *valueReg, TR::CodeGenerator *cg);
Expand Down

0 comments on commit 619b5ea

Please sign in to comment.