Skip to content

Commit

Permalink
Merge pull request #9772 from dsouzai/sccOffsets
Browse files Browse the repository at this point in the history
JIT support for re-sizable SCC
  • Loading branch information
ymanton committed Aug 7, 2020
2 parents 0f92fc4 + b635e49 commit 27dfb70
Show file tree
Hide file tree
Showing 20 changed files with 811 additions and 127 deletions.
57 changes: 57 additions & 0 deletions doc/features/SharedClassesCache.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<!--
Copyright (c) 2019, 2020 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
distribution and is available at https://www.eclipse.org/legal/epl-2.0/
or the Apache License, Version 2.0 which accompanies this distribution and
is available at https://www.apache.org/licenses/LICENSE-2.0.
This Source Code may also be made available under the following
Secondary Licenses when the conditions for such availability set
forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
General Public License, version 2 with the GNU Classpath
Exception [1] and GNU General Public License, version 2 with the
OpenJDK Assembly Exception [2].
[1] https://www.gnu.org/software/classpath/license.html
[2] http://openjdk.java.net/legal/assembly-exception.html
SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
-->

The Shared Classes Cache (SCC) is a feature of OpenJ9 that enables sharing
data between JVMs. For more information see [1].

## JIT

The JIT Compiler uses the SCC to store both AOT code as well as data either
necessary for AOT
(e.g. [Class Chains](https://github.com/eclipse/openj9/blob/master/doc/compiler/aot/ClassChains.md)),
or for performace (e.g. IProfiler data). The JIT interfaces with the SCC via
the `TR_J9SharedCache` class.

### Offsets

When data that is stored into the SCC needs to refer to other data, it is
referred to by using offsets. Traditionally, the offset would always be
relative to the start of the SCC. However, if the SCC is resized, only
offsets of data in the ROM Class section of the SCC will be invariant.
Therefore, offsets of all data, which must be in the metadata section,
are calculated relative to the start of the metadata section. Another
point of clarification is that offsets of data within the ROMClass section
is calculated using the start of the ROMClass section as no ROM Structure
pointer should point before the start of the section. The offsets that
are generated and stored as part of relocation information are first
left shifted 1 bit; the low bit is used to determine whether the offset
is relative to the start of the ROM Class section or the start of the
metadata section.

The APIs in in `TR_J9SharedCache` provide an abstraction layer so that
other parts of the compiler do not need to worry about the details.
However, it is important that one does not use the offsets directly, but
only via the `TR_J9SharedCache` class.

<hr/>

[1] https://www.eclipse.org/openj9/docs/shrc/
6 changes: 3 additions & 3 deletions runtime/compiler/aarch64/codegen/J9AheadOfTimeCompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ void J9::ARM64::AheadOfTimeCompile::processRelocations()
TR::SymbolValidationManager *svm =
self()->comp()->getSymbolValidationManager();
void *offsets = const_cast<void*>(svm->wellKnownClassChainOffsets());
*(uintptr_t *)relocationDataCursor = reinterpret_cast<uintptr_t>(
fej9->sharedCache()->offsetInSharedCacheFromPointer(offsets));
*(uintptr_t *)relocationDataCursor =
self()->offsetInSharedCacheFromPointer(fej9->sharedCache(), offsets);
relocationDataCursor += SIZEPOINTER;
}

Expand Down Expand Up @@ -681,7 +681,7 @@ uint8_t *J9::ARM64::AheadOfTimeCompile::initializeAOTRelocationHeader(TR::Iterat
// Store rom method to get name of method
J9Method *methodToValidate = reinterpret_cast<J9Method *>(record->_method);
J9ROMMethod *romMethod = static_cast<TR_J9VM *>(fej9)->getROMMethodFromRAMMethod(methodToValidate);
uintptr_t romMethodOffsetInSharedCache = self()->offsetInSharedCacheFromPointer(sharedCache, romMethod);
uintptr_t romMethodOffsetInSharedCache = self()->offsetInSharedCacheFromROMMethod(sharedCache, romMethod);

binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast<void *>(record->_method));
binaryTemplate->_definingClassID = symValManager->getIDFromSymbol(static_cast<void *>(record->definingClass()));
Expand Down
38 changes: 31 additions & 7 deletions runtime/compiler/codegen/J9AheadOfTimeCompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,31 @@ J9::AheadOfTimeCompile::offsetInSharedCacheFromPointer(TR_SharedCache *sharedCac
if (sharedCache->isPointerInSharedCache(ptr, &offset))
return offset;
else
self()->comp()->failCompilation<J9::ClassChainPersistenceFailure>("Failed to find pointer in SCC");
self()->comp()->failCompilation<J9::ClassChainPersistenceFailure>("Failed to find pointer %p in SCC", ptr);

return offset;
}

uintptr_t
J9::AheadOfTimeCompile::offsetInSharedCacheFromROMClass(TR_SharedCache *sharedCache, J9ROMClass *romClass)
{
uintptr_t offset = 0;
if (sharedCache->isROMClassInSharedCache(romClass, &offset))
return offset;
else
self()->comp()->failCompilation<J9::ClassChainPersistenceFailure>("Failed to find romClass %p in SCC", romClass);

return offset;
}

uintptr_t
J9::AheadOfTimeCompile::offsetInSharedCacheFromROMMethod(TR_SharedCache *sharedCache, J9ROMMethod *romMethod)
{
uintptr_t offset = 0;
if (sharedCache->isROMMethodInSharedCache(romMethod, &offset))
return offset;
else
self()->comp()->failCompilation<J9::ClassChainPersistenceFailure>("Failed to find romMethod %p in SCC", romMethod);

return offset;
}
Expand Down Expand Up @@ -382,8 +406,8 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal
}

TR_OpaqueClassBlock *inlinedMethodClass = resolvedMethod->containingClass();
void *romClass = reinterpret_cast<void *>(fej9->getPersistentClassPointerFromClassPointer(inlinedMethodClass));
uintptr_t romClassOffsetInSharedCache = self()->offsetInSharedCacheFromPointer(sharedCache, romClass);
J9ROMClass *romClass = reinterpret_cast<J9ROMClass *>(fej9->getPersistentClassPointerFromClassPointer(inlinedMethodClass));
uintptr_t romClassOffsetInSharedCache = self()->offsetInSharedCacheFromROMClass(sharedCache, romClass);

imRecord->setReloFlags(reloTarget, flags);
imRecord->setInlinedSiteIndex(reloTarget, inlinedSiteIndex);
Expand All @@ -405,8 +429,8 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal
uintptr_t inlinedSiteIndex = reinterpret_cast<uintptr_t>(relocation->getTargetAddress());
TR::AOTClassInfo *aotCI = reinterpret_cast<TR::AOTClassInfo*>(relocation->getTargetAddress2());

void *romClass = reinterpret_cast<void *>(fej9->getPersistentClassPointerFromClassPointer(aotCI->_clazz));
uintptr_t romClassOffsetInSharedCache = self()->offsetInSharedCacheFromPointer(sharedCache, romClass);
J9ROMClass *romClass = reinterpret_cast<J9ROMClass *>(fej9->getPersistentClassPointerFromClassPointer(aotCI->_clazz));
uintptr_t romClassOffsetInSharedCache = self()->offsetInSharedCacheFromROMClass(sharedCache, romClass);

vsfRecord->setInlinedSiteIndex(reloTarget, inlinedSiteIndex);
vsfRecord->setConstantPool(reloTarget, reinterpret_cast<uintptr_t>(aotCI->_constantPool));
Expand Down Expand Up @@ -448,8 +472,8 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal
TR_ResolvedMethod *inlinedMethod = ((TR_AOTMethodInfo *)ics._methodInfo)->resolvedMethod;
TR_OpaqueClassBlock *inlinedCodeClass = reinterpret_cast<TR_OpaqueClassBlock *>(inlinedMethod->classOfMethod());

void *romClass = reinterpret_cast<void *>(fej9->getPersistentClassPointerFromClassPointer(inlinedCodeClass));
uintptr_t romClassOffsetInSharedCache = self()->offsetInSharedCacheFromPointer(sharedCache, romClass);
J9ROMClass *romClass = reinterpret_cast<J9ROMClass *>(fej9->getPersistentClassPointerFromClassPointer(inlinedCodeClass));
uintptr_t romClassOffsetInSharedCache = self()->offsetInSharedCacheFromROMClass(sharedCache, romClass);
traceMsg(comp, "class is %p, romclass is %p, offset is %llu\n", inlinedCodeClass, romClass, romClassOffsetInSharedCache);

uintptr_t classChainIdentifyingLoaderOffsetInSharedCache = sharedCache->getClassChainOffsetOfIdentifyingLoaderForClazzInSharedCache(inlinedCodeClass);
Expand Down
26 changes: 22 additions & 4 deletions runtime/compiler/codegen/J9AheadOfTimeCompile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,9 @@ class OMR_EXTENSIBLE AheadOfTimeCompile : public OMR::AheadOfTimeCompileConnecto
static bool classAddressUsesReloRecordInfo() { return false; }

protected:

/**
* @brief Wrapper around TR_J9SharedCache::isPointerInSharedCache
*
* TR_J9SharedCache::offsetInSharedCacheFromPointer asserts if the pointer
* @brief TR_J9SharedCache::offsetInSharedCacheFrom* asserts if the pointer
* passed in does not exist in the SCC. Under HCR, when an agent redefines
* a class, it causes the J9Class pointer to stay the same, but the
* J9ROMClass pointer changes. This means that if the compiler has a
Expand All @@ -85,14 +84,33 @@ class OMR_EXTENSIBLE AheadOfTimeCompile : public OMR::AheadOfTimeCompileConnecto
*
* Calling TR_J9SharedCache::offsetInSharedCacheFromPointer after such a
* redefinition could result in an assert. Therefore, this method exists as
* a wrapper around TR_J9SharedCache::isPointerInSharedCache which doesn't
* a wrapper around TR_J9SharedCache::isROMClassInSharedCache which doesn't
* assert and conveniently, updates the location referred to by the cacheOffset
* pointer passed in as a parameter.
*
* If the ptr isn't in the the SCC, then the current method will abort the
* compilation. If the ptr is in the SCC, then the cacheOffset will be updated.
*
* @param sharedCache pointer to the TR_SharedCache object
* @param romClass J9ROMClass * whose offset in the SCC is required
* @return The offset into the SCC of romClass
*/
uintptr_t offsetInSharedCacheFromROMClass(TR_SharedCache *sharedCache, J9ROMClass *romClass);

/**
* @brief Same circumstance as offsetInSharedCacheFromROMClass above
*
* @param sharedCache pointer to the TR_SharedCache object
* @param romMethod J9ROMMethod * whose offset in the SCC is required
* @return The offset into the SCC of romMethod
*/
uintptr_t offsetInSharedCacheFromROMMethod(TR_SharedCache *sharedCache, J9ROMMethod *romMethod);

/**
* @brief Wrapper around TR_J9SharedCache::offsetInSharedCacheFromPointer for
* consistency with the above APIs
*
* @param sharedCache pointer to the TR_SharedCache object
* @param ptr pointer whose offset in the SCC is required
* @return The offset into the SCC of ptr
*/
Expand Down
2 changes: 1 addition & 1 deletion runtime/compiler/control/CompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7242,7 +7242,7 @@ TR::CompilationInfoPerThreadBase::preCompilationTasks(J9VMThread * vmThread,
!TR::CompilationInfo::isCompiled(method) &&
!entry->isDLTCompile() &&
!entry->_doNotUseAotCodeFromSharedCache &&
fe->sharedCache()->isPointerInSharedCache(J9_CLASS_FROM_METHOD(method)->romClass) &&
fe->sharedCache()->isROMClassInSharedCache(J9_CLASS_FROM_METHOD(method)->romClass) &&
!isMethodIneligibleForAot(method) &&
(!TR::Options::getAOTCmdLineOptions()->getOption(TR_AOTCompileOnlyFromBootstrap) ||
fe->isClassLibraryMethod((TR_OpaqueMethodBlock *)method), true) &&
Expand Down
4 changes: 2 additions & 2 deletions runtime/compiler/control/HookedByTheJit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ static void jitHookInitializeSendTarget(J9HookInterface * * hook, UDATA eventNum
// been created before options were processed.
TR_J9SharedCache *sc = TR_J9VMBase::get(jitConfig, vmThread, TR_J9VMBase::AOT_VM)->sharedCache();
#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_J9VMBase::get(jitConfig, vmThread, TR_J9VMBase::AOT_VM)->sharedCache()->isPointerInSharedCache(J9_CLASS_FROM_METHOD(method)->romClass))
if (TR_J9VMBase::get(jitConfig, vmThread, TR_J9VMBase::AOT_VM)->sharedCache()->isROMClassInSharedCache(J9_CLASS_FROM_METHOD(method)->romClass))
{
PORT_ACCESS_FROM_JAVAVM(jitConfig->javaVM);
I_64 sharedQueryTime = 0;
Expand Down Expand Up @@ -623,7 +623,7 @@ static void jitHookInitializeSendTarget(J9HookInterface * * hook, UDATA eventNum
int32_t sigLen = sprintf(buf, "%.*s.%.*s%.*s", className->length, utf8Data(className), name->length, utf8Data(name), signature->length, utf8Data(signature));
printf("Initial: Signature %s Count %d isLoopy %d isAOT %lu is in SCC %d SCCContainsProfilingInfo %d \n",buf,TR::CompilationInfo::getInvocationCount(method),J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod),
TR::Options::sharedClassCache() ? jitConfig->javaVM->sharedClassConfig->existsCachedCodeForROMMethod(vmThread, romMethod) : 0,
TR::Options::sharedClassCache() ? TR_J9VMBase::get(jitConfig, vmThread, TR_J9VMBase::AOT_VM)->sharedCache()->isPointerInSharedCache(J9_CLASS_FROM_METHOD(method)->romClass) : 0,containsInfo) ; fflush(stdout);
TR::Options::sharedClassCache() ? TR_J9VMBase::get(jitConfig, vmThread, TR_J9VMBase::AOT_VM)->sharedCache()->isROMClassInSharedCache(J9_CLASS_FROM_METHOD(method)->romClass) : 0,containsInfo) ; fflush(stdout);
}
}

Expand Down
2 changes: 1 addition & 1 deletion runtime/compiler/control/JITClientCompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1910,7 +1910,7 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes
// Collect AOT stats
TR_ResolvedJ9Method *resolvedMethod = std::get<0>(methodInfo).remoteMirror;

isRomClassForMethodInSC = fe->sharedCache()->isPointerInSharedCache(J9_CLASS_FROM_METHOD(j9method)->romClass);
isRomClassForMethodInSC = fe->sharedCache()->isROMClassInSharedCache(J9_CLASS_FROM_METHOD(j9method)->romClass);

J9Class *j9clazz = (J9Class *) J9_CLASS_FROM_CP(((J9RAMConstantPoolItem *) J9_CP_FROM_METHOD(((J9Method *)j9method))));
TR_OpaqueClassBlock *clazzOfInlinedMethod = fe->convertClassPtrToClassOffset(j9clazz);
Expand Down

0 comments on commit 27dfb70

Please sign in to comment.