From 3ef30cd77086ca65b3aa37cf8eb3d32b59122b86 Mon Sep 17 00:00:00 2001 From: Devin Papineau Date: Wed, 7 Nov 2018 12:14:50 -0500 Subject: [PATCH 1/3] Skip self-referential ClassFromCP and ClassByName Whenever a class C contains (in a signature or constant pool entry) a reference to a class with the same name as C, that class reference must resolve to C itself, so no record is necessary. Signed-off-by: Devin Papineau --- runtime/compiler/runtime/SymbolValidationManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/runtime/compiler/runtime/SymbolValidationManager.cpp b/runtime/compiler/runtime/SymbolValidationManager.cpp index 6272ebf1107..98c42ca6b49 100644 --- a/runtime/compiler/runtime/SymbolValidationManager.cpp +++ b/runtime/compiler/runtime/SymbolValidationManager.cpp @@ -575,6 +575,8 @@ TR::SymbolValidationManager::addClassByNameRecord(TR_OpaqueClassBlock *clazz, TR SVM_ASSERT_ALREADY_VALIDATED(this, beholder); if (isWellKnownClass(clazz)) return true; + else if (clazz == beholder) + return true; else return addClassRecordWithChain(new (_region) ClassByNameRecord(clazz, beholder)); } @@ -607,6 +609,8 @@ TR::SymbolValidationManager::addClassFromCPRecord(TR_OpaqueClassBlock *clazz, J9 SVM_ASSERT_ALREADY_VALIDATED(this, beholder); if (isWellKnownClass(clazz)) return true; + else if (clazz == beholder) + return true; else return addClassRecord(clazz, new (_region) ClassFromCPRecord(clazz, beholder, cpIndex)); } From b0af003afe820d3c7ca4a9d151b64dc50f89fffd Mon Sep 17 00:00:00 2001 From: Devin Papineau Date: Fri, 30 Nov 2018 15:21:27 -0500 Subject: [PATCH 2/3] Find SVM ClassFromCP/ClassByName redundancies No beholder needs both a ClassByName and ClassFromCP record identifying the same class, since constant pool entries are also specified by name. The name used in the constant pool at a given index will always match in a successful load, because the beholder will have passed class chain validation. Signed-off-by: Devin Papineau --- .../runtime/SymbolValidationManager.cpp | 27 ++++++++++++++-- .../runtime/SymbolValidationManager.hpp | 32 +++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/runtime/compiler/runtime/SymbolValidationManager.cpp b/runtime/compiler/runtime/SymbolValidationManager.cpp index 98c42ca6b49..b17fe67a193 100644 --- a/runtime/compiler/runtime/SymbolValidationManager.cpp +++ b/runtime/compiler/runtime/SymbolValidationManager.cpp @@ -51,6 +51,7 @@ TR::SymbolValidationManager::SymbolValidationManager(TR::Region ®ion, TR_Reso _wellKnownClassChainOffsets(NULL), _symbolValidationRecords(_region), _alreadyGeneratedRecords(LessSymbolValidationRecord(), _region), + _classesFromAnyCPIndex(LessClassFromAnyCPIndex(), _region), _symbolToIdMap((SymbolToIdComparator()), _region), _idToSymbolTable(_region), _seenSymbolsSet((SeenSymbolsComparator()), _region), @@ -396,6 +397,15 @@ TR::SymbolValidationManager::recordExists(TR::SymbolValidationRecord *record) return _alreadyGeneratedRecords.find(record) != _alreadyGeneratedRecords.end(); } +bool +TR::SymbolValidationManager::anyClassFromCPRecordExists( + TR_OpaqueClassBlock *clazz, + TR_OpaqueClassBlock *beholder) + { + ClassFromAnyCPIndex pair(clazz, beholder); + return _classesFromAnyCPIndex.find(pair) != _classesFromAnyCPIndex.end(); + } + void TR::SymbolValidationManager::appendNewRecord(void *symbol, TR::SymbolValidationRecord *record) { @@ -577,6 +587,8 @@ TR::SymbolValidationManager::addClassByNameRecord(TR_OpaqueClassBlock *clazz, TR return true; else if (clazz == beholder) return true; + else if (anyClassFromCPRecordExists(clazz, beholder)) + return true; // already have an equivalent ClassFromCP else return addClassRecordWithChain(new (_region) ClassByNameRecord(clazz, beholder)); } @@ -605,14 +617,25 @@ TR::SymbolValidationManager::addProfiledClassRecord(TR_OpaqueClassBlock *clazz) bool TR::SymbolValidationManager::addClassFromCPRecord(TR_OpaqueClassBlock *clazz, J9ConstantPool *constantPoolOfBeholder, uint32_t cpIndex) { + if (inHeuristicRegion()) + return true; // to make sure not to modify _classesFromAnyCPIndex + TR_OpaqueClassBlock *beholder = reinterpret_cast(J9_CLASS_FROM_CP(constantPoolOfBeholder)); SVM_ASSERT_ALREADY_VALIDATED(this, beholder); if (isWellKnownClass(clazz)) return true; else if (clazz == beholder) return true; - else - return addClassRecord(clazz, new (_region) ClassFromCPRecord(clazz, beholder, cpIndex)); + + ClassByNameRecord byName(clazz, beholder); + if (recordExists(&byName)) + return true; // already have an equivalent ClassByName + + bool added = addClassRecord(clazz, new (_region) ClassFromCPRecord(clazz, beholder, cpIndex)); + if (added) + _classesFromAnyCPIndex.insert(ClassFromAnyCPIndex(clazz, beholder)); + + return added; } bool diff --git a/runtime/compiler/runtime/SymbolValidationManager.hpp b/runtime/compiler/runtime/SymbolValidationManager.hpp index 04b137f29b3..98d0c47ab92 100644 --- a/runtime/compiler/runtime/SymbolValidationManager.hpp +++ b/runtime/compiler/runtime/SymbolValidationManager.hpp @@ -760,6 +760,7 @@ class SymbolValidationManager bool abandonRecord(TR::SymbolValidationRecord *record); bool recordExists(TR::SymbolValidationRecord *record); + bool anyClassFromCPRecordExists(TR_OpaqueClassBlock *clazz, TR_OpaqueClassBlock *beholder); void appendNewRecord(void *symbol, TR::SymbolValidationRecord *record); void appendRecordIfNew(void *symbol, TR::SymbolValidationRecord *record); @@ -848,6 +849,37 @@ class SymbolValidationManager typedef TR::typed_allocator LoaderAllocator; typedef std::vector LoaderVector; LoaderVector _loadersOkForWellKnownClasses; + + // Remember which classes have already been found in which beholders' + // constant pools, regardless of CP index. If a class C has already been + // found in the constant pool of class D (producing a ClassFromCP record), + // then ClassByName(C, D) is redundant. + struct ClassFromAnyCPIndex + { + TR_OpaqueClassBlock *clazz; + TR_OpaqueClassBlock *beholder; + + ClassFromAnyCPIndex(TR_OpaqueClassBlock *clazz, TR_OpaqueClassBlock *beholder) + : clazz(clazz), beholder(beholder) { } + }; + + struct LessClassFromAnyCPIndex + { + bool operator()(const ClassFromAnyCPIndex &a, const ClassFromAnyCPIndex &b) const + { + std::less lt; + if (lt(a.clazz, b.clazz)) + return true; + else if (lt(b.clazz, a.clazz)) + return false; + else + return lt(a.beholder, b.beholder); + } + }; + + typedef TR::typed_allocator ClassFromAnyCPIndexAlloc; + typedef std::set ClassFromAnyCPIndexSet; + ClassFromAnyCPIndexSet _classesFromAnyCPIndex; }; } From 9f4623839cc9ffc2d52c0faae362ab16b7164c5c Mon Sep 17 00:00:00 2001 From: Devin Papineau Date: Wed, 7 Nov 2018 12:15:56 -0500 Subject: [PATCH 3/3] Replace ClassFromCP with ClassByName for fresh classes If a class is first encountered by the symbol validation manager as the result of ClassFromCP, it is necessary to generate both the originally requested ClassFromCP record and a ClassChain validation record. A ClassByName with the same beholder has the same results as ClassFromCP would, and it subsumes ClassChain, so that only ClassByName is needed. The ClassByName record is larger than the ClassFromCP alone, but smaller than the two records would have been together. Signed-off-by: Devin Papineau --- runtime/compiler/runtime/SymbolValidationManager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/runtime/compiler/runtime/SymbolValidationManager.cpp b/runtime/compiler/runtime/SymbolValidationManager.cpp index b17fe67a193..d4f2118e155 100644 --- a/runtime/compiler/runtime/SymbolValidationManager.cpp +++ b/runtime/compiler/runtime/SymbolValidationManager.cpp @@ -631,7 +631,12 @@ TR::SymbolValidationManager::addClassFromCPRecord(TR_OpaqueClassBlock *clazz, J9 if (recordExists(&byName)) return true; // already have an equivalent ClassByName - bool added = addClassRecord(clazz, new (_region) ClassFromCPRecord(clazz, beholder, cpIndex)); + bool added; + if (!isAlreadyValidated(clazz)) // save a ClassChainRecord + added = addClassRecordWithChain(new (_region) ClassByNameRecord(clazz, beholder)); + else + added = addClassRecord(clazz, new (_region) ClassFromCPRecord(clazz, beholder, cpIndex)); + if (added) _classesFromAnyCPIndex.insert(ClassFromAnyCPIndex(clazz, beholder));