From bf518c3f6dada23175a72619aac33333fd7a7caa Mon Sep 17 00:00:00 2001 From: Marius Pirvu Date: Tue, 4 Feb 2025 15:42:04 -0500 Subject: [PATCH] Reduce the number of VM_isStable messages The frontend query `isStable(J9Class *fieldClass, int32_t cpIndex)` determines if the field at given J9Class and cpIndex has the @Stable annotation. Before this commit, the JITServer implementation had to send a VM_isStable message to the client for every such query. This commit implements caching of the isStable values at JITServer. Caching is done with a hashtable per J9Class, where the key is the cpIndex we are interested in. To further reduce the number of the hashtables that serve as a cache, the `isStable()` will answer `false` for any non-bootstrap class. The reason is that at the moment only bootstrap classs have the @stable annotation. This behavior can be disabled by defining the following environment variable: `TR_DontIgnoreStableAnnotationForUserClasses`. Another optimization regards the implementation of `isArrayWithStableElements(cpIndex, owningMethod, comp)`. In here, we first check to see if we are dealing with an array (which is simpler) and only then call the isStable() query. Signed-off-by: Marius Pirvu --- .../control/JITClientCompilationThread.cpp | 2 +- runtime/compiler/control/JITServerHelpers.cpp | 12 +++++ runtime/compiler/control/JITServerHelpers.hpp | 1 + runtime/compiler/env/VMJ9.cpp | 39 ++-------------- runtime/compiler/env/VMJ9.h | 7 ++- runtime/compiler/env/VMJ9Server.cpp | 30 ++++++++++++- runtime/compiler/env/VMJ9Server.hpp | 4 +- runtime/compiler/env/j9method.cpp | 27 +++++++++++ runtime/compiler/env/j9method.h | 1 + runtime/compiler/env/j9methodServer.cpp | 39 ++++++---------- runtime/compiler/net/CommunicationStream.hpp | 2 +- .../compiler/optimizer/J9TransformUtil.cpp | 45 +++++++++---------- runtime/compiler/runtime/JITClientSession.cpp | 1 + runtime/compiler/runtime/JITClientSession.hpp | 1 + 14 files changed, 116 insertions(+), 95 deletions(-) diff --git a/runtime/compiler/control/JITClientCompilationThread.cpp b/runtime/compiler/control/JITClientCompilationThread.cpp index 5f0ae628a19..8abe816d966 100644 --- a/runtime/compiler/control/JITClientCompilationThread.cpp +++ b/runtime/compiler/control/JITClientCompilationThread.cpp @@ -1275,7 +1275,7 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes { auto recv = client->getRecvData(); J9Class *fieldClass = std::get<0>(recv); - int cpIndex = std::get<1>(recv); + int32_t cpIndex = std::get<1>(recv); bool isStable = fe->isStable(fieldClass, cpIndex); client->write(response, isStable); diff --git a/runtime/compiler/control/JITServerHelpers.cpp b/runtime/compiler/control/JITServerHelpers.cpp index 36941164bac..05d9f9310d0 100644 --- a/runtime/compiler/control/JITServerHelpers.cpp +++ b/runtime/compiler/control/JITServerHelpers.cpp @@ -1280,6 +1280,18 @@ JITServerHelpers::getROMClassData(const ClientSessionData::ClassInfo &classInfo, } } +ClientSessionData::ClassInfo & +JITServerHelpers::getJ9ClassInfo(TR::CompilationInfoPerThread *threadCompInfo, J9Class *clazz) + { + // This function assumes that you are inside of _romMapMonitor + // Do not use it otherwise + auto &classMap = threadCompInfo->getClientData()->getROMClassMap(); + auto it = classMap.find(clazz); + TR_ASSERT_FATAL(it != classMap.end(),"compThreadID %d, ClientData %p, clazz %p: ClassInfo is not in the class map %p!!\n", + threadCompInfo->getCompThreadId(), threadCompInfo->getClientData(), clazz, &classMap); + return it->second; + } + J9ROMMethod * JITServerHelpers::romMethodOfRamMethod(J9Method* method) { diff --git a/runtime/compiler/control/JITServerHelpers.hpp b/runtime/compiler/control/JITServerHelpers.hpp index fff02eff31f..5063554d83a 100644 --- a/runtime/compiler/control/JITServerHelpers.hpp +++ b/runtime/compiler/control/JITServerHelpers.hpp @@ -116,6 +116,7 @@ class JITServerHelpers static bool getAndCacheRAMClassInfo(J9Class *clazz, ClientSessionData *clientSessionData, JITServer::ServerStream *stream, ClassInfoDataType dataType1, void *data1, ClassInfoDataType dataType2, void *data2); + static ClientSessionData::ClassInfo &getJ9ClassInfo(TR::CompilationInfoPerThread *threadCompInfo, J9Class *clazz); static J9ROMMethod *romMethodOfRamMethod(J9Method* method); static void insertIntoOOSequenceEntryList(ClientSessionData *clientData, TR_MethodToBeCompiled *entry); diff --git a/runtime/compiler/env/VMJ9.cpp b/runtime/compiler/env/VMJ9.cpp index 428f329a5d7..f34ef659724 100644 --- a/runtime/compiler/env/VMJ9.cpp +++ b/runtime/compiler/env/VMJ9.cpp @@ -1250,9 +1250,8 @@ TR_J9VMBase::getObjectClassInfoFromObjectReferenceLocation(TR::Compilation *comp if (knot) { TR::VMAccessCriticalSection getObjectReferenceLocation(comp); - uintptr_t objectReference = getStaticReferenceFieldAtAddress - (objectReferenceLocation); - ci.clazz = getObjectClass(objectReference); + uintptr_t objectReference = getStaticReferenceFieldAtAddress(objectReferenceLocation); + ci.clazz = getObjectClass(objectReference); ci.isString = isString(ci.clazz); ci.jlClass = getClassClassPointer(ci.clazz); ci.isFixedJavaLangClass = (ci.jlClass == ci.clazz); @@ -3936,7 +3935,7 @@ TR_J9VMBase::canDereferenceAtCompileTimeWithFieldSymbol(TR::Symbol * fieldSymbol { TR::Compilation *comp = TR::comp(); - if (isStable(cpIndex, owningMethod, comp)) + if (owningMethod->isStable(cpIndex, comp)) return true; switch (fieldSymbol->getRecognizedField()) @@ -4013,37 +4012,7 @@ TR_J9VMBase::canDereferenceAtCompileTime(TR::SymbolReference *fieldRef, TR::Comp } bool -TR_J9VMBase::isStable(int cpIndex, TR_ResolvedMethod *owningMethod, TR::Compilation *comp) - { - // NOTE: the field must be resolved! - - if (comp->getOption(TR_DisableStableAnnotations)) - return false; - - if (cpIndex < 0) - return false; - - J9Class *fieldClass = (J9Class*)owningMethod->classOfMethod(); - if (!fieldClass) - return false; - - bool isFieldStable = isStable(fieldClass, cpIndex); - - if (isFieldStable && comp->getOption(TR_TraceOptDetails)) - { - int classLen; - const char * className= owningMethod->classNameOfFieldOrStatic(cpIndex, classLen); - int fieldLen; - const char * fieldName = owningMethod->fieldNameChars(cpIndex, fieldLen); - traceMsg(comp, " Found stable field: %.*s.%.*s\n", classLen, className, fieldLen, fieldName); - } - - // Not checking for JCL classes since @Stable annotation only visible inside JCL - return isFieldStable; - } - -bool -TR_J9VMBase::isStable(J9Class *fieldClass, int cpIndex) +TR_J9VMBase::isStable(J9Class *fieldClass, int32_t cpIndex) { TR_ASSERT_FATAL(fieldClass, "fieldClass must not be NULL"); return jitIsFieldStable(vmThread(), fieldClass, cpIndex); diff --git a/runtime/compiler/env/VMJ9.h b/runtime/compiler/env/VMJ9.h index 8e1d7933de6..6d8e2847e90 100644 --- a/runtime/compiler/env/VMJ9.h +++ b/runtime/compiler/env/VMJ9.h @@ -1081,8 +1081,7 @@ class TR_J9VMBase : public TR_FrontEnd * the method accessing the field * */ - virtual bool isStable(int cpIndex, TR_ResolvedMethod *owningMethod, TR::Compilation *comp); - virtual bool isStable(J9Class *fieldClass, int cpIndex); + virtual bool isStable(J9Class *fieldClass, int32_t cpIndex); /* * \brief @@ -1671,8 +1670,8 @@ class TR_J9SharedCacheVM : public TR_J9VM virtual bool supportsJitMethodEntryAlignment() { return false; } virtual bool isBenefitInliningCheckIfFinalizeObject() { return true; } virtual bool needsContiguousCodeAndDataCacheAllocation() { return true; } - virtual bool needRelocatableTarget() { return true; } - virtual bool isStable(int cpIndex, TR_ResolvedMethod *owningMethod, TR::Compilation *comp) { return false; } + virtual bool needRelocatableTarget() { return true; } + virtual bool isStable(J9Class *fieldClass, int32_t cpIndex) { return false; } virtual bool isResolvedDirectDispatchGuaranteed(TR::Compilation *comp); virtual bool isResolvedVirtualDispatchGuaranteed(TR::Compilation *comp); diff --git a/runtime/compiler/env/VMJ9Server.cpp b/runtime/compiler/env/VMJ9Server.cpp index e90136f306c..382d7c6176a 100644 --- a/runtime/compiler/env/VMJ9Server.cpp +++ b/runtime/compiler/env/VMJ9Server.cpp @@ -2518,11 +2518,37 @@ TR_J9ServerVM::isLambdaFormGeneratedMethod(TR_ResolvedMethod *method) } bool -TR_J9ServerVM::isStable(J9Class *fieldClass, int cpIndex) +TR_J9ServerVM::isStable(J9Class *fieldClass, int32_t cpIndex) { + // See if we cached the presence of the annotation for this class and cpIndex + { + OMR::CriticalSection getRemoteROMClass(_compInfoPT->getClientData()->getROMMapMonitor()); + // The fieldClass is guaranteed to be cached at the server because this + // method is called from a ResolvedMethod + auto &cache = JITServerHelpers::getJ9ClassInfo(_compInfoPT, fieldClass)._isStableCache; + auto it = cache.find(cpIndex); + if (it != cache.end()) + return it->second; + } + // At the moment, @Stable annotations are only used in bootstrap classes (this can change though). + // To limit the number of VM_isStable messages further and to reduce the number of values that + // are cached in "_isStableCache" cache, we return 'false' when the `fieldClass` is not a bootstrap class. + static char *dontIgnore = feGetEnv("TR_DontIgnoreStableAnnotationForUserClasses"); + if (!dontIgnore && !isClassLibraryClass((TR_OpaqueClassBlock*)fieldClass)) + return false; + + // Not cached; send a message and obtain the value JITServer::ServerStream *stream = _compInfoPT->getMethodBeingCompiled()->_stream; stream->write(JITServer::MessageType::VM_isStable, fieldClass, cpIndex); - return std::get<0>(stream->read()); + bool answer = std::get<0>(stream->read()); + + // Cache the answer + { + OMR::CriticalSection getRemoteROMClass(_compInfoPT->getClientData()->getROMMapMonitor()); + auto &cache = JITServerHelpers::getJ9ClassInfo(_compInfoPT, fieldClass)._isStableCache; + cache.insert({cpIndex, answer}); + } + return answer; } bool diff --git a/runtime/compiler/env/VMJ9Server.hpp b/runtime/compiler/env/VMJ9Server.hpp index ae29c0092bb..bdae274a4e6 100644 --- a/runtime/compiler/env/VMJ9Server.hpp +++ b/runtime/compiler/env/VMJ9Server.hpp @@ -172,7 +172,7 @@ class TR_J9ServerVM: public TR_J9VM virtual uintptr_t getClassFlagsValue(TR_OpaqueClassBlock * clazz) override; virtual TR_OpaqueMethodBlock *getMethodFromName(const char *className, const char *methodName, const char *signature) override; virtual TR_OpaqueMethodBlock *getMethodFromClass(TR_OpaqueClassBlock *methodClass, const char *methodName, const char *signature, TR_OpaqueClassBlock *callingClass) override; - virtual bool isStable(J9Class *fieldClass, int cpIndex) override; + virtual bool isStable(J9Class *fieldClass, int32_t cpIndex) override; virtual bool isForceInline(TR_ResolvedMethod *method) override; virtual bool isIntrinsicCandidate(TR_ResolvedMethod *method) override; virtual bool isDontInline(TR_ResolvedMethod *method) override; @@ -333,7 +333,7 @@ class TR_J9SharedCacheServerVM: public TR_J9ServerVM virtual bool isResolvedVirtualDispatchGuaranteed(TR::Compilation *comp) override; virtual bool shouldDelayAotLoad() override { return true; } - virtual bool isStable(int cpIndex, TR_ResolvedMethod *owningMethod, TR::Compilation *comp) override { return false; } + virtual bool isStable(J9Class *fieldClass, int32_t cpIndex) override { return false; } virtual bool isClassVisible(TR_OpaqueClassBlock *sourceClass, TR_OpaqueClassBlock *destClass) override; virtual bool stackWalkerMaySkipFrames(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass) override; virtual bool isMethodTracingEnabled(TR_OpaqueMethodBlock *method) override; diff --git a/runtime/compiler/env/j9method.cpp b/runtime/compiler/env/j9method.cpp index 72300651d5c..2de0aad91b8 100644 --- a/runtime/compiler/env/j9method.cpp +++ b/runtime/compiler/env/j9method.cpp @@ -6449,6 +6449,33 @@ TR_ResolvedJ9Method::getClassFromCP(TR_J9VMBase *fej9, J9ConstantPool *cp, TR::C return result; } +bool +TR_ResolvedJ9Method::isStable(int32_t cpIndex, TR::Compilation *comp) + { + if (comp->getOption(TR_DisableStableAnnotations)) + return false; + + if (cpIndex < 0) + return false; + + J9Class *fieldClass = (J9Class*)classOfMethod(); + if (!fieldClass) + return false; + + bool isFieldStable = fej9()->isStable(fieldClass, cpIndex); + + if (isFieldStable && comp->getOption(TR_TraceOptDetails)) + { + int classLen; + const char * className= classNameOfFieldOrStatic(cpIndex, classLen); + int fieldLen; + const char * fieldName = fieldNameChars(cpIndex, fieldLen); + traceMsg(comp, " Found stable field: %.*s.%.*s\n", classLen, className, fieldLen, fieldName); + } + + return isFieldStable; + } + TR_OpaqueClassBlock * TR_ResolvedJ9Method::getClassFromConstantPool(TR::Compilation * comp, uint32_t cpIndex, bool) { diff --git a/runtime/compiler/env/j9method.h b/runtime/compiler/env/j9method.h index 2b3583f8bba..39f917bb2bd 100644 --- a/runtime/compiler/env/j9method.h +++ b/runtime/compiler/env/j9method.h @@ -412,6 +412,7 @@ class TR_ResolvedJ9Method : public TR_J9Method, public TR_ResolvedJ9MethodBase virtual void * callSiteTableEntryAddress(int32_t callSiteIndex); virtual bool isUnresolvedMethodTypeTableEntry(int32_t cpIndex); virtual void * methodTypeTableEntryAddress(int32_t cpIndex); + virtual bool isStable(int32_t cpIndex, TR::Compilation *comp) override; #if defined(J9VM_OPT_METHOD_HANDLE) virtual bool isUnresolvedVarHandleMethodTypeTableEntry(int32_t cpIndex); virtual void * varHandleMethodTypeTableEntryAddress(int32_t cpIndex); diff --git a/runtime/compiler/env/j9methodServer.cpp b/runtime/compiler/env/j9methodServer.cpp index 4ddda39061f..238922fa38a 100644 --- a/runtime/compiler/env/j9methodServer.cpp +++ b/runtime/compiler/env/j9methodServer.cpp @@ -31,17 +31,6 @@ #include "ilgen/J9ByteCodeIterator.hpp" #include "net/ServerStream.hpp" -ClientSessionData::ClassInfo & -getJ9ClassInfo(TR::CompilationInfoPerThread *threadCompInfo, J9Class *clazz) - { - // This function assumes that you are inside of _romMapMonitor - // Do not use it otherwise - auto &classMap = threadCompInfo->getClientData()->getROMClassMap(); - auto it = classMap.find(clazz); - TR_ASSERT_FATAL(it != classMap.end(),"compThreadID %d, ClientData %p, clazz %p: ClassInfo is not in the class map %p!!\n", - threadCompInfo->getCompThreadId(), threadCompInfo->getClientData(), clazz, &classMap); - return it->second; - } static J9ROMMethod * romMethodAtClassIndex(J9ROMClass *romClass, uint64_t methodIndex) @@ -151,7 +140,7 @@ TR_ResolvedJ9JITServerMethod::definingClassFromCPFieldRef(TR::Compilation *comp, TR::CompilationInfoPerThread *compInfoPT = _fe->_compInfoPT; { OMR::CriticalSection getRemoteROMClass(compInfoPT->getClientData()->getROMMapMonitor()); - auto &cache = getJ9ClassInfo(compInfoPT, _ramClass)._fieldOrStaticDefiningClassCache; + auto &cache = JITServerHelpers::getJ9ClassInfo(compInfoPT, _ramClass)._fieldOrStaticDefiningClassCache; auto it = cache.find(cpIndex); if (it != cache.end()) { @@ -166,7 +155,7 @@ TR_ResolvedJ9JITServerMethod::definingClassFromCPFieldRef(TR::Compilation *comp, if (resolvedClass) { OMR::CriticalSection getRemoteROMClass(compInfoPT->getClientData()->getROMMapMonitor()); - auto &cache = getJ9ClassInfo(compInfoPT, _ramClass)._fieldOrStaticDefiningClassCache; + auto &cache = JITServerHelpers::getJ9ClassInfo(compInfoPT, _ramClass)._fieldOrStaticDefiningClassCache; cache.insert({cpIndex, resolvedClass}); } if (fromResolvedJ9Method != NULL) @@ -193,7 +182,7 @@ TR_ResolvedJ9JITServerMethod::getClassFromConstantPool(TR::Compilation * comp, u // This persistent cache must only be checked when doRuntimeResolve is false, // otherwise a non method handle thunk compilation can return cached value, instead of NULL. OMR::CriticalSection getRemoteROMClass(compInfoPT->getClientData()->getROMMapMonitor()); - auto &constantClassPoolCache = getJ9ClassInfo(compInfoPT, _ramClass)._constantClassPoolCache; + auto &constantClassPoolCache = JITServerHelpers::getJ9ClassInfo(compInfoPT, _ramClass)._constantClassPoolCache; auto it = constantClassPoolCache.find(cpIndex); if (it != constantClassPoolCache.end()) return it->second; @@ -204,7 +193,7 @@ TR_ResolvedJ9JITServerMethod::getClassFromConstantPool(TR::Compilation * comp, u if (resolvedClass) { OMR::CriticalSection getRemoteROMClass(compInfoPT->getClientData()->getROMMapMonitor()); - auto &constantClassPoolCache = getJ9ClassInfo(compInfoPT, _ramClass)._constantClassPoolCache; + auto &constantClassPoolCache = JITServerHelpers::getJ9ClassInfo(compInfoPT, _ramClass)._constantClassPoolCache; constantClassPoolCache.insert({cpIndex, resolvedClass}); } return resolvedClass; @@ -216,7 +205,7 @@ TR_ResolvedJ9JITServerMethod::getDeclaringClassFromFieldOrStatic(TR::Compilation TR::CompilationInfoPerThread *compInfoPT = _fe->_compInfoPT; { OMR::CriticalSection getRemoteROMClass(compInfoPT->getClientData()->getROMMapMonitor()); - auto &cache = getJ9ClassInfo(compInfoPT, _ramClass)._fieldOrStaticDeclaringClassCache; + auto &cache = JITServerHelpers::getJ9ClassInfo(compInfoPT, _ramClass)._fieldOrStaticDeclaringClassCache; auto it = cache.find(cpIndex); if (it != cache.end()) return it->second; @@ -226,7 +215,7 @@ TR_ResolvedJ9JITServerMethod::getDeclaringClassFromFieldOrStatic(TR::Compilation if (declaringClass) { OMR::CriticalSection getRemoteROMClass(compInfoPT->getClientData()->getROMMapMonitor()); - auto &cache = getJ9ClassInfo(compInfoPT, _ramClass)._fieldOrStaticDeclaringClassCache; + auto &cache = JITServerHelpers::getJ9ClassInfo(compInfoPT, _ramClass)._fieldOrStaticDeclaringClassCache; cache.insert({cpIndex, declaringClass}); } return declaringClass; @@ -242,7 +231,7 @@ TR_ResolvedJ9JITServerMethod::classOfStatic(I_32 cpIndex, bool returnClassForAOT auto compInfoPT = static_cast(_fe->_compInfoPT); { OMR::CriticalSection getRemoteROMClass(compInfoPT->getClientData()->getROMMapMonitor()); - auto &classOfStaticCache = getJ9ClassInfo(compInfoPT, _ramClass)._classOfStaticCache; + auto &classOfStaticCache = JITServerHelpers::getJ9ClassInfo(compInfoPT, _ramClass)._classOfStaticCache; auto it = classOfStaticCache.find(cpIndex); if (it != classOfStaticCache.end()) return it->second; @@ -260,7 +249,7 @@ TR_ResolvedJ9JITServerMethod::classOfStatic(I_32 cpIndex, bool returnClassForAOT // if client returned NULL, don't cache, because class might not be fully initialized, // so the result may change in the future OMR::CriticalSection getRemoteROMClass(compInfoPT->getClientData()->getROMMapMonitor()); - auto &classOfStaticCache = getJ9ClassInfo(compInfoPT, _ramClass)._classOfStaticCache; + auto &classOfStaticCache = JITServerHelpers::getJ9ClassInfo(compInfoPT, _ramClass)._classOfStaticCache; classOfStaticCache.insert({cpIndex, classOfStatic}); } else @@ -534,8 +523,8 @@ TR_ResolvedJ9JITServerMethod::getAttributesCache(bool isStatic, bool unresolvedI // Return a persistent attributes cache for regular JIT compilations TR::CompilationInfoPerThread *compInfoPT = _fe->_compInfoPT; auto &attributesCache = isStatic ? - getJ9ClassInfo(compInfoPT, _ramClass)._staticAttributesCache : - getJ9ClassInfo(compInfoPT, _ramClass)._fieldAttributesCache; + JITServerHelpers::getJ9ClassInfo(compInfoPT, _ramClass)._staticAttributesCache : + JITServerHelpers::getJ9ClassInfo(compInfoPT, _ramClass)._fieldAttributesCache; return attributesCache; } @@ -2738,8 +2727,8 @@ TR_ResolvedRelocatableJ9JITServerMethod::getAttributesCache(bool isStatic, bool // Return persistent attributes cache for AOT compilations TR::CompilationInfoPerThread *compInfoPT = _fe->_compInfoPT; auto &attributesCache = isStatic ? - getJ9ClassInfo(compInfoPT, _ramClass)._staticAttributesCacheAOT : - getJ9ClassInfo(compInfoPT, _ramClass)._fieldAttributesCacheAOT; + JITServerHelpers::getJ9ClassInfo(compInfoPT, _ramClass)._staticAttributesCacheAOT : + JITServerHelpers::getJ9ClassInfo(compInfoPT, _ramClass)._fieldAttributesCacheAOT; return attributesCache; } @@ -2775,7 +2764,7 @@ TR_J9ServerMethod::TR_J9ServerMethod(TR_FrontEnd * fe, TR_Memory * trMemory, J9C { // look up parameters for construction of this method in a cache first OMR::CriticalSection getRemoteROMClass(compInfoPT->getClientData()->getROMMapMonitor()); - auto &cache = getJ9ClassInfo(compInfoPT, aClazz)._J9MethodNameCache; + auto &cache = JITServerHelpers::getJ9ClassInfo(compInfoPT, aClazz)._J9MethodNameCache; // search the cache for existing method parameters auto it = cache.find(cpIndex); if (it != cache.end()) @@ -2799,7 +2788,7 @@ TR_J9ServerMethod::TR_J9ServerMethod(TR_FrontEnd * fe, TR_Memory * trMemory, J9C methodSignatureStr = std::get<2>(recv); OMR::CriticalSection getRemoteROMClass(compInfoPT->getClientData()->getROMMapMonitor()); - auto &cache = getJ9ClassInfo(compInfoPT, aClazz)._J9MethodNameCache; + auto &cache = JITServerHelpers::getJ9ClassInfo(compInfoPT, aClazz)._J9MethodNameCache; cache.insert({cpIndex, {classNameStr, methodNameStr, methodSignatureStr}}); } diff --git a/runtime/compiler/net/CommunicationStream.hpp b/runtime/compiler/net/CommunicationStream.hpp index 86e8cc0ec84..ebfb9d3c231 100644 --- a/runtime/compiler/net/CommunicationStream.hpp +++ b/runtime/compiler/net/CommunicationStream.hpp @@ -129,7 +129,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 = 77; // ID: J440z7/ZN5+KF233VhGB + static const uint16_t MINOR_NUMBER = 78; // ID: DGwBSxx9FLiSwWTdQCIn static const uint8_t PATCH_NUMBER = 0; static uint32_t CONFIGURATION_FLAGS; diff --git a/runtime/compiler/optimizer/J9TransformUtil.cpp b/runtime/compiler/optimizer/J9TransformUtil.cpp index 5813267720e..1c3f5407776 100644 --- a/runtime/compiler/optimizer/J9TransformUtil.cpp +++ b/runtime/compiler/optimizer/J9TransformUtil.cpp @@ -277,10 +277,9 @@ bool J9::TransformUtil::avoidFoldingInstanceField( TR_ASSERT_FATAL( fej9->canDereferenceAtCompileTimeWithFieldSymbol(field, cpIndex, owningMethod), - "avoidFoldingInstanceField: symbol %p is never foldable (expected possibly foldable)\n", - field); + "avoidFoldingInstanceField: symbol %p is never foldable (expected possibly foldable)\n", field); - if (fej9->isStable(cpIndex, owningMethod, comp) && !field->isFinal()) + if (owningMethod->isStable(cpIndex, comp) && !field->isFinal()) { uintptr_t fieldAddress = object + fieldOffset; TR::DataType loadType = field->getDataType(); @@ -386,30 +385,27 @@ static bool isArrayWithConstantElements(TR::SymbolReference *symRef, TR::Compila static int32_t isArrayWithStableElements(int32_t cpIndex, TR_ResolvedMethod *owningMethod, TR::Compilation *comp) { TR_J9VMBase *fej9 = comp->fej9(); - if (fej9->isStable(cpIndex, owningMethod, comp)) - { - int32_t signatureLength = 0; - char *signature = owningMethod->classSignatureOfFieldOrStatic(cpIndex, signatureLength); - - if (signature) - { - int32_t rank = 0; - for (int32_t i = 0; i < signatureLength; i++) - { - if (signature[i] != '[') break; - rank++; - } - - if (comp->getOption(TR_TraceOptDetails) && rank > 0) - traceMsg(comp, "Stable array with rank %d: %.*s\n", rank, signatureLength, signature); - - return rank; - } + // First determine if we are dealing with an array + int32_t signatureLength = 0; + char *signature = owningMethod->classSignatureOfFieldOrStatic(cpIndex, signatureLength); + if (!signature || signature[0] != '[') + return 0; + // Then, check the stable annotation + if (!owningMethod->isStable(cpIndex, comp)) + return 0; + // Finally, determine the rank + int32_t rank = 1; + for (; rank < signatureLength; rank++) + { + if (signature[rank] != '[') + break; } - return 0; - } + if (comp->getOption(TR_TraceOptDetails)) + traceMsg(comp, "Stable array with rank %d: %.*s\n", rank, signatureLength, signature); + return rank; + } static bool verifyFieldAccess(void *curStruct, TR::SymbolReference *field, bool isStableArrayElement, TR::Compilation *comp) { @@ -2192,7 +2188,6 @@ J9::TransformUtil::transformIndirectLoadChainImpl(TR::Compilation *comp, node->setSymbolReference(improvedSymRef); node->setIsNull(false); node->setIsNonNull(true); - int32_t stableArrayRank = isArrayWithStableElements(symRef->getCPIndex(), symRef->getOwningMethod(comp), comp); diff --git a/runtime/compiler/runtime/JITClientSession.cpp b/runtime/compiler/runtime/JITClientSession.cpp index 4f30a444d59..b5f74e14c3b 100644 --- a/runtime/compiler/runtime/JITClientSession.cpp +++ b/runtime/compiler/runtime/JITClientSession.cpp @@ -424,6 +424,7 @@ ClientSessionData::ClassInfo::ClassInfo(TR_PersistentMemory *persistentMemory) : _fieldOrStaticDeclaringClassCache(decltype(_fieldOrStaticDeclaringClassCache)::allocator_type(persistentMemory->_persistentAllocator.get())), _fieldOrStaticDefiningClassCache(decltype(_fieldOrStaticDefiningClassCache)::allocator_type(persistentMemory->_persistentAllocator.get())), _J9MethodNameCache(decltype(_J9MethodNameCache)::allocator_type(persistentMemory->_persistentAllocator.get())), + _isStableCache(decltype(_isStableCache)::allocator_type(persistentMemory->_persistentAllocator.get())), _referencingClassLoaders(decltype(_referencingClassLoaders)::allocator_type(persistentMemory->_persistentAllocator.get())) { } diff --git a/runtime/compiler/runtime/JITClientSession.hpp b/runtime/compiler/runtime/JITClientSession.hpp index d3ffca20207..6c00d6f90c1 100644 --- a/runtime/compiler/runtime/JITClientSession.hpp +++ b/runtime/compiler/runtime/JITClientSession.hpp @@ -225,6 +225,7 @@ class ClientSessionData // a different API to populate it. In the future we may want to unify these two caches PersistentUnorderedMap _fieldOrStaticDefiningClassCache; PersistentUnorderedMap _J9MethodNameCache; // key is a cpIndex + PersistentUnorderedMap _isStableCache; // Store the presence of the Stable annotation for the field indicated by a cpIndex PersistentUnorderedSet _referencingClassLoaders; }; // struct ClassInfo