From 81af61afe36347640325a04c0084d4873624aae6 Mon Sep 17 00:00:00 2001 From: Annabelle Huo Date: Mon, 7 Dec 2020 13:52:52 -0500 Subject: [PATCH] Power: Handle monitor enter/exit on value based instances Related to JEP390 Signed-off-by: Annabelle Huo --- .../compiler/p/codegen/J9TreeEvaluator.cpp | 32 +++++++++++-------- .../compiler/p/codegen/J9TreeEvaluator.hpp | 2 +- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/runtime/compiler/p/codegen/J9TreeEvaluator.cpp b/runtime/compiler/p/codegen/J9TreeEvaluator.cpp index 37979c55d67..0bd9f125b74 100644 --- a/runtime/compiler/p/codegen/J9TreeEvaluator.cpp +++ b/runtime/compiler/p/codegen/J9TreeEvaluator.cpp @@ -5314,7 +5314,8 @@ TR::Register *J9::Power::TreeEvaluator::VMmonexitEvaluator(TR::Node *node, TR::C if (comp->getOption(TR_OptimizeForSpace) || comp->getOption(TR_FullSpeedDebug) || - (TR::Compiler->om.areValueTypesEnabled() && cg->isMonitorValueType(node) == TR_yes) || + ((TR::Compiler->om.areValueTypesEnabled() || TR::Compiler->om.areValueBasedMonitorChecksEnabled()) && + (cg->isMonitorValueBasedOrValueType(node) == TR_yes)) || comp->getOption(TR_DisableInlineMonExit)) { TR::ILOpCodes opCode = node->getOpCodeValue(); @@ -5386,10 +5387,11 @@ TR::Register *J9::Power::TreeEvaluator::VMmonexitEvaluator(TR::Node *node, TR::C generateLabelInstruction(cg, TR::InstOpCode::label, node, startLabel, NULL); startLabel->setStartInternalControlFlow(); - //If object is not known to be value type at compile time, check at run time - if (TR::Compiler->om.areValueTypesEnabled() && cg->isMonitorValueType(node) == TR_maybe) + //If object is not known to be value type or value based class at compile time, check at run time + if ((TR::Compiler->om.areValueTypesEnabled() || TR::Compiler->om.areValueBasedMonitorChecksEnabled()) + && (cg->isMonitorValueBasedOrValueType(node) == TR_maybe)) { - generateCheckForValueTypeMonitorEnterOrExit(node, callLabel, objReg, objectClassReg, tempReg, condReg, cg); + generateCheckForValueMonitorEnterOrExit(node, callLabel, objReg, objectClassReg, tempReg, threadReg, condReg, cg, J9_CLASS_DISALLOWS_LOCKING_FLAGS); } bool simpleLocking = false; @@ -7718,7 +7720,7 @@ static bool simpleReadMonitor(TR::Node *node, TR::CodeGenerator *cg, TR::Node *o return true; } -void J9::Power::TreeEvaluator::generateCheckForValueTypeMonitorEnterOrExit(TR::Node *node, TR::LabelSymbol *helperCallLabel, TR::Register *objReg, TR::Register *objectClassReg, TR::Register *tempReg, TR::Register *condReg, TR::CodeGenerator *cg) +void J9::Power::TreeEvaluator::generateCheckForValueMonitorEnterOrExit(TR::Node *node, TR::LabelSymbol *helperCallLabel, TR::Register *objReg, TR::Register *objectClassReg, TR::Register *temp1Reg, TR::Register *temp2Reg, TR::Register *condReg, TR::CodeGenerator *cg, int32_t classFlag) { //get class of object generateLoadJ9Class(node, objectClassReg, objReg, cg); @@ -7727,11 +7729,13 @@ void J9::Power::TreeEvaluator::generateCheckForValueTypeMonitorEnterOrExit(TR::N TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe()); TR::MemoryReference *classFlagsMemRef = TR::MemoryReference::createWithDisplacement(cg, objectClassReg, static_cast(fej9->getOffsetOfClassFlags()), 4); - //check J9ClassIsValueType flag - generateTrg1MemInstruction(cg,TR::InstOpCode::lwz, node, tempReg, classFlagsMemRef); - generateTrg1Src1ImmInstruction(cg, TR::InstOpCode::andi_r, node, tempReg, tempReg, condReg, J9ClassIsValueType); + //check J9_CLASS_DISALLOWS_LOCKING_FLAGS (J9ClassIsValueType | J9ClassIsValueBased) + generateTrg1MemInstruction(cg, TR::InstOpCode::lwz, node, temp1Reg, classFlagsMemRef); - //If obj is value type, call VM helper and throw IllegalMonitorState exception, else continue as usual + loadConstant(cg, node, classFlag, temp2Reg); + generateTrg1Src2Instruction(cg, TR::InstOpCode::and_r, node, temp1Reg, temp1Reg, temp2Reg); + + //If obj is value type or value based class instance, call VM helper and throw IllegalMonitorState exception, else continue as usual generateConditionalBranchInstruction(cg, TR::InstOpCode::bne, node, helperCallLabel, condReg); } @@ -7745,7 +7749,8 @@ TR::Register *J9::Power::TreeEvaluator::VMmonentEvaluator(TR::Node *node, TR::Co if (comp->getOption(TR_OptimizeForSpace) || comp->getOption(TR_MimicInterpreterFrameShape) || (comp->getOption(TR_FullSpeedDebug) && node->isSyncMethodMonitor()) || - (TR::Compiler->om.areValueTypesEnabled() && cg->isMonitorValueType(node) == TR_yes) || + ((TR::Compiler->om.areValueTypesEnabled() || TR::Compiler->om.areValueBasedMonitorChecksEnabled()) && + (cg->isMonitorValueBasedOrValueType(node) == TR_yes)) || comp->getOption(TR_DisableInlineMonEnt)) { TR::ILOpCodes opCode = node->getOpCodeValue(); @@ -7817,10 +7822,11 @@ TR::Register *J9::Power::TreeEvaluator::VMmonentEvaluator(TR::Node *node, TR::Co generateLabelInstruction(cg, TR::InstOpCode::label, node, startLabel, NULL); startLabel->setStartInternalControlFlow(); - //If object is not known to be value type at compile time, check at run time - if (TR::Compiler->om.areValueTypesEnabled() && cg->isMonitorValueType(node) == TR_maybe) + //If object is not known to be value type or value based class at compile time, check at run time + if ((TR::Compiler->om.areValueTypesEnabled() || TR::Compiler->om.areValueBasedMonitorChecksEnabled()) + && (cg->isMonitorValueBasedOrValueType(node) == TR_maybe)) { - generateCheckForValueTypeMonitorEnterOrExit(node, callLabel, objReg, objectClassReg, tempReg, condReg, cg); + generateCheckForValueMonitorEnterOrExit(node, callLabel, objReg, objectClassReg, tempReg, offsetReg, condReg, cg, J9_CLASS_DISALLOWS_LOCKING_FLAGS); } bool simpleLocking = false; diff --git a/runtime/compiler/p/codegen/J9TreeEvaluator.hpp b/runtime/compiler/p/codegen/J9TreeEvaluator.hpp index 8093b9cc0f5..b5856418966 100644 --- a/runtime/compiler/p/codegen/J9TreeEvaluator.hpp +++ b/runtime/compiler/p/codegen/J9TreeEvaluator.hpp @@ -88,7 +88,7 @@ class OMR_EXTENSIBLE TreeEvaluator: public J9::TreeEvaluator static TR::Register *ardbarEvaluator(TR::Node *node, TR::CodeGenerator *cg); static TR::Register *ardbariEvaluator(TR::Node *node, TR::CodeGenerator *cg); - static void generateCheckForValueTypeMonitorEnterOrExit(TR::Node *node, TR::LabelSymbol *helperCallLabel, TR::Register *objReg, TR::Register *objectClassReg, TR::Register *tempReg, TR::Register *condReg, TR::CodeGenerator *cg); + static void generateCheckForValueMonitorEnterOrExit(TR::Node *node, TR::LabelSymbol *helperCallLabel, TR::Register *objReg, TR::Register *objectClassReg, TR::Register *temp1Reg, TR::Register *temp2Reg, TR::Register *condReg, TR::CodeGenerator *cg, int32_t classFlag); static void restoreTOCRegister(TR::Node *node, TR::CodeGenerator *cg, TR::RegisterDependencyConditions *dependencies); static void buildArgsProcessFEDependencies(TR::Node *node, TR::CodeGenerator *cg, TR::RegisterDependencyConditions *dependencies); static TR::Register *retrieveTOCRegister(TR::Node *node, TR::CodeGenerator *cg, TR::RegisterDependencyConditions *dependencies);