Skip to content

Commit

Permalink
Merge pull request #4666 from jdmpapin/svm.wkc
Browse files Browse the repository at this point in the history
Symbol validation manager well-known classes
  • Loading branch information
Irwin D'Souza authored Feb 9, 2019
2 parents c436b1f + 7f6e42d commit 5018efa
Show file tree
Hide file tree
Showing 12 changed files with 386 additions and 185 deletions.
40 changes: 40 additions & 0 deletions doc/compiler/aot/SymbolValidationManager.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,46 @@ load, these symbols don't need to be validation records stored in
the SCC. Therefore, the SVM, in its constructor, initializes the maps
with these IDs and the associated symbols.

### Well-known Classes

Some system classes are loaded very early and are referred to by most
JIT compilations. The SVM has a list of such classes, termed "well-known
classes." It will store a single copy of their class chain offsets in
the SCC. For each AOT-compiled method using the SVM, the emitted
relocation data needs just one offset into the SCC in order to refer to
the shared data. This not only deduplicates the offsets; it also allows
many otherwise necessary records to be eliminated.

In particular, well-known classes never need SystemClassByName,
ClassByName, or ClassFromCP records. Because these latter two have
beholders, eliminating them is a bit more difficult than eliminating
SystemClassByName. In order to make them unnecessary, the SVM checks for
every class it encounters that the class can see every well-known class,
failing otherwise. Furthermore, the well-known classes must have names
that only the bootstrap loader is allowed to define. Then any
ClassByName or ClassFromCP record naming a well-known class is
definitely redundant: its beholder can see a class with the given name,
and that class must have been defined by the bootstrap loader, so it
must be the same class whose class chain was validated at the beginning
of the AOT load.

In early compilations, it's possible that not all of the well-known
classes are available. In order to avoid spurious compilation failures,
the SVM permits some of the classes to be missing, in which case the
array of class chain offsets represents only a subset of the possible
well-known classes. The key under which it is stored specifies the
subset using (the hexadecimal expansion of) a bit-set. Any classes that
were missing at the beginning of a compilation are not considered
well-known for the purpose of that compilation. When loading, the SVM
finds the well-known classes in the particular subset used for the
method being loaded.

Each well-known class that is found is assigned the next available
sequential ID after the guaranteed IDs at the beginning of compilation,
as long as the well-known class is new (i.e. different from the root
class). When loading, the well-known classes are assigned sequential IDs
in the same way, to match the IDs assigned during compilation.

## Benefits

1. Makes explicit the provenance of every symbol acquired by the compiler
Expand Down
28 changes: 9 additions & 19 deletions runtime/compiler/codegen/J9AheadOfTimeCompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,15 @@ J9::AheadOfTimeCompile::dumpRelocationData()
cursor += 4;
}

if (self()->comp()->getOption(TR_UseSymbolValidationManager))
{
traceMsg(
self()->comp(),
"SCC offset of class chain offsets of well-known classes is: 0x%llx\n\n",
(unsigned long long)*(uintptrj_t *)cursor);
cursor += sizeof (uintptrj_t);
}

traceMsg(self()->comp(), "Address Size %-31s", "Type");
traceMsg(self()->comp(), "Width EIP Index Offsets\n"); // Offsets from Code Start

Expand Down Expand Up @@ -1379,25 +1388,6 @@ J9::AheadOfTimeCompile::dumpRelocationData()
}
break;

case TR_ValidateClassClass:
{
cursor++;
if (is64BitTarget)
cursor += 4; // padding
cursor -= sizeof(TR_RelocationRecordBinaryTemplate);
TR_RelocationRecordValidateClassClassBinaryTemplate *binaryTemplate =
reinterpret_cast<TR_RelocationRecordValidateClassClassBinaryTemplate *>(cursor);
if (isVerbose)
{
traceMsg(self()->comp(), "\n Validate Class Class: classClassID=%d, objectClassID=%d ",
(uint32_t)binaryTemplate->_classClassID,
(uint32_t)binaryTemplate->_objectClassID);
}
cursor += sizeof(TR_RelocationRecordValidateClassClassBinaryTemplate);
self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair);
}
break;

case TR_ValidateConcreteSubClassFromClass:
{
cursor++;
Expand Down
2 changes: 1 addition & 1 deletion runtime/compiler/codegen/J9CodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2848,7 +2848,7 @@ J9::CodeGenerator::processRelocations()
}

TR::SymbolValidationManager::SymbolValidationRecordList &validationRecords = self()->comp()->getSymbolValidationManager()->getValidationRecordList();
if (!validationRecords.empty() && self()->comp()->getOption(TR_UseSymbolValidationManager))
if (self()->comp()->getOption(TR_UseSymbolValidationManager))
{
// Add the flags in TR_AOTMethodHeader on the compile run
J9JITDataCacheHeader *aotMethodHeader = (J9JITDataCacheHeader *)self()->comp()->getAotMethodDataStart();
Expand Down
3 changes: 3 additions & 0 deletions runtime/compiler/control/CompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8029,6 +8029,9 @@ TR::CompilationInfoPerThreadBase::compile(
TR_ASSERT_FATAL(false, "alwaysFatalAssert set");
}

if (vm.isAOT_DEPRECATED_DO_NOT_USE())
compiler->getSymbolValidationManager()->populateWellKnownClasses();

rtn = compiler->compile();

if ( TR::Options::getVerboseOption(TR_VerboseCompilationDispatch) && !rtn)
Expand Down
13 changes: 0 additions & 13 deletions runtime/compiler/env/VMJ9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9053,19 +9053,6 @@ TR_J9SharedCacheVM::isReferenceArray(TR_OpaqueClassBlock *classPointer)
return false;
}

TR_OpaqueClassBlock *
TR_J9SharedCacheVM::getClassClassPointer(TR_OpaqueClassBlock *objectClassPointer)
{
TR_OpaqueClassBlock *ccPointer = TR_J9VM::getClassClassPointer(objectClassPointer);
TR::Compilation *comp = TR::comp();
if (comp && comp->getOption(TR_UseSymbolValidationManager))
{
if (!comp->getSymbolValidationManager()->addClassClassRecord(ccPointer, objectClassPointer))
ccPointer = NULL;
}
return ccPointer;
}

TR_OpaqueMethodBlock *
TR_J9SharedCacheVM::getInlinedCallSiteMethod(TR_InlinedCallSite *ics)
{
Expand Down
2 changes: 0 additions & 2 deletions runtime/compiler/env/VMJ9.h
Original file line number Diff line number Diff line change
Expand Up @@ -1140,8 +1140,6 @@ class TR_J9SharedCacheVM : public TR_J9VM
virtual bool javaLangClassGetModifiersImpl(TR_OpaqueClassBlock * clazzPointer, int32_t &result);
virtual TR_OpaqueClassBlock * getSuperClass(TR_OpaqueClassBlock *classPointer);

virtual TR_OpaqueClassBlock * getClassClassPointer(TR_OpaqueClassBlock *);

virtual bool sameClassLoaders(TR_OpaqueClassBlock *, TR_OpaqueClassBlock *);
virtual bool isUnloadAssumptionRequired(TR_OpaqueClassBlock *, TR_ResolvedMethod *);
virtual bool classHasBeenExtended(TR_OpaqueClassBlock *);
Expand Down
66 changes: 39 additions & 27 deletions runtime/compiler/runtime/RelocationRecord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,16 @@ TR_RelocationRecordGroup::size(TR_RelocationTarget *reloTarget)
}

TR_RelocationRecordBinaryTemplate *
TR_RelocationRecordGroup::firstRecord(TR_RelocationTarget *reloTarget)
TR_RelocationRecordGroup::firstRecord(
TR_RelocationRuntime *reloRuntime,
TR_RelocationTarget *reloTarget)
{
// first word of the group is a pointer size field for the entire group
return (TR_RelocationRecordBinaryTemplate *) (((uintptr_t *)_group)+1);
// The first word is the size of the group (itself pointer-sized).
// When using the SVM, the second is a pointer-sized SCC offset to the
// well-known classes' class chain offsets.
bool useSVM = reloRuntime->comp()->getOption(TR_UseSymbolValidationManager);
int offs = 1 + int(useSVM);
return (TR_RelocationRecordBinaryTemplate *) (((uintptrj_t *)_group)+offs);
}

TR_RelocationRecordBinaryTemplate *
Expand All @@ -101,12 +107,40 @@ TR_RelocationRecordGroup::pastLastRecord(TR_RelocationTarget *reloTarget)
return (TR_RelocationRecordBinaryTemplate *) ((uint8_t *)_group + size(reloTarget));
}

const uintptrj_t *
TR_RelocationRecordGroup::wellKnownClassChainOffsets(
TR_RelocationRuntime *reloRuntime,
TR_RelocationTarget *reloTarget)
{
if (!TR::comp()->getOption(TR_UseSymbolValidationManager))
return NULL;

// The first word is the size of the group (itself pointer-sized). Skip it
// to reach the SCC offset of the well-known classes' class chain offsets.
void *offset = reinterpret_cast<void*>(*((uintptrj_t *)_group + 1));
void *classChains =
reloRuntime->fej9()->sharedCache()->pointerFromOffsetInSharedCache(offset);

return reinterpret_cast<const uintptrj_t*>(classChains);
}

int32_t
TR_RelocationRecordGroup::applyRelocations(TR_RelocationRuntime *reloRuntime,
TR_RelocationTarget *reloTarget,
uint8_t *reloOrigin)
{
TR_RelocationRecordBinaryTemplate *recordPointer = firstRecord(reloTarget);
const uintptrj_t *wkClassChainOffsets =
wellKnownClassChainOffsets(reloRuntime, reloTarget);
if (wkClassChainOffsets != NULL)
{
TR::SymbolValidationManager *svm =
reloRuntime->comp()->getSymbolValidationManager();

if (!svm->validateWellKnownClasses(wkClassChainOffsets))
return compilationAotClassReloFailure;
}

TR_RelocationRecordBinaryTemplate *recordPointer = firstRecord(reloRuntime, reloTarget);
TR_RelocationRecordBinaryTemplate *endOfRecords = pastLastRecord(reloTarget);

TR_AOTStats *aotStats = reloRuntime->aotStats();
Expand Down Expand Up @@ -355,9 +389,6 @@ TR_RelocationRecord::create(TR_RelocationRecord *storage, TR_RelocationRuntime *
case TR_ValidateDeclaringClassFromFieldOrStatic:
reloRecord = new (storage) TR_RelocationRecordValidateDeclaringClassFromFieldOrStatic(reloRuntime, record);
break;
case TR_ValidateClassClass:
reloRecord = new (storage) TR_RelocationRecordValidateClassClass(reloRuntime, record);
break;
case TR_ValidateConcreteSubClassFromClass:
reloRecord = new (storage) TR_RelocationRecordValidateConcreteSubClassFromClass(reloRuntime, record);
break;
Expand Down Expand Up @@ -3465,25 +3496,6 @@ TR_RelocationRecordValidateDeclaringClassFromFieldOrStatic::applyRelocation(TR_R
return compilationAotClassReloFailure;
}

int32_t
TR_RelocationRecordValidateClassClass::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation)
{
uint16_t classClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassClassBinaryTemplate *)_record)->_classClassID);
uint16_t objectClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassClassBinaryTemplate *)_record)->_objectClassID);

if (reloRuntime->reloLogger()->logEnabled())
{
reloRuntime->reloLogger()->printf("%s\n", name());
reloRuntime->reloLogger()->printf("\tapplyRelocation: classClassID %d\n", classClassID);
reloRuntime->reloLogger()->printf("\tapplyRelocation: objectClassID %d\n", objectClassID);
}

if (reloRuntime->comp()->getSymbolValidationManager()->validateClassClassRecord(classClassID, objectClassID))
return 0;
else
return compilationAotClassReloFailure;
}

int32_t
TR_RelocationRecordValidateConcreteSubClassFromClass::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation)
{
Expand Down Expand Up @@ -4564,7 +4576,7 @@ uint32_t TR_RelocationRecord::_relocationRecordHeaderSizeTable[TR_NumExternalRel
sizeof(TR_RelocationRecordValidateSystemClassByNameBinaryTemplate), // TR_ValidateSystemClassByName = 74
sizeof(TR_RelocationRecordValidateClassFromITableIndexCPBinaryTemplate), // TR_ValidateClassFromITableIndexCP = 75
sizeof(TR_RelocationRecordValidateDeclaringClassFromFieldOrStaticBinaryTemplate), // TR_ValidateDeclaringClassFromFieldOrStatic = 76
sizeof(TR_RelocationRecordValidateClassClassBinaryTemplate), // TR_ValidateClassClass = 77
0, // TR_ValidateClassClass = 77
sizeof(TR_RelocationRecordValidateConcreteSubFromClassBinaryTemplate), // TR_ValidateConcreteSubClassFromClass = 78
sizeof(TR_RelocationRecordValidateClassChainBinaryTemplate), // TR_ValidateClassChain = 79
0, // TR_ValidateRomClass = 80
Expand Down
21 changes: 2 additions & 19 deletions runtime/compiler/runtime/RelocationRecord.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,12 +268,6 @@ struct TR_RelocationRecordValidateClassFromITableIndexCPBinaryTemplate : public

typedef TR_RelocationRecordValidateClassFromCPBinaryTemplate TR_RelocationRecordValidateDeclaringClassFromFieldOrStaticBinaryTemplate;

struct TR_RelocationRecordValidateClassClassBinaryTemplate : public TR_RelocationRecordBinaryTemplate
{
uint16_t _classClassID;
uint16_t _objectClassID;
};

struct TR_RelocationRecordValidateConcreteSubFromClassBinaryTemplate : public TR_RelocationRecordBinaryTemplate
{
uint16_t _childClassID;
Expand Down Expand Up @@ -398,8 +392,9 @@ class TR_RelocationRecordGroup
void setSize(TR_RelocationTarget *reloTarget, uintptr_t size);
uintptr_t size(TR_RelocationTarget *reloTarget);

TR_RelocationRecordBinaryTemplate *firstRecord(TR_RelocationTarget *reloTarget);
TR_RelocationRecordBinaryTemplate *firstRecord(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget);
TR_RelocationRecordBinaryTemplate *pastLastRecord(TR_RelocationTarget *reloTarget);
const uintptrj_t *wellKnownClassChainOffsets(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget);

int32_t applyRelocations(TR_RelocationRuntime *reloRuntime,
TR_RelocationTarget *reloTarget,
Expand Down Expand Up @@ -1520,18 +1515,6 @@ class TR_RelocationRecordValidateDeclaringClassFromFieldOrStatic : public TR_Rel
virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation);
};

class TR_RelocationRecordValidateClassClass : public TR_RelocationRecord
{
public:
TR_RelocationRecordValidateClassClass() {}
TR_RelocationRecordValidateClassClass(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {}
virtual bool isValidationRecord() { return true; }
virtual char *name() { return "TR_RelocationRecordValidateClassClass"; }
virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateClassClassBinaryTemplate); }
virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {}
virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation);
};

class TR_RelocationRecordValidateConcreteSubClassFromClass : public TR_RelocationRecord
{
public:
Expand Down
Loading

0 comments on commit 5018efa

Please sign in to comment.