diff --git a/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp b/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp index 0518d60814e..5e53269cb1f 100644 --- a/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp +++ b/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp @@ -1309,6 +1309,18 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal } break; + case TR_ValidateIsClassVisible: + { + TR_RelocationRecordValidateIsClassVisible *icvRecord = reinterpret_cast(reloRecord); + + TR::IsClassVisibleRecord *svmRecord = reinterpret_cast(relocation->getTargetAddress()); + + icvRecord->setSourceClassID(reloTarget, symValManager->getSymbolIDFromValue(svmRecord->_sourceClass)); + icvRecord->setDestClassID(reloTarget, symValManager->getSymbolIDFromValue(svmRecord->_destClass)); + icvRecord->setIsVisible(reloTarget, svmRecord->_isVisible); + } + break; + default: TR_ASSERT(false, "Unknown relo type %d!\n", kind); comp->failCompilation("Unknown relo type %d!\n", kind); @@ -2218,6 +2230,23 @@ J9::AheadOfTimeCompile::dumpRelocationHeaderData(uint8_t *cursor, bool isVerbose } break; + case TR_ValidateIsClassVisible: + { + TR_RelocationRecordValidateIsClassVisible *icvRecord = reinterpret_cast(reloRecord); + + self()->traceRelocationOffsets(startOfOffsets, offsetSize, endOfCurrentRecord, orderedPair); + if (isVerbose) + { + traceMsg( + self()->comp(), + "\n Validate Is Class Visible: sourceClassID=%d, destClassID=%d, isVisible=%s ", + (uint32_t)icvRecord->sourceClassID(reloTarget), + (uint32_t)icvRecord->destClassID(reloTarget), + icvRecord->isVisible(reloTarget) ? "true" : "false"); + } + } + break; + default: TR_ASSERT_FATAL(false, "dumpRelocationHeaderData: unknown relo kind %d\n", kind); } diff --git a/runtime/compiler/env/VMJ9.cpp b/runtime/compiler/env/VMJ9.cpp index d2135b9817f..d50fbcf2dde 100644 --- a/runtime/compiler/env/VMJ9.cpp +++ b/runtime/compiler/env/VMJ9.cpp @@ -8426,13 +8426,11 @@ TR_J9SharedCacheVM::isClassVisible(TR_OpaqueClassBlock * sourceClass, TR_OpaqueC TR_ASSERT(comp, "Should be called only within a compilation"); bool validated = false; + bool isVisible = TR_J9VMBase::isClassVisible(sourceClass, destClass); if (comp->getOption(TR_UseSymbolValidationManager)) { - TR::SymbolValidationManager *svm = comp->getSymbolValidationManager(); - SVM_ASSERT_ALREADY_VALIDATED(svm, sourceClass); - SVM_ASSERT_ALREADY_VALIDATED(svm, destClass); - validated = true; + validated = comp->getSymbolValidationManager()->addIsClassVisibleRecord(sourceClass, destClass, isVisible); } else { @@ -8440,7 +8438,7 @@ TR_J9SharedCacheVM::isClassVisible(TR_OpaqueClassBlock * sourceClass, TR_OpaqueC ((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) destClass); } - return (validated ? TR_J9VMBase::isClassVisible(sourceClass, destClass) : false); + return (validated ? isVisible : false); } bool diff --git a/runtime/compiler/runtime/RelocationRecord.cpp b/runtime/compiler/runtime/RelocationRecord.cpp index fb460716838..1f91cd77eea 100644 --- a/runtime/compiler/runtime/RelocationRecord.cpp +++ b/runtime/compiler/runtime/RelocationRecord.cpp @@ -433,6 +433,13 @@ struct TR_RelocationRecordValidateJ2IThunkFromMethodBinaryTemplate : public TR_R uint16_t _methodID; }; +struct TR_RelocationRecordValidateIsClassVisibleBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _sourceClassID; + uint16_t _destClassID; + uint8_t _isVisible; + }; + // END OF BINARY TEMPLATES uint8_t @@ -854,6 +861,9 @@ TR_RelocationRecord::create(TR_RelocationRecord *storage, TR_RelocationRuntime * case TR_StaticDefaultValueInstance: reloRecord = new (storage) TR_RelocationRecordStaticDefaultValueInstance(reloRuntime, record); break; + case TR_ValidateIsClassVisible: + reloRecord = new (storage) TR_RelocationRecordValidateIsClassVisible(reloRuntime, record); + break; default: // TODO: error condition printf("Unexpected relo record: %d\n", reloType);fflush(stdout); @@ -6369,6 +6379,66 @@ TR_RelocationRecordValidateJ2IThunkFromMethod::methodID(TR_RelocationTarget *rel return reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateJ2IThunkFromMethodBinaryTemplate *)_record)->_methodID); } +TR_RelocationErrorCode +TR_RelocationRecordValidateIsClassVisible::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t sourceClassID = this->sourceClassID(reloTarget); + uint16_t destClassID = this->destClassID(reloTarget); + bool isVisible = this->isVisible(reloTarget); + + if (reloRuntime->comp()->getSymbolValidationManager()->validateIsClassVisibleRecord(sourceClassID, destClassID, isVisible)) + return TR_RelocationErrorCode::relocationOK; + else + return TR_RelocationErrorCode::isClassVisibleValidationFailure; + } + +void +TR_RelocationRecordValidateIsClassVisible::print(TR_RelocationRuntime *reloRuntime) + { + TR_RelocationTarget *reloTarget = reloRuntime->reloTarget(); + TR_RelocationRuntimeLogger *reloLogger = reloRuntime->reloLogger(); + TR_RelocationRecord::print(reloRuntime); + reloLogger->printf("\tsourceClassID %d\n", sourceClassID(reloTarget)); + reloLogger->printf("\tdestClassID %d\n", destClassID(reloTarget)); + reloLogger->printf("\tisVisible %s\n", isVisible(reloTarget) ? "true" : "false"); + } + +void +TR_RelocationRecordValidateIsClassVisible::setSourceClassID(TR_RelocationTarget *reloTarget, uint16_t sourceClassID) + { + reloTarget->storeUnsigned16b(sourceClassID, (uint8_t *) &((TR_RelocationRecordValidateIsClassVisibleBinaryTemplate *)_record)->_sourceClassID); + } + +uint16_t +TR_RelocationRecordValidateIsClassVisible::sourceClassID(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateIsClassVisibleBinaryTemplate *)_record)->_sourceClassID); + } + +void +TR_RelocationRecordValidateIsClassVisible::setDestClassID(TR_RelocationTarget *reloTarget, uint16_t destClassID) + { + reloTarget->storeUnsigned16b(destClassID, (uint8_t *) &((TR_RelocationRecordValidateIsClassVisibleBinaryTemplate *)_record)->_destClassID); + } + +uint16_t +TR_RelocationRecordValidateIsClassVisible::destClassID(TR_RelocationTarget *reloTarget) + { + return reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateIsClassVisibleBinaryTemplate *)_record)->_destClassID); + } + +void +TR_RelocationRecordValidateIsClassVisible::setIsVisible(TR_RelocationTarget *reloTarget, bool isVisible) + { + reloTarget->storeUnsigned8b((uint8_t)isVisible, (uint8_t *) &((TR_RelocationRecordValidateIsClassVisibleBinaryTemplate *)_record)->_isVisible); + } + +bool +TR_RelocationRecordValidateIsClassVisible::isVisible(TR_RelocationTarget *reloTarget) + { + return (bool)reloTarget->loadUnsigned8b((uint8_t *) &((TR_RelocationRecordValidateIsClassVisibleBinaryTemplate *)_record)->_isVisible); + } + char * TR_RelocationRecordStaticDefaultValueInstance::name() @@ -6528,5 +6598,6 @@ uint32_t TR_RelocationRecord::_relocationRecordHeaderSizeTable[TR_NumExternalRel 0, // TR_VMINLMethod = 109 sizeof(TR_RelocationRecordValidateJ2IThunkFromMethodBinaryTemplate), // TR_ValidateJ2IThunkFromMethod = 110 sizeof(TR_RelocationRecordConstantPoolWithIndexBinaryTemplate), // TR_StaticDefaultValueInstance = 111 + sizeof(TR_RelocationRecordValidateIsClassVisibleBinaryTemplate), // TR_ValidateIsClassVisible = 112 }; // 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 f9d4add6f52..d2617a9d5ff 100644 --- a/runtime/compiler/runtime/RelocationRecord.hpp +++ b/runtime/compiler/runtime/RelocationRecord.hpp @@ -1929,5 +1929,27 @@ class TR_RelocationRecordStaticDefaultValueInstance : public TR_RelocationRecord virtual TR_RelocationErrorCode applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocationHigh, uint8_t *reloLocationLow); }; +class TR_RelocationRecordValidateIsClassVisible : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateIsClassVisible() {} + TR_RelocationRecordValidateIsClassVisible(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateIsClassVisible"; } + 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 setSourceClassID(TR_RelocationTarget *reloTarget, uint16_t sourceClassID); + uint16_t sourceClassID(TR_RelocationTarget *reloTarget); + + void setDestClassID(TR_RelocationTarget *reloTarget, uint16_t destClassID); + uint16_t destClassID(TR_RelocationTarget *reloTarget); + + void setIsVisible(TR_RelocationTarget *reloTarget, bool isVisible); + bool isVisible(TR_RelocationTarget *reloTarget); + }; + #endif // RELOCATION_RECORD_INCL diff --git a/runtime/compiler/runtime/RelocationRuntime.cpp b/runtime/compiler/runtime/RelocationRuntime.cpp index 5bed227e099..5477a584483 100644 --- a/runtime/compiler/runtime/RelocationRuntime.cpp +++ b/runtime/compiler/runtime/RelocationRuntime.cpp @@ -132,23 +132,24 @@ char *TR_RelocationRuntime::_reloErrorCodeNames[] = "methodFromSingleInterfaceImplValidationFailure", // 41 "methodFromSingleAbstractImplValidationFailure", // 42 "j2iThunkFromMethodValidationFailure", // 43 - "svmValidationFailure", // 44 - "wkcValidationFailure", // 45 - - "classAddressRelocationFailure", // 46 - "inlinedMethodRelocationFailure", // 47 - "symbolFromManagerRelocationFailure", // 48 - "thunkRelocationFailure", // 49 - "trampolineRelocationFailure", // 50 - "picTrampolineRelocationFailure", // 51 - "cacheFullRelocationFailure", // 52 - "blockFrequencyRelocationFailure", // 53 - "recompQueuedFlagRelocationFailure", // 54 - "debugCounterRelocationFailure", // 55 - "directJNICallRelocationFailure", // 56 - "ramMethodConstRelocationFailure", // 57 - - "maxRelocationError" // 58 + "isClassVisibleValidationFailure", // 44 + "svmValidationFailure", // 45 + "wkcValidationFailure", // 46 + + "classAddressRelocationFailure", // 47 + "inlinedMethodRelocationFailure", // 48 + "symbolFromManagerRelocationFailure", // 49 + "thunkRelocationFailure", // 50 + "trampolineRelocationFailure", // 51 + "picTrampolineRelocationFailure", // 52 + "cacheFullRelocationFailure", // 53 + "blockFrequencyRelocationFailure", // 54 + "recompQueuedFlagRelocationFailure", // 55 + "debugCounterRelocationFailure", // 56 + "directJNICallRelocationFailure", // 57 + "ramMethodConstRelocationFailure", // 58 + + "maxRelocationError" // 59 }; TR_RelocationRuntime::TR_RelocationRuntime(J9JITConfig *jitCfg) diff --git a/runtime/compiler/runtime/RelocationRuntime.hpp b/runtime/compiler/runtime/RelocationRuntime.hpp index 681d26593e2..fa49d01f817 100644 --- a/runtime/compiler/runtime/RelocationRuntime.hpp +++ b/runtime/compiler/runtime/RelocationRuntime.hpp @@ -186,25 +186,26 @@ struct TR_RelocationError methodFromSingleInterfaceImplValidationFailure = (41 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::VALIDATION, methodFromSingleAbstractImplValidationFailure = (42 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::VALIDATION, j2iThunkFromMethodValidationFailure = (43 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::VALIDATION, - svmValidationFailure = (44 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::VALIDATION, - wkcValidationFailure = (45 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::VALIDATION, - - classAddressRelocationFailure = (46 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - inlinedMethodRelocationFailure = (47 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - symbolFromManagerRelocationFailure = (48 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - thunkRelocationFailure = (49 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - trampolineRelocationFailure = (50 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - picTrampolineRelocationFailure = (51 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - cacheFullRelocationFailure = (52 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - blockFrequencyRelocationFailure = (53 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - recompQueuedFlagRelocationFailure = (54 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - debugCounterRelocationFailure = (55 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - directJNICallRelocationFailure = (56 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - ramMethodConstRelocationFailure = (57 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - - staticDefaultValueInstanceRelocationFailure = (58 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, - - maxRelocationError = (59 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::NO_RELO_ERROR + isClassVisibleValidationFailure = (44 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::VALIDATION, + svmValidationFailure = (45 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::VALIDATION, + wkcValidationFailure = (46 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::VALIDATION, + + classAddressRelocationFailure = (47 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + inlinedMethodRelocationFailure = (48 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + symbolFromManagerRelocationFailure = (49 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + thunkRelocationFailure = (50 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + trampolineRelocationFailure = (51 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + picTrampolineRelocationFailure = (52 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + cacheFullRelocationFailure = (53 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + blockFrequencyRelocationFailure = (54 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + recompQueuedFlagRelocationFailure = (55 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + debugCounterRelocationFailure = (56 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + directJNICallRelocationFailure = (57 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + ramMethodConstRelocationFailure = (58 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + + staticDefaultValueInstanceRelocationFailure = (59 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION, + + maxRelocationError = (60 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::NO_RELO_ERROR }; static uint32_t decode(TR_RelocationErrorCode errorCode) { return static_cast(errorCode >> RELO_ERRORCODE_SHIFT); } diff --git a/runtime/compiler/runtime/SymbolValidationManager.cpp b/runtime/compiler/runtime/SymbolValidationManager.cpp index c3a6d949209..85cfa77bff0 100644 --- a/runtime/compiler/runtime/SymbolValidationManager.cpp +++ b/runtime/compiler/runtime/SymbolValidationManager.cpp @@ -1124,6 +1124,21 @@ TR::SymbolValidationManager::addJ2IThunkFromMethodRecord(void *thunk, TR_OpaqueM appendNewRecord(thunk, record); } +bool +TR::SymbolValidationManager::addIsClassVisibleRecord(TR_OpaqueClassBlock *sourceClass, TR_OpaqueClassBlock *destClass, bool isVisible) + { + SVM_ASSERT_ALREADY_VALIDATED(this, sourceClass); + SVM_ASSERT_ALREADY_VALIDATED(this, destClass); + + // Skip creating a record when destClass is a Java.lang.Object + // because Object is always visible + if (sourceClass == destClass + || _fej9->isJavaLangObject(destClass)) + return true; + + return addVanillaRecord(sourceClass, new (_region) IsClassVisibleRecord(sourceClass, destClass, isVisible)); + } + bool @@ -1569,6 +1584,17 @@ TR::SymbolValidationManager::validateJ2IThunkFromMethodRecord(uint16_t thunkID, return validateSymbol(thunkID, thunk, TR::SymbolType::typeOpaque); } +bool +TR::SymbolValidationManager::validateIsClassVisibleRecord(uint16_t sourceClassID, uint16_t destClassID, bool wasVisible) + { + TR_OpaqueClassBlock *sourceClass = getClassFromID(sourceClassID); + TR_OpaqueClassBlock *destClass = getClassFromID(destClassID); + + bool isVisible = _fej9->isClassVisible(sourceClass, destClass); + + return (isVisible == wasVisible); + } + bool TR::SymbolValidationManager::assertionsAreFatal() { @@ -2160,3 +2186,22 @@ void TR::J2IThunkFromMethodRecord::printFields() traceMsg(TR::comp(), "\t_thunk=0x%p\n", _thunk); traceMsg(TR::comp(), "\t_method=0x%p\n", _method); } + +bool TR::IsClassVisibleRecord::isLessThanWithinKind( + SymbolValidationRecord *other) + { + TR::IsClassVisibleRecord *rhs = downcast(this, other); + return LexicalOrder::by(_sourceClass, rhs->_sourceClass) + .thenBy(_destClass, rhs->_destClass) + .thenBy(_isVisible, rhs->_isVisible).less(); + } + +void TR::IsClassVisibleRecord::printFields() + { + traceMsg(TR::comp(), "IsClassVisibleRecord\n"); + traceMsg(TR::comp(), "\t_sourceClass=0x%p\n", _sourceClass); + printClass(_sourceClass); + traceMsg(TR::comp(), "\t_destClass=0x%p\n", _destClass); + printClass(_destClass); + traceMsg(TR::comp(), "\t_isVisible=%s\n", _isVisible ? "true" : "false"); + } diff --git a/runtime/compiler/runtime/SymbolValidationManager.hpp b/runtime/compiler/runtime/SymbolValidationManager.hpp index 94267b6a3cd..e9806ab1468 100644 --- a/runtime/compiler/runtime/SymbolValidationManager.hpp +++ b/runtime/compiler/runtime/SymbolValidationManager.hpp @@ -691,6 +691,23 @@ struct J2IThunkFromMethodRecord : public SymbolValidationRecord TR_OpaqueMethodBlock *_method; }; +struct IsClassVisibleRecord : public SymbolValidationRecord + { + IsClassVisibleRecord(TR_OpaqueClassBlock *sourceClass, TR_OpaqueClassBlock *destClass, bool isVisible) + : SymbolValidationRecord(TR_ValidateIsClassVisible), + _sourceClass(sourceClass), + _destClass(destClass), + _isVisible(isVisible) + {} + + virtual bool isLessThanWithinKind(SymbolValidationRecord *other); + virtual void printFields(); + + TR_OpaqueClassBlock *_sourceClass; + TR_OpaqueClassBlock *_destClass; + bool _isVisible; + }; + class SymbolValidationManager { public: @@ -775,6 +792,7 @@ class SymbolValidationManager bool addStackWalkerMaySkipFramesRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass, bool skipFrames); bool addClassInfoIsInitializedRecord(TR_OpaqueClassBlock *clazz, bool isInitialized); void addJ2IThunkFromMethodRecord(void *thunk, TR_OpaqueMethodBlock *method); + bool addIsClassVisibleRecord(TR_OpaqueClassBlock *sourceClass, TR_OpaqueClassBlock *destClass, bool isVisible); @@ -826,6 +844,8 @@ class SymbolValidationManager // that the thunk loading logic can be confined to RelocationRecord.cpp. bool validateJ2IThunkFromMethodRecord(uint16_t thunkID, void *thunk); + bool validateIsClassVisibleRecord(uint16_t sourceClassID, uint16_t destClassID, bool wasVisible); + TR_OpaqueClassBlock *getBaseComponentClass(TR_OpaqueClassBlock *clazz, int32_t & numDims);