From 176c75969c4d197f21269e06be1e352bd5fca483 Mon Sep 17 00:00:00 2001 From: Luke Li Date: Tue, 10 Dec 2024 14:04:21 -0500 Subject: [PATCH] Code refactoring --- .../control/JITClientCompilationThread.cpp | 13 +- .../compiler/optimizer/J9TransformUtil.cpp | 539 +++++++++--------- .../compiler/optimizer/J9TransformUtil.hpp | 14 +- 3 files changed, 286 insertions(+), 280 deletions(-) diff --git a/runtime/compiler/control/JITClientCompilationThread.cpp b/runtime/compiler/control/JITClientCompilationThread.cpp index 910fe702bb8..5f0ae628a19 100644 --- a/runtime/compiler/control/JITClientCompilationThread.cpp +++ b/runtime/compiler/control/JITClientCompilationThread.cpp @@ -2960,9 +2960,10 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes break; case MessageType::KnownObjectTable_addFieldAddressFromBaseIndex: { - auto recv = client->getRecvData(); + auto recv = client->getRecvData(); TR::KnownObjectTable::Index baseObjectIndex = std::get<0>(recv); intptr_t fieldOffset = std::get<1>(recv); + bool isArrayWithConstantElements = std::get<2>(recv); TR::KnownObjectTable::Index resultIndex = TR::KnownObjectTable::UNKNOWN; @@ -2974,11 +2975,11 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes uintptr_t objectPointer = fe->getReferenceFieldAtAddress(fieldAddress); if (objectPointer) - resultIndex = knot->getOrCreateIndex(objectPointer); + resultIndex = knot->getOrCreateIndexAt(&objectPointer, isArrayWithConstantElements); } - uintptr_t *resultPointer = - (resultIndex == -1) ? NULL : knot->getPointerLocation(resultIndex); + uintptr_t *resultPointer = (resultIndex == TR::KnownObjectTable::UNKNOWN) ? + NULL : knot->getPointerLocation(resultIndex); client->write(response, resultIndex, resultPointer); } @@ -2989,7 +2990,7 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes TR::KnownObjectTable::Index baseObjectIndex = std::get<0>(recv); intptr_t fieldOffset = std::get<1>(recv); - UDATA data = 0; + J9::TransformUtil::value data; { TR::VMAccessCriticalSection addFieldAddressFromBaseIndex(fe); @@ -2997,7 +2998,7 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes uintptr_t fieldAddress = baseObjectAddress + fieldOffset; - data = *(UDATA *) fieldAddress; + data = *(J9::TransformUtil::value *) fieldAddress; } client->write(response, data); diff --git a/runtime/compiler/optimizer/J9TransformUtil.cpp b/runtime/compiler/optimizer/J9TransformUtil.cpp index 53daa4bb6fc..e8af39f94d2 100644 --- a/runtime/compiler/optimizer/J9TransformUtil.cpp +++ b/runtime/compiler/optimizer/J9TransformUtil.cpp @@ -660,6 +660,138 @@ static void *dereferenceStructPointerChain(void *baseStruct, TR::Node *baseNode, return NULL; } +#if defined(J9VM_OPT_JITSERVER) +/** + * Mimics dereferenceStructPointerChain to dereference an indirect load, but only for the first + * level of the chain; executed from the JITServer only + */ +static void *dereferenceStructPointer(TR::KnownObjectTable::Index baseKnownObject, + TR::Node *node, + TR::Node *baseExpression, + bool isBaseStableArray, + TR::Compilation *comp, + J9::TransformUtil::value *valuePtr) + { + TR_ASSERT(comp->isOutOfProcessCompilation(), "must be executed from the jitserver"); + + if (node == baseExpression) + { + TR_ASSERT(false, "dereferenceStructPointerChain has no idea what to dereference"); + traceMsg(comp, "Caller has already dereferenced node %p, returning NULL as dereferenceStructPointerChain has no idea what to dereference\n", node); + return NULL; + } + TR_ASSERT(node != NULL, "Field node is NULL"); + TR_ASSERT(node->getOpCode().hasSymbolReference(), "Node must have a symref"); + + TR_J9VMBase *fej9 = comp->fej9(); + TR::SymbolReference *symRef = node->getSymbolReference(); + TR::Symbol *field = symRef->getSymbol(); + + TR::Node *addressChildNode = field->isArrayShadowSymbol() ? + node->getFirstChild()->getFirstChild() : + node->getFirstChild(); + // Abort if the indirection is more than a single level. + if (!addressChildNode->getOpCode().hasSymbolReference() + || addressChildNode != baseExpression) + return NULL; + + // We only consider the case where isJavaField is true for verifyFieldAccess + if (isJavaField(symRef, comp)) + { + TR_OpaqueClassBlock *fieldClass = NULL; + + if (symRef->getCPIndex() < 0 && + field->getRecognizedField() != TR::Symbol::UnknownField) + { + const char* className; + int32_t length; + className = field->owningClassNameCharsForRecognizedField(length); + fieldClass = fej9->getClassFromSignature(className, length, symRef->getOwningMethod(comp)); + } + else + fieldClass = symRef->getOwningMethod(comp)->getDeclaringClassFromFieldOrStatic(comp, + symRef->getCPIndex()); + + if (fieldClass == NULL) + return NULL; + + TR_OpaqueClassBlock *objectClass = + fej9->getObjectClassFromKnownObjectIndex(comp, baseKnownObject); + + // field access verified + if (fej9->isInstanceOf(objectClass, fieldClass, true) == TR_yes) + { + // Mimic avoidFoldingInstanceField by exiting in all cases where the method returns true: + // We should avoid folding instance field if: + // 1. the content of the fieldAddress is null; this is checked when we load the values + // 2. the field is of one of the two types below + if (field->getRecognizedField() == TR::Symbol::Java_lang_invoke_CallSite_target || + field->getRecognizedField() == TR::Symbol::Java_lang_invoke_MethodHandle_form) + return NULL; + + TR::DataType loadType = node->getDataType(); + + switch (loadType) + { + case TR::Int32: + case TR::Int64: + case TR::Float: + case TR::Double: + { + // not address + auto stream = comp->getStream(); + stream->write(JITServer::MessageType::KnownObjectTable_getFieldAddressData, + baseKnownObject, symRef->getOffset()); + J9::TransformUtil::value value = std::get<0>(stream->read()); + *valuePtr = value; + + // Do the null check part of avoidFoldingConstantField + // We do not have to worry about the case of address; the returned knot index will + // be UNKNOWN in that case + if (isNullValueAtAddress(comp, loadType, (uintptr_t) valuePtr, field)) + return NULL; + + return valuePtr; + } + break; + case TR::Address: + { + if (isFinalFieldPointingAtRepresentableNativeStruct(symRef, comp) || + isFinalFieldPointingAtNativeStruct(symRef, comp)) + { + return NULL; + } + else if (field->isCollectedReference()) + { + auto stream = comp->getStream(); + stream->write( + JITServer::MessageType::KnownObjectTable_addFieldAddressFromBaseIndex, + baseKnownObject, + symRef->getOffset(), + isArrayWithConstantElements(symRef, comp) + ); + auto recv = stream->read(); + TR::KnownObjectTable::Index value = std::get<0>(recv); + uintptr_t *objectReferenceLocationClient = std::get<1>(recv); + comp->getKnownObjectTable()->updateKnownObjectTableAtServer( + value, + objectReferenceLocationClient + ); + valuePtr->idx = value; + return valuePtr; + } + } + break; + default: + return NULL; + } + } + } + return NULL; + } +#endif /* defined(J9VM_OPT_JITSERVER) */ + + bool J9::TransformUtil::foldFinalFieldsIn(TR_OpaqueClassBlock *clazz, const char *className, int32_t classNameLength, bool isStatic, TR::Compilation *comp) { TR::SimpleRegex *classRegex = comp->getOptions()->getClassesWithFoldableFinalFields(); @@ -1701,7 +1833,10 @@ J9::TransformUtil::transformIndirectLoadChainAt(TR::Compilation *comp, TR::Node { baseAddress = *baseReferenceLocation; } - bool result = TR::TransformUtil::transformIndirectLoadChainImpl(comp, node, baseExpression, (void*)baseAddress, 0, removedNode); + bool result = TR::TransformUtil::transformIndirectLoadChainImpl(comp, node, baseExpression, + TR::KnownObjectTable::UNKNOWN, + (void *)baseAddress, + 0, removedNode); return result; } @@ -1716,247 +1851,37 @@ J9::TransformUtil::transformIndirectLoadChainAt(TR::Compilation *comp, TR::Node bool J9::TransformUtil::transformIndirectLoadChain(TR::Compilation *comp, TR::Node *node, TR::Node *baseExpression, TR::KnownObjectTable::Index baseKnownObject, TR::Node **removedNode) { -#if defined(J9VM_OPT_JITSERVER) - // Under JITServer, call a simplified version of transformIndirectLoadChain - // that does not access the VM - if (comp->isOutOfProcessCompilation()) - { - int32_t stableArrayRank = - comp->getKnownObjectTable()->getArrayWithStableElementsRank(baseKnownObject); - bool result = - TR::TransformUtil::transformIndirectLoadChainServerImpl(comp, - node, - baseExpression, - baseKnownObject, - stableArrayRank, - removedNode); - return result; - } -#endif /* defined(J9VM_OPT_JITSERVER) */ - - TR::VMAccessCriticalSection transformIndirectLoadChain(comp->fej9()); int32_t stableArrayRank = comp->getKnownObjectTable()->getArrayWithStableElementsRank(baseKnownObject); - - bool result = TR::TransformUtil::transformIndirectLoadChainImpl(comp, node, baseExpression, (void*)comp->getKnownObjectTable()->getPointer(baseKnownObject), stableArrayRank, removedNode); - return result; - } + bool result = false; #if defined(J9VM_OPT_JITSERVER) -/** Dereference node and fold it into a constant when possible. - * - * A simpler version of transformIndirectLoadChain() for the JITServer mode, which only considers - * the case where the node's symRef is a Java field. - */ -bool -J9::TransformUtil::transformIndirectLoadChainServerImpl(TR::Compilation *comp, TR::Node *node, TR::Node *baseExpression, TR::KnownObjectTable::Index baseKnownObject, int32_t baseStableArrayRank, TR::Node **removedNode) - { - bool isBaseStableArray = baseStableArrayRank > 0; - TR_J9VMBase *fej9 = comp->fej9(); - - TR_ASSERT(node->getOpCode().isLoadIndirect(), - "Expecting indirect load; found %s %p", node->getOpCode().getName(), node); - TR_ASSERT(node->getNumChildren() == 1, - "Expecting indirect load %s %p to have one child; actually has %d", - node->getOpCode().getName(), node, node->getNumChildren()); - - TR::SymbolReference *symRef = node->getSymbolReference(); - - if (comp->compileRelocatableCode() || - (isBaseStableArray && !symRef->getSymbol()->isArrayShadowSymbol()) || - symRef->hasKnownObjectIndex()) + if (comp->isOutOfProcessCompilation()) { - return false; + // In the JITServer, pass in the Knot Index rather than the address + result = TR::TransformUtil::transformIndirectLoadChainImpl(comp, node, baseExpression, + baseKnownObject, NULL, stableArrayRank, removedNode); } - - // Ignore the case of the J9Class whose finality is conditional on the holding value for now. - if (!symRef->isUnresolved() && - symRef == comp->getSymRefTab()->findInitializeStatusFromClassSymbolRef()) + else +#endif /* defined(J9VM_OPT_JITSERVER) */ { - return false; + TR::VMAccessCriticalSection transformIndirectLoadChain(comp->fej9()); + result = TR::TransformUtil::transformIndirectLoadChainImpl( + comp, node, baseExpression, TR::KnownObjectTable::UNKNOWN, + (void*)comp->getKnownObjectTable()->getPointer(baseKnownObject), + stableArrayRank, removedNode + ); } - if (!isBaseStableArray && !fej9->canDereferenceAtCompileTime(symRef, comp)) - { - if (comp->getOption(TR_TraceOptDetails)) - { - traceMsg(comp, "Abort transformIndirectLoadChain - cannot dereference at compile time!\n"); - } - return false; - } - - - // Instead of the recursive dereferenceStructPointerChain, we only consider a single level - // of indirection - TR::Symbol *field = symRef->getSymbol(); - TR::Node *addressChildNode = field->isArrayShadowSymbol() ? - node->getFirstChild()->getFirstChild() : - node->getFirstChild(); - if (!addressChildNode->getOpCode().hasSymbolReference() - || addressChildNode != baseExpression) - return false; - // baseStruct is always the value of baseExpression; dereference is not needed - - // We only consider the case where isJavaField is true for verifyFieldAccess - if (isJavaField(symRef, comp)) - { - TR_OpaqueClassBlock *fieldClass = NULL; - - if (symRef->getCPIndex() < 0 && - field->getRecognizedField() != TR::Symbol::UnknownField) - { - const char* className; - int32_t length; - className = field->owningClassNameCharsForRecognizedField(length); - fieldClass = fej9->getClassFromSignature(className, length, symRef->getOwningMethod(comp)); - } - else - fieldClass = symRef->getOwningMethod(comp)->getDeclaringClassFromFieldOrStatic(comp, - symRef->getCPIndex()); - - TR_OpaqueClassBlock *objectClass = - fej9->getObjectClassFromKnownObjectIndex(comp, baseKnownObject); - - // field access verified - if ((fieldClass != NULL) && (fej9->isInstanceOf(objectClass, fieldClass, true) == TR_yes)) - { - - // check the recognized fields case of avoidFoldingInstanceField - // the non-null checks are done when we get the actual values - if (field->getRecognizedField() == TR::Symbol::Java_lang_invoke_CallSite_target || - field->getRecognizedField() == TR::Symbol::Java_lang_invoke_MethodHandle_form) - return false; - - TR::DataType loadType = node->getDataType(); - - if (loadType == TR::Address) - { - if (isFinalFieldPointingAtRepresentableNativeStruct(symRef, comp) || - isFinalFieldPointingAtNativeStruct(symRef, comp)) - { - return false; - } - else if (field->isCollectedReference()) - { - auto stream = comp->getStream(); - stream->write( - JITServer::MessageType::KnownObjectTable_addFieldAddressFromBaseIndex, - baseKnownObject, symRef->getOffset()); - auto recv = stream->read(); - TR::KnownObjectTable::Index value = std::get<0>(recv); - uintptr_t *objectReferenceLocationClient = std::get<1>(recv); - comp->getKnownObjectTable()->updateKnownObjectTableAtServer( - value, - objectReferenceLocationClient - ); - - if (value != -1) - { - TR::SymbolReference *improvedSymRef = - comp->getSymRefTab()->findOrCreateSymRefWithKnownObject(symRef, value); - - if (improvedSymRef->hasKnownObjectIndex() - && performTransformation(comp, - "O^O transformIndirectLoadChain: %s [%p] with fieldOffset %d is obj%d referenceAddr is %p\n", node->getOpCode().getName(), node, improvedSymRef->getKnownObjectIndex(), symRef->getOffset(), value)) - { - node->setSymbolReference(improvedSymRef); - node->setIsNull(false); - node->setIsNonNull(true); - - int32_t stableArrayRank = isArrayWithStableElements(symRef->getCPIndex(), - symRef->getOwningMethod(comp), - comp); - if (isBaseStableArray) - stableArrayRank = baseStableArrayRank - 1; - - if (stableArrayRank > 0) - { - TR::KnownObjectTable *knot = comp->getOrCreateKnownObjectTable(); - knot->addStableArray(improvedSymRef->getKnownObjectIndex(), - stableArrayRank); - } - return true; - } - else /* has known object index */ - { - return false; - } - } - else /* value != -1 */ - { - return false; - } - } - else /* collected reference */ - { - return false; - } - } - else // non-address types - { - auto stream = comp->getStream(); - stream->write( - JITServer::MessageType::KnownObjectTable_getFieldAddressData, - baseKnownObject, symRef->getOffset()); - UDATA data = std::get<0>(stream->read()); - - if (data == 0) - return false; - - switch (loadType) - { - case TR::Int32: - { - int32_t value = (int32_t)data; - if (changeIndirectLoadIntoConst(node, TR::iconst, removedNode, comp)) - node->setInt(value); - else - return false; - } - break; - case TR::Int64: - { - int64_t value = (int64_t)data; - if (changeIndirectLoadIntoConst(node, TR::lconst, removedNode, comp)) - node->setLongInt(value); - else - return false; - } - break; - case TR::Float: - { - float value = (float)data; - if (changeIndirectLoadIntoConst(node, TR::fconst, removedNode, comp)) - node->setFloat(value); - else - return false; - } - break; - case TR::Double: - { - double value = (double)data; - if (changeIndirectLoadIntoConst(node, TR::dconst, removedNode, comp)) - node->setDouble(value); - else - return false; - } - break; - default: - return false; - } - return true; - } - } - } - return false; + return result; } -#endif /* defined(J9VM_OPT_JITSERVER) */ /** Dereference node and fold it into a constant when possible * * @parm comp The compilation object * @parm node The node to be folded * @parm baseExpression The start of the indirect load chain - * @parm baseAddress Value of baseExpression + * @parm baseKnownObject KnownObjectTable index containing the value of the base expression + * @parm baseAddress The value of the base expression * @parm removedNode Pointer to the removed node if removal happens * * @return true if the load chain has been folded, false otherwise @@ -2015,17 +1940,37 @@ J9::TransformUtil::transformIndirectLoadChainServerImpl(TR::Compilation *comp, T * */ bool -J9::TransformUtil::transformIndirectLoadChainImpl(TR::Compilation *comp, TR::Node *node, TR::Node *baseExpression, void *baseAddress, int32_t baseStableArrayRank, TR::Node **removedNode) +J9::TransformUtil::transformIndirectLoadChainImpl(TR::Compilation *comp, + TR::Node *node, TR::Node *baseExpression, + TR::KnownObjectTable::Index baseKnownObject, + void *baseAddress, + int32_t baseStableArrayRank, + TR::Node **removedNode) { - bool isBaseStableArray = baseStableArrayRank > 0; +#if defined(J9VM_OPT_JITSERVER) + bool isServer = comp->isOutOfProcessCompilation(); + + // baseKnownObject is used only for jitserver, otherwise we use baseAddress + if (isServer) + TR_ASSERT(baseKnownObject != TR::KnownObjectTable::UNKNOWN, + "invalid baseKnownObject in jitserver"); + else +#endif /* defined(J9VM_OPT_JITSERVER) */ + { + TR_ASSERT(TR::Compiler->vm.hasAccess(comp), + "transformIndirectLoadChain requires VM access for non-JITServer mode"); + TR_ASSERT(baseAddress, "invalid base address"); + } + + bool isBaseStableArray = baseStableArrayRank > 0; TR_J9VMBase *fej9 = comp->fej9(); -#if defined(J9VM_OPT_JITSERVER) - TR_ASSERT_FATAL(!comp->isOutOfProcessCompilation(), "It's not safe to call transformIndirectLoadChainImpl() in JITServer mode"); -#endif - TR_ASSERT(TR::Compiler->vm.hasAccess(comp), "transformIndirectLoadChain requires VM access"); - TR_ASSERT(node->getOpCode().isLoadIndirect(), "Expecting indirect load; found %s %p", node->getOpCode().getName(), node); - TR_ASSERT(node->getNumChildren() == 1, "Expecting indirect load %s %p to have one child; actually has %d", node->getOpCode().getName(), node, node->getNumChildren()); + + TR_ASSERT(node->getOpCode().isLoadIndirect(), "Expecting indirect load; found %s %p", + node->getOpCode().getName(), node); + TR_ASSERT(node->getNumChildren() == 1, + "Expecting indirect load %s %p to have one child; actually has %d", + node->getOpCode().getName(), node, node->getNumChildren()); if (comp->compileRelocatableCode()) { @@ -2041,31 +1986,44 @@ J9::TransformUtil::transformIndirectLoadChainImpl(TR::Compilation *comp, TR::Nod return false; // Fold initializeStatus field in J9Class whose finality is conditional on the value it is holding - if (!symRef->isUnresolved() && symRef == comp->getSymRefTab()->findInitializeStatusFromClassSymbolRef()) + if (!symRef->isUnresolved() + && symRef == comp->getSymRefTab()->findInitializeStatusFromClassSymbolRef()) { - J9Class* clazz = (J9Class*)baseAddress; - traceMsg(comp, "Looking at node %p with initializeStatusFromClassSymbol, class %p initialize status is %d\n", node, clazz, clazz->initializeStatus); - // Only fold the load if the class has been initialized - if (fej9->isClassInitialized((TR_OpaqueClassBlock *) clazz) == J9ClassInitSucceeded) +#if defined(J9VM_OPT_JITSERVER) + if (isServer) { - if (node->getDataType() == TR::Int32) + return false; + } + else +#endif /* defined(J9VM_OPT_JITSERVER) */ + { + J9Class* clazz = (J9Class*) baseAddress; + traceMsg(comp, + "Looking at node %p with initializeStatusFromClassSymbol," + " class %p initialize status is %d\n", + node, clazz, clazz->initializeStatus); + // Only fold the load if the class has been initialized + if (fej9->isClassInitialized((TR_OpaqueClassBlock *) clazz) == J9ClassInitSucceeded) { - if (changeIndirectLoadIntoConst(node, TR::iconst, removedNode, comp)) - node->setInt(J9ClassInitSucceeded); + if (node->getDataType() == TR::Int32) + { + if (changeIndirectLoadIntoConst(node, TR::iconst, removedNode, comp)) + node->setInt(J9ClassInitSucceeded); + else + return false; + } else - return false; + { + if (changeIndirectLoadIntoConst(node, TR::lconst, removedNode, comp)) + node->setLongInt(J9ClassInitSucceeded); + else + return false; + } + return true; } else - { - if (changeIndirectLoadIntoConst(node, TR::lconst, removedNode, comp)) - node->setLongInt(J9ClassInitSucceeded); - else - return false; - } - return true; + return false; } - else - return false; } if (!isBaseStableArray && !fej9->canDereferenceAtCompileTime(symRef, comp)) @@ -2077,15 +2035,34 @@ J9::TransformUtil::transformIndirectLoadChainImpl(TR::Compilation *comp, TR::Nod return false; } - // Dereference the chain starting from baseAddress and get the field address - void *fieldAddress = dereferenceStructPointerChain(baseAddress, baseExpression, isBaseStableArray, node, comp); - if (!fieldAddress) + void *valuePtr; + J9::TransformUtil::value value; +#if defined(J9VM_OPT_JITSERVER) + if (isServer) + { + // Instead of the recursive dereferenceStructPointerChain, we only consider a single level + // of indirection + void *result = dereferenceStructPointer(baseKnownObject, node, baseExpression, + isBaseStableArray, comp, &value); + valuePtr = &value; + if (result != valuePtr) + return false; + } + else // not jitserver +#endif /* defined(J9VM_OPT_JITSERVER) */ { - if (comp->getOption(TR_TraceOptDetails)) + // Dereference the chain starting from baseAddress and get the field address + void *fieldAddress = dereferenceStructPointerChain(baseAddress, baseExpression, + isBaseStableArray, node, comp); + if (!fieldAddress) { - traceMsg(comp, "Abort transformIndirectLoadChain - cannot verify/dereference field access to %s in %p!\n", symRef->getName(comp->getDebug()), baseAddress); + if (comp->getOption(TR_TraceOptDetails)) + { + traceMsg(comp, "Abort transformIndirectLoadChain - cannot verify/dereference field access to %s in %p!\n", symRef->getName(comp->getDebug()), baseAddress); + } + return false; } - return false; + valuePtr = fieldAddress; } // The last step in the dereference chain is not necessarily an address. @@ -2099,7 +2076,7 @@ J9::TransformUtil::transformIndirectLoadChainImpl(TR::Compilation *comp, TR::Nod { case TR::Int32: { - int32_t value = *(int32_t*)fieldAddress; + int32_t value = *(int32_t*)valuePtr; if (changeIndirectLoadIntoConst(node, TR::iconst, removedNode, comp)) node->setInt(value); else @@ -2108,7 +2085,7 @@ J9::TransformUtil::transformIndirectLoadChainImpl(TR::Compilation *comp, TR::Nod break; case TR::Int64: { - int64_t value = *(int64_t*)fieldAddress; + int64_t value = *(int64_t*)valuePtr; if (changeIndirectLoadIntoConst(node, TR::lconst, removedNode, comp)) node->setLongInt(value); else @@ -2117,7 +2094,7 @@ J9::TransformUtil::transformIndirectLoadChainImpl(TR::Compilation *comp, TR::Nod break; case TR::Float: { - float value = *(float*)fieldAddress; + float value = *(float*)valuePtr; if (changeIndirectLoadIntoConst(node, TR::fconst, removedNode, comp)) node->setFloat(value); else @@ -2126,7 +2103,7 @@ J9::TransformUtil::transformIndirectLoadChainImpl(TR::Compilation *comp, TR::Nod break; case TR::Double: { - double value = *(double*)fieldAddress; + double value = *(double*)valuePtr; if (changeIndirectLoadIntoConst(node, TR::dconst, removedNode, comp)) node->setDouble(value); else @@ -2137,11 +2114,15 @@ J9::TransformUtil::transformIndirectLoadChainImpl(TR::Compilation *comp, TR::Nod { if (isFinalFieldPointingAtRepresentableNativeStruct(symRef, comp)) { +#if defined(J9VM_OPT_JITSERVER) + if (isServer) + return false; +#endif /* defined(J9VM_OPT_JITSERVER) */ if (fej9->isFinalFieldPointingAtJ9Class(symRef, comp)) { if (changeIndirectLoadIntoConst(node, TR::loadaddr, removedNode, comp)) { - TR_OpaqueClassBlock *value = *(TR_OpaqueClassBlock**)fieldAddress; + TR_OpaqueClassBlock *value = *(TR_OpaqueClassBlock**)valuePtr; node->setSymbolReference(comp->getSymRefTab()->findOrCreateClassSymbol(comp->getMethodSymbol(), -1, value)); } else @@ -2158,9 +2139,13 @@ J9::TransformUtil::transformIndirectLoadChainImpl(TR::Compilation *comp, TR::Nod } else if (isFinalFieldPointingAtNativeStruct(symRef, comp)) { +#if defined(J9VM_OPT_JITSERVER) + if (isServer) + return false; +#endif /* defined(J9VM_OPT_JITSERVER) */ if (symRef->getReferenceNumber() - comp->getSymRefTab()->getNumHelperSymbols() == TR::SymbolReferenceTable::ramStaticsFromClassSymbol) { - uintptr_t value = *(uintptr_t*)fieldAddress; + uintptr_t value = *(uintptr_t*)valuePtr; if (changeIndirectLoadIntoConst(node, TR::aconst, removedNode, comp)) { node->setAddress(value); @@ -2175,10 +2160,24 @@ J9::TransformUtil::transformIndirectLoadChainImpl(TR::Compilation *comp, TR::Nod } else if (symRef->getSymbol()->isCollectedReference()) { - uintptr_t value = fej9->getReferenceFieldAtAddress((uintptr_t)fieldAddress); - if (value) + TR::KnownObjectTable::Index knotIndex = TR::KnownObjectTable::UNKNOWN; +#if defined(J9VM_OPT_JITSERVER) + if (isServer) + { + knotIndex = ((J9::TransformUtil::value *)valuePtr)->idx; + } + else +#endif /* defined(J9VM_OPT_JITSERVER) */ + { + uintptr_t value = fej9->getReferenceFieldAtAddress((uintptr_t)valuePtr); + knotIndex = comp->getKnownObjectTable()->getOrCreateIndexAt(&value, + isArrayWithConstantElements(symRef, comp)); + } + + if (knotIndex != TR::KnownObjectTable::UNKNOWN) { - TR::SymbolReference *improvedSymRef = comp->getSymRefTab()->findOrCreateSymRefWithKnownObject(symRef, &value, isArrayWithConstantElements(symRef, comp)); + TR::SymbolReference *improvedSymRef = + comp->getSymRefTab()->findOrCreateSymRefWithKnownObject(symRef, knotIndex); if (improvedSymRef->hasKnownObjectIndex() && performTransformation(comp, "O^O transformIndirectLoadChain: %s [%p] with fieldOffset %d is obj%d referenceAddr is %p\n", node->getOpCode().getName(), node, improvedSymRef->getKnownObjectIndex(), symRef->getOffset(), value)) @@ -2188,8 +2187,8 @@ J9::TransformUtil::transformIndirectLoadChainImpl(TR::Compilation *comp, TR::Nod node->setIsNonNull(true); int32_t stableArrayRank = isArrayWithStableElements(symRef->getCPIndex(), - symRef->getOwningMethod(comp), - comp); + symRef->getOwningMethod(comp), + comp); if (isBaseStableArray) stableArrayRank = baseStableArrayRank - 1; diff --git a/runtime/compiler/optimizer/J9TransformUtil.hpp b/runtime/compiler/optimizer/J9TransformUtil.hpp index 34a58c1c4a5..ecd039960ff 100644 --- a/runtime/compiler/optimizer/J9TransformUtil.hpp +++ b/runtime/compiler/optimizer/J9TransformUtil.hpp @@ -220,12 +220,18 @@ class OMR_EXTENSIBLE TransformUtil : public OMR::TransformUtilConnector TR_ResolvedMethod *owningMethod, int32_t cpIndex); + union value{ + int32_t i; + int64_t l; + float f; + double d; + void *p; + TR::KnownObjectTable::Index idx; + }; + static bool transformIndirectLoadChain(TR::Compilation *, TR::Node *node, TR::Node *baseExpression, TR::KnownObjectTable::Index baseKnownObject, TR::Node **removedNode); static bool transformIndirectLoadChainAt(TR::Compilation *, TR::Node *node, TR::Node *baseExpression, uintptr_t *baseReferenceLocation, TR::Node **removedNode); - static bool transformIndirectLoadChainImpl( TR::Compilation *, TR::Node *node, TR::Node *baseExpression, void *baseAddress, int32_t baseStableArrayRank, TR::Node **removedNode); -#if defined(J9VM_OPT_JITSERVER) - static bool transformIndirectLoadChainServerImpl( TR::Compilation *, TR::Node *node, TR::Node *baseExpression, TR::KnownObjectTable::Index baseKnownObject, int32_t baseStableArrayRank, TR::Node **removedNode); -#endif /* defined(J9VM_OPT_JITSERVER) */ + static bool transformIndirectLoadChainImpl( TR::Compilation *, TR::Node *node, TR::Node *baseExpression, TR::KnownObjectTable::Index baseKnownObject, void *baseAddress, int32_t baseStableArrayRank, TR::Node **removedNode); static bool fieldShouldBeCompressed(TR::Node *node, TR::Compilation *comp);