From ab3869094902f9ea93a5eb7b83504176ea6ee906 Mon Sep 17 00:00:00 2001 From: Annabelle Huo Date: Mon, 21 Oct 2024 13:38:04 -0400 Subject: [PATCH] Remove isPrimitiveValueTypeClass Also updated code comments where the old primitive value type is referenced Related: #18157 Signed-off-by: Annabelle Huo --- runtime/compiler/compile/J9Compilation.cpp | 13 ++++------- runtime/compiler/env/J9ClassEnv.cpp | 23 ------------------- runtime/compiler/env/J9ClassEnv.hpp | 3 +-- runtime/compiler/env/VMJ9.cpp | 2 +- runtime/compiler/optimizer/EscapeAnalysis.cpp | 18 ++++----------- .../compiler/optimizer/J9ValuePropagation.cpp | 7 +++--- runtime/compiler/optimizer/TreeLowering.cpp | 8 +++---- 7 files changed, 18 insertions(+), 56 deletions(-) diff --git a/runtime/compiler/compile/J9Compilation.cpp b/runtime/compiler/compile/J9Compilation.cpp index 29d3967d551..70cdd1dd695 100644 --- a/runtime/compiler/compile/J9Compilation.cpp +++ b/runtime/compiler/compile/J9Compilation.cpp @@ -703,7 +703,7 @@ J9::Compilation::canAllocateInline(TR::Node* node, TR_OpaqueClassBlock* &classIn } else if (node->getOpCodeValue() == TR::anewarray) { - classRef = node->getSecondChild(); + classRef = node->getSecondChild(); // In the case of dynamic array allocation, return 0 indicating variable dynamic array allocation, // unless value types are enabled, in which case return -1 to prevent inline allocation @@ -727,20 +727,15 @@ J9::Compilation::canAllocateInline(TR::Node* node, TR_OpaqueClassBlock* &classIn } } - classSymRef = classRef->getSymbolReference(); + classSymRef = classRef->getSymbolReference(); // Can't skip the allocation if the class is unresolved // clazz = self()->fej9vm()->getClassForAllocationInlining(self(), classSymRef); if (clazz == NULL) return -1; - // Arrays of null-restricted (a.k.a, primitive value type) classes must have all their elements initialized - // with the default value of the component type. For now, prevent inline allocation of them. - // - if (areValueTypesEnabled && TR::Compiler->cls.isPrimitiveValueTypeClass(reinterpret_cast(clazz))) - { - return -1; - } + // TODO-VALUETYPE: If null-restricted arrays are ever allocated using TR::anewarray, + // the JIT will need to handle the inline initialization or prevent inline allocation. auto classOffset = self()->fej9()->getArrayClassFromComponentClass(TR::Compiler->cls.convertClassPtrToClassOffset(clazz)); clazz = TR::Compiler->cls.convertClassOffsetToClassPtr(classOffset); diff --git a/runtime/compiler/env/J9ClassEnv.cpp b/runtime/compiler/env/J9ClassEnv.cpp index 1d0446074d8..d5ff819898c 100644 --- a/runtime/compiler/env/J9ClassEnv.cpp +++ b/runtime/compiler/env/J9ClassEnv.cpp @@ -833,29 +833,6 @@ J9::ClassEnv::isValueTypeClass(TR_OpaqueClassBlock *clazz) return J9_IS_J9CLASS_VALUETYPE(j9class); } -bool -J9::ClassEnv::isPrimitiveValueTypeClass(TR_OpaqueClassBlock *clazz) - { -#if defined(J9VM_OPT_JITSERVER) - if (auto stream = TR::CompilationInfo::getStream()) - { - uintptr_t classFlags = 0; - JITServerHelpers::getAndCacheRAMClassInfo((J9Class *)clazz, TR::compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_CLASS_FLAGS, (void *)&classFlags); -#ifdef DEBUG - stream->write(JITServer::MessageType::ClassEnv_classFlagsValue, clazz); - uintptr_t classFlagsRemote = std::get<0>(stream->read()); - // Check that class flags from remote call is equal to the cached ones - classFlags = classFlags & J9ClassIsPrimitiveValueType; - classFlagsRemote = classFlagsRemote & J9ClassIsPrimitiveValueType; - TR_ASSERT(classFlags == classFlagsRemote, "remote call class flags is not equal to cached class flags"); -#endif - return classFlags & J9ClassIsPrimitiveValueType; - } -#endif /* defined(J9VM_OPT_JITSERVER) */ - J9Class *j9class = reinterpret_cast(clazz); - return J9_IS_J9CLASS_PRIMITIVE_VALUETYPE(j9class); - } - bool J9::ClassEnv::isValueTypeClassFlattened(TR_OpaqueClassBlock *clazz) { diff --git a/runtime/compiler/env/J9ClassEnv.hpp b/runtime/compiler/env/J9ClassEnv.hpp index 0237456f905..88042ed0495 100644 --- a/runtime/compiler/env/J9ClassEnv.hpp +++ b/runtime/compiler/env/J9ClassEnv.hpp @@ -93,7 +93,6 @@ class OMR_EXTENSIBLE ClassEnv : public OMR::ClassEnvConnector bool isInterfaceClass(TR::Compilation *comp, TR_OpaqueClassBlock *clazzPointer); bool isConcreteClass(TR::Compilation *comp, TR_OpaqueClassBlock * clazzPointer); bool isValueTypeClass(TR_OpaqueClassBlock *); - bool isPrimitiveValueTypeClass(TR_OpaqueClassBlock *); bool isValueTypeClassFlattened(TR_OpaqueClassBlock *clazz); bool isValueBasedOrValueTypeClass(TR_OpaqueClassBlock *); bool isArrayNullRestricted(TR::Compilation *comp, TR_OpaqueClassBlock *arrayClass); @@ -145,7 +144,7 @@ class OMR_EXTENSIBLE ClassEnv : public OMR::ClassEnvConnector * \brief * Checks whether instances of the specified class can be trivially initialized by * "zeroing" their fields. - * In the case of OpenJ9, this tests whether any field is of a primitive value type that + * In the case of OpenJ9, this tests whether any field is of null-restricted type that * has not been "flattened" (that is, had the value type's fields inlined into this class). * Such a value type field must be initialized with the default value of the type. * diff --git a/runtime/compiler/env/VMJ9.cpp b/runtime/compiler/env/VMJ9.cpp index 0991a21b916..faa0f976d50 100644 --- a/runtime/compiler/env/VMJ9.cpp +++ b/runtime/compiler/env/VMJ9.cpp @@ -6324,7 +6324,7 @@ TR_J9VMBase::canAllocateInlineClass(TR_OpaqueClassBlock *clazzOffset) return false; // Cannot inline the allocation if the class is an interface, abstract, - // or if it is a class with identityless primitive value type fields that + // or if it is a class with identityless null-restricted fields that // aren't flattened, because they have to be made to refer to their type's // default values if ((clazz->romClass->modifiers & (J9AccAbstract | J9AccInterface)) diff --git a/runtime/compiler/optimizer/EscapeAnalysis.cpp b/runtime/compiler/optimizer/EscapeAnalysis.cpp index 5743049b49a..9ef08de330e 100644 --- a/runtime/compiler/optimizer/EscapeAnalysis.cpp +++ b/runtime/compiler/optimizer/EscapeAnalysis.cpp @@ -1187,12 +1187,14 @@ int32_t TR_EscapeAnalysis::performAnalysisOnce() continue; } + // TODO-VALUETYPE: Need to handle allocation of null-restricted arrays if + // null-restricted arrays are ever allocated using TR::anewarray and we + // want to allow for stack allocation of null-restricted arrays if (candidate->_kind == TR::anewarray) { // Array Candidates for contiguous allocation that have unresolved // base classes must be rejected, since we cannot initialize the array - // header. If the component type is a primitive value type, reject the array - // as we can't initialize the elements to the default value yet. + // header. // if (candidate->isContiguousAllocation()) { @@ -1205,18 +1207,6 @@ int32_t TR_EscapeAnalysis::performAnalysisOnce() rememoize(candidate); _candidates.remove(candidate); } - else - { - TR_OpaqueClassBlock *clazz = (TR_OpaqueClassBlock*)classNode->getSymbol()->castToStaticSymbol()->getStaticAddress(); - - if (TR::Compiler->cls.isPrimitiveValueTypeClass(clazz)) - { - if (trace()) - traceMsg(comp(), " Fail [%p] because array has primitive value type elements\n", candidate->_node); - rememoize(candidate); - _candidates.remove(candidate); - } - } } } diff --git a/runtime/compiler/optimizer/J9ValuePropagation.cpp b/runtime/compiler/optimizer/J9ValuePropagation.cpp index 2ea318a8c41..fa63af75fdd 100644 --- a/runtime/compiler/optimizer/J9ValuePropagation.cpp +++ b/runtime/compiler/optimizer/J9ValuePropagation.cpp @@ -1096,7 +1096,7 @@ J9::ValuePropagation::constrainRecognizedMethod(TR::Node *node) } if (!canTransformIdentityArrayElementLoadStoreUseTypeHint && - TR::Compiler->cls.isPrimitiveValueTypeClass(hintComponentClass)) + TR::Compiler->cls.isArrayNullRestricted(comp(), typeHintClass)) //TODO-VALUETYPE: typeHintClass eventually should be the null-restricted array class { if (TR::Compiler->cls.isValueTypeClassFlattened(hintComponentClass)) { @@ -1719,8 +1719,9 @@ J9::ValuePropagation::constrainRecognizedMethod(TR::Node *node) // (ii) The operand is definitely a non-null instance of java.lang.Class. In that case, load the // J9Class from the java.lang.Class by way of // - // The result of Class.isValueType(), Class.isPrimitiveValueType() or Class.isIdentity() can then - // be determined by checking the corresponding bit in the classFlags field. + // The result of Class.isValueType() and Class.isIdentity() can then be determined by checking + // the corresponding bit in the classFlags field. + // TR::SymbolReference *symRef = classChild->getOpCode().hasSymbolReference() ? classChild->getSymbolReference() : NULL; TR::Node *classOperand = NULL; diff --git a/runtime/compiler/optimizer/TreeLowering.cpp b/runtime/compiler/optimizer/TreeLowering.cpp index cde2292a655..300d5a65957 100644 --- a/runtime/compiler/optimizer/TreeLowering.cpp +++ b/runtime/compiler/optimizer/TreeLowering.cpp @@ -871,7 +871,7 @@ static bool skipBoundChecks(TR::Compilation *comp, TR::Node *node) * LoadArrayElementTransformer transforms the block that contains the jitLoadFlattenableArrayElement helper call into three blocks: * 1. The merge block (blockAfterHelperCall) that contains the tree tops after the helper call * 2. The helper call block (helperCallBlock) that contains the helper call and is moved to the end of the tree top list - * 3. The new non-primitive VT array load block (arrayElementLoadBlock) which is an extended block of the original block + * 3. The new nullable array load block (arrayElementLoadBlock) which is an extended block of the original block * * originalBlock----------+ * arrayElementLoadBlock | @@ -996,7 +996,7 @@ LoadArrayElementTransformer::lower(TR::Node* const node, TR::TreeTop* const tt) // 1. Anchor helper call node after the helper call // Anchor elementIndex and arrayBaseAddress before the helper call - // Anchoring the helper call ensures that the return value from the helper call or from the non-primitive VT array element load + // Anchoring the helper call ensures that the return value from the helper call or from the nullable array element load // will be saved to a register or a temp. TR::TreeTop *anchoredCallTT = TR::TreeTop::create(comp, tt, TR::Node::create(TR::treetop, 1, node)); TR::TreeTop *anchoredElementIndexTT = TR::TreeTop::create(comp, tt->getPrevTreeTop(), TR::Node::create(TR::treetop, 1, elementIndexNode)); @@ -1206,7 +1206,7 @@ static bool skipArrayStoreChecks(TR::Compilation *comp, TR::Node *node) * StoreArrayElementTransformer transforms the block that contains the jitStoreFlattenableArrayElement helper call into three blocks: * 1. The merge block that contains the tree tops after the helper call * 2. The helper call block that contains the helper call and is moved to the end of the tree top list - * 3. The new non-primitive VT array store block which is an extended block of the original block + * 3. The new nullable array store block which is an extended block of the original block * * originalBlock ----------+ * arrayElementStoreBlock | @@ -1372,7 +1372,7 @@ StoreArrayElementTransformer::lower(TR::Node* const node, TR::TreeTop* const tt) /////////////////////////////////////// // 5. Split (2) at the helper call node into its own helperCallBlock - // Insert NULLCHK for Primitive VT + // Insert NULLCHK for null-restricted VT TR::Node *anchoredValueNode = anchoredValueTT->getNode()->getFirstChild(); TR::TreeTop *ttForHelperCallBlock = tt;