diff --git a/runtime/compiler/control/JITClientCompilationThread.cpp b/runtime/compiler/control/JITClientCompilationThread.cpp index c628f38610a..79456ffa8af 100644 --- a/runtime/compiler/control/JITClientCompilationThread.cpp +++ b/runtime/compiler/control/JITClientCompilationThread.cpp @@ -617,6 +617,12 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes client->write(response, fe->getArrayClassFromComponentClass(clazz)); } break; + case MessageType::VM_getNullRestrictedArrayClassFromComponentClass: + { + auto clazz = std::get<0>(client->getRecvData()); + client->write(response, fe->getNullRestrictedArrayClassFromComponentClass(clazz)); + } + break; case MessageType::VM_matchRAMclassFromROMclass: { J9ROMClass *clazz = std::get<0>(client->getRecvData()); diff --git a/runtime/compiler/control/JITServerHelpers.cpp b/runtime/compiler/control/JITServerHelpers.cpp index 95169d2057f..4509ae9c0be 100644 --- a/runtime/compiler/control/JITServerHelpers.cpp +++ b/runtime/compiler/control/JITServerHelpers.cpp @@ -969,6 +969,7 @@ JITServerHelpers::cacheRemoteROMClass(ClientSessionData *clientSessionData, J9Cl classInfoStruct._classNameIdentifyingLoader = std::get<22>(classInfoTuple); classInfoStruct._arrayElementSize = std::get<23>(classInfoTuple); classInfoStruct._defaultValueSlotAddress = std::get<24>(classInfoTuple); + classInfoStruct._nullRestrictedArrayClass = std::get<26>(classInfoTuple); auto result = clientSessionData->getROMClassMap().insert({ clazz, classInfoStruct }); @@ -1031,6 +1032,7 @@ JITServerHelpers::packRemoteROMClassInfo(J9Class *clazz, J9VMThread *vmThread, T TR_OpaqueClassBlock *hostClass = fe->convertClassPtrToClassOffset(clazz->hostClass); TR_OpaqueClassBlock *componentClass = fe->getComponentClassFromArrayClass((TR_OpaqueClassBlock *)clazz); TR_OpaqueClassBlock *arrayClass = fe->getArrayClassFromComponentClass((TR_OpaqueClassBlock *)clazz); + TR_OpaqueClassBlock *nullRestrictedArrayClass = fe->getNullRestrictedArrayClassFromComponentClass((TR_OpaqueClassBlock *)clazz); uintptr_t totalInstanceSize = clazz->totalInstanceSize; uintptr_t cp = fe->getConstantPoolFromClass((TR_OpaqueClassBlock *)clazz); uintptr_t classFlags = fe->getClassFlagsValue((TR_OpaqueClassBlock *)clazz); @@ -1082,7 +1084,7 @@ JITServerHelpers::packRemoteROMClassInfo(J9Class *clazz, J9VMThread *vmThread, T classHasFinalFields, classDepthAndFlags, classInitialized, byteOffsetToLockword, leafComponentClass, classLoader, hostClass, componentClass, arrayClass, totalInstanceSize, clazz->romClass, cp, classFlags, classChainOffsetIdentifyingLoader, origROMMethods, classNameIdentifyingLoader, arrayElementSize, - defaultValueSlotAddress, romClassHash + defaultValueSlotAddress, romClassHash, nullRestrictedArrayClass ); } @@ -1261,6 +1263,9 @@ JITServerHelpers::getROMClassData(const ClientSessionData::ClassInfo &classInfo, case CLASSINFO_DEFAULT_VALUE_SLOT_ADDRESS: *(j9object_t **)data = classInfo._defaultValueSlotAddress; break; + case CLASSINFO_NULLRESTRICTED_ARRAY_CLASS : + *(TR_OpaqueClassBlock **)data = classInfo._nullRestrictedArrayClass; + break; default: TR_ASSERT(false, "Class Info not supported %u\n", dataType); break; diff --git a/runtime/compiler/control/JITServerHelpers.hpp b/runtime/compiler/control/JITServerHelpers.hpp index 2465c9c754d..fff02eff31f 100644 --- a/runtime/compiler/control/JITServerHelpers.hpp +++ b/runtime/compiler/control/JITServerHelpers.hpp @@ -57,6 +57,7 @@ class JITServerHelpers CLASSINFO_CLASS_CHAIN_OFFSET_IDENTIFYING_LOADER, CLASSINFO_ARRAY_ELEMENT_SIZE, CLASSINFO_DEFAULT_VALUE_SLOT_ADDRESS, + CLASSINFO_NULLRESTRICTED_ARRAY_CLASS, }; // NOTE: when adding new elements to this tuple, add them to the end, @@ -88,7 +89,8 @@ class JITServerHelpers std::string, // 22: _classNameIdentifyingLoader int32_t, // 23: _arrayElementSize j9object_t *, // 24: _defaultValueSlotAddress - std::string // 25: optional hash of packedROMClass + std::string, // 25: optional hash of packedROMClass + TR_OpaqueClassBlock * // 26: _nullRestrictedArrayClass >; // Packs a ROMClass to be transferred to the server. diff --git a/runtime/compiler/env/J9ClassEnv.cpp b/runtime/compiler/env/J9ClassEnv.cpp index 085ad90eebd..1d0446074d8 100644 --- a/runtime/compiler/env/J9ClassEnv.cpp +++ b/runtime/compiler/env/J9ClassEnv.cpp @@ -902,6 +902,29 @@ J9::ClassEnv::isValueBasedOrValueTypeClass(TR_OpaqueClassBlock *clazz) return J9_ARE_ANY_BITS_SET(j9class->classFlags, J9_CLASS_DISALLOWS_LOCKING_FLAGS); } +bool +J9::ClassEnv::isArrayNullRestricted(TR::Compilation *comp,TR_OpaqueClassBlock *arrayClass) + { +#if defined(J9VM_OPT_JITSERVER) + if (auto stream = comp->getStream()) + { + uintptr_t classFlags = 0; + JITServerHelpers::getAndCacheRAMClassInfo((J9Class *)arrayClass, 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 & J9ClassArrayIsNullRestricted; + classFlagsRemote = classFlagsRemote & J9ClassArrayIsNullRestricted; + TR_ASSERT_FATAL(classFlags == classFlagsRemote, "remote call class flags is not equal to cached class flags"); +#endif + return J9_ARE_ALL_BITS_SET(classFlags, J9ClassArrayIsNullRestricted); + } +#endif /* defined(J9VM_OPT_JITSERVER) */ + J9ArrayClass *j9class = reinterpret_cast(arrayClass); + return J9_IS_J9ARRAYCLASS_NULL_RESTRICTED(j9class); + } + bool J9::ClassEnv::classHasIdentity(TR_OpaqueClassBlock *clazz) { diff --git a/runtime/compiler/env/J9ClassEnv.hpp b/runtime/compiler/env/J9ClassEnv.hpp index 6f832f6493a..0237456f905 100644 --- a/runtime/compiler/env/J9ClassEnv.hpp +++ b/runtime/compiler/env/J9ClassEnv.hpp @@ -96,6 +96,7 @@ class OMR_EXTENSIBLE ClassEnv : public OMR::ClassEnvConnector bool isPrimitiveValueTypeClass(TR_OpaqueClassBlock *); bool isValueTypeClassFlattened(TR_OpaqueClassBlock *clazz); bool isValueBasedOrValueTypeClass(TR_OpaqueClassBlock *); + bool isArrayNullRestricted(TR::Compilation *comp, TR_OpaqueClassBlock *arrayClass); /** \brief * Returns the size of the flattened array element diff --git a/runtime/compiler/env/VMJ9.cpp b/runtime/compiler/env/VMJ9.cpp index 7c257556ccc..ee552820987 100644 --- a/runtime/compiler/env/VMJ9.cpp +++ b/runtime/compiler/env/VMJ9.cpp @@ -7106,6 +7106,13 @@ TR_J9VM::getArrayClassFromComponentClass(TR_OpaqueClassBlock * componentClass) return convertClassPtrToClassOffset(TR::Compiler->cls.convertClassOffsetToClassPtr(componentClass)->arrayClass); } +TR_OpaqueClassBlock * +TR_J9VM::getNullRestrictedArrayClassFromComponentClass(TR_OpaqueClassBlock * componentClass) + { + J9Class *clazz = TR::Compiler->cls.convertClassOffsetToClassPtr(componentClass); + return convertClassPtrToClassOffset(J9CLASS_GET_NULLRESTRICTED_ARRAY(clazz)); + } + TR_OpaqueClassBlock * TR_J9VM::getLeafComponentClassFromArrayClass(TR_OpaqueClassBlock * arrayClass) { @@ -9284,6 +9291,27 @@ TR_J9SharedCacheVM::getArrayClassFromComponentClass(TR_OpaqueClassBlock * compon return NULL; } +TR_OpaqueClassBlock * +TR_J9SharedCacheVM::getNullRestrictedArrayClassFromComponentClass(TR_OpaqueClassBlock * componentClass) + { + TR::Compilation* comp = _compInfoPT->getCompilation(); + TR_ASSERT(comp, "Should be called only within a compilation"); + + bool validated = false; + TR_OpaqueClassBlock *nullRestrictedArrayClass = TR_J9VM::getNullRestrictedArrayClassFromComponentClass(componentClass); + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + validated = comp->getSymbolValidationManager()->addArrayClassFromComponentClassRecord(nullRestrictedArrayClass, componentClass); + } + else + { + validated = ((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) componentClass); + } + + return validated ? nullRestrictedArrayClass : NULL; + } + TR_OpaqueClassBlock * TR_J9SharedCacheVM::getLeafComponentClassFromArrayClass(TR_OpaqueClassBlock * arrayClass) { diff --git a/runtime/compiler/env/VMJ9.h b/runtime/compiler/env/VMJ9.h index 336795de5d6..fdd7bd1a488 100644 --- a/runtime/compiler/env/VMJ9.h +++ b/runtime/compiler/env/VMJ9.h @@ -1559,6 +1559,16 @@ class TR_J9VM : public TR_J9VMBase virtual TR_OpaqueClassBlock * getComponentClassFromArrayClass(TR_OpaqueClassBlock * arrayClass); virtual TR_OpaqueClassBlock * getArrayClassFromComponentClass(TR_OpaqueClassBlock *componentClass); + /** \brief + * Retrieves the nullRestrictedArrayClass from the array component class. + * + * \param componentClass + * The array component class + * + * \return + * A pointer to nullRestrictedArrayClass if it exists, otherwise NULL + */ + virtual TR_OpaqueClassBlock * getNullRestrictedArrayClassFromComponentClass(TR_OpaqueClassBlock *componentClass); virtual TR_OpaqueClassBlock * getLeafComponentClassFromArrayClass(TR_OpaqueClassBlock * arrayClass); virtual int32_t getNewArrayTypeFromClass(TR_OpaqueClassBlock *clazz); virtual TR_OpaqueClassBlock * getClassFromSignature(const char * sig, int32_t length, TR_ResolvedMethod *method, bool isVettedForAOT=false); @@ -1685,6 +1695,16 @@ class TR_J9SharedCacheVM : public TR_J9VM virtual bool isPrimitiveClass(TR_OpaqueClassBlock *clazz); virtual TR_OpaqueClassBlock * getComponentClassFromArrayClass(TR_OpaqueClassBlock * arrayClass); virtual TR_OpaqueClassBlock * getArrayClassFromComponentClass(TR_OpaqueClassBlock *componentClass); + /** \brief + * Retrieves the nullRestrictedArrayClass from the array component class. + * + * \param componentClass + * The array component class + * + * \return + * A pointer to nullRestrictedArrayClass if it exists, otherwise NULL + */ + virtual TR_OpaqueClassBlock * getNullRestrictedArrayClassFromComponentClass(TR_OpaqueClassBlock *componentClass); virtual TR_OpaqueClassBlock * getLeafComponentClassFromArrayClass(TR_OpaqueClassBlock * arrayClass); virtual TR_OpaqueClassBlock * getBaseComponentClass(TR_OpaqueClassBlock * clazz, int32_t & numDims); virtual TR_OpaqueClassBlock * getClassFromNewArrayType(int32_t arrayType); diff --git a/runtime/compiler/env/VMJ9Server.cpp b/runtime/compiler/env/VMJ9Server.cpp index f606237cd2d..0bc52f25216 100644 --- a/runtime/compiler/env/VMJ9Server.cpp +++ b/runtime/compiler/env/VMJ9Server.cpp @@ -1171,6 +1171,30 @@ TR_J9ServerVM::getArrayClassFromComponentClass(TR_OpaqueClassBlock *componentCla return arrayClass; } +TR_OpaqueClassBlock * +TR_J9ServerVM::getNullRestrictedArrayClassFromComponentClass(TR_OpaqueClassBlock *componentClass) + { + JITServer::ServerStream *stream = _compInfoPT->getMethodBeingCompiled()->_stream; + TR_OpaqueClassBlock *nullRestrictedArrayClass = NULL; + JITServerHelpers::getAndCacheRAMClassInfo((J9Class *)componentClass, _compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_NULLRESTRICTED_ARRAY_CLASS, (void *)&nullRestrictedArrayClass); + if (!nullRestrictedArrayClass) + { + stream->write(JITServer::MessageType::VM_getNullRestrictedArrayClassFromComponentClass, componentClass); + nullRestrictedArrayClass = std::get<0>(stream->read()); + if (nullRestrictedArrayClass) + { + // if client initialized nullRestrictedArrayClass, cache the new value + OMR::CriticalSection getRemoteROMClass(_compInfoPT->getClientData()->getROMMapMonitor()); + auto it = _compInfoPT->getClientData()->getROMClassMap().find((J9Class*) componentClass); + if (it != _compInfoPT->getClientData()->getROMClassMap().end()) + { + it->second._nullRestrictedArrayClass = nullRestrictedArrayClass; + } + } + } + return nullRestrictedArrayClass; + } + J9Class * TR_J9ServerVM::matchRAMclassFromROMclass(J9ROMClass *clazz, TR::Compilation *comp) { @@ -3292,6 +3316,26 @@ TR_J9SharedCacheServerVM::getArrayClassFromComponentClass(TR_OpaqueClassBlock * return validated ? arrayClass : NULL; } +TR_OpaqueClassBlock * +TR_J9SharedCacheServerVM::getNullRestrictedArrayClassFromComponentClass(TR_OpaqueClassBlock * componentClass) + { + TR::Compilation* comp = _compInfoPT->getCompilation(); + TR_ASSERT(comp, "Should be called only within a compilation"); + + bool validated = false; + TR_OpaqueClassBlock *nullRestrictedArrayClass = TR_J9ServerVM::getNullRestrictedArrayClassFromComponentClass(componentClass); + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + validated = comp->getSymbolValidationManager()->addArrayClassFromComponentClassRecord(nullRestrictedArrayClass, componentClass); + } + else + { + validated = ((TR_ResolvedRelocatableJ9JITServerMethod *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) componentClass); + } + return validated ? nullRestrictedArrayClass : NULL; + } + TR_OpaqueClassBlock * TR_J9SharedCacheServerVM::getLeafComponentClassFromArrayClass(TR_OpaqueClassBlock * arrayClass) { diff --git a/runtime/compiler/env/VMJ9Server.hpp b/runtime/compiler/env/VMJ9Server.hpp index 727f23a6f70..7036dcc3f25 100644 --- a/runtime/compiler/env/VMJ9Server.hpp +++ b/runtime/compiler/env/VMJ9Server.hpp @@ -126,6 +126,16 @@ class TR_J9ServerVM: public TR_J9VM virtual bool isCloneable(TR_OpaqueClassBlock *clazzPointer) override; virtual bool canAllocateInlineClass(TR_OpaqueClassBlock *clazz) override; virtual TR_OpaqueClassBlock * getArrayClassFromComponentClass(TR_OpaqueClassBlock *componentClass) override; + /** \brief + * Retrieves the nullRestrictedArrayClass from the array component class. + * + * \param componentClass + * The array component class + * + * \return + * A pointer to nullRestrictedArrayClass if it exists, otherwise NULL + */ + virtual TR_OpaqueClassBlock * getNullRestrictedArrayClassFromComponentClass(TR_OpaqueClassBlock *componentClass) override; virtual J9Class * matchRAMclassFromROMclass(J9ROMClass *clazz, TR::Compilation *comp) override; virtual int32_t * getCurrentLocalsMapForDLT(TR::Compilation *comp) override; virtual uintptr_t getReferenceFieldAt(uintptr_t objectPointer, uintptr_t offsetFromHeader) override; @@ -345,6 +355,16 @@ class TR_J9SharedCacheServerVM: public TR_J9ServerVM virtual bool isPrimitiveClass(TR_OpaqueClassBlock *clazzPointer) override; virtual TR_OpaqueClassBlock *getComponentClassFromArrayClass(TR_OpaqueClassBlock *arrayClass) override; virtual TR_OpaqueClassBlock *getArrayClassFromComponentClass(TR_OpaqueClassBlock *componentClass) override; + /** \brief + * Retrieves the nullRestrictedArrayClass from the array component class. + * + * \param componentClass + * The array component class + * + * \return + * A pointer to nullRestrictedArrayClass if it exists, otherwise NULL + */ + virtual TR_OpaqueClassBlock * getNullRestrictedArrayClassFromComponentClass(TR_OpaqueClassBlock *componentClass) override; virtual TR_OpaqueClassBlock *getLeafComponentClassFromArrayClass(TR_OpaqueClassBlock *arrayClass) override; virtual TR_OpaqueClassBlock *getBaseComponentClass(TR_OpaqueClassBlock *clazz, int32_t & numDims) override; virtual TR_OpaqueClassBlock *getClassFromNewArrayType(int32_t arrayType) override; diff --git a/runtime/compiler/net/CommunicationStream.hpp b/runtime/compiler/net/CommunicationStream.hpp index fc379a725d9..24eddcc1283 100644 --- a/runtime/compiler/net/CommunicationStream.hpp +++ b/runtime/compiler/net/CommunicationStream.hpp @@ -128,7 +128,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 = 67; // ID: eJ9ynEzY1XevZygVpTws + static const uint16_t MINOR_NUMBER = 68; // ID: JVYubJGrIrWjb+DHoQBY 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 b3d0ee619a7..02d1dd47843 100644 --- a/runtime/compiler/net/MessageTypes.cpp +++ b/runtime/compiler/net/MessageTypes.cpp @@ -122,6 +122,7 @@ const char *messageNames[] = "VM_classInitIsFinished", "VM_getClassFromNewArrayType", "VM_getArrayClassFromComponentClass", + "VM_getNullRestrictedArrayClassFromComponentClass", "VM_matchRAMclassFromROMclass", "VM_getInt32FieldAt", "VM_getInt64FieldAt", diff --git a/runtime/compiler/net/MessageTypes.hpp b/runtime/compiler/net/MessageTypes.hpp index aa696bbb08c..0e88fb04fee 100644 --- a/runtime/compiler/net/MessageTypes.hpp +++ b/runtime/compiler/net/MessageTypes.hpp @@ -131,6 +131,7 @@ enum MessageType : uint16_t VM_classInitIsFinished, VM_getClassFromNewArrayType, VM_getArrayClassFromComponentClass, + VM_getNullRestrictedArrayClassFromComponentClass, VM_matchRAMclassFromROMclass, VM_getInt32FieldAt, VM_getInt64FieldAt, diff --git a/runtime/compiler/runtime/JITClientSession.cpp b/runtime/compiler/runtime/JITClientSession.cpp index e2ca7bcd1f6..4f30a444d59 100644 --- a/runtime/compiler/runtime/JITClientSession.cpp +++ b/runtime/compiler/runtime/JITClientSession.cpp @@ -413,6 +413,7 @@ ClientSessionData::ClassInfo::ClassInfo(TR_PersistentMemory *persistentMemory) : _aotCacheClassRecord(NULL), _arrayElementSize(0), _defaultValueSlotAddress(NULL), + _nullRestrictedArrayClass(NULL), _classOfStaticCache(decltype(_classOfStaticCache)::allocator_type(persistentMemory->_persistentAllocator.get())), _constantClassPoolCache(decltype(_constantClassPoolCache)::allocator_type(persistentMemory->_persistentAllocator.get())), _fieldAttributesCache(decltype(_fieldAttributesCache)::allocator_type(persistentMemory->_persistentAllocator.get())), diff --git a/runtime/compiler/runtime/JITClientSession.hpp b/runtime/compiler/runtime/JITClientSession.hpp index e5c7a1f7988..4d0e8c6cff7 100644 --- a/runtime/compiler/runtime/JITClientSession.hpp +++ b/runtime/compiler/runtime/JITClientSession.hpp @@ -203,6 +203,7 @@ class ClientSessionData TR_OpaqueClassBlock *_hostClass; TR_OpaqueClassBlock *_componentClass; // caching the componentType of the J9ArrayClass TR_OpaqueClassBlock *_arrayClass; + TR_OpaqueClassBlock *_nullRestrictedArrayClass; uintptr_t _totalInstanceSize; J9ConstantPool *_constantPool; uintptr_t _classFlags; diff --git a/runtime/compiler/runtime/SymbolValidationManager.cpp b/runtime/compiler/runtime/SymbolValidationManager.cpp index 4d7cb23e238..dc16b86daee 100644 --- a/runtime/compiler/runtime/SymbolValidationManager.cpp +++ b/runtime/compiler/runtime/SymbolValidationManager.cpp @@ -1252,7 +1252,12 @@ TR::SymbolValidationManager::validateArrayClassFromComponentClassRecord(uint16_t if (isDefinedID(componentClassID)) { TR_OpaqueClassBlock *componentClass = getClassFromID(componentClassID); - return validateSymbol(arrayClassID, _fej9->getArrayClassFromComponentClass(componentClass)); + if (validateSymbol(arrayClassID, _fej9->getArrayClassFromComponentClass(componentClass))) + return true; + + TR_OpaqueClassBlock *nullRestrictedArray = TR::Compiler->om.areFlattenableValueTypesEnabled() ? + _fej9->getNullRestrictedArrayClassFromComponentClass(componentClass) : NULL; + return nullRestrictedArray ? validateSymbol(arrayClassID, nullRestrictedArray) : false; } else {