diff --git a/runtime/compiler/control/JITClientCompilationThread.cpp b/runtime/compiler/control/JITClientCompilationThread.cpp index 8e43bbf1335..d4034543391 100644 --- a/runtime/compiler/control/JITClientCompilationThread.cpp +++ b/runtime/compiler/control/JITClientCompilationThread.cpp @@ -1845,6 +1845,16 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes client->write(response, methodInfos, ramMethods, implCount); } break; + case MessageType::ResolvedMethod_isFieldNullRestricted: + { + auto recv = client->getRecvData(); + auto mirror = std::get<0>(recv); + int32_t cpIndex = std::get<1>(recv); + bool isStatic = std::get<2>(recv); + bool isStore = std::get<3>(recv); + client->write(response, mirror->isFieldNullRestricted(comp, cpIndex, isStatic, isStore)); + } + break; case MessageType::ResolvedMethod_isFieldFlattened: { auto recv = client->getRecvData(); @@ -2060,14 +2070,6 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes client->write(response, TR::Compiler->cls.superClassesOf(clazz)[index]); } break; - case MessageType::ClassEnv_isClassRefPrimitiveValueType: - { - auto recv = client->getRecvData(); - auto clazz = std::get<0>(recv); - auto cpIndex = std::get<1>(recv); - client->write(response, TR::Compiler->cls.isClassRefPrimitiveValueType(comp, clazz, cpIndex)); - } - break; case MessageType::ClassEnv_flattenedArrayElementSize: { auto recv = client->getRecvData(); diff --git a/runtime/compiler/env/J9ClassEnv.cpp b/runtime/compiler/env/J9ClassEnv.cpp index d45b434a86a..5f497bf2a2e 100644 --- a/runtime/compiler/env/J9ClassEnv.cpp +++ b/runtime/compiler/env/J9ClassEnv.cpp @@ -524,7 +524,7 @@ static void addEntryForFieldImpl(TR_VMField *field, TR::TypeLayoutBuilder &tlb, } else { - TR_ASSERT_FATAL(false, "Support for null-restricted types without Q descriptor is to be implemented!!!"); + isFieldPrimitiveValueType = vm->internalVMFunctions->isFieldNullRestricted(field->shape); } } @@ -1018,24 +1018,6 @@ J9::ClassEnv::containsZeroOrOneConcreteClass(TR::Compilation *comp, ListgetStream()) - { - stream->write(JITServer::MessageType::ClassEnv_isClassRefPrimitiveValueType, cpContextClass, cpIndex); - return std::get<0>(stream->read()); - } - else // non-jitserver -#endif /* defined(J9VM_OPT_JITSERVER) */ - { - J9Class * j9class = reinterpret_cast(cpContextClass); - J9JavaVM *vm = comp->fej9()->getJ9JITConfig()->javaVM; - return vm->internalVMFunctions->isClassRefQtype(j9class, cpIndex); - } - } - char * J9::ClassEnv::classNameToSignature(const char *name, int32_t &len, TR::Compilation *comp, TR_AllocationKind allocKind, TR_OpaqueClassBlock *clazz) { diff --git a/runtime/compiler/env/J9ClassEnv.hpp b/runtime/compiler/env/J9ClassEnv.hpp index ab3bd3d3f3d..7cb2399375f 100644 --- a/runtime/compiler/env/J9ClassEnv.hpp +++ b/runtime/compiler/env/J9ClassEnv.hpp @@ -183,21 +183,6 @@ class OMR_EXTENSIBLE ClassEnv : public OMR::ClassEnvConnector bool isString(TR::Compilation *comp, TR_OpaqueClassBlock *clazz); bool jitStaticsAreSame(TR::Compilation *comp, TR_ResolvedMethod * method1, int32_t cpIndex1, TR_ResolvedMethod * method2, int32_t cpIndex2); bool jitFieldsAreSame(TR::Compilation *comp, TR_ResolvedMethod * method1, int32_t cpIndex1, TR_ResolvedMethod * method2, int32_t cpIndex2, int32_t isStatic); - /* - * \brief - * Tells whether a class reference entry in the constant pool represents a primitive value type class. - * - * \param cpContextClass - * The class whose constant pool contains the class reference entry being looked at. In another words, - * it's the class of the method referring to the class reference entry. - * - * \param cpIndex - * The constant pool index of the class reference entry. - * - * \note - * The class reference entry doesn't need to be resolved because the information is encoded in class name string - */ - bool isClassRefPrimitiveValueType(TR::Compilation *comp, TR_OpaqueClassBlock *cpContextClass, int32_t cpIndex); /** \brief * Populates a TypeLayout object. diff --git a/runtime/compiler/env/j9method.cpp b/runtime/compiler/env/j9method.cpp index 65e9d986a82..0571e56604d 100644 --- a/runtime/compiler/env/j9method.cpp +++ b/runtime/compiler/env/j9method.cpp @@ -9312,17 +9312,58 @@ TR_J9ByteCodeIlGenerator::packReferenceChainOffsets(TR::Node *node, std::vector< bool TR_ResolvedJ9Method::isFieldQType(int32_t cpIndex) + { + J9ROMFieldRef *ref = (J9ROMFieldRef *) (&romCPBase()[cpIndex]); + J9ROMNameAndSignature *nameAndSignature = J9ROMFIELDREF_NAMEANDSIGNATURE(ref); + J9UTF8 *signature = J9ROMNAMEANDSIGNATURE_SIGNATURE(nameAndSignature); + + J9VMThread *vmThread = fej9()->vmThread(); + return vmThread->javaVM->internalVMFunctions->isNameOrSignatureQtype(signature); + } + +bool +TR_ResolvedJ9Method::isFieldNullRestricted(TR::Compilation *comp, int32_t cpIndex, bool isStatic, bool isStore) { if (!TR::Compiler->om.areFlattenableValueTypesEnabled() || (-1 == cpIndex)) return false; + if (TR::Compiler->om.isQDescriptorForValueTypesSupported()) + { + if (isFieldQType(cpIndex)) // Temporary until javac supports NullRestricted attribute + return true; + } + J9VMThread *vmThread = fej9()->vmThread(); - J9ROMFieldRef *ref = (J9ROMFieldRef *) (&romCPBase()[cpIndex]); - J9ROMNameAndSignature *nameAndSignature = J9ROMFIELDREF_NAMEANDSIGNATURE(ref); - J9UTF8 *signature = J9ROMNAMEANDSIGNATURE_SIGNATURE(nameAndSignature); + J9ROMFieldShape *fieldShape = NULL; - return vmThread->javaVM->internalVMFunctions->isNameOrSignatureQtype(signature); + bool failCompilation = false; + { + TR::VMAccessCriticalSection isFieldNullRestricted(fej9()); + if (isStatic) + { + void *staticAddress = jitCTResolveStaticFieldRefWithMethod(vmThread, ramMethod(), cpIndex, isStore, &fieldShape); + if (!staticAddress) + { + failCompilation = true; + } + } + else + { + IDATA fieldOffset = jitCTResolveInstanceFieldRefWithMethod(vmThread, ramMethod(), cpIndex, isStore, &fieldShape); + if (fieldOffset == -1) + { + failCompilation = true; + } + } + } + + if (failCompilation) + { + comp->failCompilation(isStatic ? "jitCTResolveStaticFieldRefWithMethod failed" : "jitCTResolveInstanceFieldRefWithMethod failed"); + } + + return vmThread->javaVM->internalVMFunctions->isFieldNullRestricted(fieldShape); } bool diff --git a/runtime/compiler/env/j9method.h b/runtime/compiler/env/j9method.h index 94350da89a6..323248f6e39 100644 --- a/runtime/compiler/env/j9method.h +++ b/runtime/compiler/env/j9method.h @@ -470,6 +470,13 @@ class TR_ResolvedJ9Method : public TR_J9Method, public TR_ResolvedJ9MethodBase TR_ResolvedMethod * aotMaskResolvedPossiblyPrivateVirtualMethod(TR::Compilation *comp, TR_ResolvedMethod *method); TR_ResolvedMethod * aotMaskResolvedImproperInterfaceMethod(TR::Compilation *comp, TR_ResolvedMethod *method); + /** + * @brief Check if a field is a QType or not. + * + * @param[in] cpIndex : the constant pool index of the field + */ + virtual bool isFieldQType(int32_t cpIndex); + public: virtual bool virtualMethodIsOverridden(); virtual void setVirtualMethodIsOverridden(); @@ -518,17 +525,21 @@ class TR_ResolvedJ9Method : public TR_J9Method, public TR_ResolvedJ9MethodBase virtual void makeParameterList(TR::ResolvedMethodSymbol *methodSym); /** - * @brief Check if a field is a QType or not. + * @brief Check if a field has the NullRestricted attribute. * + * @param[in] comp : The current compilation object * @param[in] cpIndex : the constant pool index of the field + * @param[in] isStatic: whether the field is static + * @param[in] isStore : whether the field is being used in the context of a store into the field */ - virtual bool isFieldQType(int32_t cpIndex); + virtual bool isFieldNullRestricted(TR::Compilation *comp, int32_t cpIndex, bool isStatic, bool isStore); + /** * @brief Check if a field is flattened or not by calling the VM API. * * @param[in] comp : The current compilation object * @param[in] cpIndex : the constant pool index of the field - * @param[in] isStatic : whether the field is static + * @param[in] isStatic : whether the field is static */ virtual bool isFieldFlattened(TR::Compilation *comp, int32_t cpIndex, bool isStatic); diff --git a/runtime/compiler/env/j9methodServer.cpp b/runtime/compiler/env/j9methodServer.cpp index 08f71ab9bc5..b23390ca0cf 100644 --- a/runtime/compiler/env/j9methodServer.cpp +++ b/runtime/compiler/env/j9methodServer.cpp @@ -1845,10 +1845,6 @@ TR_ResolvedJ9JITServerMethod::archetypeArgPlaceholderSlot() bool TR_ResolvedJ9JITServerMethod::isFieldQType(int32_t cpIndex) { - if (!TR::Compiler->om.areFlattenableValueTypesEnabled() || - (-1 == cpIndex)) - return false; - auto comp = _fe->_compInfoPT->getCompilation(); int32_t sigLen; char *sig = fieldOrStaticSignatureChars(cpIndex, sigLen); @@ -1858,6 +1854,22 @@ TR_ResolvedJ9JITServerMethod::isFieldQType(int32_t cpIndex) return vmThread->javaVM->internalVMFunctions->isNameOrSignatureQtype(utfWrapper); } +bool +TR_ResolvedJ9JITServerMethod::isFieldNullRestricted(TR::Compilation *comp, int32_t cpIndex, bool isStatic, bool isStore) + { + if (!TR::Compiler->om.areFlattenableValueTypesEnabled() || + (-1 == cpIndex)) + return false; + + if (TR::Compiler->om.isQDescriptorForValueTypesSupported()) + { + return isFieldQType(cpIndex); + } + + _stream->write(JITServer::MessageType::ResolvedMethod_isFieldNullRestricted, _remoteMirror, cpIndex, isStatic, isStore); + return std::get<0>(_stream->read()); + } + bool TR_ResolvedJ9JITServerMethod::isFieldFlattened(TR::Compilation *comp, int32_t cpIndex, bool isStatic) { diff --git a/runtime/compiler/env/j9methodServer.hpp b/runtime/compiler/env/j9methodServer.hpp index 414eb6bf182..305b84bc57e 100644 --- a/runtime/compiler/env/j9methodServer.hpp +++ b/runtime/compiler/env/j9methodServer.hpp @@ -216,7 +216,7 @@ class TR_ResolvedJ9JITServerMethod : public TR_ResolvedJ9Method virtual void getFaninInfo(uint32_t *count, uint32_t *weight, uint32_t *otherBucketWeight = NULL) override; virtual bool getCallerWeight(TR_ResolvedJ9Method *caller, uint32_t *weight, uint32_t pcIndex=~0) override; virtual uint16_t archetypeArgPlaceholderSlot() override; - virtual bool isFieldQType(int32_t cpIndex) override; + virtual bool isFieldNullRestricted(TR::Compilation *comp, int32_t cpIndex, bool isStatic, bool isStore) override; virtual bool isFieldFlattened(TR::Compilation *comp, int32_t cpIndex, bool isStatic) override; bool isForceInline() const { return _isForceInline; } bool isDontInline() const { return _isDontInline; } @@ -242,6 +242,8 @@ class TR_ResolvedJ9JITServerMethod : public TR_ResolvedJ9Method virtual bool validateMethodFieldAttributes(const TR_J9MethodFieldAttributes &attributes, bool isStatic, int32_t cpIndex, bool isStore, bool needAOTValidation); virtual bool canCacheFieldAttributes(int32_t cpIndex, const TR_J9MethodFieldAttributes &attributes, bool isStatic); + virtual bool isFieldQType(int32_t cpIndex) override; + private: J9ROMClass *_romClass; // cached copy of ROM class from client diff --git a/runtime/compiler/ilgen/Walker.cpp b/runtime/compiler/ilgen/Walker.cpp index 50522766e36..b32f7ca6034 100644 --- a/runtime/compiler/ilgen/Walker.cpp +++ b/runtime/compiler/ilgen/Walker.cpp @@ -4947,24 +4947,18 @@ TR_J9ByteCodeIlGenerator::loadInstance(int32_t cpIndex) comp()->failCompilation("NO support for AOT in field watch"); TR_ResolvedJ9Method * owningMethod = static_cast(_methodSymbol->getResolvedMethod()); - if (TR::Compiler->om.areFlattenableValueTypesEnabled()) + + if (owningMethod->isFieldNullRestricted(comp(), cpIndex, false /* isStatic */, false /* isStore */)) { - if (!TR::Compiler->om.isQDescriptorForValueTypesSupported()) + if (!isFieldResolved(comp(), owningMethod, cpIndex, false)) { - TR_ASSERT_FATAL(false, "Support for null-restricted types without Q descriptor is to be implemented!!!"); + abortForUnresolvedValueTypeOp("getfield", "field"); } - else if (owningMethod->isFieldQType(cpIndex)) + else if (owningMethod->isFieldFlattened(comp(), cpIndex, false /* isStatic */)) { - if (!isFieldResolved(comp(), owningMethod, cpIndex, false)) - { - abortForUnresolvedValueTypeOp("getfield", "field"); - } - else if (owningMethod->isFieldFlattened(comp(), cpIndex, _methodSymbol->isStatic())) - { - return comp()->getOption(TR_UseFlattenedFieldRuntimeHelpers) ? - loadFlattenableInstanceWithHelper(cpIndex) : - loadFlattenableInstance(cpIndex); - } + return comp()->getOption(TR_UseFlattenedFieldRuntimeHelpers) ? + loadFlattenableInstanceWithHelper(cpIndex) : + loadFlattenableInstance(cpIndex); } } @@ -6195,36 +6189,30 @@ TR_J9ByteCodeIlGenerator::genWithField(int32_t fieldCpIndex) } TR_ResolvedJ9Method * owningMethod = static_cast(_methodSymbol->getResolvedMethod()); - if (TR::Compiler->om.areFlattenableValueTypesEnabled()) + + if (owningMethod->isFieldNullRestricted(comp(), fieldCpIndex, false /* isStatic */, true /* isStore */)) { - if (!TR::Compiler->om.isQDescriptorForValueTypesSupported()) + if (owningMethod->isFieldFlattened(comp(), fieldCpIndex, false /* isStatic */)) { - TR_ASSERT_FATAL(false, "Support for null-restricted types without Q descriptor is to be implemented!!!"); + return comp()->getOption(TR_UseFlattenedFieldRuntimeHelpers) ? + genFlattenableWithFieldWithHelper(fieldCpIndex) : + genFlattenableWithField(fieldCpIndex, valueClass); } - else if (owningMethod->isFieldQType(fieldCpIndex)) + else { - if (owningMethod->isFieldFlattened(comp(), fieldCpIndex, _methodSymbol->isStatic())) + TR::Node *newFieldValue = pop(); + if (comp()->getOption(TR_TraceILGen)) { - return comp()->getOption(TR_UseFlattenedFieldRuntimeHelpers) ? - genFlattenableWithFieldWithHelper(fieldCpIndex) : - genFlattenableWithField(fieldCpIndex, valueClass); + traceMsg(comp(), "%s: fieldCpIndex %d isFieldFlattened 0 newFieldValue n%dn isNonNull %d\n", __FUNCTION__, fieldCpIndex, newFieldValue->getGlobalIndex(), newFieldValue->isNonNull()); } - else - { - TR::Node *newFieldValue = pop(); - if (comp()->getOption(TR_TraceILGen)) - { - traceMsg(comp(), "%s: fieldCpIndex %d isFieldFlattened 0 newFieldValue n%dn isNonNull %d\n", __FUNCTION__, fieldCpIndex, newFieldValue->getGlobalIndex(), newFieldValue->isNonNull()); - } - if (!newFieldValue->isNonNull()) - { - TR::Node *passThruNode = TR::Node::create(TR::PassThrough, 1, newFieldValue); - genTreeTop(genNullCheck(passThruNode)); - } - - push(newFieldValue); + if (!newFieldValue->isNonNull()) + { + TR::Node *passThruNode = TR::Node::create(TR::PassThrough, 1, newFieldValue); + genTreeTop(genNullCheck(passThruNode)); } + + push(newFieldValue); } } @@ -6973,40 +6961,33 @@ TR_J9ByteCodeIlGenerator::storeInstance(int32_t cpIndex) TR_ResolvedJ9Method * owningMethod = static_cast(_methodSymbol->getResolvedMethod()); - if (TR::Compiler->om.areFlattenableValueTypesEnabled()) + if (owningMethod->isFieldNullRestricted(comp(), cpIndex, false /* isStatic */, true /* isStore */)) { - if (!TR::Compiler->om.isQDescriptorForValueTypesSupported()) + if (!isFieldResolved(comp(), owningMethod, cpIndex, true)) + { + abortForUnresolvedValueTypeOp("putfield", "field"); + } + else if (owningMethod->isFieldFlattened(comp(), cpIndex, false /* isStatic */)) { - TR_ASSERT_FATAL(false, "Support for null-restricted types without Q descriptor is to be implemented!!!"); + return comp()->getOption(TR_UseFlattenedFieldRuntimeHelpers) ? + storeFlattenableInstanceWithHelper(cpIndex) : + storeFlattenableInstance(cpIndex); } - else if (owningMethod->isFieldQType(cpIndex)) + else { - if (!isFieldResolved(comp(), owningMethod, cpIndex, true)) + TR::Node *value = pop(); + if (comp()->getOption(TR_TraceILGen)) { - abortForUnresolvedValueTypeOp("putfield", "field"); + traceMsg(comp(), "%s: cpIndex %d isFieldFlattened 0 value n%dn isNonNull %d\n", __FUNCTION__, cpIndex, value->getGlobalIndex(), value->isNonNull()); } - else if (owningMethod->isFieldFlattened(comp(), cpIndex, _methodSymbol->isStatic())) + + if (!value->isNonNull()) { - return comp()->getOption(TR_UseFlattenedFieldRuntimeHelpers) ? - storeFlattenableInstanceWithHelper(cpIndex) : - storeFlattenableInstance(cpIndex); + TR::Node *passThruNode = TR::Node::create(TR::PassThrough, 1, value); + genTreeTop(genNullCheck(passThruNode)); } - else - { - TR::Node *value = pop(); - if (comp()->getOption(TR_TraceILGen)) - { - traceMsg(comp(), "%s: cpIndex %d isFieldFlattened 0 value n%dn isNonNull %d\n", __FUNCTION__, cpIndex, value->getGlobalIndex(), value->isNonNull()); - } - - if (!value->isNonNull()) - { - TR::Node *passThruNode = TR::Node::create(TR::PassThrough, 1, value); - genTreeTop(genNullCheck(passThruNode)); - } - push(value); - } + push(value); } } @@ -7266,26 +7247,18 @@ TR_J9ByteCodeIlGenerator::storeStatic(int32_t cpIndex) _staticFieldReferenceEncountered = true; TR::Node * value = pop(); - if (TR::Compiler->om.areFlattenableValueTypesEnabled()) + TR_ResolvedJ9Method * owningMethod = static_cast(_methodSymbol->getResolvedMethod()); + if (owningMethod->isFieldNullRestricted(comp(), cpIndex, true /* isStatic */, true /* isStore */)) { - TR_ResolvedJ9Method * owningMethod = static_cast(_methodSymbol->getResolvedMethod()); - - if (!TR::Compiler->om.isQDescriptorForValueTypesSupported()) + if (comp()->getOption(TR_TraceILGen)) { - TR_ASSERT_FATAL(false, "Support for null-restricted types without Q descriptor is to be implemented!!!"); + traceMsg(comp(), "%s: cpIndex %d isFieldNullRestricted 1 value n%dn isNonNull %d\n", __FUNCTION__, cpIndex, value->getGlobalIndex(), value->isNonNull()); } - else if (owningMethod->isFieldQType(cpIndex)) - { - if (comp()->getOption(TR_TraceILGen)) - { - traceMsg(comp(), "%s: cpIndex %d isFieldQType 1 value %d isNonNull %d\n", __FUNCTION__, cpIndex, value->getGlobalIndex(), value->isNonNull()); - } - if (!value->isNonNull()) - { - TR::Node *passThruNode = TR::Node::create(TR::PassThrough, 1, value); - genTreeTop(genNullCheck(passThruNode)); - } + if (!value->isNonNull()) + { + TR::Node *passThruNode = TR::Node::create(TR::PassThrough, 1, value); + genTreeTop(genNullCheck(passThruNode)); } } diff --git a/runtime/compiler/net/CommunicationStream.hpp b/runtime/compiler/net/CommunicationStream.hpp index 3ba27ce0c39..e75575628a8 100644 --- a/runtime/compiler/net/CommunicationStream.hpp +++ b/runtime/compiler/net/CommunicationStream.hpp @@ -118,7 +118,7 @@ class CommunicationStream // likely to lose an increment when merging/rebasing/etc. // static const uint8_t MAJOR_NUMBER = 1; - static const uint16_t MINOR_NUMBER = 51; // ID: cGK/z3DilpnVN85FsPsD + static const uint16_t MINOR_NUMBER = 52; // ID: vKDVVxR2fImMeQKnbv6I static const uint8_t PATCH_NUMBER = 0; static uint32_t CONFIGURATION_FLAGS; diff --git a/runtime/compiler/net/MessageTypes.cpp b/runtime/compiler/net/MessageTypes.cpp index 9862c3f429f..85c0cae3f1e 100644 --- a/runtime/compiler/net/MessageTypes.cpp +++ b/runtime/compiler/net/MessageTypes.cpp @@ -86,6 +86,7 @@ const char *messageNames[] = "ResolvedMethod_dynamicConstant", "ResolvedMethod_definingClassFromCPFieldRef", "ResolvedMethod_getResolvedImplementorMethods", + "ResolvedMethod_isFieldNullRestricted", "ResolvedMethod_isFieldFlattened", "ResolvedRelocatableMethod_createResolvedRelocatableJ9Method", "ResolvedRelocatableMethod_fieldAttributes", @@ -207,7 +208,6 @@ const char *messageNames[] = "ClassEnv_iTableRomClass", "ClassEnv_getITable", "ClassEnv_enumerateFields", - "ClassEnv_isClassRefPrimitiveValueType", "ClassEnv_flattenedArrayElementSize", "ClassEnv_getDefaultValueSlotAddress", "SharedCache_getClassChainOffsetIdentifyingLoader", diff --git a/runtime/compiler/net/MessageTypes.hpp b/runtime/compiler/net/MessageTypes.hpp index 3ec6e89d9a8..f7dc6b65e22 100644 --- a/runtime/compiler/net/MessageTypes.hpp +++ b/runtime/compiler/net/MessageTypes.hpp @@ -92,6 +92,7 @@ enum MessageType : uint16_t ResolvedMethod_dynamicConstant, ResolvedMethod_definingClassFromCPFieldRef, ResolvedMethod_getResolvedImplementorMethods, + ResolvedMethod_isFieldNullRestricted, ResolvedMethod_isFieldFlattened, ResolvedRelocatableMethod_createResolvedRelocatableJ9Method, @@ -220,7 +221,6 @@ enum MessageType : uint16_t ClassEnv_iTableRomClass, ClassEnv_getITable, ClassEnv_enumerateFields, - ClassEnv_isClassRefPrimitiveValueType, ClassEnv_flattenedArrayElementSize, ClassEnv_getDefaultValueSlotAddress, diff --git a/test/functional/Valhalla/playlist.xml b/test/functional/Valhalla/playlist.xml index 600f6c3f30e..51149731acb 100644 --- a/test/functional/Valhalla/playlist.xml +++ b/test/functional/Valhalla/playlist.xml @@ -292,6 +292,15 @@ ValhallaAttributeTests + + -Xint + -Xint -XX:ValueTypeFlatteningThreshold=99999 -XX:-EnableArrayFlattening + -Xint -XX:ValueTypeFlatteningThreshold=99999 -XX:+EnableArrayFlattening + -Xjit:count=0 + -Xjit:count=1,disableAsyncCompilation + -Xjit:count=1,disableAsyncCompilation -XX:ValueTypeFlatteningThreshold=99999 -XX:-EnableArrayFlattening + -Xjit:count=1,disableAsyncCompilation -XX:ValueTypeFlatteningThreshold=99999 -XX:+EnableArrayFlattening + $(JAVA_COMMAND) $(JVM_OPTIONS) \ -cp $(Q)$(LIB_DIR)$(D)asm.jar$(P)$(RESOURCES_DIR)$(P)$(TESTNG)$(P)$(TEST_RESROOT)$(D)ValhallaTests.jar$(Q) \ org.testng.TestNG -d $(REPORTDIR) $(Q)$(TEST_RESROOT)$(D)testng.xml$(Q) -testnames ValhallaAttributeTests \ diff --git a/test/functional/Valhalla/src/org/openj9/test/lworld/ValhallaAttributeTests.java b/test/functional/Valhalla/src/org/openj9/test/lworld/ValhallaAttributeTests.java index 10f7568a14f..fd9049b2e9c 100644 --- a/test/functional/Valhalla/src/org/openj9/test/lworld/ValhallaAttributeTests.java +++ b/test/functional/Valhalla/src/org/openj9/test/lworld/ValhallaAttributeTests.java @@ -154,11 +154,24 @@ static public void testStaticNullRestrictedFieldWhereImplicitCreationHasNoDefaul c.newInstance(); } + static public Class testPutFieldNullToNullRestrictedFieldClass = null; + static public Class testPutStaticNullToNullRestrictedFieldClass = null; + static public Class testWithFieldStoreNullToNullRestrictedFieldClass = null; + + @Test(priority=1) + static public void testCreateTestPutFieldNullToNullRestrictedField() throws Throwable { + testPutFieldNullToNullRestrictedFieldClass = ValhallaAttributeGenerator.generatePutFieldNullToNullRestrictedField("TestPutFieldNullToNullRestrictedField", "TestPutFieldNullToNullRestrictedFieldField"); + } + /* Instance field with NullRestricted attribute cannot be set to null. */ - @Test(expectedExceptions = java.lang.NullPointerException.class) + @Test(priority=2, invocationCount=2, expectedExceptions = java.lang.NullPointerException.class) static public void testPutFieldNullToNullRestrictedField() throws Throwable { - Class c = ValhallaAttributeGenerator.generatePutFieldNullToNullRestrictedField("TestPutFieldNullToNullRestrictedField", "TestPutFieldNullToNullRestrictedFieldField"); - c.newInstance(); + testPutFieldNullToNullRestrictedFieldClass.newInstance(); + } + + @Test(priority=1) + static public void testCreateTestPutStaticNullToNullRestrictedField() throws Throwable { + testPutStaticNullToNullRestrictedFieldClass = ValhallaAttributeGenerator.generatePutStaticNullToNullRestrictedField("TestPutStaticNullToNullRestrictedField", "TestPutStaticNullToNullRestrictedFieldField"); } /* Static field with NullRestricted attribute cannot be set to null. @@ -167,23 +180,33 @@ static public void testPutFieldNullToNullRestrictedField() throws Throwable { * it should be wrapped in ExceptionInInitializerError. * Since value fields are implicitly final this will always be the case. */ - @Test + @Test(priority=2, invocationCount=2) static public void testPutStaticNullToNullRestrictedField() throws Throwable { try { - Class c = ValhallaAttributeGenerator.generatePutStaticNullToNullRestrictedField("TestPutStaticNullToNullRestrictedField", "TestPutStaticNullToNullRestrictedFieldField"); - c.newInstance(); + testPutStaticNullToNullRestrictedFieldClass.newInstance(); } catch(java.lang.ExceptionInInitializerError e) { if (e.getCause() instanceof NullPointerException) { return; /* pass */ } throw e; + } catch (java.lang.NoClassDefFoundError e) { + // In the second invocation, java.lang.NoClassDefFoundError should be thrown + // because the initialization of Class has previously failed initialization + if (e.getCause() instanceof java.lang.ExceptionInInitializerError) { + return; /* pass */ + } + throw e; } Assert.fail("Test expected a NullPointerException wrapped in ExceptionInInitializerError."); } - @Test(expectedExceptions = java.lang.NullPointerException.class) + @Test(priority=1) + static public void testCreateTestWithFieldStoreNullToNullRestrictedField() throws Throwable { + testWithFieldStoreNullToNullRestrictedFieldClass = ValhallaAttributeGenerator.generateWithFieldStoreNullToNullRestrictedField("TestWithFieldStoreNullToNullRestrictedField", "TestWithFieldStoreNullToNullRestrictedFieldField"); + } + + @Test(priority=2, invocationCount=2, expectedExceptions = java.lang.NullPointerException.class) static public void testWithFieldStoreNullToNullRestrictedField() throws Throwable { - Class c = ValhallaAttributeGenerator.generateWithFieldStoreNullToNullRestrictedField("TestWithFieldStoreNullToNullRestrictedField", "TestWithFieldStoreNullToNullRestrictedFieldField"); - c.newInstance(); + testWithFieldStoreNullToNullRestrictedFieldClass.newInstance(); } }