From e920550ef5c385c1527cf4d48c4aeaaf7ba5c9d0 Mon Sep 17 00:00:00 2001 From: Irwin D'Souza Date: Tue, 5 Nov 2024 13:25:45 -0500 Subject: [PATCH 1/8] Add getTargetMethodFromMemberName getTargetMethodFromMemberName is used for to get both a resolved dynamic method as well as a resolved handle method. It is a refactoring of code to enable resolved dispatch of invokeDynamic/invokeHandle in AOT in both local as well as remote compilation. Signed-off-by: Irwin D'Souza --- .../control/JITClientCompilationThread.cpp | 12 +++++ runtime/compiler/env/j9method.cpp | 48 +++++++++++-------- runtime/compiler/env/j9method.h | 2 + runtime/compiler/env/j9methodServer.cpp | 12 +++++ runtime/compiler/env/j9methodServer.hpp | 1 + runtime/compiler/net/MessageTypes.cpp | 1 + runtime/compiler/net/MessageTypes.hpp | 1 + 7 files changed, 57 insertions(+), 20 deletions(-) diff --git a/runtime/compiler/control/JITClientCompilationThread.cpp b/runtime/compiler/control/JITClientCompilationThread.cpp index a1fbabc0e33..d8bd9a846d7 100644 --- a/runtime/compiler/control/JITClientCompilationThread.cpp +++ b/runtime/compiler/control/JITClientCompilationThread.cpp @@ -1915,6 +1915,18 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes client->write(response, mirror->isFieldFlattened(comp, cpIndex, isStatic)); } break; + case MessageType::ResolvedMethod_getTargetMethodFromMemberName: + { + auto recv = client->getRecvData(); + TR_ResolvedJ9Method *owningMethod = std::get<0>(recv); + uintptr_t * invokeCacheArray = std::get<1>(recv); + + bool isInvokeCacheAppendixNull; + TR_OpaqueMethodBlock *targetMethod = owningMethod->getTargetMethodFromMemberName(invokeCacheArray, &isInvokeCacheAppendixNull); + + client->write(response, targetMethod, isInvokeCacheAppendixNull); + } + break; case MessageType::ResolvedRelocatableMethod_createResolvedRelocatableJ9Method: { auto recv = client->getRecvData(); diff --git a/runtime/compiler/env/j9method.cpp b/runtime/compiler/env/j9method.cpp index 3c65db055f6..e113bbffcf2 100644 --- a/runtime/compiler/env/j9method.cpp +++ b/runtime/compiler/env/j9method.cpp @@ -6970,6 +6970,20 @@ TR_ResolvedJ9Method::handleUnresolvedVirtualMethodInCP(int32_t cpIndex, bool * u { } +TR_OpaqueMethodBlock * +TR_ResolvedJ9Method::getTargetMethodFromMemberName(uintptr_t * invokeCacheArray, bool * isInvokeCacheAppendixNull) + { + TR::VMAccessCriticalSection getTargetMethodCS(fej9()); + TR_OpaqueMethodBlock *targetJ9MethodBlock = fej9()->targetMethodFromMemberName((uintptr_t) fej9()->getReferenceElement(*invokeCacheArray, JSR292_invokeCacheArrayMemberNameIndex)); + // if the callSite table entry / method type table entry is resolved, + // we can check if the appendix object is null, + // in which case the appendix object must not be pushed to stack + auto appendixObject = fej9()->getReferenceElement(*invokeCacheArray, JSR292_invokeCacheArrayAppendixIndex); + if (isInvokeCacheAppendixNull && !appendixObject) + *isInvokeCacheAppendixNull = true; + return targetJ9MethodBlock; + } + TR_ResolvedMethod * TR_ResolvedJ9Method::getResolvedDynamicMethod(TR::Compilation * comp, I_32 callSiteIndex, bool * unresolvedInCP, bool * isInvokeCacheAppendixNull) { @@ -7006,13 +7020,12 @@ TR_ResolvedJ9Method::getResolvedDynamicMethod(TR::Compilation * comp, I_32 callS J9UTF8 *signature = J9ROMNAMEANDSIGNATURE_SIGNATURE(nameAndSig); #if defined(J9VM_OPT_OPENJDK_METHODHANDLE) - if (isInvokeCacheAppendixNull) - *isInvokeCacheAppendixNull = false; + bool invokeCacheAppendixNull = false; if (!isUnresolvedEntry) { - TR_OpaqueMethodBlock * targetJ9MethodBlock = NULL; uintptr_t * invokeCacheArray = (uintptr_t *) callSiteTableEntryAddress(callSiteIndex); + // invokedynamic resolution can either result in a valid entry in the corresponding CallSite table slot if successful, // or an exception object otherwise. The CallSite table entry is a two-element array containing the MemberName // and appendix objects necessary for constructing a resolved invokedynamic adapter method call. @@ -7023,14 +7036,8 @@ TR_ResolvedJ9Method::getResolvedDynamicMethod(TR::Compilation * comp, I_32 callS comp->failCompilation("Invalid CallSite table entry for invokedynamic"); } - { - TR::VMAccessCriticalSection getResolvedDynamicMethod(fej9()); - targetJ9MethodBlock = fej9()->targetMethodFromMemberName((uintptr_t) fej9()->getReferenceElement(*invokeCacheArray, JSR292_invokeCacheArrayMemberNameIndex)); // this will not work in AOT or JITServer - // if the callSite table entry is resolved, we can check if the appendix object is null, - // in which case the appendix object must not be pushed to stack - uintptr_t appendixObject = (uintptr_t) fej9()->getReferenceElement(*invokeCacheArray, JSR292_invokeCacheArrayAppendixIndex); - if (isInvokeCacheAppendixNull && !appendixObject) *isInvokeCacheAppendixNull = true; - } + TR_OpaqueMethodBlock * targetJ9MethodBlock = getTargetMethodFromMemberName(invokeCacheArray, &invokeCacheAppendixNull); + result = fej9()->createResolvedMethod(comp->trMemory(), targetJ9MethodBlock, this); } else @@ -7044,6 +7051,9 @@ TR_ResolvedJ9Method::getResolvedDynamicMethod(TR::Compilation * comp, I_32 callS char * linkToStaticSignature = _fe->getSignatureForLinkToStaticForInvokeDynamic(comp, signature, signatureLength); result = _fe->createResolvedMethodWithSignature(comp->trMemory(), dummyInvoke, NULL, linkToStaticSignature, signatureLength, this); } + + if (isInvokeCacheAppendixNull) + *isInvokeCacheAppendixNull = invokeCacheAppendixNull; #else TR_OpaqueMethodBlock *dummyInvokeExact = _fe->getMethodFromName("java/lang/invoke/MethodHandle", "invokeExact", JSR292_invokeExactSig); result = _fe->createResolvedMethodWithSignature(comp->trMemory(), dummyInvokeExact, NULL, utf8Data(signature), J9UTF8_LENGTH(signature), this); @@ -7081,19 +7091,14 @@ TR_ResolvedJ9Method::getResolvedHandleMethod(TR::Compilation * comp, I_32 cpInde #if defined(J9VM_OPT_OPENJDK_METHODHANDLE) J9UTF8 *signature = J9ROMNAMEANDSIGNATURE_SIGNATURE(nameAndSig); - if (isInvokeCacheAppendixNull) - *isInvokeCacheAppendixNull = false; + bool invokeCacheAppendixNull = false; if (!isUnresolvedEntry) { uintptr_t * invokeCacheArray = (uintptr_t *) methodTypeTableEntryAddress(cpIndex); - TR_OpaqueMethodBlock * targetJ9MethodBlock = NULL; - { - TR::VMAccessCriticalSection getResolvedHandleMethod(fej9()); - targetJ9MethodBlock = fej9()->targetMethodFromMemberName((uintptr_t) fej9()->getReferenceElement(*invokeCacheArray, JSR292_invokeCacheArrayMemberNameIndex)); // this will not work in AOT or JITServer - uintptr_t appendixObject = (uintptr_t) fej9()->getReferenceElement(*invokeCacheArray, JSR292_invokeCacheArrayAppendixIndex); - if (isInvokeCacheAppendixNull && !appendixObject) *isInvokeCacheAppendixNull = true; - } + + TR_OpaqueMethodBlock * targetJ9MethodBlock = getTargetMethodFromMemberName(invokeCacheArray, &invokeCacheAppendixNull); + result = fej9()->createResolvedMethod(comp->trMemory(), targetJ9MethodBlock, this); } else @@ -7107,6 +7112,9 @@ TR_ResolvedJ9Method::getResolvedHandleMethod(TR::Compilation * comp, I_32 cpInde char * linkToStaticSignature = _fe->getSignatureForLinkToStaticForInvokeHandle(comp, signature, signatureLength); result = _fe->createResolvedMethodWithSignature(comp->trMemory(), dummyInvoke, NULL, linkToStaticSignature, signatureLength, this); } + + if (isInvokeCacheAppendixNull) + *isInvokeCacheAppendixNull = invokeCacheAppendixNull; #else TR_OpaqueMethodBlock *dummyInvokeExact = _fe->getMethodFromName("java/lang/invoke/MethodHandle", "invokeExact", JSR292_invokeExactSig); diff --git a/runtime/compiler/env/j9method.h b/runtime/compiler/env/j9method.h index 29473b7f23c..6631718bcb1 100644 --- a/runtime/compiler/env/j9method.h +++ b/runtime/compiler/env/j9method.h @@ -457,6 +457,8 @@ class TR_ResolvedJ9Method : public TR_J9Method, public TR_ResolvedJ9MethodBase virtual TR_ResolvedMethod * getResolvedPossiblyPrivateVirtualMethod( TR::Compilation *, int32_t cpIndex, bool ignoreRtResolve, bool * unresolvedInCP); virtual TR_OpaqueClassBlock * getResolvedInterfaceMethod(int32_t cpIndex, uintptr_t * pITableIndex); + virtual TR_OpaqueMethodBlock * getTargetMethodFromMemberName(uintptr_t * invokeCacheArray, bool * isInvokeCacheAppendixNull); + virtual TR_ResolvedMethod * getResolvedDynamicMethod( TR::Compilation *, int32_t cpIndex, bool * unresolvedInCP, bool * isInvokeCacheAppendixNull = 0); virtual TR_ResolvedMethod * getResolvedHandleMethod( TR::Compilation *, int32_t cpIndex, bool * unresolvedInCP, bool * isInvokeCacheAppendixNull = 0); virtual TR_ResolvedMethod * getResolvedHandleMethodWithSignature( TR::Compilation *, int32_t cpIndex, char *signature); diff --git a/runtime/compiler/env/j9methodServer.cpp b/runtime/compiler/env/j9methodServer.cpp index f400eb25e30..8f4b856c2e8 100644 --- a/runtime/compiler/env/j9methodServer.cpp +++ b/runtime/compiler/env/j9methodServer.cpp @@ -1055,6 +1055,18 @@ TR_ResolvedJ9JITServerMethod::isSubjectToPhaseChange(TR::Compilation *comp) } } +TR_OpaqueMethodBlock * +TR_ResolvedJ9JITServerMethod::getTargetMethodFromMemberName(uintptr_t * invokeCacheArray, bool * isInvokeCacheAppendixNull) + { + _stream->write(JITServer::MessageType::ResolvedMethod_getTargetMethodFromMemberName, _remoteMirror, invokeCacheArray); + auto recv = _stream->read(); + auto targetMethod = std::get<0>(recv); + auto invokeCacheAppendixNull = std::get<1>(recv); + if (isInvokeCacheAppendixNull) + *isInvokeCacheAppendixNull = invokeCacheAppendixNull; + return targetMethod; + } + TR_ResolvedMethod * TR_ResolvedJ9JITServerMethod::getResolvedHandleMethod(TR::Compilation *comp, I_32 cpIndex, bool *unresolvedInCP, bool *isInvokeCacheAppendixNull) diff --git a/runtime/compiler/env/j9methodServer.hpp b/runtime/compiler/env/j9methodServer.hpp index c8ee41c9b77..edd980d2e65 100644 --- a/runtime/compiler/env/j9methodServer.hpp +++ b/runtime/compiler/env/j9methodServer.hpp @@ -195,6 +195,7 @@ class TR_ResolvedJ9JITServerMethod : public TR_ResolvedJ9Method virtual TR_ResolvedMethod *getResolvedVirtualMethod(TR::Compilation * comp, TR_OpaqueClassBlock * classObject, I_32 virtualCallOffset , bool ignoreRtResolve) override; virtual bool isSubjectToPhaseChange(TR::Compilation *comp) override; virtual void * stringConstant(int32_t cpIndex) override; + virtual TR_OpaqueMethodBlock * getTargetMethodFromMemberName(uintptr_t * invokeCacheArray, bool * isInvokeCacheAppendixNull) override; virtual TR_ResolvedMethod *getResolvedHandleMethod(TR::Compilation *, int32_t cpIndex, bool * unresolvedInCP, bool * isInvokeCacheAppendixNull = 0) override; virtual bool isUnresolvedMethodTypeTableEntry(int32_t cpIndex) override; virtual void * methodTypeTableEntryAddress(int32_t cpIndex) override; diff --git a/runtime/compiler/net/MessageTypes.cpp b/runtime/compiler/net/MessageTypes.cpp index 8aa3c561d40..7b9f312e008 100644 --- a/runtime/compiler/net/MessageTypes.cpp +++ b/runtime/compiler/net/MessageTypes.cpp @@ -90,6 +90,7 @@ const char *messageNames[] = "ResolvedMethod_getResolvedImplementorMethods", "ResolvedMethod_isFieldNullRestricted", "ResolvedMethod_isFieldFlattened", + "ResolvedMethod_getTargetMethodFromMemberName", "ResolvedRelocatableMethod_createResolvedRelocatableJ9Method", "ResolvedRelocatableMethod_fieldAttributes", "ResolvedRelocatableMethod_staticAttributes", diff --git a/runtime/compiler/net/MessageTypes.hpp b/runtime/compiler/net/MessageTypes.hpp index ab2a6c587e8..5b8a679a17c 100644 --- a/runtime/compiler/net/MessageTypes.hpp +++ b/runtime/compiler/net/MessageTypes.hpp @@ -96,6 +96,7 @@ enum MessageType : uint16_t ResolvedMethod_getResolvedImplementorMethods, ResolvedMethod_isFieldNullRestricted, ResolvedMethod_isFieldFlattened, + ResolvedMethod_getTargetMethodFromMemberName, ResolvedRelocatableMethod_createResolvedRelocatableJ9Method, ResolvedRelocatableMethod_fieldAttributes, From d6f28074333c23a48ef409eabe1bc457132f04d9 Mon Sep 17 00:00:00 2001 From: Irwin D'Souza Date: Tue, 30 Jul 2024 10:48:08 -0400 Subject: [PATCH 2/8] Add new TR_RelocationErrorCode kinds Add new TR_RelocationErrorCode kinds to indicate validation failures for TR_ValidateDynamicMethodFromCallsiteIndex and TR_ValidateHandleMethodFromCPIndex. Signed-off-by: Irwin D'Souza --- .../compiler/runtime/RelocationRuntime.cpp | 37 ++++++++++--------- .../compiler/runtime/RelocationRuntime.hpp | 36 +++++++++--------- 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/runtime/compiler/runtime/RelocationRuntime.cpp b/runtime/compiler/runtime/RelocationRuntime.cpp index 36ae4d888ea..6cb81fb088e 100644 --- a/runtime/compiler/runtime/RelocationRuntime.cpp +++ b/runtime/compiler/runtime/RelocationRuntime.cpp @@ -133,24 +133,25 @@ const char *TR_RelocationRuntime::_reloErrorCodeNames[] = "svmValidationFailure", // 45 "wkcValidationFailure", // 46 "methodTracingValidationFailure", // 47 - - "classAddressRelocationFailure", // 48 - "inlinedMethodRelocationFailure", // 49 - "symbolFromManagerRelocationFailure", // 50 - "thunkRelocationFailure", // 51 - "trampolineRelocationFailure", // 52 - "picTrampolineRelocationFailure", // 53 - "cacheFullRelocationFailure", // 54 - "blockFrequencyRelocationFailure", // 55 - "recompQueuedFlagRelocationFailure", // 56 - "debugCounterRelocationFailure", // 57 - "directJNICallRelocationFailure", // 58 - "ramMethodConstRelocationFailure", // 59 - "catchBlockCounterRelocationFailure", // 60 - "staticDefaultValueInstanceRelocationFailure", // 61 - - "maxRelocationError" // 62 - + "dynamicMethodFromcallsiteIndexValidationFailure", // 48 + "handleMethodFromcallsiteIndexValidationFailure" , // 49 + + "classAddressRelocationFailure", // 50 + "inlinedMethodRelocationFailure", // 51 + "symbolFromManagerRelocationFailure", // 52 + "thunkRelocationFailure", // 53 + "trampolineRelocationFailure", // 54 + "picTrampolineRelocationFailure", // 55 + "cacheFullRelocationFailure", // 56 + "blockFrequencyRelocationFailure", // 57 + "recompQueuedFlagRelocationFailure", // 58 + "debugCounterRelocationFailure", // 59 + "directJNICallRelocationFailure", // 60 + "ramMethodConstRelocationFailure", // 61 + "catchBlockCounterRelocationFailure", // 62 + "staticDefaultValueInstanceRelocationFailure", // 63 + + "maxRelocationError" // 64 }; TR_RelocationRuntime::TR_RelocationRuntime(J9JITConfig *jitCfg) diff --git a/runtime/compiler/runtime/RelocationRuntime.hpp b/runtime/compiler/runtime/RelocationRuntime.hpp index 346ff8c6295..e82447387cb 100644 --- a/runtime/compiler/runtime/RelocationRuntime.hpp +++ b/runtime/compiler/runtime/RelocationRuntime.hpp @@ -194,23 +194,25 @@ struct TR_RelocationError svmValidationFailure = (45 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::VALIDATION, wkcValidationFailure = (46 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::VALIDATION, methodTracingValidationFailure = (47 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::VALIDATION, - - classAddressRelocationFailure = (48 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - inlinedMethodRelocationFailure = (49 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - symbolFromManagerRelocationFailure = (50 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - thunkRelocationFailure = (51 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - trampolineRelocationFailure = (52 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - picTrampolineRelocationFailure = (53 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - cacheFullRelocationFailure = (54 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - blockFrequencyRelocationFailure = (55 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - recompQueuedFlagRelocationFailure = (56 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - debugCounterRelocationFailure = (57 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - directJNICallRelocationFailure = (58 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - ramMethodConstRelocationFailure = (59 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - catchBlockCounterRelocationFailure = (60 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - staticDefaultValueInstanceRelocationFailure = (61 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - - maxRelocationError = (62 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::NO_RELO_ERROR + dynamicMethodFromCallsiteIndexValidationFailure = (48 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::VALIDATION, + handleMethodFromCPIndexValidationFailure = (49 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::VALIDATION, + + classAddressRelocationFailure = (50 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + inlinedMethodRelocationFailure = (51 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + symbolFromManagerRelocationFailure = (52 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + thunkRelocationFailure = (53 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + trampolineRelocationFailure = (54 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + picTrampolineRelocationFailure = (55 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + cacheFullRelocationFailure = (56 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + blockFrequencyRelocationFailure = (57 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + recompQueuedFlagRelocationFailure = (58 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + debugCounterRelocationFailure = (59 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + directJNICallRelocationFailure = (60 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + ramMethodConstRelocationFailure = (61 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + catchBlockCounterRelocationFailure = (62 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + staticDefaultValueInstanceRelocationFailure = (63 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + + maxRelocationError = (64 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::NO_RELO_ERROR }; static uint32_t decode(TR_RelocationErrorCode errorCode) { return static_cast(errorCode >> RELO_ERRORCODE_SHIFT); } From e3c491d5a2d1736d0c9de62ba25dbd5ef622822f Mon Sep 17 00:00:00 2001 From: Irwin D'Souza Date: Wed, 2 Oct 2024 11:11:53 -0400 Subject: [PATCH 3/8] Add TR_ValidateDynamicMethodFromCallsiteIndex Validation Record Signed-off-by: Irwin D'Souza --- doc/compiler/aot/RelocationRecords.md | 2 + .../compiler/codegen/J9AheadOfTimeCompile.cpp | 35 +++++ runtime/compiler/env/j9method.cpp | 13 ++ runtime/compiler/runtime/RelocationRecord.cpp | 127 ++++++++++++++++++ runtime/compiler/runtime/RelocationRecord.hpp | 31 +++++ .../runtime/SymbolValidationManager.cpp | 78 +++++++++++ .../runtime/SymbolValidationManager.hpp | 27 ++++ 7 files changed, 313 insertions(+) diff --git a/doc/compiler/aot/RelocationRecords.md b/doc/compiler/aot/RelocationRecords.md index f300f3b7090..6f9eff236e6 100644 --- a/doc/compiler/aot/RelocationRecords.md +++ b/doc/compiler/aot/RelocationRecords.md @@ -137,3 +137,5 @@ exact type of the API class for each relocation kind can be found in |`TR_CatchBlockCounter`|Relocates the address of the catch block counter in the `TR_PersistentMethodInfo` of the method being compiled.| |`TR_StartPC`|Relocates the startPC of the method being compiled. Only implemented and used on Power.| |`TR_MethodEnterExitHookAddress`|Relocates the address of the method enter or exit hook.| +|`TR_ValidateDynamicMethodFromCallsiteIndex`|Validates the target method of an `invokeDynamic` invocation.| + diff --git a/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp b/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp index 6f584a62e75..7ad5337979b 100644 --- a/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp +++ b/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp @@ -1349,6 +1349,21 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal } break; + case TR_ValidateDynamicMethodFromCallsiteIndex: + { + auto *dmciRecord = reinterpret_cast(reloRecord); + + TR::DynamicMethodFromCallsiteIndexRecord *svmRecord = reinterpret_cast(relocation->getTargetAddress()); + + dmciRecord->setMethodID(reloTarget, symValManager->getSymbolIDFromValue(svmRecord->_method)); + dmciRecord->setCallerID(reloTarget, symValManager->getSymbolIDFromValue(svmRecord->_caller)); + dmciRecord->setCallsiteIndex(reloTarget, svmRecord->_callsiteIndex); + dmciRecord->setAppendixObjectNull(reloTarget, svmRecord->_appendixObjectNull); + dmciRecord->setDefiningClassID(reloTarget, symValManager->getSymbolIDFromValue(svmRecord->_definingClass)); + dmciRecord->setMethodIndex(reloTarget, fej9->getMethodIndexInClass(svmRecord->_definingClass, svmRecord->_method)); + } + break; + default: TR_ASSERT(false, "Unknown relo type %d!\n", kind); comp->failCompilation("Unknown relo type %d!\n", kind); @@ -2292,6 +2307,26 @@ J9::AheadOfTimeCompile::dumpRelocationHeaderData(uint8_t *cursor, bool isVerbose } break; + case TR_ValidateDynamicMethodFromCallsiteIndex: + { + auto *dmciRecord = reinterpret_cast(reloRecord); + + self()->traceRelocationOffsets(startOfOffsets, offsetSize, endOfCurrentRecord, orderedPair); + if (isVerbose) + { + traceMsg( + self()->comp(), + "\n Validate Dynamic Method From Callsite Index: methodID=%d, callerID=%d, callsiteIndex=%d, appendixObjectNull=%s, definingClassID=%d, methodIndex=%d ", + (uint32_t)dmciRecord->methodID(reloTarget), + (uint32_t)dmciRecord->callerID(reloTarget), + dmciRecord->callsiteIndex(reloTarget), + dmciRecord->appendixObjectNull(reloTarget) ? "true" : "false", + (uint32_t)dmciRecord->definingClassID(reloTarget), + dmciRecord->methodIndex(reloTarget)); + } + } + break; + default: TR_ASSERT_FATAL(false, "dumpRelocationHeaderData: unknown relo kind %d\n", kind); } diff --git a/runtime/compiler/env/j9method.cpp b/runtime/compiler/env/j9method.cpp index e113bbffcf2..eede50e1cc9 100644 --- a/runtime/compiler/env/j9method.cpp +++ b/runtime/compiler/env/j9method.cpp @@ -7038,6 +7038,19 @@ TR_ResolvedJ9Method::getResolvedDynamicMethod(TR::Compilation * comp, I_32 callS TR_OpaqueMethodBlock * targetJ9MethodBlock = getTargetMethodFromMemberName(invokeCacheArray, &invokeCacheAppendixNull); + if (comp->compileRelocatableCode()) + { + bool valid = + comp->getSymbolValidationManager()->addDynamicMethodFromCallsiteIndex( + targetJ9MethodBlock, + getNonPersistentIdentifier(), + callSiteIndex, + invokeCacheAppendixNull); + + if (!valid) + comp->failCompilation("Failed to add validation record for resolved dynamic method %p", targetJ9MethodBlock); + } + result = fej9()->createResolvedMethod(comp->trMemory(), targetJ9MethodBlock, this); } else diff --git a/runtime/compiler/runtime/RelocationRecord.cpp b/runtime/compiler/runtime/RelocationRecord.cpp index bb075e89f16..23cbbb5eb95 100644 --- a/runtime/compiler/runtime/RelocationRecord.cpp +++ b/runtime/compiler/runtime/RelocationRecord.cpp @@ -346,6 +346,16 @@ struct TR_RelocationRecordValidateMethodFromSingleAbstractImplBinaryTemplate : p int32_t _vftSlot; }; +struct TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + uint16_t _callerID; + int32_t _callsiteIndex; + uint8_t _appendixObjectNull; + uint16_t _definingClassID; + uint32_t _methodIndex; + }; + struct TR_RelocationRecordValidateStackWalkerMaySkipFramesBinaryTemplate : public TR_RelocationRecordBinaryTemplate { uint16_t _methodID; @@ -803,6 +813,9 @@ TR_RelocationRecord::create(TR_RelocationRecord *storage, TR_RelocationRuntime * case TR_ValidateMethodFromSingleAbstractImplementer: reloRecord = new (storage) TR_RelocationRecordValidateMethodFromSingleAbstractImpl(reloRuntime, record); break; + case TR_ValidateDynamicMethodFromCallsiteIndex: + reloRecord = new (storage) TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex(reloRuntime, record); + break; case TR_SymbolFromManager: reloRecord = new (storage) TR_RelocationRecordSymbolFromManager(reloRuntime, record); break; @@ -4910,6 +4923,119 @@ TR_RelocationRecordValidateMethodFromClassAndSig::romMethodOffsetInSCC(TR_Reloca return reloTarget->loadRelocationRecordValue((uintptr_t *) &((TR_RelocationRecordValidateMethodFromClassAndSigBinaryTemplate *)_record)->_romMethodOffsetInSCC); } +TR_RelocationErrorCode +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + bool valid = false; + + uint16_t methodID = this->methodID(reloTarget); + uint16_t callerID = this->callerID(reloTarget); + int32_t callsiteIndex = this->callsiteIndex(reloTarget); + bool appendixObjectNull = this->appendixObjectNull(reloTarget); + uint16_t definingClassID = this->definingClassID(reloTarget); + uint32_t methodIndex = this->methodIndex(reloTarget); + + valid = + reloRuntime->comp()->getSymbolValidationManager()->validateDynamicMethodFromCallsiteIndex( + methodID, + callerID, + callsiteIndex, + appendixObjectNull, + definingClassID, + methodIndex); + + if (valid) + return TR_RelocationError::relocationOK; + else + return TR_RelocationError::dynamicMethodFromCallsiteIndexValidationFailure; + } + +void +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::print(TR_RelocationRuntime *reloRuntime) + { + TR_RelocationTarget *reloTarget = reloRuntime->reloTarget(); + TR_RelocationRuntimeLogger *reloLogger = reloRuntime->reloLogger(); + TR_RelocationRecord::print(reloRuntime); + reloLogger->printf("\tmethodID %d\n", methodID(reloTarget)); + reloLogger->printf("\tcallerID %d\n", callerID(reloTarget)); + reloLogger->printf("\tcallsiteIndex %d\n", callsiteIndex(reloTarget)); + reloLogger->printf("\tappendixObjectNull %s\n", appendixObjectNull(reloTarget) ? "true" : "false"); + reloLogger->printf("\tdefiningClassID %d\n", definingClassID(reloTarget)); + reloLogger->printf("\tmethodIndex %d\n", methodIndex(reloTarget)); + } + +void +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::setMethodID(TR_RelocationTarget *reloTarget, uint16_t methodID) + { + reloTarget->storeUnsigned16b(methodID, (uint8_t *) &((TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate *)_record)->_methodID); + } + +uint16_t +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::methodID(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate *)_record)->_methodID); + } + +void +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::setCallerID(TR_RelocationTarget *reloTarget, uint16_t callerID) + { + reloTarget->storeUnsigned16b(callerID, (uint8_t *) &((TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate *)_record)->_callerID); + } + +uint16_t +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::callerID(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate *)_record)->_callerID); + } + +void +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::setCallsiteIndex(TR_RelocationTarget *reloTarget, int32_t callsiteIndex) + { + reloTarget->storeSigned32b(callsiteIndex, (uint8_t *) &((TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate *)_record)->_callsiteIndex); + } + +int32_t +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::callsiteIndex(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadSigned32b((uint8_t *) &((TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate *)_record)->_callsiteIndex); + } + +void +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::setAppendixObjectNull(TR_RelocationTarget *reloTarget, bool appendixObjectNull) + { + reloTarget->storeUnsigned8b((uint8_t)appendixObjectNull, (uint8_t *) &((TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate *)_record)->_appendixObjectNull); + } + +bool +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::appendixObjectNull(TR_RelocationTarget *reloTarget) + { + return (bool)reloTarget->loadUnsigned8b((uint8_t *) &((TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate *)_record)->_appendixObjectNull); + } + +void +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::setDefiningClassID(TR_RelocationTarget *reloTarget, uint16_t definingClassID) + { + reloTarget->storeUnsigned16b(definingClassID, (uint8_t *) &((TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate *)_record)->_definingClassID); + } + +uint16_t +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::definingClassID(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate *)_record)->_definingClassID); + } + +void +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::setMethodIndex(TR_RelocationTarget *reloTarget, uint32_t methodIndex) + { + reloTarget->storeUnsigned32b(methodIndex, (uint8_t *) &((TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate *)_record)->_methodIndex); + } + +uint32_t +TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::methodIndex(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate *)_record)->_methodIndex); + } + TR_RelocationErrorCode TR_RelocationRecordValidateStackWalkerMaySkipFrames::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) { @@ -6690,5 +6816,6 @@ uint32_t TR_RelocationRecord::_relocationRecordHeaderSizeTable[TR_NumExternalRel sizeof(TR_RelocationRecordBinaryTemplate), // TR_CatchBlockCounter = 113 sizeof(TR_RelocationRecordBinaryTemplate), // TR_StartPC = 114 sizeof(TR_RelocationRecordMethodEnterExitHookAddressBinaryTemplate), // TR_MethodEnterExitHookAddress = 115 + sizeof(TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate), // TR_ValidateDynamicMethodFromCallsiteIndex = 116 }; // The _relocationRecordHeaderSizeTable table should be the last thing in this file diff --git a/runtime/compiler/runtime/RelocationRecord.hpp b/runtime/compiler/runtime/RelocationRecord.hpp index 00e59c802ec..6616329560f 100644 --- a/runtime/compiler/runtime/RelocationRecord.hpp +++ b/runtime/compiler/runtime/RelocationRecord.hpp @@ -1538,6 +1538,37 @@ class TR_RelocationRecordValidateMethodFromClassAndSig : public TR_RelocationRec uintptr_t romMethodOffsetInSCC(TR_RelocationTarget *reloTarget); }; +class TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex() {} + TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual const char *name() { return "TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex"; } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual TR_RelocationErrorCode applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + + virtual void print(TR_RelocationRuntime *reloRuntime); + + void setMethodID(TR_RelocationTarget *reloTarget, uint16_t methodID); + uint16_t methodID(TR_RelocationTarget *reloTarget); + + void setCallerID(TR_RelocationTarget *reloTarget, uint16_t callerID); + uint16_t callerID(TR_RelocationTarget *reloTarget); + + void setCallsiteIndex(TR_RelocationTarget *reloTarget, int32_t callsiteIndex); + int32_t callsiteIndex(TR_RelocationTarget *reloTarget); + + void setAppendixObjectNull(TR_RelocationTarget *reloTarget, bool appendixObjectNull); + bool appendixObjectNull(TR_RelocationTarget *reloTarget); + + void setDefiningClassID(TR_RelocationTarget *reloTarget, uint16_t definingClassID); + uint16_t definingClassID(TR_RelocationTarget *reloTarget); + + void setMethodIndex(TR_RelocationTarget *reloTarget, uint32_t methodIndex); + uint32_t methodIndex(TR_RelocationTarget *reloTarget); + }; + class TR_RelocationRecordValidateStackWalkerMaySkipFrames : public TR_RelocationRecord { public: diff --git a/runtime/compiler/runtime/SymbolValidationManager.cpp b/runtime/compiler/runtime/SymbolValidationManager.cpp index 45b5111d758..f628daeb2ca 100644 --- a/runtime/compiler/runtime/SymbolValidationManager.cpp +++ b/runtime/compiler/runtime/SymbolValidationManager.cpp @@ -23,6 +23,7 @@ #include #include "env/VMJ9.h" #include "env/ClassLoaderTable.hpp" +#include "env/JSR292Methods.h" #include "env/PersistentCHTable.hpp" #include "env/VMAccessCriticalSection.hpp" #include "exceptions/AOTFailure.hpp" @@ -1054,6 +1055,16 @@ TR::SymbolValidationManager::addMethodFromSingleAbstractImplementerRecord(TR_Opa return addMethodRecord(new (_region) MethodFromSingleAbstractImplementer(method, thisClass, vftSlot, callerMethod)); } +bool +TR::SymbolValidationManager::addDynamicMethodFromCallsiteIndex(TR_OpaqueMethodBlock *method, + TR_OpaqueMethodBlock *caller, + int32_t callsiteIndex, + bool appendixObjectNull) + { + SVM_ASSERT_ALREADY_VALIDATED(this, caller); + return addMethodRecord(new (_region) DynamicMethodFromCallsiteIndexRecord(method, caller, callsiteIndex, appendixObjectNull)); + } + bool TR::SymbolValidationManager::addStackWalkerMaySkipFramesRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass, bool skipFrames) { @@ -1549,6 +1560,54 @@ TR::SymbolValidationManager::validateMethodFromSingleAbstractImplementerRecord(u return validateSymbol(methodID, definingClassID, method); } +bool +TR::SymbolValidationManager::validateDynamicMethodFromCallsiteIndex(uint16_t methodID, + uint16_t callerID, + int32_t callsiteIndex, + bool appendixObjectNull, + uint16_t definingClassID, + uint32_t methodIndex) + { + bool valid = false; + + TR_OpaqueMethodBlock *caller = getMethodFromID(callerID); + TR_ResolvedMethod *resolvedCaller = _fej9->createResolvedMethod(_trMemory, caller, NULL); + + // If dispatch was resolved at compile time, it must also be resolved + // at load time. + if (!resolvedCaller->isUnresolvedCallSiteTableEntry(callsiteIndex)) + { + uintptr_t * invokeCacheArray = (uintptr_t *)resolvedCaller->callSiteTableEntryAddress(callsiteIndex); + if (_fej9->isInvokeCacheEntryAnArray(invokeCacheArray)) + { + bool invokeCacheAppendixNull = false; + + TR_OpaqueMethodBlock *targetMethod = + static_cast(resolvedCaller)->getTargetMethodFromMemberName( + invokeCacheArray, &invokeCacheAppendixNull); + + TR_OpaqueClassBlock *targetMethodClass = + reinterpret_cast( + J9_CLASS_FROM_METHOD(reinterpret_cast(targetMethod))); + + valid = + validateSymbol(methodID, definingClassID, targetMethod) + + // The generated code is different depending on whether the + // appendix object was null or not. + && (appendixObjectNull == invokeCacheAppendixNull) + + // Because the target method is not named, this (indirectly) ensures + // that the target method has the same name as in the compile run; + // the class chain validation of the defining class will ensure the + // bytecodes are the same. + && (methodIndex == _fej9->getMethodIndexInClass(targetMethodClass, targetMethod)); + } + } + + return valid; + } + bool TR::SymbolValidationManager::validateStackWalkerMaySkipFramesRecord(uint16_t methodID, uint16_t methodClassID, bool couldSkipFrames) { @@ -2174,3 +2233,22 @@ void TR::IsClassVisibleRecord::printFields() printClass(_destClass); traceMsg(TR::comp(), "\t_isVisible=%s\n", _isVisible ? "true" : "false"); } + +bool TR::DynamicMethodFromCallsiteIndexRecord::isLessThanWithinKind( + SymbolValidationRecord *other) + { + TR::DynamicMethodFromCallsiteIndexRecord *rhs = downcast(this, other); + return LexicalOrder::by(_method, rhs->_method) + .thenBy(_caller, rhs->_caller) + .thenBy(_callsiteIndex, rhs->_callsiteIndex) + .thenBy(_appendixObjectNull, rhs->_appendixObjectNull).less(); + } + +void TR::DynamicMethodFromCallsiteIndexRecord::printFields() + { + traceMsg(TR::comp(), "DynamicMethodFromCallsiteIndexRecord\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_caller=0x%p\n", _caller); + traceMsg(TR::comp(), "\t_callsiteIndex=%d\n", _callsiteIndex); + traceMsg(TR::comp(), "\t_appendixObjectNull=%s\n", _appendixObjectNull ? "true" : "false"); + } diff --git a/runtime/compiler/runtime/SymbolValidationManager.hpp b/runtime/compiler/runtime/SymbolValidationManager.hpp index 7080ae2b2d8..8ff384a415b 100644 --- a/runtime/compiler/runtime/SymbolValidationManager.hpp +++ b/runtime/compiler/runtime/SymbolValidationManager.hpp @@ -708,6 +708,26 @@ struct IsClassVisibleRecord : public SymbolValidationRecord bool _isVisible; }; +struct DynamicMethodFromCallsiteIndexRecord : public MethodValidationRecord + { + DynamicMethodFromCallsiteIndexRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueMethodBlock *caller, + int32_t callsiteIndex, + bool appendixObjectNull) + : MethodValidationRecord(TR_ValidateDynamicMethodFromCallsiteIndex, method), + _caller(caller), + _callsiteIndex(callsiteIndex), + _appendixObjectNull(appendixObjectNull) + {} + + virtual bool isLessThanWithinKind(SymbolValidationRecord *other); + virtual void printFields(); + + TR_OpaqueMethodBlock *_caller; + int32_t _callsiteIndex; + bool _appendixObjectNull; + }; + class SymbolValidationManager { public: @@ -787,6 +807,7 @@ class SymbolValidationManager TR_OpaqueClassBlock *thisClass, int32_t vftSlot, TR_OpaqueMethodBlock *callerMethod); + bool addDynamicMethodFromCallsiteIndex(TR_OpaqueMethodBlock *method, TR_OpaqueMethodBlock *caller, int32_t callsiteIndex, bool appendixObjectNull); bool addStackWalkerMaySkipFramesRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass, bool skipFrames); bool addClassInfoIsInitializedRecord(TR_OpaqueClassBlock *clazz, bool isInitialized); @@ -834,6 +855,12 @@ class SymbolValidationManager uint16_t thisClassID, int32_t vftSlot, uint16_t callerMethodID); + bool validateDynamicMethodFromCallsiteIndex(uint16_t methodID, + uint16_t callerID, + int32_t callsiteIndex, + bool appendixObjectNull, + uint16_t definingClassID, + uint32_t methodIndex); bool validateStackWalkerMaySkipFramesRecord(uint16_t methodID, uint16_t methodClassID, bool couldSkipFrames); bool validateClassInfoIsInitializedRecord(uint16_t classID, bool wasInitialized); From 4f8cea6c2056967240f9c090a8699a12130aba1e Mon Sep 17 00:00:00 2001 From: Irwin D'Souza Date: Wed, 2 Oct 2024 13:02:44 -0400 Subject: [PATCH 4/8] Add TR_ValidateHandleMethodFromCPIndex Validation Record Signed-off-by: Irwin D'Souza --- doc/compiler/aot/RelocationRecords.md | 2 +- .../compiler/codegen/J9AheadOfTimeCompile.cpp | 35 +++++ runtime/compiler/env/j9method.cpp | 13 ++ runtime/compiler/runtime/RelocationRecord.cpp | 127 ++++++++++++++++++ runtime/compiler/runtime/RelocationRecord.hpp | 31 +++++ .../runtime/SymbolValidationManager.cpp | 74 ++++++++++ .../runtime/SymbolValidationManager.hpp | 27 ++++ 7 files changed, 308 insertions(+), 1 deletion(-) diff --git a/doc/compiler/aot/RelocationRecords.md b/doc/compiler/aot/RelocationRecords.md index 6f9eff236e6..9c1188e283b 100644 --- a/doc/compiler/aot/RelocationRecords.md +++ b/doc/compiler/aot/RelocationRecords.md @@ -138,4 +138,4 @@ exact type of the API class for each relocation kind can be found in |`TR_StartPC`|Relocates the startPC of the method being compiled. Only implemented and used on Power.| |`TR_MethodEnterExitHookAddress`|Relocates the address of the method enter or exit hook.| |`TR_ValidateDynamicMethodFromCallsiteIndex`|Validates the target method of an `invokeDynamic` invocation.| - +|`TR_ValidateHandleMethodFromCPIndex`|Validates the target method of an `invokeHandle` invocation.| diff --git a/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp b/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp index 7ad5337979b..fe98f0322b6 100644 --- a/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp +++ b/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp @@ -1364,6 +1364,21 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal } break; + case TR_ValidateHandleMethodFromCPIndex: + { + auto *hmciRecord = reinterpret_cast(reloRecord); + + TR::HandleMethodFromCPIndex *svmRecord = reinterpret_cast(relocation->getTargetAddress()); + + hmciRecord->setMethodID(reloTarget, symValManager->getSymbolIDFromValue(svmRecord->_method)); + hmciRecord->setCallerID(reloTarget, symValManager->getSymbolIDFromValue(svmRecord->_caller)); + hmciRecord->setCpIndex(reloTarget, svmRecord->_cpIndex); + hmciRecord->setAppendixObjectNull(reloTarget, svmRecord->_appendixObjectNull); + hmciRecord->setDefiningClassID(reloTarget, symValManager->getSymbolIDFromValue(svmRecord->_definingClass)); + hmciRecord->setMethodIndex(reloTarget, fej9->getMethodIndexInClass(svmRecord->_definingClass, svmRecord->_method)); + } + break; + default: TR_ASSERT(false, "Unknown relo type %d!\n", kind); comp->failCompilation("Unknown relo type %d!\n", kind); @@ -2327,6 +2342,26 @@ J9::AheadOfTimeCompile::dumpRelocationHeaderData(uint8_t *cursor, bool isVerbose } break; + case TR_ValidateHandleMethodFromCPIndex: + { + auto *hmciRecord = reinterpret_cast(reloRecord); + + self()->traceRelocationOffsets(startOfOffsets, offsetSize, endOfCurrentRecord, orderedPair); + if (isVerbose) + { + traceMsg( + self()->comp(), + "\n Validate Handle Method From CP Index: methodID=%d, callerID=%d, cpIndex=%d, appendixObjectNull=%s, definingClassID=%d, methodIndex=%d ", + (uint32_t)hmciRecord->methodID(reloTarget), + (uint32_t)hmciRecord->callerID(reloTarget), + hmciRecord->cpIndex(reloTarget), + hmciRecord->appendixObjectNull(reloTarget) ? "true" : "false", + (uint32_t)hmciRecord->definingClassID(reloTarget), + hmciRecord->methodIndex(reloTarget)); + } + } + break; + default: TR_ASSERT_FATAL(false, "dumpRelocationHeaderData: unknown relo kind %d\n", kind); } diff --git a/runtime/compiler/env/j9method.cpp b/runtime/compiler/env/j9method.cpp index eede50e1cc9..9906bb4dc7c 100644 --- a/runtime/compiler/env/j9method.cpp +++ b/runtime/compiler/env/j9method.cpp @@ -7112,6 +7112,19 @@ TR_ResolvedJ9Method::getResolvedHandleMethod(TR::Compilation * comp, I_32 cpInde TR_OpaqueMethodBlock * targetJ9MethodBlock = getTargetMethodFromMemberName(invokeCacheArray, &invokeCacheAppendixNull); + if (comp->compileRelocatableCode()) + { + bool valid = + comp->getSymbolValidationManager()->addHandleMethodFromCPIndex( + targetJ9MethodBlock, + getNonPersistentIdentifier(), + cpIndex, + invokeCacheAppendixNull); + + if (!valid) + comp->failCompilation("Failed to add validation record for resolved handle method %p", targetJ9MethodBlock); + } + result = fej9()->createResolvedMethod(comp->trMemory(), targetJ9MethodBlock, this); } else diff --git a/runtime/compiler/runtime/RelocationRecord.cpp b/runtime/compiler/runtime/RelocationRecord.cpp index 23cbbb5eb95..6007098b218 100644 --- a/runtime/compiler/runtime/RelocationRecord.cpp +++ b/runtime/compiler/runtime/RelocationRecord.cpp @@ -356,6 +356,16 @@ struct TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate : uint32_t _methodIndex; }; +struct TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + uint16_t _callerID; + int32_t _cpIndex; + uint8_t _appendixObjectNull; + uint16_t _definingClassID; + uint32_t _methodIndex; + }; + struct TR_RelocationRecordValidateStackWalkerMaySkipFramesBinaryTemplate : public TR_RelocationRecordBinaryTemplate { uint16_t _methodID; @@ -816,6 +826,9 @@ TR_RelocationRecord::create(TR_RelocationRecord *storage, TR_RelocationRuntime * case TR_ValidateDynamicMethodFromCallsiteIndex: reloRecord = new (storage) TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex(reloRuntime, record); break; + case TR_ValidateHandleMethodFromCPIndex: + reloRecord = new (storage) TR_RelocationRecordValidateHandleMethodFromCPIndex(reloRuntime, record); + break; case TR_SymbolFromManager: reloRecord = new (storage) TR_RelocationRecordSymbolFromManager(reloRuntime, record); break; @@ -5036,6 +5049,119 @@ TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex::methodIndex(TR_Reloca return reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate *)_record)->_methodIndex); } +TR_RelocationErrorCode +TR_RelocationRecordValidateHandleMethodFromCPIndex::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + bool valid = false; + + uint16_t methodID = this->methodID(reloTarget); + uint16_t callerID = this->callerID(reloTarget); + int32_t cpIndex = this->cpIndex(reloTarget); + bool appendixObjectNull = this->appendixObjectNull(reloTarget); + uint16_t definingClassID = this->definingClassID(reloTarget); + uint32_t methodIndex = this->methodIndex(reloTarget); + + valid = + reloRuntime->comp()->getSymbolValidationManager()->validateHandleMethodFromCPIndex( + methodID, + callerID, + cpIndex, + appendixObjectNull, + definingClassID, + methodIndex); + + if (valid) + return TR_RelocationError::relocationOK; + else + return TR_RelocationError::handleMethodFromCPIndexValidationFailure; + } + +void +TR_RelocationRecordValidateHandleMethodFromCPIndex::print(TR_RelocationRuntime *reloRuntime) + { + TR_RelocationTarget *reloTarget = reloRuntime->reloTarget(); + TR_RelocationRuntimeLogger *reloLogger = reloRuntime->reloLogger(); + TR_RelocationRecord::print(reloRuntime); + reloLogger->printf("\tmethodID %d\n", methodID(reloTarget)); + reloLogger->printf("\tcallerID %d\n", callerID(reloTarget)); + reloLogger->printf("\tcpIndex %d\n", cpIndex(reloTarget)); + reloLogger->printf("\tappendixObjectNull %s\n", appendixObjectNull(reloTarget) ? "true" : "false"); + reloLogger->printf("\tdefiningClassID %d\n", definingClassID(reloTarget)); + reloLogger->printf("\tmethodIndex %d\n", methodIndex(reloTarget)); + } + +void +TR_RelocationRecordValidateHandleMethodFromCPIndex::setMethodID(TR_RelocationTarget *reloTarget, uint16_t methodID) + { + reloTarget->storeUnsigned16b(methodID, (uint8_t *) &((TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate *)_record)->_methodID); + } + +uint16_t +TR_RelocationRecordValidateHandleMethodFromCPIndex::methodID(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate *)_record)->_methodID); + } + +void +TR_RelocationRecordValidateHandleMethodFromCPIndex::setCallerID(TR_RelocationTarget *reloTarget, uint16_t callerID) + { + reloTarget->storeUnsigned16b(callerID, (uint8_t *) &((TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate *)_record)->_callerID); + } + +uint16_t +TR_RelocationRecordValidateHandleMethodFromCPIndex::callerID(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate *)_record)->_callerID); + } + +void +TR_RelocationRecordValidateHandleMethodFromCPIndex::setCpIndex(TR_RelocationTarget *reloTarget, int32_t cpIndex) + { + reloTarget->storeSigned32b(cpIndex, (uint8_t *) &((TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate *)_record)->_cpIndex); + } + +int32_t +TR_RelocationRecordValidateHandleMethodFromCPIndex::cpIndex(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadSigned32b((uint8_t *) &((TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate *)_record)->_cpIndex); + } + +void +TR_RelocationRecordValidateHandleMethodFromCPIndex::setAppendixObjectNull(TR_RelocationTarget *reloTarget, bool appendixObjectNull) + { + reloTarget->storeUnsigned8b((uint8_t)appendixObjectNull, (uint8_t *) &((TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate *)_record)->_appendixObjectNull); + } + +bool +TR_RelocationRecordValidateHandleMethodFromCPIndex::appendixObjectNull(TR_RelocationTarget *reloTarget) + { + return (bool)reloTarget->loadUnsigned8b((uint8_t *) &((TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate *)_record)->_appendixObjectNull); + } + +void +TR_RelocationRecordValidateHandleMethodFromCPIndex::setDefiningClassID(TR_RelocationTarget *reloTarget, uint16_t definingClassID) + { + reloTarget->storeUnsigned16b(definingClassID, (uint8_t *) &((TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate *)_record)->_definingClassID); + } + +uint16_t +TR_RelocationRecordValidateHandleMethodFromCPIndex::definingClassID(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate *)_record)->_definingClassID); + } + +void +TR_RelocationRecordValidateHandleMethodFromCPIndex::setMethodIndex(TR_RelocationTarget *reloTarget, uint32_t methodIndex) + { + reloTarget->storeUnsigned32b(methodIndex, (uint8_t *) &((TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate *)_record)->_methodIndex); + } + +uint32_t +TR_RelocationRecordValidateHandleMethodFromCPIndex::methodIndex(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate *)_record)->_methodIndex); + } + TR_RelocationErrorCode TR_RelocationRecordValidateStackWalkerMaySkipFrames::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) { @@ -6817,5 +6943,6 @@ uint32_t TR_RelocationRecord::_relocationRecordHeaderSizeTable[TR_NumExternalRel sizeof(TR_RelocationRecordBinaryTemplate), // TR_StartPC = 114 sizeof(TR_RelocationRecordMethodEnterExitHookAddressBinaryTemplate), // TR_MethodEnterExitHookAddress = 115 sizeof(TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate), // TR_ValidateDynamicMethodFromCallsiteIndex = 116 + sizeof(TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate), // TR_ValidateHandleMethodFromCPIndex = 117 }; // The _relocationRecordHeaderSizeTable table should be the last thing in this file diff --git a/runtime/compiler/runtime/RelocationRecord.hpp b/runtime/compiler/runtime/RelocationRecord.hpp index 6616329560f..9d361e0604a 100644 --- a/runtime/compiler/runtime/RelocationRecord.hpp +++ b/runtime/compiler/runtime/RelocationRecord.hpp @@ -1569,6 +1569,37 @@ class TR_RelocationRecordValidateDynamicMethodFromCallsiteIndex : public TR_Relo uint32_t methodIndex(TR_RelocationTarget *reloTarget); }; +class TR_RelocationRecordValidateHandleMethodFromCPIndex : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateHandleMethodFromCPIndex() {} + TR_RelocationRecordValidateHandleMethodFromCPIndex(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual const char *name() { return "TR_RelocationRecordValidateHandleMethodFromCPIndex"; } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual TR_RelocationErrorCode applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + + virtual void print(TR_RelocationRuntime *reloRuntime); + + void setMethodID(TR_RelocationTarget *reloTarget, uint16_t methodID); + uint16_t methodID(TR_RelocationTarget *reloTarget); + + void setCallerID(TR_RelocationTarget *reloTarget, uint16_t callerID); + uint16_t callerID(TR_RelocationTarget *reloTarget); + + void setCpIndex(TR_RelocationTarget *reloTarget, int32_t cpIndex); + int32_t cpIndex(TR_RelocationTarget *reloTarget); + + void setAppendixObjectNull(TR_RelocationTarget *reloTarget, bool appendixObjectNull); + bool appendixObjectNull(TR_RelocationTarget *reloTarget); + + void setDefiningClassID(TR_RelocationTarget *reloTarget, uint16_t definingClassID); + uint16_t definingClassID(TR_RelocationTarget *reloTarget); + + void setMethodIndex(TR_RelocationTarget *reloTarget, uint32_t methodIndex); + uint32_t methodIndex(TR_RelocationTarget *reloTarget); + }; + class TR_RelocationRecordValidateStackWalkerMaySkipFrames : public TR_RelocationRecord { public: diff --git a/runtime/compiler/runtime/SymbolValidationManager.cpp b/runtime/compiler/runtime/SymbolValidationManager.cpp index f628daeb2ca..c8524290180 100644 --- a/runtime/compiler/runtime/SymbolValidationManager.cpp +++ b/runtime/compiler/runtime/SymbolValidationManager.cpp @@ -1065,6 +1065,16 @@ TR::SymbolValidationManager::addDynamicMethodFromCallsiteIndex(TR_OpaqueMethodBl return addMethodRecord(new (_region) DynamicMethodFromCallsiteIndexRecord(method, caller, callsiteIndex, appendixObjectNull)); } +bool +TR::SymbolValidationManager::addHandleMethodFromCPIndex(TR_OpaqueMethodBlock *method, + TR_OpaqueMethodBlock *caller, + int32_t cpIndex, + bool appendixObjectNull) + { + SVM_ASSERT_ALREADY_VALIDATED(this, caller); + return addMethodRecord(new (_region) HandleMethodFromCPIndex(method, caller, cpIndex, appendixObjectNull)); + } + bool TR::SymbolValidationManager::addStackWalkerMaySkipFramesRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass, bool skipFrames) { @@ -1608,6 +1618,51 @@ TR::SymbolValidationManager::validateDynamicMethodFromCallsiteIndex(uint16_t met return valid; } +bool +TR::SymbolValidationManager::validateHandleMethodFromCPIndex(uint16_t methodID, + uint16_t callerID, + int32_t cpIndex, + bool appendixObjectNull, + uint16_t definingClassID, + uint32_t methodIndex) + { + bool valid = false; + + TR_OpaqueMethodBlock *caller = getMethodFromID(callerID); + TR_ResolvedMethod *resolvedCaller = _fej9->createResolvedMethod(_trMemory, caller, NULL); + + // If dispatch was resolved at compile time, it must also be resolved + // at load time. + if (!resolvedCaller->isUnresolvedMethodTypeTableEntry(cpIndex)) + { + uintptr_t * invokeCacheArray = (uintptr_t *)resolvedCaller->methodTypeTableEntryAddress(cpIndex); + bool invokeCacheAppendixNull = false; + + TR_OpaqueMethodBlock *targetMethod = + static_cast(resolvedCaller)->getTargetMethodFromMemberName( + invokeCacheArray, &invokeCacheAppendixNull); + + TR_OpaqueClassBlock *targetMethodClass = + reinterpret_cast( + J9_CLASS_FROM_METHOD(reinterpret_cast(targetMethod))); + + valid = + validateSymbol(methodID, definingClassID, targetMethod) + + // The generated code is different depending on whether the + // appendix object was null or not. + && (appendixObjectNull == invokeCacheAppendixNull) + + // Because the target method is not named, this (indirectly) ensures + // that the target method has the same name as in the compile run; + // the class chain validation of the defining class will ensure the + // bytecodes are the same. + && (methodIndex == _fej9->getMethodIndexInClass(targetMethodClass, targetMethod)); + } + + return valid; + } + bool TR::SymbolValidationManager::validateStackWalkerMaySkipFramesRecord(uint16_t methodID, uint16_t methodClassID, bool couldSkipFrames) { @@ -2252,3 +2307,22 @@ void TR::DynamicMethodFromCallsiteIndexRecord::printFields() traceMsg(TR::comp(), "\t_callsiteIndex=%d\n", _callsiteIndex); traceMsg(TR::comp(), "\t_appendixObjectNull=%s\n", _appendixObjectNull ? "true" : "false"); } + +bool TR::HandleMethodFromCPIndex::isLessThanWithinKind( + SymbolValidationRecord *other) + { + TR::HandleMethodFromCPIndex *rhs = downcast(this, other); + return LexicalOrder::by(_method, rhs->_method) + .thenBy(_caller, rhs->_caller) + .thenBy(_cpIndex, rhs->_cpIndex) + .thenBy(_appendixObjectNull, rhs->_appendixObjectNull).less(); + } + +void TR::HandleMethodFromCPIndex::printFields() + { + traceMsg(TR::comp(), "HandleMethodFromCPIndex\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_caller=0x%p\n", _caller); + traceMsg(TR::comp(), "\t_cpIndex=%d\n", _cpIndex); + traceMsg(TR::comp(), "\t_appendixObjectNull=%s\n", _appendixObjectNull ? "true" : "false"); + } diff --git a/runtime/compiler/runtime/SymbolValidationManager.hpp b/runtime/compiler/runtime/SymbolValidationManager.hpp index 8ff384a415b..49f643e2c8f 100644 --- a/runtime/compiler/runtime/SymbolValidationManager.hpp +++ b/runtime/compiler/runtime/SymbolValidationManager.hpp @@ -728,6 +728,26 @@ struct DynamicMethodFromCallsiteIndexRecord : public MethodValidationRecord bool _appendixObjectNull; }; +struct HandleMethodFromCPIndex : public MethodValidationRecord + { + HandleMethodFromCPIndex(TR_OpaqueMethodBlock *method, + TR_OpaqueMethodBlock *caller, + int32_t cpIndex, + bool appendixObjectNull) + : MethodValidationRecord(TR_ValidateHandleMethodFromCPIndex, method), + _caller(caller), + _cpIndex(cpIndex), + _appendixObjectNull(appendixObjectNull) + {} + + virtual bool isLessThanWithinKind(SymbolValidationRecord *other); + virtual void printFields(); + + TR_OpaqueMethodBlock *_caller; + int32_t _cpIndex; + bool _appendixObjectNull; + }; + class SymbolValidationManager { public: @@ -808,6 +828,7 @@ class SymbolValidationManager int32_t vftSlot, TR_OpaqueMethodBlock *callerMethod); bool addDynamicMethodFromCallsiteIndex(TR_OpaqueMethodBlock *method, TR_OpaqueMethodBlock *caller, int32_t callsiteIndex, bool appendixObjectNull); + bool addHandleMethodFromCPIndex(TR_OpaqueMethodBlock *method, TR_OpaqueMethodBlock *caller, int32_t cpIndex, bool appendixObjectNull); bool addStackWalkerMaySkipFramesRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass, bool skipFrames); bool addClassInfoIsInitializedRecord(TR_OpaqueClassBlock *clazz, bool isInitialized); @@ -861,6 +882,12 @@ class SymbolValidationManager bool appendixObjectNull, uint16_t definingClassID, uint32_t methodIndex); + bool validateHandleMethodFromCPIndex(uint16_t methodID, + uint16_t callerID, + int32_t cpIndex, + bool appendixObjectNull, + uint16_t definingClassID, + uint32_t methodIndex); bool validateStackWalkerMaySkipFramesRecord(uint16_t methodID, uint16_t methodClassID, bool couldSkipFrames); bool validateClassInfoIsInitializedRecord(uint16_t classID, bool wasInitialized); From 0d0b0f463ba3a718478a76dadc129aeab9b6fabc Mon Sep 17 00:00:00 2001 From: Irwin D'Souza Date: Tue, 30 Jul 2024 14:20:47 -0400 Subject: [PATCH 5/8] Add TR_CallsiteTableEntryAddress relocations Signed-off-by: Irwin D'Souza --- doc/compiler/aot/RelocationRecords.md | 2 + .../compiler/codegen/J9AheadOfTimeCompile.cpp | 31 ++++++++ .../compiler/il/J9StaticSymbol_inlines.hpp | 3 + .../p/runtime/PPCRelocationTarget.cpp | 1 + runtime/compiler/runtime/RelocationRecord.cpp | 78 +++++++++++++++++++ runtime/compiler/runtime/RelocationRecord.hpp | 27 +++++++ runtime/compiler/runtime/Runtime.cpp | 1 + .../compiler/z/codegen/S390AOTRelocation.cpp | 13 ++++ 8 files changed, 156 insertions(+) diff --git a/doc/compiler/aot/RelocationRecords.md b/doc/compiler/aot/RelocationRecords.md index 9c1188e283b..ce6cc026387 100644 --- a/doc/compiler/aot/RelocationRecords.md +++ b/doc/compiler/aot/RelocationRecords.md @@ -139,3 +139,5 @@ exact type of the API class for each relocation kind can be found in |`TR_MethodEnterExitHookAddress`|Relocates the address of the method enter or exit hook.| |`TR_ValidateDynamicMethodFromCallsiteIndex`|Validates the target method of an `invokeDynamic` invocation.| |`TR_ValidateHandleMethodFromCPIndex`|Validates the target method of an `invokeHandle` invocation.| +|`TR_CallsiteTableEntryAddress`|Relocates the callsite table entry address.| + diff --git a/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp b/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp index fe98f0322b6..d0b047daf41 100644 --- a/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp +++ b/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp @@ -1379,6 +1379,21 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal } break; + case TR_CallsiteTableEntryAddress: + { + auto *cteaRecord = reinterpret_cast(reloRecord); + + TR::SymbolReference *symRef = reinterpret_cast(relocation->getTargetAddress()); + uint8_t flags = static_cast(reinterpret_cast(relocation->getTargetAddress2())); + + TR_OpaqueMethodBlock *method = symRef->getOwningMethod(comp)->getNonPersistentIdentifier(); + + cteaRecord->setReloFlags(reloTarget, flags); + cteaRecord->setMethodID(reloTarget, symValManager->getSymbolIDFromValue(method)); + cteaRecord->setCallsiteIndex(reloTarget, symRef->getSymbol()->getStaticSymbol()->getCallSiteIndex()); + } + break; + default: TR_ASSERT(false, "Unknown relo type %d!\n", kind); comp->failCompilation("Unknown relo type %d!\n", kind); @@ -2362,6 +2377,22 @@ J9::AheadOfTimeCompile::dumpRelocationHeaderData(uint8_t *cursor, bool isVerbose } break; + case TR_CallsiteTableEntryAddress: + { + auto *cteaRecord = reinterpret_cast(reloRecord); + + self()->traceRelocationOffsets(startOfOffsets, offsetSize, endOfCurrentRecord, orderedPair); + if (isVerbose) + { + traceMsg( + self()->comp(), + "\n Callsite Table Entry Address: methodID=%d, callsiteIndex=%d ", + (uint32_t)cteaRecord->methodID(reloTarget), + cteaRecord->callsiteIndex(reloTarget)); + } + } + break; + default: TR_ASSERT_FATAL(false, "dumpRelocationHeaderData: unknown relo kind %d\n", kind); } diff --git a/runtime/compiler/il/J9StaticSymbol_inlines.hpp b/runtime/compiler/il/J9StaticSymbol_inlines.hpp index d432496d362..45c6d66377c 100644 --- a/runtime/compiler/il/J9StaticSymbol_inlines.hpp +++ b/runtime/compiler/il/J9StaticSymbol_inlines.hpp @@ -50,6 +50,9 @@ J9::StaticSymbol::makeCallSiteTableEntry(int32_t callSiteIndex) TR_ASSERT(self()->getDataType() == TR::Address, "CallSiteTableEntries have historically had TR::Address as data type"); _callSiteIndex = callSiteIndex; self()->setCallSiteTableEntry(); + + // Needed so that the relo infra does not think this is a static field address + self()->setNotDataAddress(); } diff --git a/runtime/compiler/p/runtime/PPCRelocationTarget.cpp b/runtime/compiler/p/runtime/PPCRelocationTarget.cpp index 161bf1ec996..71f9728cbec 100644 --- a/runtime/compiler/p/runtime/PPCRelocationTarget.cpp +++ b/runtime/compiler/p/runtime/PPCRelocationTarget.cpp @@ -313,6 +313,7 @@ TR_PPC32RelocationTarget::isOrderedPairRelocation(TR_RelocationRecord *reloRecor case TR_DataAddress: case TR_DebugCounter: case TR_MethodEnterExitHookAddress: + case TR_CallsiteTableEntryAddress: return true; default: return false; diff --git a/runtime/compiler/runtime/RelocationRecord.cpp b/runtime/compiler/runtime/RelocationRecord.cpp index 6007098b218..7acd6ae9561 100644 --- a/runtime/compiler/runtime/RelocationRecord.cpp +++ b/runtime/compiler/runtime/RelocationRecord.cpp @@ -423,6 +423,12 @@ struct TR_RelocationRecordMethodEnterExitHookAddressBinaryTemplate : public TR_R uint8_t _isEnterHookAddr; }; +struct TR_RelocationRecordCallsiteTableEntryAddressBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + int32_t _callsiteIndex; + }; + // END OF BINARY TEMPLATES uint8_t @@ -862,6 +868,9 @@ TR_RelocationRecord::create(TR_RelocationRecord *storage, TR_RelocationRuntime * case TR_MethodEnterExitHookAddress: reloRecord = new (storage) TR_RelocationRecordMethodEnterExitHookAddress(reloRuntime, record); break; + case TR_CallsiteTableEntryAddress: + reloRecord = new (storage) TR_RelocationRecordCallsiteTableEntryAddress(reloRuntime, record); + break; default: // TODO: error condition printf("Unexpected relo record: %d\n", reloType);fflush(stdout); @@ -6823,6 +6832,74 @@ TR_RelocationRecordMethodEnterExitHookAddress::applyRelocation(TR_RelocationRunt return TR_RelocationErrorCode::relocationOK; } +// TR_RelocationRecordCallsiteTableEntryAddress +void +TR_RelocationRecordCallsiteTableEntryAddress::print(TR_RelocationRuntime *reloRuntime) + { + TR_RelocationTarget *reloTarget = reloRuntime->reloTarget(); + TR_RelocationRuntimeLogger *reloLogger = reloRuntime->reloLogger(); + TR_RelocationRecord::print(reloRuntime); + reloLogger->printf("\tmethodID %d\n", methodID(reloTarget)); + reloLogger->printf("\tcallsiteIndex %d\n", callsiteIndex(reloTarget)); + } + +void +TR_RelocationRecordCallsiteTableEntryAddress::setMethodID(TR_RelocationTarget *reloTarget, uint16_t methodID) + { + reloTarget->storeUnsigned16b(methodID, (uint8_t *) &((TR_RelocationRecordCallsiteTableEntryAddressBinaryTemplate *)_record)->_methodID); + } + +uint16_t +TR_RelocationRecordCallsiteTableEntryAddress::methodID(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordCallsiteTableEntryAddressBinaryTemplate *)_record)->_methodID); + } + +void +TR_RelocationRecordCallsiteTableEntryAddress::setCallsiteIndex(TR_RelocationTarget *reloTarget, int32_t callsiteIndex) + { + reloTarget->storeSigned32b(callsiteIndex, (uint8_t *) &((TR_RelocationRecordCallsiteTableEntryAddressBinaryTemplate *)_record)->_callsiteIndex); + } + +int32_t +TR_RelocationRecordCallsiteTableEntryAddress::callsiteIndex(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadSigned32b((uint8_t *) &((TR_RelocationRecordCallsiteTableEntryAddressBinaryTemplate *)_record)->_callsiteIndex); + } + +void +TR_RelocationRecordCallsiteTableEntryAddress::preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) + { + TR_RelocationRecordCallsiteTableEntryAddressPrivateData *reloPrivateData = &(privateData()->callsiteTableEntryAddr); + + TR_OpaqueMethodBlock *method = reloRuntime->comp()->getSymbolValidationManager()->getMethodFromID(methodID(reloTarget)); + TR_ResolvedMethod *resolvedMethod = reloRuntime->fej9()->createResolvedMethod(reloRuntime->trMemory(), method, NULL); + + reloPrivateData->_callsiteTableEntryAddress = resolvedMethod->callSiteTableEntryAddress(callsiteIndex(reloTarget)); + } + +TR_RelocationErrorCode +TR_RelocationRecordCallsiteTableEntryAddress::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + TR_RelocationRecordCallsiteTableEntryAddressPrivateData *reloPrivateData = &(privateData()->callsiteTableEntryAddr); + void *callsiteTableEntryAddr = reloPrivateData->_callsiteTableEntryAddress; + + reloTarget->storeAddressSequence((uint8_t *)callsiteTableEntryAddr, reloLocation, reloFlags(reloTarget)); + + return TR_RelocationErrorCode::relocationOK; + } + +TR_RelocationErrorCode +TR_RelocationRecordCallsiteTableEntryAddress::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocationHigh, uint8_t *reloLocationLow) + { + TR_RelocationRecordCallsiteTableEntryAddressPrivateData *reloPrivateData = &(privateData()->callsiteTableEntryAddr); + void *callsiteTableEntryAddr = reloPrivateData->_callsiteTableEntryAddress; + + reloTarget->storeAddress((uint8_t *)callsiteTableEntryAddr, reloLocationHigh, reloLocationLow, reloFlags(reloTarget)); + + return TR_RelocationErrorCode::relocationOK; + } + // The _relocationRecordHeaderSizeTable table should be the last thing in this file uint32_t TR_RelocationRecord::_relocationRecordHeaderSizeTable[TR_NumExternalRelocationKinds] = { @@ -6944,5 +7021,6 @@ uint32_t TR_RelocationRecord::_relocationRecordHeaderSizeTable[TR_NumExternalRel sizeof(TR_RelocationRecordMethodEnterExitHookAddressBinaryTemplate), // TR_MethodEnterExitHookAddress = 115 sizeof(TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate), // TR_ValidateDynamicMethodFromCallsiteIndex = 116 sizeof(TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate), // TR_ValidateHandleMethodFromCPIndex = 117 + sizeof(TR_RelocationRecordCallsiteTableEntryAddressBinaryTemplate), // TR_CallsiteTableEntryAddress = 118 }; // The _relocationRecordHeaderSizeTable table should be the last thing in this file diff --git a/runtime/compiler/runtime/RelocationRecord.hpp b/runtime/compiler/runtime/RelocationRecord.hpp index 9d361e0604a..00b5b75472c 100644 --- a/runtime/compiler/runtime/RelocationRecord.hpp +++ b/runtime/compiler/runtime/RelocationRecord.hpp @@ -176,6 +176,11 @@ struct TR_RelocationRecordMethodEnterExitHookAddressPrivateData bool _isEnterHookAddr; }; +struct TR_RelocationRecordCallsiteTableEntryAddressPrivateData + { + void *_callsiteTableEntryAddress; + }; + union TR_RelocationRecordPrivateData { TR_RelocationRecordHelperAddressPrivateData helperAddress; @@ -195,6 +200,7 @@ union TR_RelocationRecordPrivateData TR_RelocationRecordRecompQueuedFlagPrivateData recompQueuedFlag; TR_RelocationRecordBreakpointGuardPrivateData breakpointGuard; TR_RelocationRecordMethodEnterExitHookAddressPrivateData hookAddress; + TR_RelocationRecordCallsiteTableEntryAddressPrivateData callsiteTableEntryAddr; }; enum TR_RelocationRecordAction @@ -2063,5 +2069,26 @@ class TR_RelocationRecordMethodEnterExitHookAddress : public TR_RelocationRecord virtual TR_RelocationErrorCode applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocationHigh, uint8_t *reloLocationLow); }; +class TR_RelocationRecordCallsiteTableEntryAddress : public TR_RelocationRecord + { + public: + TR_RelocationRecordCallsiteTableEntryAddress() {} + TR_RelocationRecordCallsiteTableEntryAddress(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + + virtual const char *name() { return "TR_RelocationRecordCallsiteTableEntryAddress"; } + virtual void print(TR_RelocationRuntime *reloRuntime); + + void setMethodID(TR_RelocationTarget *reloTarget, uint16_t methodID); + uint16_t methodID(TR_RelocationTarget *reloTarget); + + void setCallsiteIndex(TR_RelocationTarget *reloTarget, int32_t callsiteIndex); + int32_t callsiteIndex(TR_RelocationTarget *reloTarget); + + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget); + + virtual TR_RelocationErrorCode applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + virtual TR_RelocationErrorCode applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocationHigh, uint8_t *reloLocationLow); + }; + #endif // RELOCATION_RECORD_INCL diff --git a/runtime/compiler/runtime/Runtime.cpp b/runtime/compiler/runtime/Runtime.cpp index 00c2fc2a56c..7669af61f24 100644 --- a/runtime/compiler/runtime/Runtime.cpp +++ b/runtime/compiler/runtime/Runtime.cpp @@ -2098,6 +2098,7 @@ bool isOrderedPair(U_8 recordType) case TR_DataAddress: case TR_DebugCounter: case TR_MethodEnterExitHookAddress: + case TR_CallsiteTableEntryAddress: #endif isOrderedPair = true; break; diff --git a/runtime/compiler/z/codegen/S390AOTRelocation.cpp b/runtime/compiler/z/codegen/S390AOTRelocation.cpp index 7127ce4882f..fd13c9e5e07 100644 --- a/runtime/compiler/z/codegen/S390AOTRelocation.cpp +++ b/runtime/compiler/z/codegen/S390AOTRelocation.cpp @@ -247,6 +247,19 @@ void TR::S390EncodingRelocation::addRelocation(TR::CodeGenerator *cg, uint8_t *c line, node); } + else if (_reloType==TR_CallsiteTableEntryAddress) + { + cg->addExternalRelocation( + TR::ExternalRelocation::create( + cursor, + (uint8_t *)_symbolReference, + NULL, + TR_CallsiteTableEntryAddress, + cg), + file, + line, + node); + } else { TR_ASSERT(0,"relocation type [%d] not handled yet", _reloType); From aa2f319e3e05467e9b396f1df3f2191247d6a1c6 Mon Sep 17 00:00:00 2001 From: Irwin D'Souza Date: Tue, 30 Jul 2024 23:31:26 -0400 Subject: [PATCH 6/8] Add TR_MethodTypeTableEntryAddress relocations Signed-off-by: Irwin D'Souza --- doc/compiler/aot/RelocationRecords.md | 2 +- .../compiler/codegen/J9AheadOfTimeCompile.cpp | 32 ++++++++ .../compiler/il/J9StaticSymbol_inlines.hpp | 3 + .../p/runtime/PPCRelocationTarget.cpp | 1 + runtime/compiler/runtime/RelocationRecord.cpp | 78 +++++++++++++++++++ runtime/compiler/runtime/RelocationRecord.hpp | 27 +++++++ runtime/compiler/runtime/Runtime.cpp | 1 + .../compiler/z/codegen/S390AOTRelocation.cpp | 13 ++++ 8 files changed, 156 insertions(+), 1 deletion(-) diff --git a/doc/compiler/aot/RelocationRecords.md b/doc/compiler/aot/RelocationRecords.md index ce6cc026387..e3173b71982 100644 --- a/doc/compiler/aot/RelocationRecords.md +++ b/doc/compiler/aot/RelocationRecords.md @@ -140,4 +140,4 @@ exact type of the API class for each relocation kind can be found in |`TR_ValidateDynamicMethodFromCallsiteIndex`|Validates the target method of an `invokeDynamic` invocation.| |`TR_ValidateHandleMethodFromCPIndex`|Validates the target method of an `invokeHandle` invocation.| |`TR_CallsiteTableEntryAddress`|Relocates the callsite table entry address.| - +|`TR_MethodTypeTableEntryAddress`|Relocates the method type table entry address.| diff --git a/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp b/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp index d0b047daf41..d733a24cf8d 100644 --- a/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp +++ b/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp @@ -1394,6 +1394,22 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal } break; + + case TR_MethodTypeTableEntryAddress: + { + auto *mteaRecord = reinterpret_cast(reloRecord); + + TR::SymbolReference *symRef = reinterpret_cast(relocation->getTargetAddress()); + uint8_t flags = static_cast(reinterpret_cast(relocation->getTargetAddress2())); + + TR_OpaqueMethodBlock *method = symRef->getOwningMethod(comp)->getNonPersistentIdentifier(); + + mteaRecord->setReloFlags(reloTarget, flags); + mteaRecord->setMethodID(reloTarget, symValManager->getSymbolIDFromValue(method)); + mteaRecord->setCpIndex(reloTarget, symRef->getSymbol()->getStaticSymbol()->getMethodTypeIndex()); + } + break; + default: TR_ASSERT(false, "Unknown relo type %d!\n", kind); comp->failCompilation("Unknown relo type %d!\n", kind); @@ -2393,6 +2409,22 @@ J9::AheadOfTimeCompile::dumpRelocationHeaderData(uint8_t *cursor, bool isVerbose } break; + case TR_MethodTypeTableEntryAddress: + { + auto *mteaRecord = reinterpret_cast(reloRecord); + + self()->traceRelocationOffsets(startOfOffsets, offsetSize, endOfCurrentRecord, orderedPair); + if (isVerbose) + { + traceMsg( + self()->comp(), + "\n Method Type Table Entry Address: methodID=%d, cpIndex=%d ", + (uint32_t)mteaRecord->methodID(reloTarget), + mteaRecord->cpIndex(reloTarget)); + } + } + break; + default: TR_ASSERT_FATAL(false, "dumpRelocationHeaderData: unknown relo kind %d\n", kind); } diff --git a/runtime/compiler/il/J9StaticSymbol_inlines.hpp b/runtime/compiler/il/J9StaticSymbol_inlines.hpp index 45c6d66377c..c730b9e9965 100644 --- a/runtime/compiler/il/J9StaticSymbol_inlines.hpp +++ b/runtime/compiler/il/J9StaticSymbol_inlines.hpp @@ -42,6 +42,9 @@ J9::StaticSymbol::makeMethodTypeTableEntry(int32_t methodTypeIndex) TR_ASSERT(self()->getDataType() == TR::Address, "MethodTypeTableEntries have historically had TR::Address as data type"); _methodTypeIndex = methodTypeIndex; self()->setMethodTypeTableEntry(); + + // Needed so that the relo infra does not think this is a static field address + self()->setNotDataAddress(); } inline void diff --git a/runtime/compiler/p/runtime/PPCRelocationTarget.cpp b/runtime/compiler/p/runtime/PPCRelocationTarget.cpp index 71f9728cbec..6c8525199e8 100644 --- a/runtime/compiler/p/runtime/PPCRelocationTarget.cpp +++ b/runtime/compiler/p/runtime/PPCRelocationTarget.cpp @@ -314,6 +314,7 @@ TR_PPC32RelocationTarget::isOrderedPairRelocation(TR_RelocationRecord *reloRecor case TR_DebugCounter: case TR_MethodEnterExitHookAddress: case TR_CallsiteTableEntryAddress: + case TR_MethodTypeTableEntryAddress: return true; default: return false; diff --git a/runtime/compiler/runtime/RelocationRecord.cpp b/runtime/compiler/runtime/RelocationRecord.cpp index 7acd6ae9561..887d40c75aa 100644 --- a/runtime/compiler/runtime/RelocationRecord.cpp +++ b/runtime/compiler/runtime/RelocationRecord.cpp @@ -429,6 +429,12 @@ struct TR_RelocationRecordCallsiteTableEntryAddressBinaryTemplate : public TR_Re int32_t _callsiteIndex; }; +struct TR_RelocationRecordMethodTypeTableEntryAddressBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + int32_t _cpIndex; + }; + // END OF BINARY TEMPLATES uint8_t @@ -871,6 +877,9 @@ TR_RelocationRecord::create(TR_RelocationRecord *storage, TR_RelocationRuntime * case TR_CallsiteTableEntryAddress: reloRecord = new (storage) TR_RelocationRecordCallsiteTableEntryAddress(reloRuntime, record); break; + case TR_MethodTypeTableEntryAddress: + reloRecord = new (storage) TR_RelocationRecordMethodTypeTableEntryAddress(reloRuntime, record); + break; default: // TODO: error condition printf("Unexpected relo record: %d\n", reloType);fflush(stdout); @@ -6900,6 +6909,74 @@ TR_RelocationRecordCallsiteTableEntryAddress::applyRelocation(TR_RelocationRunti return TR_RelocationErrorCode::relocationOK; } +// TR_RelocationRecordMethodTypeTableEntryAddress +void +TR_RelocationRecordMethodTypeTableEntryAddress::print(TR_RelocationRuntime *reloRuntime) + { + TR_RelocationTarget *reloTarget = reloRuntime->reloTarget(); + TR_RelocationRuntimeLogger *reloLogger = reloRuntime->reloLogger(); + TR_RelocationRecord::print(reloRuntime); + reloLogger->printf("\tmethodID %d\n", methodID(reloTarget)); + reloLogger->printf("\tcpIndex %d\n", cpIndex(reloTarget)); + } + +void +TR_RelocationRecordMethodTypeTableEntryAddress::setMethodID(TR_RelocationTarget *reloTarget, uint16_t methodID) + { + reloTarget->storeUnsigned16b(methodID, (uint8_t *) &((TR_RelocationRecordMethodTypeTableEntryAddressBinaryTemplate *)_record)->_methodID); + } + +uint16_t +TR_RelocationRecordMethodTypeTableEntryAddress::methodID(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordMethodTypeTableEntryAddressBinaryTemplate *)_record)->_methodID); + } + +void +TR_RelocationRecordMethodTypeTableEntryAddress::setCpIndex(TR_RelocationTarget *reloTarget, int32_t cpIndex) + { + reloTarget->storeSigned32b(cpIndex, (uint8_t *) &((TR_RelocationRecordMethodTypeTableEntryAddressBinaryTemplate *)_record)->_cpIndex); + } + +int32_t +TR_RelocationRecordMethodTypeTableEntryAddress::cpIndex(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadSigned32b((uint8_t *) &((TR_RelocationRecordMethodTypeTableEntryAddressBinaryTemplate *)_record)->_cpIndex); + } + +void +TR_RelocationRecordMethodTypeTableEntryAddress::preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) + { + TR_RelocationRecordMethodTypeTableEntryAddressPrivateData *reloPrivateData = &(privateData()->methodTypeTableEntryAddr); + + TR_OpaqueMethodBlock *method = reloRuntime->comp()->getSymbolValidationManager()->getMethodFromID(methodID(reloTarget)); + TR_ResolvedMethod *resolvedMethod = reloRuntime->fej9()->createResolvedMethod(reloRuntime->trMemory(), method, NULL); + + reloPrivateData->_methodTypeTableEntryAddress = resolvedMethod->methodTypeTableEntryAddress(cpIndex(reloTarget)); + } + +TR_RelocationErrorCode +TR_RelocationRecordMethodTypeTableEntryAddress::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + TR_RelocationRecordMethodTypeTableEntryAddressPrivateData *reloPrivateData = &(privateData()->methodTypeTableEntryAddr); + void *methodTypeTableEntryAddr = reloPrivateData->_methodTypeTableEntryAddress; + + reloTarget->storeAddressSequence((uint8_t *)methodTypeTableEntryAddr, reloLocation, reloFlags(reloTarget)); + + return TR_RelocationErrorCode::relocationOK; + } + +TR_RelocationErrorCode +TR_RelocationRecordMethodTypeTableEntryAddress::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocationHigh, uint8_t *reloLocationLow) + { + TR_RelocationRecordMethodTypeTableEntryAddressPrivateData *reloPrivateData = &(privateData()->methodTypeTableEntryAddr); + void *methodTypeTableEntryAddr = reloPrivateData->_methodTypeTableEntryAddress; + + reloTarget->storeAddress((uint8_t *)methodTypeTableEntryAddr, reloLocationHigh, reloLocationLow, reloFlags(reloTarget)); + + return TR_RelocationErrorCode::relocationOK; + } + // The _relocationRecordHeaderSizeTable table should be the last thing in this file uint32_t TR_RelocationRecord::_relocationRecordHeaderSizeTable[TR_NumExternalRelocationKinds] = { @@ -7022,5 +7099,6 @@ uint32_t TR_RelocationRecord::_relocationRecordHeaderSizeTable[TR_NumExternalRel sizeof(TR_RelocationRecordValidateDynamicMethodFromCallsiteIndexBinaryTemplate), // TR_ValidateDynamicMethodFromCallsiteIndex = 116 sizeof(TR_RelocationRecordValidateHandleMethodFromCPIndexBinaryTemplate), // TR_ValidateHandleMethodFromCPIndex = 117 sizeof(TR_RelocationRecordCallsiteTableEntryAddressBinaryTemplate), // TR_CallsiteTableEntryAddress = 118 + sizeof(TR_RelocationRecordMethodTypeTableEntryAddressBinaryTemplate), // TR_MethodTypeTableEntryAddress = 119 }; // The _relocationRecordHeaderSizeTable table should be the last thing in this file diff --git a/runtime/compiler/runtime/RelocationRecord.hpp b/runtime/compiler/runtime/RelocationRecord.hpp index 00b5b75472c..151b85ad055 100644 --- a/runtime/compiler/runtime/RelocationRecord.hpp +++ b/runtime/compiler/runtime/RelocationRecord.hpp @@ -181,6 +181,11 @@ struct TR_RelocationRecordCallsiteTableEntryAddressPrivateData void *_callsiteTableEntryAddress; }; +struct TR_RelocationRecordMethodTypeTableEntryAddressPrivateData + { + void *_methodTypeTableEntryAddress; + }; + union TR_RelocationRecordPrivateData { TR_RelocationRecordHelperAddressPrivateData helperAddress; @@ -201,6 +206,7 @@ union TR_RelocationRecordPrivateData TR_RelocationRecordBreakpointGuardPrivateData breakpointGuard; TR_RelocationRecordMethodEnterExitHookAddressPrivateData hookAddress; TR_RelocationRecordCallsiteTableEntryAddressPrivateData callsiteTableEntryAddr; + TR_RelocationRecordMethodTypeTableEntryAddressPrivateData methodTypeTableEntryAddr; }; enum TR_RelocationRecordAction @@ -2090,5 +2096,26 @@ class TR_RelocationRecordCallsiteTableEntryAddress : public TR_RelocationRecord virtual TR_RelocationErrorCode applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocationHigh, uint8_t *reloLocationLow); }; +class TR_RelocationRecordMethodTypeTableEntryAddress : public TR_RelocationRecord + { + public: + TR_RelocationRecordMethodTypeTableEntryAddress() {} + TR_RelocationRecordMethodTypeTableEntryAddress(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + + virtual const char *name() { return "TR_RelocationRecordMethodTypeTableEntryAddress"; } + virtual void print(TR_RelocationRuntime *reloRuntime); + + void setMethodID(TR_RelocationTarget *reloTarget, uint16_t methodID); + uint16_t methodID(TR_RelocationTarget *reloTarget); + + void setCpIndex(TR_RelocationTarget *reloTarget, int32_t cpIndex); + int32_t cpIndex(TR_RelocationTarget *reloTarget); + + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget); + + virtual TR_RelocationErrorCode applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + virtual TR_RelocationErrorCode applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocationHigh, uint8_t *reloLocationLow); + }; + #endif // RELOCATION_RECORD_INCL diff --git a/runtime/compiler/runtime/Runtime.cpp b/runtime/compiler/runtime/Runtime.cpp index 7669af61f24..ebccd083db4 100644 --- a/runtime/compiler/runtime/Runtime.cpp +++ b/runtime/compiler/runtime/Runtime.cpp @@ -2099,6 +2099,7 @@ bool isOrderedPair(U_8 recordType) case TR_DebugCounter: case TR_MethodEnterExitHookAddress: case TR_CallsiteTableEntryAddress: + case TR_MethodTypeTableEntryAddress: #endif isOrderedPair = true; break; diff --git a/runtime/compiler/z/codegen/S390AOTRelocation.cpp b/runtime/compiler/z/codegen/S390AOTRelocation.cpp index fd13c9e5e07..c46163eda09 100644 --- a/runtime/compiler/z/codegen/S390AOTRelocation.cpp +++ b/runtime/compiler/z/codegen/S390AOTRelocation.cpp @@ -260,6 +260,19 @@ void TR::S390EncodingRelocation::addRelocation(TR::CodeGenerator *cg, uint8_t *c line, node); } + else if (_reloType==TR_MethodTypeTableEntryAddress) + { + cg->addExternalRelocation( + TR::ExternalRelocation::create( + cursor, + (uint8_t *)_symbolReference, + NULL, + TR_MethodTypeTableEntryAddress, + cg), + file, + line, + node); + } else { TR_ASSERT(0,"relocation type [%d] not handled yet", _reloType); From 411f8c0b7f75eaf76b96bcfcecff6bf86a1761f6 Mon Sep 17 00:00:00 2001 From: Irwin D'Souza Date: Fri, 16 Aug 2024 10:16:42 -0400 Subject: [PATCH 7/8] Store LambdaForms into the SCC Signed-off-by: Irwin D'Souza --- runtime/bcutil/ROMClassBuilder.cpp | 8 +++++++- runtime/oti/shcflags.h | 1 + runtime/shared_common/shrinit.cpp | 13 +++++++------ runtime/shared_common/shrinit.h | 1 + 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/runtime/bcutil/ROMClassBuilder.cpp b/runtime/bcutil/ROMClassBuilder.cpp index d7adf4e65ef..16230105b0d 100644 --- a/runtime/bcutil/ROMClassBuilder.cpp +++ b/runtime/bcutil/ROMClassBuilder.cpp @@ -283,8 +283,14 @@ ROMClassBuilder::handleAnonClassName(J9CfrClassFile *classfile, ROMClassCreation * Performance can be much worse (compared to shared cache turned off). */ if (isLambdaFormClassName(originalStringBytes, originalStringLength, NULL/*deterministicPrefixLength*/)) { - context->addFindClassFlags(J9_FINDCLASS_FLAG_DO_NOT_SHARE); context->addFindClassFlags(J9_FINDCLASS_FLAG_LAMBDAFORM); +#if defined(J9VM_OPT_SHARED_CLASSES) + if ((NULL != _javaVM) && (NULL != _javaVM->sharedClassConfig)) { + if (J9_ARE_NO_BITS_SET(_javaVM->sharedClassConfig->runtimeFlags2, J9SHR_RUNTIMEFLAG2_SHARE_LAMBDAFORM)) { + context->addFindClassFlags(J9_FINDCLASS_FLAG_DO_NOT_SHARE); + } + } +#endif /* defined(J9VM_OPT_SHARED_CLASSES) */ } #if JAVA_SPEC_VERSION >= 15 diff --git a/runtime/oti/shcflags.h b/runtime/oti/shcflags.h index 9bcc370c927..a13e64a7f09 100644 --- a/runtime/oti/shcflags.h +++ b/runtime/oti/shcflags.h @@ -130,6 +130,7 @@ #define J9SHR_RUNTIMEFLAG2_ENABLE_CACHEORPHAN 1 #define J9SHR_RUNTIMEFLAG2_TEST_DOUBLE_PAGESIZE 2 #define J9SHR_RUNTIMEFLAG2_TEST_HALF_PAGESIZE 4 +#define J9SHR_RUNTIMEFLAG2_SHARE_LAMBDAFORM 8 #define J9SHR_VERBOSEFLAG_ENABLE_VERBOSE_DEFAULT 1 #define J9SHR_VERBOSEFLAG_ENABLE_VERBOSE 2 diff --git a/runtime/shared_common/shrinit.cpp b/runtime/shared_common/shrinit.cpp index 7eb19629458..1e098c7e0ea 100644 --- a/runtime/shared_common/shrinit.cpp +++ b/runtime/shared_common/shrinit.cpp @@ -387,6 +387,7 @@ J9SharedClassesOptions J9SHAREDCLASSESOPTIONS[] = { { OPTION_TEST_DOUBLE_PAGESIZE, PARSE_TYPE_EXACT, RESULT_DO_ADD_RUNTIMEFLAG2, J9SHR_RUNTIMEFLAG2_TEST_DOUBLE_PAGESIZE}, { OPTION_TEST_HALF_PAGESIZE, PARSE_TYPE_EXACT, RESULT_DO_ADD_RUNTIMEFLAG2, J9SHR_RUNTIMEFLAG2_TEST_HALF_PAGESIZE}, { OPTION_EXTRA_STARTUPHINTS_EQUALS, PARSE_TYPE_STARTSWITH, RESULT_DO_SET_EXTRA_STARTUPHINTS, 0}, + { OPTION_SHARE_LAMBDAFORM, PARSE_TYPE_EXACT, RESULT_DO_ADD_RUNTIMEFLAG2, J9SHR_RUNTIMEFLAG2_SHARE_LAMBDAFORM}, { NULL, 0, 0 } }; @@ -1278,7 +1279,7 @@ j9shr_dump_help(J9JavaVM* vm, UDATA more) tmpcstr = j9nls_lookup_message((J9NLS_INFO | J9NLS_DO_NOT_PRINT_MESSAGE_TAG), J9NLS_EXELIB_INTERNAL_HELP_XXDISABLESHAREUNSAFECLASSES, NULL); j9file_printf(PORTLIB, J9PORT_TTY_OUT, "%s", tmpcstr); - + tmpcstr = j9nls_lookup_message((J9NLS_INFO | J9NLS_DO_NOT_PRINT_MESSAGE_TAG), J9NLS_EXELIB_INTERNAL_HELP_XXENABLESHAREORPAH, NULL); j9file_printf(PORTLIB, J9PORT_TTY_OUT, "%s", tmpcstr); @@ -1374,7 +1375,7 @@ void registerStoreFilter(J9JavaVM* vm, J9ClassLoader* classloader, const char* fixedName, UDATA fixedNameSize, J9Pool** filterPoolPtr) { PORT_ACCESS_FROM_JAVAVM(vm); - + Trc_SHR_Assert_ShouldHaveLocalMutex(vm->classMemorySegments->segmentMutex); if (*filterPoolPtr == NULL) { @@ -2448,13 +2449,13 @@ reportUtilityNotApplicable(J9JavaVM* vm, const char* ctrlDirName, const char* ca static void j9shr_printStats_dump_help(J9JavaVM* vm, bool moreHelp, UDATA command) { PORT_ACCESS_FROM_JAVAVM(vm); - + const char* option = OPTION_PRINTSTATS_EQUALS; if (RESULT_DO_PRINTALLSTATS_EQUALS == command) { option = OPTION_PRINTALLSTATS_EQUALS; } else if (RESULT_DO_PRINT_TOP_LAYER_STATS_EQUALS == command) { option = OPTION_PRINT_TOP_LAYER_STATS_EQUALS; - } + } SHRINIT_TRACE2_NOTAG(1, J9NLS_SHRC_SHRINIT_HELPTEXT_PRINTSTATS_HELP_V1, option, option); @@ -4058,7 +4059,7 @@ j9shr_getCacheSizeBytes(J9JavaVM *vm) * @param [in] vm Pointer to the VM structure for the JVM * * @return J9SharedClassCacheMode enum that indicates the Shared Class Cache that is in effect - * + * */ J9SharedClassCacheMode j9shr_getSharedClassCacheMode(J9JavaVM *vm) @@ -4457,7 +4458,7 @@ getDefaultRuntimeFlags(void) J9SHR_RUNTIMEFLAG_ENABLE_TIMESTAMP_CHECKS | J9SHR_RUNTIMEFLAG_ENABLE_REDUCE_STORE_CONTENTION | J9SHR_RUNTIMEFLAG_ENABLE_SHAREANONYMOUSCLASSES | - J9SHR_RUNTIMEFLAG_ENABLE_SHAREUNSAFECLASSES | + J9SHR_RUNTIMEFLAG_ENABLE_SHAREUNSAFECLASSES | J9SHR_RUNTIMEFLAG_ENABLE_ROUND_TO_PAGE_SIZE | J9SHR_RUNTIMEFLAG_ENABLE_MPROTECT | #if !defined(J9ZOS390) && !defined(AIXPPC) diff --git a/runtime/shared_common/shrinit.h b/runtime/shared_common/shrinit.h index d7b1e7b0114..ca67e128567 100644 --- a/runtime/shared_common/shrinit.h +++ b/runtime/shared_common/shrinit.h @@ -199,6 +199,7 @@ typedef struct J9SharedClassesOptions { #define OPTION_TEST_DOUBLE_PAGESIZE "testDoublePageSize" #define OPTION_TEST_HALF_PAGESIZE "testHalfPageSize" #define OPTION_EXTRA_STARTUPHINTS_EQUALS "extraStartupHints=" +#define OPTION_SHARE_LAMBDAFORM "shareLambdaForm" /* internal option for dev/testing */ /* public options for printallstats= and printstats= */ #define SUB_OPTION_PRINTSTATS_ALL "all" From 9a7438fb7a33617e375d6ca2bd5391fdae1aeea1 Mon Sep 17 00:00:00 2001 From: Irwin D'Souza Date: Tue, 5 Nov 2024 13:09:12 -0500 Subject: [PATCH 8/8] Support resolved invokeHandle/invokeDynamic dispatch in SVM AOT Signed-off-by: Irwin D'Souza --- .../control/JITClientCompilationThread.cpp | 5 ++++ runtime/compiler/env/J9SharedCache.hpp | 3 +- runtime/compiler/env/j9method.cpp | 24 ++++++++++++++++ runtime/compiler/env/j9method.h | 4 +-- runtime/compiler/env/j9methodServer.cpp | 28 +++++++++++++++++++ runtime/compiler/env/j9methodServer.hpp | 4 +-- runtime/compiler/net/CommunicationStream.hpp | 2 +- runtime/compiler/runtime/JITClientSession.hpp | 1 + 8 files changed, 65 insertions(+), 6 deletions(-) diff --git a/runtime/compiler/control/JITClientCompilationThread.cpp b/runtime/compiler/control/JITClientCompilationThread.cpp index d8bd9a846d7..2dd1fa3c4e0 100644 --- a/runtime/compiler/control/JITClientCompilationThread.cpp +++ b/runtime/compiler/control/JITClientCompilationThread.cpp @@ -486,6 +486,11 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes // These offsets are initialized later on vmInfo._vmtargetOffset = 0; vmInfo._vmindexOffset = 0; + auto sharedCacheConfig = fe->sharedCache() ? fe->sharedCache()->sharedCacheConfig() : NULL; + if (sharedCacheConfig) + vmInfo._shareLambdaForm = J9_ARE_ALL_BITS_SET(sharedCacheConfig->runtimeFlags2, J9SHR_RUNTIMEFLAG2_SHARE_LAMBDAFORM); + else + vmInfo._shareLambdaForm = false; #endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */ } diff --git a/runtime/compiler/env/J9SharedCache.hpp b/runtime/compiler/env/J9SharedCache.hpp index 3b6a37cd4e7..aa83593b756 100644 --- a/runtime/compiler/env/J9SharedCache.hpp +++ b/runtime/compiler/env/J9SharedCache.hpp @@ -448,6 +448,8 @@ class TR_J9SharedCache : public TR_SharedCache virtual J9SharedClassCacheDescriptor *getCacheDescriptorList(); + J9SharedClassConfig *sharedCacheConfig() { return _sharedCacheConfig; } + protected: static bool disclaim(const uint8_t *start, const uint8_t *end, UDATA pageSize, bool trace); @@ -503,7 +505,6 @@ class TR_J9SharedCache : public TR_SharedCache J9JITConfig *jitConfig() { return _jitConfig; } J9JavaVM *javaVM() { return _javaVM; } - J9SharedClassConfig *sharedCacheConfig() { return _sharedCacheConfig; } TR_AOTStats *aotStats() { return _aotStats; } diff --git a/runtime/compiler/env/j9method.cpp b/runtime/compiler/env/j9method.cpp index 9906bb4dc7c..59971b208f8 100644 --- a/runtime/compiler/env/j9method.cpp +++ b/runtime/compiler/env/j9method.cpp @@ -1294,6 +1294,30 @@ TR_ResolvedRelocatableJ9Method::isUnresolvedMethodHandle(I_32 cpIndex) return true; } +bool +TR_ResolvedRelocatableJ9Method::isUnresolvedCallSiteTableEntry(int32_t callSiteIndex) + { + bool unresolved = true; + J9JavaVM * javaVM = fej9()->_jitConfig->javaVM; + if (J9_ARE_ALL_BITS_SET(javaVM->sharedClassConfig->runtimeFlags2, J9SHR_RUNTIMEFLAG2_SHARE_LAMBDAFORM)) + { + unresolved = TR_ResolvedJ9Method::isUnresolvedCallSiteTableEntry(callSiteIndex); + } + return unresolved; + } + +bool +TR_ResolvedRelocatableJ9Method::isUnresolvedMethodTypeTableEntry(int32_t cpIndex) + { + bool unresolved = true; + J9JavaVM * javaVM = fej9()->_jitConfig->javaVM; + if (J9_ARE_ALL_BITS_SET(javaVM->sharedClassConfig->runtimeFlags2, J9SHR_RUNTIMEFLAG2_SHARE_LAMBDAFORM)) + { + unresolved = TR_ResolvedJ9Method::isUnresolvedMethodTypeTableEntry(cpIndex); + } + return unresolved; + } + TR_ResolvedMethod * TR_ResolvedRelocatableJ9Method::getResolvedPossiblyPrivateVirtualMethod( TR::Compilation *comp, diff --git a/runtime/compiler/env/j9method.h b/runtime/compiler/env/j9method.h index 6631718bcb1..2e7987922c8 100644 --- a/runtime/compiler/env/j9method.h +++ b/runtime/compiler/env/j9method.h @@ -606,8 +606,8 @@ class TR_ResolvedRelocatableJ9Method : public TR_ResolvedJ9Method virtual bool isUnresolvedMethodType(int32_t cpIndex); virtual void * methodHandleConstant(int32_t cpIndex); virtual bool isUnresolvedMethodHandle(int32_t cpIndex); - virtual bool isUnresolvedCallSiteTableEntry(int32_t callSiteIndex) { return true; } - virtual bool isUnresolvedMethodTypeTableEntry(int32_t cpIndex) { return true; } + virtual bool isUnresolvedCallSiteTableEntry(int32_t callSiteIndex); + virtual bool isUnresolvedMethodTypeTableEntry(int32_t cpIndex); virtual bool fieldAttributes ( TR::Compilation *, int32_t cpIndex, uint32_t * fieldOffset, TR::DataType * type, bool * volatileP, bool * isFinal, bool *isPrivate, bool isStore, bool * unresolvedInCP, bool needsAOTValidation); diff --git a/runtime/compiler/env/j9methodServer.cpp b/runtime/compiler/env/j9methodServer.cpp index 8f4b856c2e8..7fb487b4306 100644 --- a/runtime/compiler/env/j9methodServer.cpp +++ b/runtime/compiler/env/j9methodServer.cpp @@ -2336,6 +2336,34 @@ TR_ResolvedRelocatableJ9JITServerMethod::isUnresolvedMethodHandle(I_32 cpIndex) return true; } +bool +TR_ResolvedRelocatableJ9JITServerMethod::isUnresolvedMethodTypeTableEntry(int32_t cpIndex) + { + bool unresolved = true; +#if defined(J9VM_OPT_OPENJDK_METHODHANDLE) + auto *vmInfo = _fe->_compInfoPT->getClientData()->getOrCacheVMInfo(_stream); + if (vmInfo->_shareLambdaForm) + { + unresolved = TR_ResolvedJ9JITServerMethod::isUnresolvedMethodTypeTableEntry(cpIndex); + } +#endif // defined(J9VM_OPT_OPENJDK_METHODHANDLE) + return unresolved; + } + +bool +TR_ResolvedRelocatableJ9JITServerMethod::isUnresolvedCallSiteTableEntry(int32_t callSiteIndex) + { + bool unresolved = true; +#if defined(J9VM_OPT_OPENJDK_METHODHANDLE) + auto *vmInfo = _fe->_compInfoPT->getClientData()->getOrCacheVMInfo(_stream); + if (vmInfo->_shareLambdaForm) + { + unresolved = TR_ResolvedJ9JITServerMethod::isUnresolvedCallSiteTableEntry(callSiteIndex); + } +#endif // defined(J9VM_OPT_OPENJDK_METHODHANDLE) + return unresolved; + } + TR_OpaqueClassBlock * TR_ResolvedRelocatableJ9JITServerMethod::getDeclaringClassFromFieldOrStatic(TR::Compilation *comp, int32_t cpIndex) { diff --git a/runtime/compiler/env/j9methodServer.hpp b/runtime/compiler/env/j9methodServer.hpp index edd980d2e65..95adc56b360 100644 --- a/runtime/compiler/env/j9methodServer.hpp +++ b/runtime/compiler/env/j9methodServer.hpp @@ -306,8 +306,8 @@ class TR_ResolvedRelocatableJ9JITServerMethod : public TR_ResolvedJ9JITServerMet virtual bool isUnresolvedMethodType(int32_t cpIndex) override; virtual void * methodHandleConstant(int32_t cpIndex) override; virtual bool isUnresolvedMethodHandle(int32_t cpIndex) override; - virtual bool isUnresolvedMethodTypeTableEntry(int32_t cpIndex) override { return true; } - virtual bool isUnresolvedCallSiteTableEntry(int32_t callSiteIndex) override { return true; } + virtual bool isUnresolvedMethodTypeTableEntry(int32_t cpIndex) override; + virtual bool isUnresolvedCallSiteTableEntry(int32_t callSiteIndex) override; virtual TR_OpaqueClassBlock * classOfStatic(int32_t cpIndex, bool returnClassForAOT = false) override; virtual TR_ResolvedMethod * getResolvedPossiblyPrivateVirtualMethod(TR::Compilation *, int32_t cpIndex, bool ignoreRtResolve, bool * unresolvedInCP) override; virtual bool getUnresolvedFieldInCP(I_32 cpIndex) override; diff --git a/runtime/compiler/net/CommunicationStream.hpp b/runtime/compiler/net/CommunicationStream.hpp index ae5b4a056eb..afbcaf2ef70 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 = 70; // ID:5nbb7nhW+R7OABuv+aRm + static const uint16_t MINOR_NUMBER = 71; // ID:1QMsN16q0acJzn1qRQHY static const uint8_t PATCH_NUMBER = 0; static uint32_t CONFIGURATION_FLAGS; diff --git a/runtime/compiler/runtime/JITClientSession.hpp b/runtime/compiler/runtime/JITClientSession.hpp index 4d0e8c6cff7..dbcc1d72e44 100644 --- a/runtime/compiler/runtime/JITClientSession.hpp +++ b/runtime/compiler/runtime/JITClientSession.hpp @@ -319,6 +319,7 @@ class ClientSessionData #if defined(J9VM_OPT_OPENJDK_METHODHANDLE) UDATA _vmtargetOffset; UDATA _vmindexOffset; + bool _shareLambdaForm; #endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */ bool _useAOTCache; // Should we use server offsets (idAndType of AOT cache serialization records) instead of