From 2efb2ea671ec7e1ce658f6afb153cc487f26f226 Mon Sep 17 00:00:00 2001 From: Irwin D'Souza Date: Fri, 27 Jan 2023 14:56:56 -0500 Subject: [PATCH 1/3] Refactor j9ThunkEncodeSignature Refactor the part of j9ThunkEncodeSignature that determines the encoding of the J2I Thunk Signature so that it can be reused by other functions. Signed-off-by: Irwin D'Souza --- runtime/codert_vm/thunkcrt.c | 57 ++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/runtime/codert_vm/thunkcrt.c b/runtime/codert_vm/thunkcrt.c index be3e3d8595a..88413268d2d 100644 --- a/runtime/codert_vm/thunkcrt.c +++ b/runtime/codert_vm/thunkcrt.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1991, 2022 IBM Corp. and others + * Copyright (c) 1991, 2023 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -106,6 +106,7 @@ static UDATA j9ThunkEncodeSignature(char *signatureData, U_8 * encodedSignature) static UDATA j9ThunkTableHash(void *key, void *userData); static UDATA j9ThunkTableEquals(void *leftKey, void *rightKey, void *userData); +typedef UDATA (*encodeByteFn)(UDATA encodedTypeByteStored, U_8 *encodedTypeBytePtr, U_8 encodedType); void * j9ThunkLookupNameAndSig(void * jitConfig, void *parm) @@ -297,21 +298,22 @@ j9ThunkNewSignature(void * jitConfig, int signatureLength, char *signatureChars, return 0; } -/* Returns the total number of bytes used in the encodedSignature buffer */ - static UDATA -j9ThunkEncodeSignature(char *signatureData, U_8 * encodedSignature) +j9ThunkEncodeByte(UDATA encodedTypeByteStored, U_8 *encodedTypeBytePtr, U_8 encodedType) { - U_8 * encodedTypes = encodedSignature + 1; - U_8 argCount = 0; + *encodedTypeBytePtr = ((*encodedTypeBytePtr) << 4) | encodedType; + return !encodedTypeByteStored; +} + +static void +j9ThunkIterateAndEncode(char ** signatureDataPtr, U_8 ** encodedTypesPtr, U_8 * argCountPtr, encodeByteFn encodeByte) +{ + UDATA done = FALSE; U_8 encodedTypeByte = 0; UDATA encodedTypeByteStored = TRUE; - UDATA done = FALSE; - UDATA totalSize; -#ifdef DEBUG - char * origSig = signatureData; - UDATA i; -#endif + U_8 * encodedTypes = *encodedTypesPtr; + char * signatureData = *signatureDataPtr; + U_8 argCount = *argCountPtr; /* Skip opening bracket */ ++signatureData; @@ -365,10 +367,9 @@ j9ThunkEncodeSignature(char *signatureData, U_8 * encodedSignature) break; } - /* Store encoded value into nybble */ + /* Store encoded value */ - encodedTypeByte = (encodedTypeByte << 4) | encodedType; - encodedTypeByteStored = !encodedTypeByteStored; + encodedTypeByteStored = encodeByte(encodedTypeByteStored, &encodedTypeByte, encodedType); if (encodedTypeByteStored) { *encodedTypes++ = encodedTypeByte; } @@ -377,9 +378,33 @@ j9ThunkEncodeSignature(char *signatureData, U_8 * encodedSignature) /* Store the final byte if necessary */ if (!encodedTypeByteStored) { - *encodedTypes++ = (encodedTypeByte << 4) | J9_THUNK_TYPE_FILL; + encodedTypeByteStored = encodeByte(encodedTypeByteStored, &encodedTypeByte, J9_THUNK_TYPE_FILL); + *encodedTypes++ = encodedTypeByte; } + *argCountPtr = argCount; + *encodedTypesPtr = encodedTypes; + *signatureDataPtr = signatureData; +} + +/* Returns the total number of bytes used in the encodedSignature buffer */ + +static UDATA +j9ThunkEncodeSignature(char *signatureData, U_8 * encodedSignature) +{ + /* Leave room for storing argCount */ + U_8 * encodedTypes = encodedSignature + 1; + U_8 argCount = 0; + UDATA totalSize; +#ifdef DEBUG + char * origSig = signatureData; + UDATA i; +#endif + + /* Iterate and encode the signature from signatureData into encodedTypes */ + + j9ThunkIterateAndEncode(&signatureData, &encodedTypes, &argCount, j9ThunkEncodeByte); + /* Store arg count and compute total size */ encodedSignature[0] = argCount; From de0f9fc80ffe42eafd0526a820dd7137b4da9456 Mon Sep 17 00:00:00 2001 From: Irwin D'Souza Date: Thu, 12 Jan 2023 16:17:22 -0500 Subject: [PATCH 2/3] Add methods to find/persist J2I Thunks from/to the SCC Add methods that will find and store J2I Thunks into the SCC rather than the hash tables. Because the SCC key needs to be a UTF8 string, generate the encoding of the signature (used as the key for the SCC entry) in ASCII. Signed-off-by: Irwin D'Souza --- runtime/codert_vm/thunkcrt.c | 94 ++++++++++++++++++++++++++++++++++++ runtime/oti/jitprotos.h | 12 +++-- 2 files changed, 102 insertions(+), 4 deletions(-) diff --git a/runtime/codert_vm/thunkcrt.c b/runtime/codert_vm/thunkcrt.c index 88413268d2d..1a16264bf0d 100644 --- a/runtime/codert_vm/thunkcrt.c +++ b/runtime/codert_vm/thunkcrt.c @@ -21,6 +21,7 @@ *******************************************************************************/ #include "j9.h" +#include "j9nonbuilder.h" #include "j9protos.h" #include "jitprotos.h" #include "ut_j9codertvm.h" @@ -102,6 +103,7 @@ extern void * icallVMprJavaSendInvokeExactL; #endif static U_8 j9ThunkGetEncodedSignature(J9ThunkTableEntry * entry, U_8 ** encodedSignaturePtr); +static UDATA j9ThunkEncodeSignatureASCII(char *signatureData, U_8 * encodedSignature); static UDATA j9ThunkEncodeSignature(char *signatureData, U_8 * encodedSignature); static UDATA j9ThunkTableHash(void *key, void *userData); static UDATA j9ThunkTableEquals(void *leftKey, void *rightKey, void *userData); @@ -305,6 +307,13 @@ j9ThunkEncodeByte(UDATA encodedTypeByteStored, U_8 *encodedTypeBytePtr, U_8 enco return !encodedTypeByteStored; } +static UDATA +j9ThunkEncodeByteASCII(UDATA encodedTypeByteStored, U_8 *encodedTypeBytePtr, U_8 encodedType) +{ + *encodedTypeBytePtr = (encodedType > 9 ? (encodedType - 10 + 'a') : (encodedType + '0')); + return TRUE; +} + static void j9ThunkIterateAndEncode(char ** signatureDataPtr, U_8 ** encodedTypesPtr, U_8 * argCountPtr, encodeByteFn encodeByte) { @@ -389,6 +398,38 @@ j9ThunkIterateAndEncode(char ** signatureDataPtr, U_8 ** encodedTypesPtr, U_8 * /* Returns the total number of bytes used in the encodedSignature buffer */ +static UDATA +j9ThunkEncodeSignatureASCII(char *signatureData, U_8 * encodedSignature) +{ + U_8 * encodedTypes = encodedSignature; + U_8 argCount = 0; + UDATA totalSize; +#ifdef DEBUG + char * origSig = signatureData; + UDATA i; +#endif + + /* Iterate and encode the signature in signatureData into encodedTypes */ + + j9ThunkIterateAndEncode(&signatureData, &encodedTypes, &argCount, j9ThunkEncodeByteASCII); + + /* Compute total size */ + + totalSize = encodedTypes - encodedSignature; + +#ifdef DEBUG + printf("encode: %.*s -> ", signatureData - origSig, origSig); + for (i = 0; i < totalSize; ++i) { + printf("%c", encodedSignature[i]); + } + printf(" (length %d)\n", totalSize); +#endif + + return totalSize; +} + +/* Returns the total number of bytes used in the encodedSignature buffer */ + static UDATA j9ThunkEncodeSignature(char *signatureData, U_8 * encodedSignature) { @@ -518,3 +559,56 @@ j9ThunkVMHelperFromNameAndSig(void * jitConfig, void *parm) return j9ThunkVMHelperFromSignature(jitConfig, J9UTF8_LENGTH(J9ROMNAMEANDSIGNATURE_SIGNATURE(nameAndSignature)), (char *) J9UTF8_DATA((J9ROMNAMEANDSIGNATURE_SIGNATURE(nameAndSignature)))); } + +const void * +j9ThunkPersist(J9JITConfig *jitConfig, char *signatureChars, U_32 signatureLength, U_8 *thunkStart, U_32 totalSize) +{ + const void *store = NULL; + +#if defined(J9VM_OPT_SHARED_CLASSES) + J9JavaVM *vm = jitConfig->javaVM; + J9VMThread *vmThread = vm->internalVMFunctions->currentVMThread(vm); + + U_8 encodedSignatureArray[2 * (J9_THUNK_MAX_ENCODED_BYTES - 1)]; + U_8 *encodedSignature = encodedSignatureArray; + UDATA encodedLength; + + J9SharedDataDescriptor dataDescriptor; + dataDescriptor.address = (U_8 *)thunkStart; + dataDescriptor.length = totalSize; + dataDescriptor.type = J9SHR_DATA_TYPE_AOTTHUNK; + dataDescriptor.flags = 0; + + encodedLength = j9ThunkEncodeSignatureASCII(signatureChars, encodedSignature); + + store = vm->sharedClassConfig->storeSharedData(vmThread, (const char *)encodedSignature, encodedLength, &dataDescriptor); +#endif + + return store; +} + +void * +j9ThunkFindPersistentThunk(J9JITConfig *jitConfig, char *signatureChars, U_32 signatureLength, UDATA *thunkSize) +{ + void * thunk = NULL; + +#if defined(J9VM_OPT_SHARED_CLASSES) + J9JavaVM *vm = jitConfig->javaVM; + J9VMThread *vmThread = vm->internalVMFunctions->currentVMThread(vm); + + U_8 encodedSignatureArray[2 * (J9_THUNK_MAX_ENCODED_BYTES - 1)]; + U_8 *encodedSignature = encodedSignatureArray; + UDATA encodedLength; + + J9SharedDataDescriptor dataDescriptor; + dataDescriptor.address = NULL; + + encodedLength = j9ThunkEncodeSignatureASCII(signatureChars, encodedSignature); + + vm->sharedClassConfig->findSharedData(vmThread, (const char *)encodedSignature, encodedLength, J9SHR_DATA_TYPE_AOTTHUNK, FALSE, &dataDescriptor, NULL); + thunk = dataDescriptor.address; + *thunkSize = dataDescriptor.length; +#endif + + return thunk; +} diff --git a/runtime/oti/jitprotos.h b/runtime/oti/jitprotos.h index 55b998ba768..eff80ad623b 100644 --- a/runtime/oti/jitprotos.h +++ b/runtime/oti/jitprotos.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 1991, 2021 IBM Corp. and others + * Copyright (c) 1991, 2023 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -57,11 +57,11 @@ extern J9_CFUNC void jitDecompileMethodForFramePop (J9VMThread * currentThread extern J9_CFUNC void jitExceptionCaught (J9VMThread * currentThread); extern J9_CFUNC void jitSingleStepRemoved (J9VMThread * currentThread); extern J9_CFUNC void jitDataBreakpointAdded (J9VMThread * currentThread); -extern J9_CFUNC void +extern J9_CFUNC void jitBreakpointedMethodCompiled (J9VMThread * currentThread, J9Method * method, void * startAddress); extern J9_CFUNC UDATA initializeFSD (J9JavaVM * vm); -extern J9_CFUNC void +extern J9_CFUNC void induceOSROnCurrentThread(J9VMThread * currentThread); #if (defined(J9VM_INTERP_HOT_CODE_REPLACEMENT)) /* priv. proto (autogen) */ extern J9_CFUNC void jitHotswapOccurred (J9VMThread * currentThread); @@ -83,6 +83,8 @@ extern J9_CFUNC void c_jitReportExceptionCatch(J9VMThread * currentThread); extern J9_CFUNC void c_jitDecompileOnReturn(J9VMThread * currentThread); extern J9_CFUNC void * j9ThunkLookupNameAndSig (void * jitConfig, void *parm); +extern J9_CFUNC const void * j9ThunkPersist(J9JITConfig *jitConfig, char *signatureChars, U_32 signatureLength, U_8 *thunkStart, U_32 totalSize); +extern J9_CFUNC void * j9ThunkFindPersistentThunk(J9JITConfig *jitConfig, char *signatureChars, U_32 signatureLength, UDATA *thunkSize); extern J9_CFUNC J9JITHashTable *avl_jit_artifact_insert_existing_table (J9AVLTree * tree, J9JITHashTable * hashTable); extern J9_CFUNC J9AVLTree * jit_allocate_artifacts (J9PortLibrary * portLibrary); @@ -97,7 +99,7 @@ extern J9_CFUNC UDATA jitWalkStackFrames (J9StackWalkState *walkState); * * @return The metadata corresponding to the method which was JIT compiled at the specified PC if such a method * exists; NULL if no such method can be found. - * + * * @note If jitPC is NULL this function will return NULL. */ extern J9_CFUNC J9JITExceptionTable * jitGetExceptionTableFromPC (J9VMThread * vmThread, UDATA jitPC); @@ -115,6 +117,8 @@ extern J9_CFUNC UDATA jit_artifact_remove (J9PortLibrary * portLibrary, J9AVLTre /* prototypes from thunkcrt.c */ void * j9ThunkLookupNameAndSig(void * jitConfig, void *parm); +const void * j9ThunkPersist(J9JITConfig *jitConfig, char *signatureChars, U_32 signatureLength, U_8 *thunkStart, U_32 totalSize); +void * j9ThunkFindPersistentThunk(J9JITConfig *jitConfig, char *signatureChars, U_32 signatureLength, UDATA *thunkSize); UDATA j9ThunkTableAllocate(J9JavaVM * vm); void j9ThunkTableFree(J9JavaVM * vm); void * j9ThunkLookupSignature(void * jitConfig, UDATA signatureLength, char *signatureChars); From 96d36b70b798406d146ead39433ad7b520650d4e Mon Sep 17 00:00:00 2001 From: Irwin D'Souza Date: Fri, 13 Jan 2023 16:11:40 -0500 Subject: [PATCH 3/3] Use VM APIs to find/persist J2I Thunks from/to the SCC Signed-off-by: Irwin D'Souza --- runtime/compiler/env/VMJ9.cpp | 37 +++++++++++++++++-- runtime/compiler/runtime/RelocationRecord.cpp | 19 +++------- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/runtime/compiler/env/VMJ9.cpp b/runtime/compiler/env/VMJ9.cpp index 89312479df0..8a3bf38f925 100644 --- a/runtime/compiler/env/VMJ9.cpp +++ b/runtime/compiler/env/VMJ9.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2022 IBM Corp. and others + * Copyright (c) 2000, 2023 IBM Corp. and others * * This program and the accompanying materials are made available under * the terms of the Eclipse Public License 2.0 which accompanies this @@ -9195,13 +9195,44 @@ TR_J9SharedCacheVM::getDesignatedCodeCache(TR::Compilation *comp) void * TR_J9SharedCacheVM::getJ2IThunk(char *signatureChars, uint32_t signatureLength, TR::Compilation *comp) { - return (void *)findPersistentThunk(signatureChars, signatureLength); + void *thunk = NULL; + +#if defined(J9VM_INTERP_AOT_COMPILE_SUPPORT) && defined(J9VM_OPT_SHARED_CLASSES) && (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64)) + uintptr_t length; + thunk = j9ThunkFindPersistentThunk(_jitConfig, signatureChars, signatureLength, &length); +#endif + + return thunk; } void * TR_J9SharedCacheVM::setJ2IThunk(char *signatureChars, uint32_t signatureLength, void *thunkptr, TR::Compilation *comp) { - return persistThunk(signatureChars, signatureLength, (U_8*)thunkptr - 8 /* start of thunk */, *((U_32 *)((U_8*)thunkptr -8)) + 8 /* size of thunk */); + uint8_t *thunkStart = (uint8_t *)thunkptr - 8; + uint32_t totalSize = *((uint32_t *)((uint8_t *)thunkptr - 8)) + 8; + +#if defined(J9VM_INTERP_AOT_COMPILE_SUPPORT) && defined(J9VM_OPT_SHARED_CLASSES) && (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64)) + if (TR::Options::getAOTCmdLineOptions()->getOption(TR_TraceRelocatableDataDetailsCG)) + { + TR_VerboseLog::writeLine(""); + TR_VerboseLog::writeLine("%.*s", signatureLength, signatureChars); + TR_VerboseLog::writeLine("thunkAddress: %p, thunkSize: %x", thunkStart, totalSize); + TR_VerboseLog::writeLine(""); + } + + thunkStart = (uint8_t *)j9ThunkPersist(_jitConfig, signatureChars, signatureLength, thunkStart, totalSize); + + if (!thunkStart) + { + TR::Compilation* comp = _compInfoPT->getCompilation(); + if (comp) + comp->failCompilation("Failed to persist thunk"); + else + throw TR::CompilationException(); + } +#endif + + return thunkStart; } void * diff --git a/runtime/compiler/runtime/RelocationRecord.cpp b/runtime/compiler/runtime/RelocationRecord.cpp index e9eade738d5..8b5009d854c 100644 --- a/runtime/compiler/runtime/RelocationRecord.cpp +++ b/runtime/compiler/runtime/RelocationRecord.cpp @@ -2319,21 +2319,12 @@ static TR_RelocationErrorCode relocateAndRegisterThunk( return TR_RelocationErrorCode::relocationOK; // return successful } - // search shared cache for thunk, copy it over and create thunk entry - J9SharedDataDescriptor firstDescriptor; - firstDescriptor.address = NULL; - - javaVM->sharedClassConfig->findSharedData(reloRuntime->currentThread(), - signatureString, - signatureLength, - J9SHR_DATA_TYPE_AOTTHUNK, - false, - &firstDescriptor, - NULL); + uintptr_t thunkSize; + uint8_t *persistentThunk = (uint8_t *)j9ThunkFindPersistentThunk(jitConfig, signatureString, signatureLength, &thunkSize); // if found thunk, then need to copy thunk into code cache, create thunk mapping, and register thunk mapping // - if (firstDescriptor.address) + if (persistentThunk) { //Copy thunk from shared cache into local memory and relocate target address // @@ -2344,7 +2335,7 @@ static TR_RelocationErrorCode relocateAndRegisterThunk( // allocate in the current code cache. The reason is that, when a new code cache is needed // the reservation of the old cache is cancelled and further allocation attempts from // the old cache (which is not switched) will fail - U_8 *thunkStart = TR::CodeCacheManager::instance()->allocateCodeMemory(firstDescriptor.length, 0, &codeCache, &coldCode, true); + U_8 *thunkStart = TR::CodeCacheManager::instance()->allocateCodeMemory(thunkSize, 0, &codeCache, &coldCode, true); U_8 *thunkAddress; omrthread_jit_write_protect_disable(); if (thunkStart) @@ -2352,7 +2343,7 @@ static TR_RelocationErrorCode relocateAndRegisterThunk( // Relocate the thunk // RELO_LOG(reloRuntime->reloLogger(), 7, "\t\t\trelocateAndRegisterThunk: thunkStart from cache %p\n", thunkStart); - memcpy(thunkStart, firstDescriptor.address, firstDescriptor.length); + memcpy(thunkStart, persistentThunk, thunkSize); thunkAddress = thunkStart + 2*sizeof(I_32);