diff --git a/doc/compiler/aot/SymbolValidationManager.md b/doc/compiler/aot/SymbolValidationManager.md new file mode 100644 index 00000000000..331f3ec3acb --- /dev/null +++ b/doc/compiler/aot/SymbolValidationManager.md @@ -0,0 +1,173 @@ + + +# Symbol Validation Manager + +In order for the OpenJ9 Compiler to compile Ahead Of Time (AOT), +or more accurately, Relocatable, code, it needs to be able to store +information for the AOT load infrastructure to validate all the +assumptions made during the compile run, since the AOT load is +performed in a different JVM environment than the one the compilation +was performed in. For these reasons, the Compiler and the Shared Class +Cache (SCC) has infrastructure to facilate these validations. + +Without the Symbol Validation Manager, the validations involves either +creating a relocation record to validate an Arbitrary Class, a Class +from a Constant Pool, an Instance Field, or a Static Field. However, +when getting a Class By Name, the validation stored would be an +Arbitrary Class Validation, which is technically incorrect when the +Name is retrieved from the signature of a method (since the answer +depends on what the Class of that method "sees"). In order to deal +with this, the compiler needs to know where the "beholder" Class comes +from. The Symbol Validation Manager fixes this problem by making the +answer to the question "where does this _whatever_ come from?" explicit +and unambigious. + +## How it works + +The Symbol Validation Manager (SVM) is very much similar to a symbol table +that a linker might use. The idea is to store information about where +a particular symbol (eg `J9Class`, `J9Method`, etc.) came from. For example, +if the compiler got the `J9Class` of `java/lang/String` by name from the +parameter list of method `C.foo(Ljava/lang/String)V`, then the SVM will +store a record stating that the compiler got `J9Class` `java/lang/String` +By Name as seen by `J9Class` `C`. Then in the load run, the load +infrastructure can validate these answers the compiler got by redoing the +same queries *in the same order as during the AOT compilation*. In this +manner, if the AOT load succeeds validations, the compiled body is 100% +guaranteed to be compatible in the current environment. + +However, since `J9Class`es are artifacts of the current environment, how +does the SVM enable a new environment to validate it? The core idea is to +associate unique IDs to each new symbol the compiler gets a hold of. Thus, +when a symbol is acquired by asking a query using a different symbol, the +validation record that gets generated refers to these two symbols by their +IDs, which are environment agnostic. In the load run, the AOT load +infrastructure uses these IDs to build up its table of symbols that are +valid in _its_ environment. + +To give a concrete example: + +The compiler decides to compile `A.foo()`. As part of the compilation, it +gets class `B` from `A`'s constant pool, gets class `C` from `A`'s +constant pool, and finally gets `B` by name as seen by `C`. Thus, the +validation records that get generated would be: + +1. Root Class Record for `A`; `A` gets ID 1 +2. Method From Class Record for `foo`; `foo` gets ID 2 +3. Class From CP of `A` for `B`; `B` gets ID 3 +4. Class From CP of `A` for `C`; `C` gets ID 4 +5. Class By Name as seen by `C` + +When writing out the records, the information would be written out in the +following manner: + +1. Root Class Record: ID=1 +2. Method From Class Record: ID=2, classID=1, index=x +3. Class From CP Record: ID=3, beholderID=1, cpIndex=y +4. Class From CP Record: ID=4, beholderID=1, cpIndex=z +5. Class By Name Record: ID=3, beholder=4 + +Thus the information written in the validation records are entirely +environment agnostic. In the load run, the AOT infrastructure will +go through these validations and build up the symbols that are valid +in _its_ environment: + +1. Map ID=1 to the class of the method being compiled +2. Get the method at index=x from the class associated with ID=1 and +map it to ID=2 +3. Get the class from cpIndex=y from the class associated with ID=1 +and map it to ID=3 +4. Get the class from cpIndex=z from the class associated with ID=1 +and map it to ID=4 +5. Get the class by name as seen by the class associated with ID=4 +and verify that it is the same class associated with ID=3 + +If any of the validations fail, the load is aborted. Thus the general +approach in the load run is: + +1. Find the symbol as specified by the validation record +2. Map the ID from the validation record to the symbol +3. If the map already contains a symbol for that ID, validate that +the symbol in the map is the same as the symbol currently being +validated; fail otherwise + + +## Subtleties + +### Class Chains + +Class Chains are a core component of AOT validation; they ensure that +the shape of a class is the same as that during the compile run. For +technical details about Class Chains, see +[AOT Class Chains](https://github.com/eclipse/openj9/blob/master/doc/compiler/aot/AOTClassChains.md). +Thus, for every validation record involving classes, a Class Chain +Validation Record is also created (unless a record for that class +already exists). + +### Array Classes + +Array Classes create a problem for validation. Class Chains can only +exist for non-array classes. However, if the compiler acquired an +array class by name or via profiling, in order to use it during an AOT +compilation, it still needs to ensure that the shape of that class will +be valid in the load run. Therefore, for every validation record +involving classes, what actually happens is the SVM will get the +leaf component class, store the record as if the compiler acquired the +leaf component class from the query, and then store as many +Array From Component Class Validation Records as there are array +dimensions. Therefore, on the load run, when performing a validation, +the SVM also has ensure to get the leaf component class in order for +the validation to be consistent with the compile run. The actual array +class gets validated via the Array From Component Class records. + +### Primitive Classes + +Primitive Classes create a different problem for validation. As it turns +out, the ROM Classes for primitive classes aren't stored in the SCC. +This is an issue when storing Class By Name records, since the name +portion of the validation is derived from the ROM Class. In order to +deal with this problem, the Profiled Class and Class By Name +Validations also store a char value representing the primitive type; +if the char value is '\0', then the class being validated isn't +primitive and the rest of the validation process continues. If the +char value is not '\0', then class is primitive, and the Profiled +Class or Class By Name record returns validaion succeeded, which is +correct because Primitive Classes are guaranteed to always be the +same regardless of how they are acquired. + +### Guaranteed IDs + +Because Primitive Classes (and their associated array classes) are always +guaranteed to exist, and because the Root Class and method from root class +have already been validated prior to even attempting to perfom the AOT +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. + +## Benefits + +1. Makes explicit the providence of every symbol acquired by the compiler +2. Enables code paths previously disabled under AOT +3. Allows relocations of classes/methods associated with cpIndex=-1 +4. Facilitates the enablement of Known Object Table under AOT +5. Facilitates the enablement of JSR292 under AOT diff --git a/runtime/compiler/build/files/common.mk b/runtime/compiler/build/files/common.mk index 68ca889b2e4..6e0f14f46f7 100644 --- a/runtime/compiler/build/files/common.mk +++ b/runtime/compiler/build/files/common.mk @@ -359,6 +359,7 @@ JIT_PRODUCT_SOURCE_FILES+=\ compiler/runtime/Runtime.cpp \ compiler/runtime/RuntimeAssumptions.cpp \ compiler/runtime/SignalHandler.c \ + compiler/runtime/SymbolValidationManager.cpp \ compiler/runtime/Trampoline.cpp \ compiler/runtime/ValueProfiler.cpp \ compiler/runtime/codertinit.cpp \ diff --git a/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp b/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp index a286ea4371a..26d90483c61 100644 --- a/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp +++ b/runtime/compiler/codegen/J9AheadOfTimeCompile.cpp @@ -27,6 +27,7 @@ #include "il/DataTypes.hpp" #include "env/VMJ9.h" #include "codegen/AheadOfTimeCompile.hpp" +#include "runtime/RelocationRecord.hpp" extern bool isOrderedPair(uint8_t reloType); @@ -698,6 +699,7 @@ J9::AheadOfTimeCompile::dumpRelocationData() case TR_InlinedSpecialMethodWithNopGuard: case TR_InlinedVirtualMethodWithNopGuard: case TR_InlinedInterfaceMethodWithNopGuard: + case TR_InlinedAbstractMethodWithNopGuard: case TR_InlinedHCRMethod: cursor++; // unused field if (is64BitTarget) @@ -1079,9 +1081,729 @@ J9::AheadOfTimeCompile::dumpRelocationData() traceMsg(self()->comp(), "\n ClassUnloadAssumption \n"); break; + case TR_ValidateRootClass: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateRootClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Root Class: classID=%d ", (uint32_t)binaryTemplate->_classID); + } + cursor += sizeof(TR_RelocationRecordValidateRootClassBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateClassByName: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateClassByNameBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Class By Name: classID=%d beholderID=%d primitiveType=%c romClassOffsetInSCC=%p ", + (uint32_t)binaryTemplate->_classID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_primitiveType, + binaryTemplate->_romClassOffsetInSCC); + } + cursor += sizeof(TR_RelocationRecordValidateClassByNameBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateProfiledClass: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateProfiledClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Profiled Class: classID=%d primitiveType=%c classChainOffsetInSCC=%d classChainOffsetForCLInScc=%p ", + (uint32_t)binaryTemplate->_classID, + binaryTemplate->_primitiveType, + binaryTemplate->_classChainOffsetInSCC, + binaryTemplate->_classChainOffsetForCLInScc); + } + cursor += sizeof(TR_RelocationRecordValidateProfiledClassBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateClassFromCP: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateClassFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Class From CP: classID=%d, beholderID=%d, cpIndex=%d ", + (uint32_t)binaryTemplate->_classID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_cpIndex); + } + cursor += sizeof(TR_RelocationRecordValidateClassFromCPBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateDefiningClassFromCP: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateDefiningClassFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Defining Class From CP: classID=%d, beholderID=%d, cpIndex=%d, isStatic=%s ", + (uint32_t)binaryTemplate->_classID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_cpIndex, + binaryTemplate->_isStatic ? "true" : "false"); + } + cursor += sizeof(TR_RelocationRecordValidateDefiningClassFromCPBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateStaticClassFromCP: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateStaticClassFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Static Class From CP: classID=%d, beholderID=%d, cpIndex=%d ", + (uint32_t)binaryTemplate->_classID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_cpIndex); + } + cursor += sizeof(TR_RelocationRecordValidateStaticClassFromCPBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateClassFromMethod: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateClassFromMethodBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Class From Method: classID=%d, methodID=%d ", + (uint32_t)binaryTemplate->_classID, + (uint32_t)binaryTemplate->_methodID); + } + cursor += sizeof(TR_RelocationRecordValidateClassFromMethodBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateComponentClassFromArrayClass: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateCompFromArrayBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Component Class From Array: componentClassID=%d, arrayClassID=%d ", + (uint32_t)binaryTemplate->_componentClassID, + (uint32_t)binaryTemplate->_arrayClassID); + } + cursor += sizeof(TR_RelocationRecordValidateCompFromArrayBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateArrayClassFromComponentClass: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateArrayFromCompBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Array Class From Component: arrayClassID=%d, componentClassID=%d ", + (uint32_t)binaryTemplate->_arrayClassID, + (uint32_t)binaryTemplate->_componentClassID); + } + cursor += sizeof(TR_RelocationRecordValidateArrayFromCompBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateSuperClassFromClass: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateSuperClassFromClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Super Class From Class: superClassID=%d, childClassID=%d ", + (uint32_t)binaryTemplate->_superClassID, + (uint32_t)binaryTemplate->_childClassID); + } + cursor += sizeof(TR_RelocationRecordValidateSuperClassFromClassBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateClassInstanceOfClass: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateClassInstanceOfClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Class InstanceOf Class: classOneID=%d, classTwoID=%d, objectTypeIsFixed=%s, castTypeIsFixed=%s, isInstanceOf=%s ", + (uint32_t)binaryTemplate->_classOneID, + (uint32_t)binaryTemplate->_classTwoID, + binaryTemplate->_objectTypeIsFixed ? "true" : "false", + binaryTemplate->_castTypeIsFixed ? "true" : "false", + binaryTemplate->_isInstanceOf ? "true" : "false"); + } + cursor += sizeof(TR_RelocationRecordValidateClassInstanceOfClassBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateSystemClassByName: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateSystemClassByNameBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate System Class By Name: systemClassID=%d romClassOffsetInSCC=%p ", + (uint32_t)binaryTemplate->_systemClassID, + binaryTemplate->_romClassOffsetInSCC); + } + cursor += sizeof(TR_RelocationRecordValidateSystemClassByNameBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateClassFromITableIndexCP: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateClassFromITableIndexCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Class From ITableIndex CP: classID=%d beholderID=%d cpIndex=%d ", + (uint32_t)binaryTemplate->_classID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_cpIndex); + } + cursor += sizeof(TR_RelocationRecordValidateClassFromITableIndexCPBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateDeclaringClassFromFieldOrStatic: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateDeclaringClassFromFieldOrStaticBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Declaring Class From Field Or Static: classID=%d, beholderID=%d, cpIndex=%d ", + (uint32_t)binaryTemplate->_classID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_cpIndex); + } + cursor += sizeof(TR_RelocationRecordValidateDeclaringClassFromFieldOrStaticBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateClassClass: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateClassClassBinaryTemplate *binaryTemplate = + reinterpret_cast(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++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateConcreteSubFromClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Concrete SubClass From Class: childClassID=%d, superClassID=%d ", + (uint32_t)binaryTemplate->_childClassID, + (uint32_t)binaryTemplate->_superClassID); + } + cursor += sizeof(TR_RelocationRecordValidateConcreteSubFromClassBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateClassChain: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateClassChainBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Class Chain: classID=%d classChainOffsetInSCC=%p ", + (uint32_t)binaryTemplate->_classID, + binaryTemplate->_classChainOffsetInSCC); + } + cursor += sizeof(TR_RelocationRecordValidateClassChainBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateRomClass: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateRomClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate RomClass: classID=%d romClassOffsetInSCC=%p ", + (uint32_t)binaryTemplate->_classID, + binaryTemplate->_romClassOffsetInSCC); + } + cursor += sizeof(TR_RelocationRecordValidateRomClassBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidatePrimitiveClass: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidatePrimitiveClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Primitive Class: classID=%d, primitiveType=%c ", + (uint32_t)binaryTemplate->_classID, + binaryTemplate->_primitiveType); + } + cursor += sizeof(TR_RelocationRecordValidatePrimitiveClassBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateMethodFromInlinedSite: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateMethodFromInlSiteBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Method From Inlined Site: methodID=%d, inlinedSiteIndex=%d ", + (uint32_t)binaryTemplate->_methodID, + (int32_t)binaryTemplate->_inlinedSiteIndex); + } + cursor += sizeof(TR_RelocationRecordValidateMethodFromInlSiteBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateMethodByName: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateMethodByNameBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Method By Name: methodID=%d, beholderID=%d, romClassOffsetInSCC=%p romMethodOffsetInSCC=%p ", + (uint32_t)binaryTemplate->_methodID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_romClassOffsetInSCC, + binaryTemplate->_romMethodOffsetInSCC); + } + cursor += sizeof(TR_RelocationRecordValidateMethodByNameBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateMethodFromClass: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateMethodFromClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Method By Name: methodID=%d, beholderID=%d, index=%d ", + (uint32_t)binaryTemplate->_methodID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_index); + } + cursor += sizeof(TR_RelocationRecordValidateMethodFromClassBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateStaticMethodFromCP: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateStaticMethodFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Static Method From CP: methodID=%d, beholderID=%d, cpIndex=%d ", + (uint32_t)binaryTemplate->_methodID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_cpIndex); + } + cursor += sizeof(TR_RelocationRecordValidateStaticMethodFromCPBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateSpecialMethodFromCP: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateSpecialMethodFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Special Method From CP: methodID=%d, beholderID=%d, cpIndex=%d ", + (uint32_t)binaryTemplate->_methodID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_cpIndex); + } + cursor += sizeof(TR_RelocationRecordValidateSpecialMethodFromCPBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateVirtualMethodFromCP: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateVirtualMethodFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Virtual Method From CP: methodID=%d, beholderID=%d, cpIndex=%d ", + (uint32_t)binaryTemplate->_methodID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_cpIndex); + } + cursor += sizeof(TR_RelocationRecordValidateVirtualMethodFromCPBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateVirtualMethodFromOffset: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateVirtualMethodFromOffsetBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Virtual Method From Offset: methodID=%d, beholderID=%d, virtualCallOffset=%d, ignoreRtResolve=%s ", + (uint32_t)binaryTemplate->_methodID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_virtualCallOffset, + binaryTemplate->_ignoreRtResolve ? "true" : "false"); + } + cursor += sizeof(TR_RelocationRecordValidateVirtualMethodFromOffsetBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateInterfaceMethodFromCP: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateInterfaceMethodFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Interface Method From CP: methodID=%d, beholderID=%d, lookupID=%d, cpIndex=%d ", + (uint32_t)binaryTemplate->_methodID, + (uint32_t)binaryTemplate->_beholderID, + (uint32_t)binaryTemplate->_lookupID, + binaryTemplate->_cpIndex); + } + cursor += sizeof(TR_RelocationRecordValidateInterfaceMethodFromCPBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateImproperInterfaceMethodFromCP: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateImproperInterfaceMethodFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Improper Interface Method From CP: methodID=%d, beholderID=%d, cpIndex=%d ", + (uint32_t)binaryTemplate->_methodID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_cpIndex); + } + cursor += sizeof(TR_RelocationRecordValidateImproperInterfaceMethodFromCPBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateMethodFromClassAndSig: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateMethodFromClassAndSigBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Method From Class and Sig: methodID=%d, methodClassID=%d, beholderID=%d, romMethodOffsetInSCC=%p ", + (uint32_t)binaryTemplate->_methodID, + (uint32_t)binaryTemplate->_methodClassID, + (uint32_t)binaryTemplate->_beholderID, + binaryTemplate->_romMethodOffsetInSCC); + } + cursor += sizeof(TR_RelocationRecordValidateMethodFromClassAndSigBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateStackWalkerMaySkipFramesRecord: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateStackWalkerMaySkipFramesBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Stack Walker May Skip Frames: methodID=%d, methodClassID=%d, beholderID=%d, skipFrames=%s ", + (uint32_t)binaryTemplate->_methodID, + (uint32_t)binaryTemplate->_methodClassID, + binaryTemplate->_skipFrames ? "true" : "false"); + } + cursor += sizeof(TR_RelocationRecordValidateStackWalkerMaySkipFramesBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateArrayClassFromJavaVM: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateArrayClassFromJavaVMBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Array Class From JavaVM: arrayClassID=%d, arrayClassIndex=%d ", + (uint32_t)binaryTemplate->_arrayClassID, + binaryTemplate->_arrayClassIndex); + } + cursor += sizeof(TR_RelocationRecordValidateArrayClassFromJavaVMBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateClassInfoIsInitialized: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateClassInfoIsInitializedBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Class Info Is Initialized: classID=%d, isInitialized=%s ", + (uint32_t)binaryTemplate->_classID, + binaryTemplate->_isInitialized ? "true" : "false"); + } + cursor += sizeof(TR_RelocationRecordValidateClassInfoIsInitializedBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateMethodFromSingleImplementer: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateMethodFromSingleImplBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Method From Single Implementor: methodID=%d, thisClassID=%d, cpIndexOrVftSlot=%d, callerMethodID=%d, useGetResolvedInterfaceMethod=%d ", + (uint32_t)binaryTemplate->_methodID, + (uint32_t)binaryTemplate->_thisClassID, + binaryTemplate->_cpIndexOrVftSlot, + (uint32_t)binaryTemplate->_callerMethodID, + binaryTemplate->_useGetResolvedInterfaceMethod); + } + cursor += sizeof(TR_RelocationRecordValidateMethodFromSingleImplBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateMethodFromSingleInterfaceImplementer: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateMethodFromSingleInterfaceImplBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Method From Single Interface Implementor: methodID=%d, thisClassID=%d, cpIndex=%d, callerMethodID=%d ", + (uint32_t)binaryTemplate->_methodID, + (uint32_t)binaryTemplate->_thisClassID, + binaryTemplate->_cpIndex, + (uint32_t)binaryTemplate->_callerMethodID); + } + cursor += sizeof(TR_RelocationRecordValidateMethodFromSingleInterfaceImplBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + case TR_ValidateMethodFromSingleAbstractImplementer: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordValidateMethodFromSingleAbstractImplBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Validate Method From Single Interface Implementor: methodID=%d, thisClassID=%d, vftSlot=%d, callerMethodID=%d ", + (uint32_t)binaryTemplate->_methodID, + (uint32_t)binaryTemplate->_thisClassID, + binaryTemplate->_vftSlot, + (uint32_t)binaryTemplate->_callerMethodID); + } + cursor += sizeof(TR_RelocationRecordValidateMethodFromSingleAbstractImplBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + + + case TR_SymbolFromManager: + { + cursor++; + if (is64BitTarget) + cursor += 4; // padding + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + TR_RelocationRecordSymbolFromManagerBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + if (isVerbose) + { + traceMsg(self()->comp(), "\n Symbol From Manager: symbolID=%d symbolType=%d ", + (uint32_t)binaryTemplate->_symbolID, (uint32_t)binaryTemplate->_symbolType); + } + cursor += sizeof(TR_RelocationRecordSymbolFromManagerBinaryTemplate); + self()->traceRelocationOffsets(cursor, offsetSize, endOfCurrentRecord, orderedPair); + } + break; + default: traceMsg(self()->comp(), "Unknown Relocation type = %d\n", kind); TR_ASSERT(false, "should be unreachable"); + printf("Unknown Relocation type = %d\n", kind); + fflush(stdout); + exit(0); + break; } diff --git a/runtime/compiler/codegen/J9CodeGenerator.cpp b/runtime/compiler/codegen/J9CodeGenerator.cpp index 0ee9e074330..03e46987795 100644 --- a/runtime/compiler/codegen/J9CodeGenerator.cpp +++ b/runtime/compiler/codegen/J9CodeGenerator.cpp @@ -1133,7 +1133,7 @@ J9::CodeGenerator::lowerTreeIfNeeded( { if (!((methodSymbol && methodSymbol->getResolvedMethodSymbol() && methodSymbol->getResolvedMethodSymbol()->getResolvedMethod() && - methodSymbol->getResolvedMethodSymbol()->getResolvedMethod()->isInterpreted()) || + methodSymbol->getResolvedMethodSymbol()->getResolvedMethod()->isInterpretedForHeuristics()) || methodSymbol->isVMInternalNative() || methodSymbol->isHelper() || methodSymbol->isNative() || @@ -2516,6 +2516,10 @@ J9::CodeGenerator::processRelocations() type = TR_InlinedInterfaceMethod; break; + case TR_AbstractGuard: + type = TR_InlinedAbstractMethodWithNopGuard; + break; + case TR_HCRGuard: // devinmp: TODO/FIXME this should arrange to create an AOT // relocation which, when loaded, creates a @@ -2572,6 +2576,7 @@ J9::CodeGenerator::processRelocations() case TR_InlinedSpecialMethodWithNopGuard: case TR_InlinedVirtualMethodWithNopGuard: case TR_InlinedInterfaceMethodWithNopGuard: + case TR_InlinedAbstractMethodWithNopGuard: case TR_InlinedHCRMethod: case TR_ProfiledClassGuardRelocation: case TR_ProfiledMethodGuardRelocation: @@ -2692,6 +2697,24 @@ J9::CodeGenerator::processRelocations() } } } + + TR::SymbolValidationManager::SymbolValidationRecordList &validationRecords = self()->comp()->getSymbolValidationManager()->getValidationRecordList(); + if (!validationRecords.empty() && self()->comp()->getOption(TR_UseSymbolValidationManager)) + { + // Add the flags in TR_AOTMethodHeader on the compile run + J9JITDataCacheHeader *aotMethodHeader = (J9JITDataCacheHeader *)self()->comp()->getAotMethodDataStart(); + TR_AOTMethodHeader *aotMethodHeaderEntry = (TR_AOTMethodHeader *)(aotMethodHeader + 1); + aotMethodHeaderEntry->flags |= TR_AOTMethodHeader_UsesSymbolValidationManager; + + for (auto it = validationRecords.begin(); it != validationRecords.end(); it++) + { + self()->addExternalRelocation(new (self()->trHeapMemory()) TR::ExternalRelocation(NULL, + (uint8_t *)(*it), + (*it)->_kind, self()), + __FILE__, __LINE__, NULL); + } + } + //#endif // Now call the platform specific processing of relocations self()->getAheadOfTimeCompile()->processRelocations(); diff --git a/runtime/compiler/compile/J9Compilation.cpp b/runtime/compiler/compile/J9Compilation.cpp index 62b81caaed0..6c9d6802c38 100644 --- a/runtime/compiler/compile/J9Compilation.cpp +++ b/runtime/compiler/compile/J9Compilation.cpp @@ -170,12 +170,7 @@ J9::Compilation::Compilation( _profileInfo(NULL), _skippedJProfilingBlock(false) { - _ObjectClassPointer = fe->getClassFromSignature("Ljava/lang/Object;", 18, compilee); - _RunnableClassPointer = fe->getClassFromSignature("Ljava/lang/Runnable;", 20, compilee); - _StringClassPointer = fe->getClassFromSignature("Ljava/lang/String;", 18, compilee); - _SystemClassPointer = fe->getClassFromSignature("Ljava/lang/System;", 18, compilee); - _ReferenceClassPointer = fe->getClassFromSignature("Ljava/lang/ref/Reference;", 25, compilee); - _JITHelpersClassPointer = fe->getClassFromSignature("Lcom/ibm/jit/JITHelpers;", 24, compilee); + _symbolValidationManager = new (self()->region()) TR::SymbolValidationManager(self()->region(), compilee); _aotClassClassPointer = NULL; _aotClassClassPointerInitialized = false; @@ -188,6 +183,13 @@ J9::Compilation::Compilation( _hiresTimeForPreviousCallingContext = TR::Compiler->vm.getHighResClock(self()); _profileInfo = new (m->trHeapMemory()) TR_AccessedProfileInfo(heapMemoryRegion); + + _ObjectClassPointer = fe->getClassFromSignature("Ljava/lang/Object;", 18, compilee); + _RunnableClassPointer = fe->getClassFromSignature("Ljava/lang/Runnable;", 20, compilee); + _StringClassPointer = fe->getClassFromSignature("Ljava/lang/String;", 18, compilee); + _SystemClassPointer = fe->getClassFromSignature("Ljava/lang/System;", 18, compilee); + _ReferenceClassPointer = fe->getClassFromSignature("Ljava/lang/ref/Reference;", 25, compilee); + _JITHelpersClassPointer = fe->getClassFromSignature("Lcom/ibm/jit/JITHelpers;", 24, compilee); } J9::Compilation::~Compilation() @@ -653,7 +655,7 @@ J9::Compilation::canAllocateInline(TR::Node* node, TR_OpaqueClassBlock* &classIn if (clazz == NULL) return -1; - clazz = clazz->arrayClass; + clazz = (J9Class *)self()->fej9vm()->getArrayClassFromComponentClass((TR_OpaqueClassBlock *)clazz); if (!clazz) return -1; @@ -1071,6 +1073,39 @@ J9::Compilation::compilationShouldBeInterrupted(TR_CallingContext callingContext return self()->fej9()->compilationShouldBeInterrupted(self(), callingContext); } +void +J9::Compilation::enterHeuristicRegion() + { + if (self()->getOption(TR_UseSymbolValidationManager) + && self()->compileRelocatableCode()) + { + self()->getSymbolValidationManager()->enterHeuristicRegion(); + } + } + +void +J9::Compilation::exitHeuristicRegion() + { + if (self()->getOption(TR_UseSymbolValidationManager) + && self()->compileRelocatableCode()) + { + self()->getSymbolValidationManager()->exitHeuristicRegion(); + } + } + +bool +J9::Compilation::validateTargetToBeInlined(TR_ResolvedMethod *implementer) + { + if (self()->getOption(TR_UseSymbolValidationManager) + && self()->compileRelocatableCode()) + { + return self()->getSymbolValidationManager()->addMethodFromClassRecord(implementer->getPersistentIdentifier(), + implementer->classOfMethod(), + -1); + } + return true; + } + void J9::Compilation::reportILGeneratorPhase() diff --git a/runtime/compiler/compile/J9Compilation.hpp b/runtime/compiler/compile/J9Compilation.hpp index 343eadc2053..170b4447b97 100644 --- a/runtime/compiler/compile/J9Compilation.hpp +++ b/runtime/compiler/compile/J9Compilation.hpp @@ -41,6 +41,7 @@ namespace J9 { typedef J9::Compilation CompilationConnector; } #include "env/CompilerEnv.hpp" #include "env/OMRMemory.hpp" #include "compile/AOTClassInfo.hpp" +#include "runtime/SymbolValidationManager.hpp" class TR_AOTGuardSite; class TR_FrontEnd; @@ -195,6 +196,25 @@ class OMR_EXTENSIBLE Compilation : public OMR::CompilationConnector bool compilationShouldBeInterrupted(TR_CallingContext); + /* Heuristic Region APIs + * + * Heuristic Regions denotes regions where decisions + * within the region do not need to be remembered. In relocatable compiles, + * when the compiler requests some information via front end query, + * it's possible that the front end might walk a data structure, + * looking at several different possible answers before finally deciding + * on one. For a relocatable compile, only the final answer is important. + * Thus, a heuristic region is used to ignore all of the intermediate + * steps in determining the final answer. + */ + void enterHeuristicRegion(); + void exitHeuristicRegion(); + + /* Used to ensure that a implementer chosen for inlining is valid under + * AOT. + */ + bool validateTargetToBeInlined(TR_ResolvedMethod *implementer); + void reportILGeneratorPhase(); void reportAnalysisPhase(uint8_t id); void reportOptimizationPhase(OMR::Optimizations); @@ -287,6 +307,8 @@ class OMR_EXTENSIBLE Compilation : public OMR::CompilationConnector // bool supportsQuadOptimization(); + TR::SymbolValidationManager *getSymbolValidationManager() { return _symbolValidationManager; } + private: J9VMThread *_j9VMThread; @@ -360,6 +382,8 @@ class OMR_EXTENSIBLE Compilation : public OMR::CompilationConnector TR_AccessedProfileInfo *_profileInfo; bool _skippedJProfilingBlock; + + TR::SymbolValidationManager *_symbolValidationManager; }; } diff --git a/runtime/compiler/compile/J9SymbolReferenceTable.cpp b/runtime/compiler/compile/J9SymbolReferenceTable.cpp index 7fba9c5dd24..b6663d872b3 100644 --- a/runtime/compiler/compile/J9SymbolReferenceTable.cpp +++ b/runtime/compiler/compile/J9SymbolReferenceTable.cpp @@ -1928,8 +1928,7 @@ J9::SymbolReferenceTable::checkImmutable(TR::SymbolReference *symRef) isClassInitialized = true; if ((classOfStatic != comp()->getSystemClassPointer()) && - isClassInitialized && TR::Compiler->cls.isClassFinal(comp(), classOfStatic) && - !comp()->getOption(TR_AOT)) + isClassInitialized && TR::Compiler->cls.isClassFinal(comp(), classOfStatic)) { if (!classInfo->getFieldInfo() && (comp()->getMethodHotness() >= hot)) diff --git a/runtime/compiler/control/CompilationThread.cpp b/runtime/compiler/control/CompilationThread.cpp index dc67596e34f..01d41828fa2 100644 --- a/runtime/compiler/control/CompilationThread.cpp +++ b/runtime/compiler/control/CompilationThread.cpp @@ -1792,6 +1792,7 @@ bool TR::CompilationInfo::shouldRetryCompilation(TR_MethodToBeCompiled *entry, T case compilationAotValidateMethodEnterFailure: case compilationAotClassChainPersistenceFailure: case compilationAotValidateStringCompressionFailure: + case compilationSymbolValidationManagerFailure: // switch to JIT for these cases (we don't want to relocate again) entry->_doNotUseAotCodeFromSharedCache = true; tryCompilingAgain = true; @@ -2844,6 +2845,8 @@ void TR::CompilationInfo::stopCompilationThreads() fprintf(stderr, "numVirtualMethodsValidationSucceeded: %d\n", aotStats->virtualMethods.numSucceededValidations); fprintf(stderr, "numInterfaceMethodsValidationFailed: %d\n", aotStats->interfaceMethods.numFailedValidations); fprintf(stderr, "numInterfaceMethodsValidationSucceeded: %d\n", aotStats->interfaceMethods.numSucceededValidations); + fprintf(stderr, "numAbstractMethodsValidationFailed: %d\n", aotStats->abstractMethods.numFailedValidations); + fprintf(stderr, "numAbstractMethodsValidationSucceeded: %d\n", aotStats->abstractMethods.numSucceededValidations); fprintf(stderr, "-------------------------\n"); fprintf(stderr, "numProfiledClassGuardsValidationFailed: %d\n", aotStats->profiledClassGuards.numFailedValidations); @@ -7073,6 +7076,12 @@ TR::CompilationInfoPerThreadBase::wrappedCompile(J9PortLibrary *portLib, void * options->setOption(TR_EnableAnnotations,false); } + if (vm->canUseSymbolValidationManager() && options->getOption(TR_EnableSymbolValidationManager)) + { + options->setOption(TR_UseSymbolValidationManager); + options->setOption(TR_DisableKnownObjectTable); + } + // Set jitDump specific options TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig); TR::CompilationInfoPerThread *threadCompInfo = compInfo ? compInfo->getCompInfoForThread(vmThread) : NULL; @@ -7417,6 +7426,11 @@ TR::CompilationInfoPerThreadBase::wrappedCompile(J9PortLibrary *portLib, void * options->setOption(TR_EnableGRACostBenefitModel, false); } + if (jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP || options->getOptLevel() < warm) + { + options->setOption(TR_UseSymbolValidationManager, false); + } + // See if we need to inset GCR trees if (!details.supportsInvalidation()) @@ -10074,6 +10088,10 @@ TR::CompilationInfoPerThreadBase::processException( { _methodBeingCompiled->_compErrCode = compilationGCRPatchFailure; } + catch (const J9::AOTSymbolValidationManagerFailure &e) + { + _methodBeingCompiled->_compErrCode = compilationSymbolValidationManagerFailure; + } catch (const J9::ClassChainPersistenceFailure &e) { shouldProcessExceptionCommonTasks = false; diff --git a/runtime/compiler/control/HookedByTheJit.cpp b/runtime/compiler/control/HookedByTheJit.cpp index 22f0f71e934..1c37b29fce7 100644 --- a/runtime/compiler/control/HookedByTheJit.cpp +++ b/runtime/compiler/control/HookedByTheJit.cpp @@ -5681,6 +5681,7 @@ static void classLoadPhaseLogic(J9JITConfig * jitConfig, TR::CompilationInfo * c !TR::Options::getCmdLineOptions()->getOption(TR_DisableSelectiveNoOptServer)) { TR::Options::getCmdLineOptions()->setOption(TR_DisableSelectiveNoOptServer); // Turn this feature off + TR::Options::getAOTCmdLineOptions()->setOption(TR_DisableSelectiveNoOptServer); // Turn this feature off if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance)) TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%u selectiveNoOptServer feature turned off", crtElapsedTime); } diff --git a/runtime/compiler/control/J9Options.cpp b/runtime/compiler/control/J9Options.cpp index 8035f845be2..2a07b819c35 100644 --- a/runtime/compiler/control/J9Options.cpp +++ b/runtime/compiler/control/J9Options.cpp @@ -1941,6 +1941,10 @@ J9::Options::fePreProcess(void * base) } } +#if defined(TR_HOST_X86) && defined(TR_TARGET_64BIT) + self()->setOption(TR_EnableSymbolValidationManager); +#endif + return true; } diff --git a/runtime/compiler/control/rossa.cpp b/runtime/compiler/control/rossa.cpp index 7f93b967ca3..7fb3ee85281 100644 --- a/runtime/compiler/control/rossa.cpp +++ b/runtime/compiler/control/rossa.cpp @@ -195,6 +195,7 @@ char *compilationErrorNames[]={ "compilationFSDHasInvokeHandle", //47 "compilationVirtualAddressExhaustion", //48 "compilationEnforceProfiling", //49 + "compilationSymbolValidationManagerFailure", //50 "compilationMaxError" }; diff --git a/runtime/compiler/control/rossa.h b/runtime/compiler/control/rossa.h index 186048bab78..4824c336161 100644 --- a/runtime/compiler/control/rossa.h +++ b/runtime/compiler/control/rossa.h @@ -73,6 +73,7 @@ typedef enum { compilationFSDHasInvokeHandle = 47, compilationVirtualAddressExhaustion = 48, compilationEnforceProfiling = 49, + compilationSymbolValidationManagerFailure = 50, /* please insert new codes before compilationMaxError which is used in jar2jxe to test the error codes range */ /* If new codes are added then add the corresponding names in compilationErrorNames table in rossa.cpp */ compilationMaxError /* must be the last one */ diff --git a/runtime/compiler/env/PersistentCHTable.cpp b/runtime/compiler/env/PersistentCHTable.cpp index 2e8ef6d134d..7eed188572e 100644 --- a/runtime/compiler/env/PersistentCHTable.cpp +++ b/runtime/compiler/env/PersistentCHTable.cpp @@ -230,7 +230,7 @@ FindSingleJittedImplementer::visitSubclass(TR_PersistentClassInfo *cl) } // check to see if there are any duplicates - if (!method->isInterpreted()) + if (!method->isInterpretedForHeuristics()) { if (_implementer) { @@ -309,17 +309,29 @@ TR_PersistentCHTable::findClassInfo(TR_OpaqueClassBlock * classId) * The class table lock is used to synchronize use of this method */ TR_PersistentClassInfo * -TR_PersistentCHTable::findClassInfoAfterLocking( - TR_OpaqueClassBlock *classId, +TR_PersistentCHTable::findClassInfoAfterLocking(TR_OpaqueClassBlock *classId, TR::Compilation *comp, - bool returnClassInfoForAOT) + bool returnClassInfoForAOT, + bool validate) { - if (comp->fej9()->isAOT_DEPRECATED_DO_NOT_USE() && !returnClassInfoForAOT) // for AOT do not use the class hierarchy + // for AOT do not use the class hierarchy + if (comp->compileRelocatableCode() && !returnClassInfoForAOT) + { return NULL; + } if (comp->getOption(TR_DisableCHOpts)) return NULL; - return findClassInfoAfterLocking(classId, comp->fe(), returnClassInfoForAOT); + + TR_PersistentClassInfo *classInfo = findClassInfoAfterLocking(classId, comp->fe(), returnClassInfoForAOT); + if (classInfo && + comp->compileRelocatableCode() && + comp->getOption(TR_UseSymbolValidationManager) && + validate) + { + comp->getSymbolValidationManager()->addClassInfoIsInitializedRecord(classId, classInfo->isInitialized()); + } + return classInfo; } /** @@ -387,22 +399,51 @@ TR_PersistentCHTable::isOverriddenInThisHierarchy( } TR_ResolvedMethod * TR_PersistentCHTable::findSingleImplementer( - TR_OpaqueClassBlock * thisClass, int32_t cpIndexOrVftSlot, TR_ResolvedMethod * callerMethod, TR::Compilation * comp, bool locked, TR_YesNoMaybe useGetResolvedInterfaceMethod) + TR_OpaqueClassBlock * thisClass, + int32_t cpIndexOrVftSlot, + TR_ResolvedMethod * callerMethod, + TR::Compilation * comp, + bool locked, + TR_YesNoMaybe useGetResolvedInterfaceMethod, + bool validate) { if (comp->getOption(TR_DisableCHOpts)) return 0; - TR_PersistentClassInfo * classInfo = comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(thisClass, comp, true); + TR_PersistentClassInfo * classInfo = comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(thisClass, comp, true, validate); if (!classInfo) { return 0; } TR_ResolvedMethod *implArray[2]; // collect maximum 2 implemeters if you can + comp->enterHeuristicRegion(); int32_t implCount = TR_ClassQueries::collectImplementorsCapped(classInfo, implArray, 2, cpIndexOrVftSlot, callerMethod, comp, locked, useGetResolvedInterfaceMethod); - return (implCount == 1 ? implArray[0] : 0); + comp->exitHeuristicRegion(); + + TR_ResolvedMethod *implementer = NULL; + if (implCount == 1) + implementer =implArray[0]; + + if (implementer && comp->getOption(TR_UseSymbolValidationManager) && validate) + { + TR::SymbolValidationManager *svm = comp->getSymbolValidationManager(); + + bool validated = svm->addMethodFromSingleImplementerRecord(implementer->getPersistentIdentifier(), + thisClass, + cpIndexOrVftSlot, + callerMethod->getPersistentIdentifier(), + useGetResolvedInterfaceMethod); + if (validated) + validated = svm->addClassFromMethodRecord(implementer->classOfMethod(), implementer->getPersistentIdentifier()); + + if (!validated) + implementer = NULL; + } + + return implementer; } TR_ResolvedMethod * @@ -411,7 +452,8 @@ TR_PersistentCHTable::findSingleInterfaceImplementer( int32_t cpIndex, TR_ResolvedMethod *callerMethod, TR::Compilation *comp, - bool locked) + bool locked, + bool validate) { if (comp->getOption(TR_DisableCHOpts)) return 0; @@ -421,15 +463,37 @@ TR_PersistentCHTable::findSingleInterfaceImplementer( return 0; } - TR_PersistentClassInfo * classInfo = findClassInfoAfterLocking(thisClass, comp, true); + TR_PersistentClassInfo * classInfo = findClassInfoAfterLocking(thisClass, comp, true, validate); if (!classInfo) { return 0; } TR_ResolvedMethod *implArray[2]; // collect maximum 2 implemeters if you can + comp->enterHeuristicRegion(); int32_t implCount = TR_ClassQueries::collectImplementorsCapped(classInfo, implArray, 2, cpIndex, callerMethod, comp, locked); - return (implCount == 1 ? implArray[0] : 0); + comp->exitHeuristicRegion(); + + TR_ResolvedMethod *implementer = NULL; + if (implCount == 1) + implementer = implArray[0]; + + if (implementer && comp->getOption(TR_UseSymbolValidationManager) && validate) + { + TR::SymbolValidationManager *svm = comp->getSymbolValidationManager(); + bool validated = svm->addMethodFromSingleInterfaceImplementerRecord(implementer->getPersistentIdentifier(), + thisClass, + cpIndex, + callerMethod->getPersistentIdentifier()); + + if (validated) + validated = svm->addClassFromMethodRecord(implementer->classOfMethod(), implementer->getPersistentIdentifier()); + + if (!validated) + implementer = NULL; + } + + return implementer; } bool @@ -496,32 +560,63 @@ TR_PersistentCHTable::isKnownToHaveMoreThanTwoInterfaceImplementers( TR_ResolvedMethod * TR_PersistentCHTable::findSingleAbstractImplementer( - TR_OpaqueClassBlock * thisClass, int32_t vftSlot, TR_ResolvedMethod * callerMethod, TR::Compilation * comp, bool locked) + TR_OpaqueClassBlock * thisClass, + int32_t vftSlot, + TR_ResolvedMethod * callerMethod, + TR::Compilation * comp, + bool locked, + bool validate) { if (comp->getOption(TR_DisableCHOpts)) return 0; - TR_PersistentClassInfo * classInfo = findClassInfoAfterLocking(thisClass, comp); + bool allowForAOT = comp->getOption(TR_UseSymbolValidationManager); + TR_PersistentClassInfo * classInfo = findClassInfoAfterLocking(thisClass, comp, allowForAOT, validate); if (!classInfo) return 0; if (TR::Compiler->cls.isInterfaceClass(comp, thisClass)) return 0; TR_ResolvedMethod *implArray[2]; // collect maximum 2 implemeters if you can + comp->enterHeuristicRegion(); int32_t implCount = TR_ClassQueries::collectImplementorsCapped(classInfo, implArray, 2, vftSlot, callerMethod, comp, locked); - return (implCount == 1 ? implArray[0] : 0); + comp->exitHeuristicRegion(); + + TR_ResolvedMethod *implementer = NULL; + if(implCount == 1) + implementer = implArray[0]; + + if (implementer && comp->getOption(TR_UseSymbolValidationManager) && validate) + { + TR::SymbolValidationManager *svm = comp->getSymbolValidationManager(); + bool validated = svm->addMethodFromSingleAbstractImplementerRecord(implementer->getPersistentIdentifier(), + thisClass, + vftSlot, + callerMethod->getPersistentIdentifier()); + + if (validated) + validated = svm->addClassFromMethodRecord(implementer->classOfMethod(), implementer->getPersistentIdentifier()); + + if (!validated) + implementer = NULL; + } + + return implementer; } TR_OpaqueClassBlock * TR_PersistentCHTable::findSingleConcreteSubClass( TR_OpaqueClassBlock *opaqueClass, - TR::Compilation *comp) + TR::Compilation *comp, + bool validate) { TR_OpaqueClassBlock *concreteSubClass = NULL; if (comp->getOption(TR_DisableCHOpts)) return 0; - TR_PersistentClassInfo *classInfo = comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(opaqueClass, comp); + bool allowForAOT = comp->getOption(TR_UseSymbolValidationManager); + + TR_PersistentClassInfo *classInfo = comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(opaqueClass, comp, allowForAOT, validate); if (classInfo) { TR_ScratchList subClasses(comp->trMemory()); @@ -539,6 +634,12 @@ TR_PersistentCHTable::findSingleConcreteSubClass( } } + if (validate && comp->getOption(TR_UseSymbolValidationManager)) + { + if (!comp->getSymbolValidationManager()->addConcreteSubClassFromClassRecord(concreteSubClass, opaqueClass)) + concreteSubClass = NULL; + } + return concreteSubClass; } diff --git a/runtime/compiler/env/PersistentCHTable.hpp b/runtime/compiler/env/PersistentCHTable.hpp index 348a95641a8..a464354b480 100644 --- a/runtime/compiler/env/PersistentCHTable.hpp +++ b/runtime/compiler/env/PersistentCHTable.hpp @@ -50,7 +50,7 @@ class TR_PersistentCHTable TR_PersistentClassInfo * findClassInfo(TR_OpaqueClassBlock * classId); - TR_PersistentClassInfo * findClassInfoAfterLocking(TR_OpaqueClassBlock * classId, TR::Compilation *, bool returnClassInfoForAOT = false); + TR_PersistentClassInfo * findClassInfoAfterLocking(TR_OpaqueClassBlock * classId, TR::Compilation *, bool returnClassInfoForAOT = false, bool validate = true); TR_PersistentClassInfo * findClassInfoAfterLocking(TR_OpaqueClassBlock * classId, TR_FrontEnd *, bool returnClassInfoForAOT = false); void dumpMethodCounts(TR_FrontEnd *fe, TR_Memory &trMemory); // A routine to dump initial method compilation counts @@ -58,15 +58,15 @@ class TR_PersistentCHTable void commitSideEffectGuards(TR::Compilation *c); bool isOverriddenInThisHierarchy(TR_ResolvedMethod *, TR_OpaqueClassBlock *, int32_t, TR::Compilation *comp, bool locked = false); - TR_ResolvedMethod * findSingleInterfaceImplementer(TR_OpaqueClassBlock *, int32_t, TR_ResolvedMethod *, TR::Compilation *, bool locked = false); - TR_ResolvedMethod * findSingleAbstractImplementer(TR_OpaqueClassBlock *, int32_t, TR_ResolvedMethod *, TR::Compilation *, bool locked = false); + TR_ResolvedMethod * findSingleInterfaceImplementer(TR_OpaqueClassBlock *, int32_t, TR_ResolvedMethod *, TR::Compilation *, bool locked = false, bool validate = true); + TR_ResolvedMethod * findSingleAbstractImplementer(TR_OpaqueClassBlock *, int32_t, TR_ResolvedMethod *, TR::Compilation *, bool locked = false, bool validate = true); // profiler bool isKnownToHaveMoreThanTwoInterfaceImplementers(TR_OpaqueClassBlock *, int32_t, TR_ResolvedMethod *, TR::Compilation *, bool locked = false); // optimizer - TR_OpaqueClassBlock *findSingleConcreteSubClass(TR_OpaqueClassBlock *, TR::Compilation *); - TR_ResolvedMethod * findSingleImplementer(TR_OpaqueClassBlock * thisClass, int32_t cpIndexOrVftSlot, TR_ResolvedMethod * callerMethod, TR::Compilation * comp, bool locked, TR_YesNoMaybe useGetResolvedInterfaceMethod); + TR_OpaqueClassBlock *findSingleConcreteSubClass(TR_OpaqueClassBlock *, TR::Compilation *, bool validate = true); + TR_ResolvedMethod * findSingleImplementer(TR_OpaqueClassBlock * thisClass, int32_t cpIndexOrVftSlot, TR_ResolvedMethod * callerMethod, TR::Compilation * comp, bool locked, TR_YesNoMaybe useGetResolvedInterfaceMethod, bool validate = true); bool hasThreeOrMoreCompiledImplementors(TR_OpaqueClassBlock *, int32_t, TR_ResolvedMethod *, TR::Compilation *, TR_Hotness hotness = warm, bool locked = false); int32_t findnInterfaceImplementers(TR_OpaqueClassBlock *, int32_t, TR_ResolvedMethod *implArray[], int32_t, TR_ResolvedMethod *, TR::Compilation *, bool locked = false); diff --git a/runtime/compiler/env/VMJ9.cpp b/runtime/compiler/env/VMJ9.cpp index d87a441095e..1a29c90d3f3 100644 --- a/runtime/compiler/env/VMJ9.cpp +++ b/runtime/compiler/env/VMJ9.cpp @@ -66,6 +66,7 @@ #include "runtime/CodeCacheExceptions.hpp" #include "exceptions/JITShutDown.hpp" #include "exceptions/DataCacheError.hpp" +#include "exceptions/AOTFailure.hpp" #include "env/exports.h" #include "env/CompilerEnv.hpp" #include "env/CHTable.hpp" @@ -193,7 +194,7 @@ TR_J9VMBase::getCompThreadIDForVMThread(void *vmThread) bool -TR_J9VMBase::stackWalkerMaySkipFrames(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass) +TR_J9VM::stackWalkerMaySkipFrames(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass) { if(!method) return false; @@ -212,7 +213,7 @@ TR_J9VMBase::stackWalkerMaySkipFrames(TR_OpaqueMethodBlock *method, TR_OpaqueCla } if ( ( vmThread()->javaVM->jlrAccessibleObject != NULL) && - isInstanceOf( methodClass, (TR_OpaqueClassBlock*) J9VM_J9CLASS_FROM_JCLASS(vmThread(), vmThread()->javaVM->jlrAccessibleObject),false) ) + TR_J9VM::isInstanceOf( methodClass, (TR_OpaqueClassBlock*) J9VM_J9CLASS_FROM_JCLASS(vmThread(), vmThread()->javaVM->jlrAccessibleObject),false) ) { return true; } @@ -220,13 +221,13 @@ TR_J9VMBase::stackWalkerMaySkipFrames(TR_OpaqueMethodBlock *method, TR_OpaqueCla #if defined(J9VM_OPT_SIDECAR) if ( ( vmThread()->javaVM->srMethodAccessor != NULL) && - isInstanceOf(methodClass, (TR_OpaqueClassBlock*) J9VM_J9CLASS_FROM_JCLASS(vmThread(), vmThread()->javaVM->srMethodAccessor), false) ) + TR_J9VM::isInstanceOf(methodClass, (TR_OpaqueClassBlock*) J9VM_J9CLASS_FROM_JCLASS(vmThread(), vmThread()->javaVM->srMethodAccessor), false) ) { return true; } if ( ( vmThread()->javaVM->srConstructorAccessor != NULL) && - isInstanceOf(methodClass, (TR_OpaqueClassBlock*) J9VM_J9CLASS_FROM_JCLASS(vmThread(), vmThread()->javaVM->srConstructorAccessor), false) ) + TR_J9VM::isInstanceOf(methodClass, (TR_OpaqueClassBlock*) J9VM_J9CLASS_FROM_JCLASS(vmThread(), vmThread()->javaVM->srConstructorAccessor), false) ) { return true; } @@ -6532,13 +6533,13 @@ TR_J9VMBase::getResolvedMethods(TR_Memory * trMemory, TR_OpaqueClassBlock * clas } } - -TR_ResolvedMethod * -TR_J9VMBase::getResolvedMethodForNameAndSignature(TR_Memory * trMemory, TR_OpaqueClassBlock * classPointer, - const char* methodName, const char *signature) +/* + * Should be called with VMAccess + */ +TR_OpaqueMethodBlock * +TR_J9VMBase::getMatchingMethodFromNameAndSignature(TR_OpaqueClassBlock * classPointer, + const char* methodName, const char *signature, bool validate) { - TR::VMAccessCriticalSection vmCS(this); // Prevent HCR - TR_ResolvedMethod *rm = NULL; size_t nameLength = strlen(methodName); size_t sigLength = strlen(signature); @@ -6548,6 +6549,8 @@ TR_J9VMBase::getResolvedMethodForNameAndSignature(TR_Memory * trMemory, TR_Opaqu J9ROMMethod *romMethod = J9ROMCLASS_ROMMETHODS(romClass); + TR_OpaqueMethodBlock *method = NULL; + // Iterate over all romMethods until the desired one is found for (uint32_t i = 0; i < numMethods; i++) { @@ -6558,12 +6561,34 @@ TR_J9VMBase::getResolvedMethodForNameAndSignature(TR_Memory * trMemory, TR_Opaqu memcmp(utf8Data(mName), methodName, nameLength) == 0 && memcmp(utf8Data(mSig), signature, sigLength) == 0) { - rm = createResolvedMethod(trMemory, (TR_OpaqueMethodBlock *)(j9Methods + i), 0); + method = (TR_OpaqueMethodBlock *)(j9Methods + i); + if (validate) + { + TR::Compilation *comp = TR::comp(); + if (comp && comp->getOption(TR_UseSymbolValidationManager)) + { + comp->getSymbolValidationManager()->addMethodFromClassRecord(method, classPointer, i); + } + } break; } romMethod = nextROMMethod(romMethod); } + return method; + } + +TR_ResolvedMethod * +TR_J9VMBase::getResolvedMethodForNameAndSignature(TR_Memory * trMemory, TR_OpaqueClassBlock * classPointer, + const char* methodName, const char *signature) + { + TR::VMAccessCriticalSection vmCS(this); // Prevent HCR + TR_ResolvedMethod *rm = NULL; + + TR_OpaqueMethodBlock *method = getMatchingMethodFromNameAndSignature(classPointer, methodName, signature); + if (method) + rm = createResolvedMethod(trMemory, method, 0); + return rm; } @@ -6790,13 +6815,12 @@ TR_J9VM::getClassDepthAndFlagsValue(TR_OpaqueClassBlock * classPointer) #define LOOKUP_OPTION_NO_THROW 8192 TR_OpaqueMethodBlock * -TR_J9VM::getMethodFromName(char *className, char *methodName, char *signature, TR_OpaqueMethodBlock *callingMethod) +TR_J9VM::getMethodFromName(char *className, char *methodName, char *signature, J9ConstantPool *constantPool) { TR::VMAccessCriticalSection getMethodFromName(this); J9Class *methodClass = 0; - if (callingMethod) + if (constantPool) { - J9ConstantPool * constantPool = (J9ConstantPool *) (J9_CP_FROM_METHOD((J9Method*)callingMethod)); methodClass = jitGetClassFromUTF8(vmThread(), constantPool, className, strlen(className)); } if (!methodClass) // try the system class loader @@ -6806,11 +6830,27 @@ TR_J9VM::getMethodFromName(char *className, char *methodName, char *signature, T className, strlen(className)); } TR_OpaqueMethodBlock * result = NULL; + /* + * Call the TR_J9VM version of getMethodFromClass since at this point, + * the methodClass may have never been seen before; if we call the + * TR_J9SharedCacheVM version, the validation manager could assert. + */ if (methodClass) - result = (TR_OpaqueMethodBlock *)getMethodFromClass((TR_OpaqueClassBlock *)methodClass, methodName, signature); + result = (TR_OpaqueMethodBlock *)TR_J9VM::getMethodFromClass((TR_OpaqueClassBlock *)methodClass, methodName, signature); return result; } +TR_OpaqueMethodBlock * +TR_J9VM::getMethodFromName(char *className, char *methodName, char *signature, TR_OpaqueMethodBlock *callingMethod) + { + J9ConstantPool *cp = NULL; + + if (callingMethod) + cp = (J9ConstantPool *) (J9_CP_FROM_METHOD((J9Method*)callingMethod)); + + return getMethodFromName(className, methodName, signature, cp); + } + /** \brief * Look up a method from a given class by name * @@ -7198,8 +7238,14 @@ TR_J9VM::getClassFromSignature(const char * sig, int32_t sigLength, TR_ResolvedM TR_OpaqueClassBlock * TR_J9VM::getClassFromSignature(const char * sig, int32_t sigLength, TR_OpaqueMethodBlock * method, bool isVettedForAOT) { - TR::VMAccessCriticalSection getClassFromSignature(this); J9ConstantPool * constantPool = (J9ConstantPool *) (J9_CP_FROM_METHOD((J9Method*)method)); + return getClassFromSignature(sig, sigLength, constantPool); + } + +TR_OpaqueClassBlock * +TR_J9VM::getClassFromSignature(const char * sig, int32_t sigLength, J9ConstantPool * constantPool) + { + TR::VMAccessCriticalSection getClassFromSignature(this); J9Class * j9class = NULL; TR_OpaqueClassBlock * returnValue = NULL; @@ -7663,8 +7709,9 @@ TR_J9VM::inlineNativeCall(TR::Compilation * comp, TR::TreeTop * callNodeTreeTop, // 2 1 0 { //we need to bail out since we create a class pointer const with cpIndex of -1 - if (isAOT_DEPRECATED_DO_NOT_USE() || ((!(vmThread()->javaVM->extendedRuntimeFlags & J9_EXTENDED_RUNTIME_ALLOW_GET_CALLER_CLASS)) && - methodID == TR::sun_reflect_Reflection_getCallerClass)) + if ((isAOT_DEPRECATED_DO_NOT_USE() && !comp->getOption(TR_UseSymbolValidationManager)) || + ((!(vmThread()->javaVM->extendedRuntimeFlags & J9_EXTENDED_RUNTIME_ALLOW_GET_CALLER_CLASS)) && + methodID == TR::sun_reflect_Reflection_getCallerClass)) { return 0; } @@ -7708,34 +7755,14 @@ TR_J9VM::inlineNativeCall(TR::Compilation * comp, TR::TreeTop * callNodeTreeTop, callerClass = (J9Class*) callerMethodSymbol->getResolvedMethod()->classOfMethod(); } - { - TR::VMAccessCriticalSection jlrMethodInvoke(this); - - if (vmThread()->javaVM->jlrMethodInvoke == NULL) - return 0; - - skipFrame = false; - skipFrame = (vmThread()->javaVM->jlrMethodInvoke == callerMethod); - if (!skipFrame) - skipFrame = (vmThread()->javaVM->jlrAccessibleObject != NULL) && - isInstanceOf((TR_OpaqueClassBlock*) callerClass, - (TR_OpaqueClassBlock*) J9VM_J9CLASS_FROM_JCLASS(vmThread(), vmThread()->javaVM->jlrAccessibleObject), - false); -#if defined(J9VM_OPT_SIDECAR) - if (!skipFrame) - skipFrame = (vmThread()->javaVM->srMethodAccessor != NULL) && - isInstanceOf((TR_OpaqueClassBlock*) callerClass, - (TR_OpaqueClassBlock*) J9VM_J9CLASS_FROM_JCLASS(vmThread(), vmThread()->javaVM->srMethodAccessor), - false); - if (!skipFrame) - skipFrame = (vmThread()->javaVM->srConstructorAccessor != NULL) && - isInstanceOf((TR_OpaqueClassBlock*) callerClass, - (TR_OpaqueClassBlock*) J9VM_J9CLASS_FROM_JCLASS(vmThread(), vmThread()->javaVM->srConstructorAccessor), - false); -#endif // J9VM_OPT_SIDECAR + { + TR::VMAccessCriticalSection jlrMethodInvoke(this); - } + if (vmThread()->javaVM->jlrMethodInvoke == NULL) + return 0; + } + skipFrame = stackWalkerMaySkipFrames((TR_OpaqueMethodBlock *)callerMethod, (TR_OpaqueClassBlock *)callerClass); if (!skipFrame && inlineDepth == stackDepth) break; @@ -8517,9 +8544,45 @@ TR_J9SharedCacheVM::isClassVisible(TR_OpaqueClassBlock * sourceClass, TR_OpaqueC TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - return ((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) sourceClass) && - ((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) destClass) && - TR_J9VMBase::isClassVisible(sourceClass, destClass); + bool validated = false; + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(sourceClass)) && + comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(destClass))) + { + validated = true; + } + else + { + TR_ASSERT(false, "Classes 0x%p and 0x%p should already be validated\n", sourceClass, destClass); + comp->failCompilation("Failed to validate in isClassVisible"); + } + } + else + { + validated = ((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) sourceClass) && + ((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) destClass); + } + + return (validated ? TR_J9VMBase::isClassVisible(sourceClass, destClass) : false); + } + +bool +TR_J9SharedCacheVM::stackWalkerMaySkipFrames(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass) + { + bool skipFrames = TR_J9VM::stackWalkerMaySkipFrames(method, methodClass); + TR::Compilation *comp = TR::comp(); + if (comp && comp->getOption(TR_UseSymbolValidationManager)) + { + if (!comp->getSymbolValidationManager()->addStackWalkerMaySkipFramesRecord(method, methodClass, skipFrames)) + { + TR_ASSERT(false, "Failed to validate addStackWalkerMaySkipFramesRecord\n"); + comp->failCompilation("Failed to validate in stackWalkerMaySkipFrames"); + } + } + + return skipFrames; } bool @@ -8582,7 +8645,26 @@ TR_J9SharedCacheVM::getInstanceFieldOffset(TR_OpaqueClassBlock * classPointer, c TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method*) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class*)classPointer)) + bool validated = false; + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(classPointer))) + { + validated = true; + } + else + { + TR_ASSERT(false, "Class 0x%p should already be validated\n", classPointer); + comp->failCompilation("Failed to validate in getInstanceFieldOffset"); + } + } + else + { + validated = ((TR_ResolvedRelocatableJ9Method*) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class*)classPointer); + } + + if (validated) return this->TR_J9VM::getInstanceFieldOffset (classPointer, fieldName, fieldLen, sig, sigLen, options); return ~0; @@ -8595,7 +8677,19 @@ TR_J9SharedCacheVM::getClassOfMethod(TR_OpaqueMethodBlock *method) TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) + + bool validated = false; + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + validated = comp->getSymbolValidationManager()->addClassFromMethodRecord(classPointer, method); + } + else + { + validated = ((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer); + } + + if (validated) return classPointer; return NULL; @@ -8606,8 +8700,21 @@ TR_J9SharedCacheVM::getSuperClass(TR_OpaqueClassBlock * classPointer) { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) - return TR_J9VM::getSuperClass(classPointer); + + bool validated = false; + TR_OpaqueClassBlock *superClass = TR_J9VM::getSuperClass(classPointer); + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + validated = comp->getSymbolValidationManager()->addSuperClassFromClassRecord(superClass, classPointer); + } + else + { + validated = ((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer); + } + + if (validated) + return superClass; return NULL; } @@ -8617,8 +8724,44 @@ TR_J9SharedCacheVM::getResolvedMethods(TR_Memory *trMemory, TR_OpaqueClassBlock { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) + + bool validated = false; + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(classPointer))) + { + validated = true; + } + else + { + TR_ASSERT(false, "Class 0x%p should already be validated\n", classPointer); + comp->failCompilation("Failed to validate in getResolvedMethods"); + } + } + else + { + validated = ((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer); + } + + if (validated) + { + if (comp->getOption(TR_UseSymbolValidationManager)) + { + TR::VMAccessCriticalSection getResolvedMethods(this); // Prevent HCR + J9Method * resolvedMethods = (J9Method *) getMethods(classPointer); + uint32_t indexIntoArray; + uint32_t numMethods = getNumMethods(classPointer); + for (indexIntoArray = 0; indexIntoArray < numMethods; indexIntoArray++) + { + comp->getSymbolValidationManager()->addMethodFromClassRecord((TR_OpaqueMethodBlock *) &(resolvedMethods[indexIntoArray]), + classPointer, + indexIntoArray); + } + } + TR_J9VM::getResolvedMethods(trMemory, classPointer, resolvedMethodsInClass); + } } @@ -8628,8 +8771,28 @@ TR_J9SharedCacheVM::getResolvedMethodForNameAndSignature(TR_Memory * trMemory, T { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *)comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *)classPointer)) - return TR_J9VM::getResolvedMethodForNameAndSignature(trMemory, classPointer, methodName, signature); + + bool validated = false; + TR_ResolvedMethod *resolvedMethod = TR_J9VM::getResolvedMethodForNameAndSignature(trMemory, classPointer, methodName, signature); + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + TR_OpaqueMethodBlock *method = (TR_OpaqueMethodBlock *)((TR_ResolvedJ9Method *)resolvedMethod)->ramMethod(); + /* + * TR_J9VM::getResolvedMethodForNameAndSignature will call getMatchingMethodFromNameAndSignature + * which adds a MethodFromClassRecord. Not sure if adding a MethodByNameRecord here will do the + * right validation, since the way TR_J9VM::getResolvedMethodForNameAndSignature gets the class + * by name and signature is different than TR_J9VM::getMethodFromName... + */ + validated = comp->getSymbolValidationManager()->addClassFromMethodRecord(getClassFromMethodBlock(method), method); + } + else + { + validated = ((TR_ResolvedRelocatableJ9Method *)comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *)classPointer); + } + + if (validated) + return resolvedMethod; else return NULL; } @@ -8641,12 +8804,29 @@ TR_J9SharedCacheVM::getMethodFromName(char *className, char *methodName, char *s TR_OpaqueMethodBlock *omb = this->TR_J9VM::getMethodFromName(className, methodName, signature, callingMethod); if (omb) { - J9Class* methodClass = (J9Class*)getClassFromMethodBlock(omb); - TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (!((TR_ResolvedRelocatableJ9Method*) comp->getCurrentMethod())->validateArbitraryClass(comp, methodClass)) - omb = NULL; + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + TR::SymbolValidationManager *svm = comp->getSymbolValidationManager(); + if (!svm->verifySymbolHasBeenValidated(static_cast(callingMethod))) + { + TR_ASSERT(false, "callingMethod %p should be valid\n", callingMethod); + comp->failCompilation("Failed to validate in getMethodFromName"); + } + bool validated = svm->addMethodByNameRecord(omb, getClassFromMethodBlock(callingMethod)) && + svm->addClassFromMethodRecord(getClassFromMethodBlock(omb), omb); + + if (!validated) + omb = NULL; + } + else + { + J9Class* methodClass = (J9Class*)getClassFromMethodBlock(omb); + if (!((TR_ResolvedRelocatableJ9Method*) comp->getCurrentMethod())->validateArbitraryClass(comp, methodClass)) + omb = NULL; + } } return omb; @@ -8672,10 +8852,22 @@ TR_J9SharedCacheVM::getMethodFromClass(TR_OpaqueClassBlock * methodClass, char * { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (!((TR_ResolvedRelocatableJ9Method*) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class*)methodClass)) - omb = NULL; - if (callingClass && !((TR_ResolvedRelocatableJ9Method*) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class*)callingClass)) - omb = NULL; + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + bool validated = callingClass && + comp->getSymbolValidationManager()->addMethodFromClassAndSignatureRecord(omb, methodClass, callingClass); + + if (!validated) + omb = NULL; + } + else + { + if (!((TR_ResolvedRelocatableJ9Method*) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class*)methodClass)) + omb = NULL; + if (callingClass && !((TR_ResolvedRelocatableJ9Method*) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class*)callingClass)) + omb = NULL; + } } return omb; @@ -8699,51 +8891,91 @@ TR_J9SharedCacheVM::supportAllocationInlining(TR::Compilation *comp, TR::Node *n TR_YesNoMaybe TR_J9SharedCacheVM::isInstanceOf(TR_OpaqueClassBlock * a, TR_OpaqueClassBlock *b, bool objectTypeIsFixed, bool castTypeIsFixed, bool optimizeForAOT) { - if (optimizeForAOT) - return TR_J9VM::isInstanceOf(a, b, objectTypeIsFixed, castTypeIsFixed, optimizeForAOT); + TR::Compilation *comp = TR::comp(); + TR_YesNoMaybe isAnInstanceOf = TR_J9VM::isInstanceOf(a, b, objectTypeIsFixed, castTypeIsFixed); + bool validated = false; + + if (comp && comp->getOption(TR_UseSymbolValidationManager)) + { + if (isAnInstanceOf != TR_maybe) + validated = comp->getSymbolValidationManager()->addClassInstanceOfClassRecord(a, b, objectTypeIsFixed, castTypeIsFixed, (isAnInstanceOf == TR_yes)); + } + else + { + validated = optimizeForAOT; + } - return TR_maybe; + if (validated) + return isAnInstanceOf; + else + return TR_maybe; } TR_OpaqueClassBlock * TR_J9SharedCacheVM::getClassFromSignature(const char * sig, int32_t sigLength, TR_ResolvedMethod * method, bool isVettedForAOT) { - if (isVettedForAOT) - { - TR_OpaqueClassBlock* j9class = TR_J9VM::getClassFromSignature(sig, sigLength, method, true); - TR::Compilation* comp = TR::comp(); - if (j9class && ((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) j9class)) - return j9class; - } - - return NULL; + return getClassFromSignature(sig, sigLength, (TR_OpaqueMethodBlock *)method->getPersistentIdentifier(), isVettedForAOT); } TR_OpaqueClassBlock * TR_J9SharedCacheVM::getClassFromSignature(const char * sig, int32_t sigLength, TR_OpaqueMethodBlock * method, bool isVettedForAOT) { - if (isVettedForAOT) + TR_OpaqueClassBlock* j9class = TR_J9VM::getClassFromSignature(sig, sigLength, method, true); + bool validated = false; + TR::Compilation* comp = TR::comp(); + + if (j9class) { - TR_OpaqueClassBlock* j9class = TR_J9VM::getClassFromSignature(sig, sigLength, method, true); - TR::Compilation* comp = TR::comp(); - if (j9class && ((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) j9class)) - return j9class; + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (!comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(method))) + { + TR_ASSERT(false, "method %p should be valid\n", method); + comp->failCompilation("Failed to validate in getClassFromSignature"); + } + + validated = comp->getSymbolValidationManager()->addClassByNameRecord(j9class, getClassFromMethodBlock(method)); + } + else + { + if (isVettedForAOT) + { + if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) j9class)) + validated = true; + } + } } - return NULL; + if (validated) + return j9class; + else + return NULL; } TR_OpaqueClassBlock * TR_J9SharedCacheVM::getSystemClassFromClassName(const char * name, int32_t length, bool isVettedForAOT) { - if (isVettedForAOT) + TR::Compilation *comp = TR::comp(); + TR_OpaqueClassBlock *classPointer = TR_J9VM::getSystemClassFromClassName(name, length); + bool validated = false; + + if (comp && comp->getOption(TR_UseSymbolValidationManager)) + { + validated = comp->getSymbolValidationManager()->addSystemClassByNameRecord(classPointer); + } + else { - TR_OpaqueClassBlock *classPointer = TR_J9VM::getSystemClassFromClassName(name, length); - if (((TR_ResolvedRelocatableJ9Method *) TR::comp()->getCurrentMethod())->validateArbitraryClass(TR::comp(), (J9Class *) classPointer)) - return classPointer; + if (isVettedForAOT) + { + if (((TR_ResolvedRelocatableJ9Method *) TR::comp()->getCurrentMethod())->validateArbitraryClass(TR::comp(), (J9Class *) classPointer)) + validated = true; + } } - return NULL; + if (validated) + return classPointer; + else + return NULL; } TR_OpaqueClassBlock * @@ -8755,9 +8987,23 @@ TR_J9SharedCacheVM::getProfiledClassFromProfiledInfo(TR_ExtraAddressInfo *profil if (comp->getPersistentInfo()->isObsoleteClass((void *)classPointer, comp->fe())) return NULL; - if (((TR_ResolvedRelocatableJ9Method*) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class*)classPointer)) + + bool validated = false; + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + validated = comp->getSymbolValidationManager()->addProfiledClassRecord(classPointer); + } + else + { + if (((TR_ResolvedRelocatableJ9Method*) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class*)classPointer)) + validated = true; + } + + if (validated) return classPointer; - return NULL; + else + return NULL; } bool @@ -8765,10 +9011,32 @@ TR_J9SharedCacheVM::isPublicClass(TR_OpaqueClassBlock * classPointer) { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) - return TR_J9VM::isPublicClass(classPointer); - return true; + bool publicClass = TR_J9VM::isPublicClass(classPointer); + bool validated = false; + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(classPointer))) + { + validated = true; + } + else + { + TR_ASSERT(false, "Class 0x%p should already be validated\n", classPointer); + comp->failCompilation("Failed to validate in isPublicClass"); + } + } + else + { + if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) + validated = true; + } + + if (validated) + return publicClass; + else + return true; } bool @@ -8776,10 +9044,32 @@ TR_J9SharedCacheVM::hasFinalizer(TR_OpaqueClassBlock * classPointer) { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) - return TR_J9VM::hasFinalizer(classPointer); - return true; + bool classHasFinalizer = TR_J9VM::hasFinalizer(classPointer); + bool validated = false; + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(classPointer))) + { + validated = true; + } + else + { + TR_ASSERT(false, "Class 0x%p should already be validated\n", classPointer); + comp->failCompilation("Failed to validate in hasFinalizer"); + } + } + else + { + if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) + validated = true; + } + + if (validated) + return classHasFinalizer; + else + return true; } uintptrj_t @@ -8787,10 +9077,32 @@ TR_J9SharedCacheVM::getClassDepthAndFlagsValue(TR_OpaqueClassBlock * classPointe { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) - return TR_J9VM::getClassDepthAndFlagsValue(classPointer); - return 0; + bool validated = false; + uintptrj_t classDepthFlags = TR_J9VM::getClassDepthAndFlagsValue(classPointer); + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(classPointer))) + { + validated = true; + } + else + { + TR_ASSERT(false, "Class 0x%p should already be validated\n", classPointer); + comp->failCompilation("Failed to validate in getClassDepthAndFlagsValue"); + } + } + else + { + if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) + validated = true; + } + + if (validated) + return classDepthFlags; + else + return 0; } bool @@ -8798,10 +9110,32 @@ TR_J9SharedCacheVM::isPrimitiveClass(TR_OpaqueClassBlock * classPointer) { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) - return TR_J9VMBase::isPrimitiveClass(classPointer); - return false; + bool validated = false; + bool isPrimClass = TR_J9VMBase::isPrimitiveClass(classPointer);; + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(classPointer))) + { + validated = true; + } + else + { + TR_ASSERT(false, "Class 0x%p should already be validated\n", classPointer); + comp->failCompilation("Failed to validate in isPrimitiveClass"); + } + } + else + { + if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) + validated = true; + } + + if (validated) + return isPrimClass; + else + return false; } TR_OpaqueClassBlock * @@ -8809,10 +9143,32 @@ TR_J9SharedCacheVM::getComponentClassFromArrayClass(TR_OpaqueClassBlock * arrayC { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) arrayClass)) - return TR_J9VM::getComponentClassFromArrayClass(arrayClass); - return NULL; + bool validated = false; + TR_OpaqueClassBlock *componentClass = TR_J9VM::getComponentClassFromArrayClass(arrayClass); + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(componentClass))) + { + validated = true; + } + else + { + TR_ASSERT(false, "Class 0x%p should already be validated\n", componentClass); + comp->failCompilation("Failed to validate in getComponentClassFromArrayClass"); + } + } + else + { + if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) arrayClass)) + validated = true; + } + + if (validated) + return componentClass; + else + return NULL; } TR_OpaqueClassBlock * @@ -8820,10 +9176,24 @@ TR_J9SharedCacheVM::getArrayClassFromComponentClass(TR_OpaqueClassBlock * compon { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) componentClass)) - return TR_J9VM::getArrayClassFromComponentClass(componentClass); - return NULL; + bool validated = false; + TR_OpaqueClassBlock *arrayClass = TR_J9VM::getArrayClassFromComponentClass(componentClass); + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + validated = comp->getSymbolValidationManager()->addArrayClassFromComponentClassRecord(arrayClass, componentClass); + } + else + { + if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) componentClass)) + validated = true; + } + + if (validated) + return arrayClass; + else + return NULL; } TR_OpaqueClassBlock * @@ -8831,10 +9201,32 @@ TR_J9SharedCacheVM::getLeafComponentClassFromArrayClass(TR_OpaqueClassBlock * ar { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) arrayClass)) - return TR_J9VM::getLeafComponentClassFromArrayClass(arrayClass); - return NULL; + bool validated = false; + TR_OpaqueClassBlock *leafComponent = TR_J9VM::getLeafComponentClassFromArrayClass(arrayClass); + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(leafComponent))) + { + validated = true; + } + else + { + TR_ASSERT(false, "Class 0x%p should already be validated\n", leafComponent); + comp->failCompilation("Failed to validate in getLeafComponentClassFromArrayClass"); + } + } + else + { + if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) arrayClass)) + validated = true; + } + + if (validated) + return leafComponent; + else + return NULL; } TR_OpaqueClassBlock * @@ -8842,15 +9234,40 @@ TR_J9SharedCacheVM::getBaseComponentClass(TR_OpaqueClassBlock * classPointer, in { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) - return TR_J9VM::getBaseComponentClass(classPointer, numDims); - return classPointer; // not sure about this return value, but it's what we used to return before we got "smart" + bool validated = false; + TR_OpaqueClassBlock *baseComponent = TR_J9VM::getBaseComponentClass(classPointer, numDims); + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(baseComponent))) + { + validated = true; + } + else + { + TR_ASSERT(false, "Class 0x%p should already be validated\n", baseComponent); + comp->failCompilation("Failed to validate in getBaseComponentClass"); + } + } + else + { + if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) + validated = true; + } + + if (validated) + return baseComponent; + else + return classPointer; // not sure about this return value, but it's what we used to return before we got "smart" } TR_OpaqueClassBlock * TR_J9SharedCacheVM::getClassFromNewArrayType(int32_t arrayType) { + TR::Compilation *comp = TR::comp(); + if (comp && comp->getOption(TR_UseSymbolValidationManager)) + return TR_J9VM::getClassFromNewArrayType(arrayType); return NULL; } @@ -8860,10 +9277,32 @@ TR_J9SharedCacheVM::isPrimitiveArray(TR_OpaqueClassBlock *classPointer) { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) - return TR_J9VMBase::isPrimitiveArray(classPointer); - return false; + bool validated = false; + bool isPrimArray = TR_J9VMBase::isPrimitiveArray(classPointer); + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(classPointer))) + { + validated = true; + } + else + { + TR_ASSERT(false, "Class 0x%p should already be validated\n", classPointer); + comp->failCompilation("Failed to validate in isPrimitiveArray"); + } + } + else + { + if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) + validated = true; + } + + if (validated) + return isPrimArray; + else + return false; } bool @@ -8871,10 +9310,45 @@ TR_J9SharedCacheVM::isReferenceArray(TR_OpaqueClassBlock *classPointer) { TR::Compilation* comp = _compInfo->getCompInfoForCompOnAppThread() ? _compInfo->getCompInfoForCompOnAppThread()->getCompilation() : _compInfoPT->getCompilation(); TR_ASSERT(comp, "Should be called only within a compilation"); - if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) - return TR_J9VMBase::isReferenceArray(classPointer); - return false; + bool validated = false; + bool isRefArray = TR_J9VMBase::isReferenceArray(classPointer); + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(classPointer))) + { + validated = true; + } + else + { + TR_ASSERT(false, "Class 0x%p should already be validated\n", classPointer); + comp->failCompilation("Failed to validate in isReferenceArray"); + } + } + else + { + if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) classPointer)) + validated = true; + } + + if (validated) + return isRefArray; + else + 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 * diff --git a/runtime/compiler/env/VMJ9.h b/runtime/compiler/env/VMJ9.h index 2e5da57c68d..958f1f42872 100644 --- a/runtime/compiler/env/VMJ9.h +++ b/runtime/compiler/env/VMJ9.h @@ -225,6 +225,7 @@ class TR_J9VMBase : public TR_FrontEnd virtual bool isAOT_DEPRECATED_DO_NOT_USE() { return false; } virtual bool supportsMethodEntryPadding() { return true; } + virtual bool canUseSymbolValidationManager() { return false; } #if defined(TR_TARGET_S390) virtual void initializeS390zLinuxProcessorFeatures(); @@ -311,7 +312,7 @@ class TR_J9VMBase : public TR_FrontEnd // Not implemented virtual TR_ResolvedMethod * getObjectNewInstanceImplMethod(TR_Memory *) { return 0; } - bool stackWalkerMaySkipFrames(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass); + virtual bool stackWalkerMaySkipFrames(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass) = 0; virtual bool supportsEmbeddedHeapBounds() { return true; } virtual bool supportsFastNanoTime(); @@ -323,6 +324,8 @@ class TR_J9VMBase : public TR_FrontEnd virtual TR_OpaqueMethodBlock * getMethodFromClass(TR_OpaqueClassBlock *, char *, char *, TR_OpaqueClassBlock * = NULL); + TR_OpaqueMethodBlock * getMatchingMethodFromNameAndSignature(TR_OpaqueClassBlock * classPointer, const char* methodName, const char *signature, bool validate = true); + virtual void getResolvedMethods(TR_Memory *, TR_OpaqueClassBlock *, List *); /** * @brief Create a TR_ResolvedMethod given a class, method name and signature @@ -340,6 +343,8 @@ class TR_J9VMBase : public TR_FrontEnd virtual TR_OpaqueMethodBlock *getResolvedVirtualMethod(TR_OpaqueClassBlock * classObject, int32_t cpIndex, bool ignoreReResolve = true); virtual TR_OpaqueMethodBlock *getResolvedInterfaceMethod(TR_OpaqueMethodBlock *ownerMethod, TR_OpaqueClassBlock * classObject, int32_t cpIndex); + TR_OpaqueMethodBlock *getResolvedInterfaceMethod(J9ConstantPool *ownerCP, TR_OpaqueClassBlock * classObject, int32_t cpIndex); + uintptrj_t getReferenceField(uintptrj_t objectPointer, char *fieldName, char *fieldSignature) { return getReferenceFieldAt(objectPointer, getInstanceFieldOffset(getObjectClass(objectPointer), fieldName, fieldSignature)); @@ -1043,7 +1048,8 @@ class TR_J9VM : public TR_J9VMBase virtual void initializeHasFixedFrameC_CallingConvention(); virtual bool isPublicClass(TR_OpaqueClassBlock *clazz); - virtual TR_OpaqueMethodBlock * getMethodFromName(char * className, char *methodName, char *signature, TR_OpaqueMethodBlock *callingMethod=0); + TR_OpaqueMethodBlock * getMethodFromName(char * className, char *methodName, char *signature, J9ConstantPool *constantPool); + virtual TR_OpaqueMethodBlock *getMethodFromName(char * className, char *methodName, char *signature, TR_OpaqueMethodBlock *callingMethod=0); virtual uintptrj_t getClassDepthAndFlagsValue(TR_OpaqueClassBlock * classPointer); virtual TR_OpaqueClassBlock * getComponentClassFromArrayClass(TR_OpaqueClassBlock * arrayClass); @@ -1057,6 +1063,7 @@ class TR_J9VM : public TR_J9VMBase virtual TR_OpaqueClassBlock * getSystemClassFromClassName(const char * name, int32_t length, bool isVettedForAOT=false); virtual TR_YesNoMaybe isInstanceOf(TR_OpaqueClassBlock *instanceClass, TR_OpaqueClassBlock *castClass, bool instanceIsFixed, bool castIsFixed = true, bool optimizeForAOT=false); + virtual bool stackWalkerMaySkipFrames(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass); virtual TR_OpaqueClassBlock * getSuperClass(TR_OpaqueClassBlock *classPointer); virtual bool isUnloadAssumptionRequired(TR_OpaqueClassBlock *, TR_ResolvedMethod *); @@ -1087,6 +1094,8 @@ class TR_J9VM : public TR_J9VMBase virtual bool isDecimalFormatPattern( TR::Compilation *comp, TR_ResolvedMethod *method); + TR_OpaqueClassBlock * getClassFromSignature(const char * sig, int32_t sigLength, J9ConstantPool * constantPool); + private: void transformJavaLangClassIsArrayOrIsPrimitive( TR::Compilation *, TR::Node * callNode, TR::TreeTop * treeTop, int32_t andMask); void transformJavaLangClassIsArray( TR::Compilation *, TR::Node * callNode, TR::TreeTop * treeTop); @@ -1103,6 +1112,7 @@ class TR_J9SharedCacheVM : public TR_J9VM virtual bool isAOT_DEPRECATED_DO_NOT_USE() { return true; } // replacing calls to isAOT + virtual bool canUseSymbolValidationManager() { return true; } virtual bool supportsCodeCacheSnippets() { return false; } virtual bool canRelocateDirectNativeCalls() { return false; } virtual bool needClassAndMethodPointerRelocations() { return true; } @@ -1125,6 +1135,8 @@ class TR_J9SharedCacheVM : public TR_J9VM virtual bool isClassLibraryMethod(TR_OpaqueMethodBlock *method, bool vettedForAOT = false); + virtual bool stackWalkerMaySkipFrames(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass); + virtual bool isMethodEnterTracingEnabled(TR_OpaqueMethodBlock *method); virtual bool isMethodExitTracingEnabled(TR_OpaqueMethodBlock *method); virtual bool traceableMethodsCanBeInlined(); @@ -1137,6 +1149,10 @@ class TR_J9SharedCacheVM : public TR_J9VM virtual TR_ResolvedMethod *getResolvedMethodForNameAndSignature(TR_Memory * trMemory, TR_OpaqueClassBlock * classPointer, const char* methodName, const char *signature); virtual uint32_t getInstanceFieldOffset(TR_OpaqueClassBlock * classPointer, char * fieldName, uint32_t fieldLen, char * sig, uint32_t sigLen, UDATA options); + + virtual TR_OpaqueMethodBlock *getResolvedVirtualMethod(TR_OpaqueClassBlock * classObject, int32_t cpIndex, bool ignoreReResolve = true); + virtual TR_OpaqueMethodBlock *getResolvedInterfaceMethod(TR_OpaqueMethodBlock *ownerMethod, TR_OpaqueClassBlock * classObject, int32_t cpIndex); + #if defined(TR_TARGET_S390) virtual void initializeS390zLinuxProcessorFeatures(); virtual void initializeS390zOSProcessorFeatures(); @@ -1146,6 +1162,8 @@ 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 *); diff --git a/runtime/compiler/env/j9method.cpp b/runtime/compiler/env/j9method.cpp index 5ff5e56836e..c911fd5358b 100644 --- a/runtime/compiler/env/j9method.cpp +++ b/runtime/compiler/env/j9method.cpp @@ -44,6 +44,7 @@ #include "env/VMAccessCriticalSection.hpp" #include "env/VMJ9.h" #include "exceptions/DataCacheError.hpp" +#include "exceptions/AOTFailure.hpp" #include "il/DataTypes.hpp" #include "il/Node.hpp" #include "il/Node_inlines.hpp" @@ -229,6 +230,12 @@ TR_J9VMBase::createResolvedMethodWithSignature(TR_Memory * trMemory, TR_OpaqueMe if (TR::Options::sharedClassCache()) { result = new (trMemory->trHeapMemory()) TR_ResolvedRelocatableJ9Method(aMethod, this, trMemory, owningMethod); + TR::Compilation *comp = TR::comp(); + if (comp && comp->getOption(TR_UseSymbolValidationManager)) + { + if (!comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(result->containingClass()))) + return NULL; + } } else #endif @@ -1193,7 +1200,7 @@ TR_ResolvedJ9MethodBase::isCold(TR::Compilation * comp, bool isIndirectCall, TR: // For overridden virtual calls we may decide at some point to traverse all the // existing targets to see if they are all interpreted with high counts // - if (!isInterpreted() || maxBytecodeIndex() <= TRIVIAL_INLINER_MAX_SIZE) + if (!isInterpretedForHeuristics() || maxBytecodeIndex() <= TRIVIAL_INLINER_MAX_SIZE) return false; if (isIndirectCall && virtualMethodIsOverridden()) @@ -1362,7 +1369,19 @@ TR_ResolvedRelocatableJ9Method::TR_ResolvedRelocatableJ9Method(TR_OpaqueMethodBl { if (fej9->sharedCache()->rememberClass(containingClass())) { - ((TR_ResolvedRelocatableJ9Method *) owner)->validateArbitraryClass(comp, (J9Class*)containingClass()); + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (!comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(aMethod))) + { + TR_ASSERT(false, "aMethod 0x%p should already be validated\n", aMethod); + comp->failCompilation("Failed to validate in TR_ResolvedRelocatableJ9Method"); + } + comp->getSymbolValidationManager()->addClassFromMethodRecord(containingClass(), aMethod); + } + else + { + ((TR_ResolvedRelocatableJ9Method *) owner)->validateArbitraryClass(comp, (J9Class*)containingClass()); + } } else { @@ -1478,6 +1497,12 @@ TR_ResolvedRelocatableJ9Method::isInterpreted() return TR_ResolvedJ9Method::isInterpreted(); } +bool +TR_ResolvedRelocatableJ9Method::isInterpretedForHeuristics() + { + return TR_ResolvedJ9Method::isInterpreted(); + } + void * TR_ResolvedRelocatableJ9Method::startAddressForJittedMethod() { @@ -1515,29 +1540,36 @@ TR_ResolvedRelocatableJ9Method::constantPool() TR_OpaqueClassBlock * TR_ResolvedRelocatableJ9Method::getClassFromConstantPool(TR::Compilation *comp, uint32_t cpIndex, bool returnClassForAOT) { - TR_OpaqueClassBlock * resolvedClass = NULL; + TR_OpaqueClassBlock * resolvedClass = NULL; - if (returnClassForAOT) + if (returnClassForAOT || comp->getOption(TR_UseSymbolValidationManager)) + { + resolvedClass = TR_ResolvedJ9Method::getClassFromConstantPool(comp, cpIndex); + if (resolvedClass) { - resolvedClass = TR_ResolvedJ9Method::getClassFromConstantPool(comp, cpIndex); - if (resolvedClass) + bool validated = validateClassFromConstantPool(comp, (J9Class *)resolvedClass, cpIndex); + if (validated) { - bool validated = validateClassFromConstantPool(comp, (J9Class *)resolvedClass, cpIndex); - if (validated) - { - return (TR_OpaqueClassBlock*)resolvedClass; - } + return (TR_OpaqueClassBlock*)resolvedClass; } - return 0; } + return 0; + } - return resolvedClass; + return resolvedClass; } bool TR_ResolvedRelocatableJ9Method::validateClassFromConstantPool(TR::Compilation *comp, J9Class *clazz, uint32_t cpIndex, TR_ExternalRelocationTargetKind reloKind) { - return storeValidationRecordIfNecessary(comp, cp(), cpIndex, reloKind, ramMethod(), clazz); + if (comp->getOption(TR_UseSymbolValidationManager)) + { + return comp->getSymbolValidationManager()->addClassFromCPRecord(reinterpret_cast(clazz), cp(), cpIndex); + } + else + { + return storeValidationRecordIfNecessary(comp, cp(), cpIndex, reloKind, ramMethod(), clazz); + } } bool @@ -1637,6 +1669,9 @@ TR_ResolvedRelocatableJ9Method::getResolvedPossiblyPrivateVirtualMethod( ignoreRtResolve, unresolvedInCP); + if (comp->getOption(TR_UseSymbolValidationManager)) + return method; + // For now leave private invokevirtual unresolved in AOT. If we resolve it, // we may forceUnresolvedDispatch in codegen, in which case the generated // code would attempt to resolve the wrong kind of constant pool entry. @@ -1793,7 +1828,34 @@ TR_ResolvedRelocatableJ9Method::fieldAttributes(TR::Compilation * comp, int32_t if (comp->getOption(TR_DisableAOTInstanceFieldResolution)) resolveField = false; else - fieldInfoCanBeUsed = !needAOTValidation || storeValidationRecordIfNecessary(comp, constantPool, cpIndex, TR_ValidateInstanceField, ramMethod()); + { + if (needAOTValidation) + { + if (comp->getOption(TR_UseSymbolValidationManager)) + { + TR_J9VMBase *fej9 = (TR_J9VMBase *) comp->fe(); + TR::CompilationInfo *compInfo = TR::CompilationInfo::get(fej9->_jitConfig); + TR::CompilationInfoPerThreadBase *compInfoPerThreadBase = compInfo->getCompInfoForCompOnAppThread(); + TR_RelocationRuntime *reloRuntime; + if (compInfoPerThreadBase) + reloRuntime = compInfoPerThreadBase->reloRuntime(); + else + reloRuntime = compInfo->getCompInfoForThread(fej9->vmThread())->reloRuntime(); + + TR_OpaqueClassBlock *clazz = reloRuntime->getClassFromCP(fej9->vmThread(), fej9->_jitConfig->javaVM, constantPool, cpIndex, false); + + fieldInfoCanBeUsed = comp->getSymbolValidationManager()->addDefiningClassFromCPRecord(clazz, constantPool, cpIndex); + } + else + { + fieldInfoCanBeUsed = storeValidationRecordIfNecessary(comp, constantPool, cpIndex, TR_ValidateInstanceField, ramMethod()); + } + } + else + { + fieldInfoCanBeUsed = true; + } + } } if (offset == J9JIT_RESOLVE_FAIL_COMPILE) @@ -1892,7 +1954,32 @@ TR_ResolvedRelocatableJ9Method::staticAttributes(TR::Compilation * comp, bool fieldInfoCanBeUsed = false; bool aotStats = comp->getOption(TR_EnableAOTStats); - fieldInfoCanBeUsed = !needAOTValidation || storeValidationRecordIfNecessary(comp, constantPool, cpIndex, TR_ValidateStaticField, ramMethod()); + if (needAOTValidation) + { + if (comp->getOption(TR_UseSymbolValidationManager)) + { + TR_J9VMBase *fej9 = (TR_J9VMBase *) comp->fe(); + TR::CompilationInfo *compInfo = TR::CompilationInfo::get(fej9->_jitConfig); + TR::CompilationInfoPerThreadBase *compInfoPerThreadBase = compInfo->getCompInfoForCompOnAppThread(); + TR_RelocationRuntime *reloRuntime; + if (compInfoPerThreadBase) + reloRuntime = compInfoPerThreadBase->reloRuntime(); + else + reloRuntime = compInfo->getCompInfoForThread(fej9->vmThread())->reloRuntime(); + + TR_OpaqueClassBlock *clazz = reloRuntime->getClassFromCP(fej9->vmThread(), fej9->_jitConfig->javaVM, constantPool, cpIndex, true); + + fieldInfoCanBeUsed = comp->getSymbolValidationManager()->addDefiningClassFromCPRecord(clazz, constantPool, cpIndex, true); + } + else + { + fieldInfoCanBeUsed = storeValidationRecordIfNecessary(comp, constantPool, cpIndex, TR_ValidateStaticField, ramMethod()); + } + } + else + { + fieldInfoCanBeUsed = true; + } if (offset == (void *)J9JIT_RESOLVE_FAIL_COMPILE) { @@ -1955,14 +2042,24 @@ TR_ResolvedRelocatableJ9Method::staticSignatureChars(int32_t cpIndex, int32_t & TR_OpaqueClassBlock * TR_ResolvedRelocatableJ9Method::classOfStatic(int32_t cpIndex, bool returnClassForAOT) { - TR_OpaqueClassBlock * resolveClassOfStatic = NULL; + TR_OpaqueClassBlock * clazz = TR_ResolvedJ9Method::classOfStatic(cpIndex, returnClassForAOT); - if (returnClassForAOT) + TR::Compilation *comp = TR::comp(); + bool validated = false; + + if (comp && comp->getOption(TR_UseSymbolValidationManager)) + { + validated = comp->getSymbolValidationManager()->addStaticClassFromCPRecord(clazz, cp(), cpIndex); + } + else { - resolveClassOfStatic = TR_ResolvedJ9Method::classOfStatic(cpIndex, returnClassForAOT); + validated = returnClassForAOT; } - return resolveClassOfStatic; + if (validated) + return clazz; + else + return NULL; } void @@ -2065,6 +2162,9 @@ TR_ResolvedRelocatableJ9Method::getResolvedImproperInterfaceMethod( TR::Compilation * comp, I_32 cpIndex) { + if (comp->getOption(TR_UseSymbolValidationManager)) + return TR_ResolvedJ9Method::getResolvedImproperInterfaceMethod(comp, cpIndex); + // For now leave private and Object invokeinterface unresolved in AOT. If we // resolve it, we may forceUnresolvedDispatch in codegen, in which case the // generated code would attempt to resolve the wrong kind of constant pool @@ -2113,7 +2213,14 @@ TR_ResolvedRelocatableJ9Method::createResolvedMethodFromJ9Method(TR::Compilation isSystemClassLoader) { resolvedMethod = new (comp->trHeapMemory()) TR_ResolvedRelocatableJ9Method((TR_OpaqueMethodBlock *) j9method, _fe, comp->trMemory(), this, vTableSlot); - if (aotStats) + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (!comp->getSymbolValidationManager()->verifySymbolHasBeenValidated(static_cast(resolvedMethod->containingClass()))) + { + return NULL; + } + } + else if (aotStats) { aotStats->numMethodResolvedAtCompile++; if (_fe->convertClassPtrToClassOffset(J9_CLASS_FROM_METHOD(ramMethod())) == _fe->convertClassPtrToClassOffset(J9_CLASS_FROM_METHOD(j9method))) @@ -4627,7 +4734,7 @@ TR_ResolvedJ9Method::setRecognizedMethodInfo(TR::RecognizedMethod rm) TR_PersistentClassInfo *clazzInfo = NULL; if (compInfo->getPersistentInfo()->getPersistentCHTable()) { - clazzInfo = compInfo->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(clazz, fej9()); + clazzInfo = compInfo->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(clazz, fej9(), true); } if (!clazzInfo) @@ -5155,6 +5262,12 @@ TR_ResolvedJ9Method::isInterpreted() return !(TR::CompilationInfo::isCompiled(ramMethod())); } +bool +TR_ResolvedJ9Method::isInterpretedForHeuristics() + { + return isInterpreted(); + } + TR_OpaqueMethodBlock * TR_ResolvedJ9Method::getNonPersistentIdentifier() { @@ -5737,14 +5850,20 @@ TR_ResolvedJ9Method::staticSignatureChars(I_32 cpIndex, int32_t & len) } TR_OpaqueClassBlock * -TR_ResolvedJ9Method::classOfStatic(I_32 cpIndex, bool returnClassForAOT) +TR_ResolvedJ9Method::getClassOfStaticFromCP(TR_J9VMBase *fej9, J9ConstantPool *cp, int32_t cpIndex) { - TR::VMAccessCriticalSection classOfStatic(fej9()); + TR::VMAccessCriticalSection classOfStatic(fej9); TR_OpaqueClassBlock *result; - result = _fe->convertClassPtrToClassOffset(cpIndex >= 0 ? jitGetClassOfFieldFromCP(_fe->vmThread(), cp(), cpIndex) : 0); + result = fej9->convertClassPtrToClassOffset(cpIndex >= 0 ? jitGetClassOfFieldFromCP(fej9->vmThread(), cp, cpIndex) : 0); return result; } +TR_OpaqueClassBlock * +TR_ResolvedJ9Method::classOfStatic(I_32 cpIndex, bool returnClassForAOT) + { + return getClassOfStaticFromCP(fej9(), cp(), cpIndex); + } + TR_OpaqueClassBlock * TR_ResolvedJ9Method::classOfMethod() { @@ -6005,27 +6124,33 @@ TR_ResolvedJ9Method::isUnresolvedMethodTypeTableEntry(int32_t cpIndex) #endif TR_OpaqueClassBlock * -TR_ResolvedJ9Method::getClassFromConstantPool(TR::Compilation * comp, uint32_t cpIndex, bool) +TR_ResolvedJ9Method::getClassFromCP(TR_J9VMBase *fej9, J9ConstantPool *cp, TR::Compilation *comp, uint32_t cpIndex) { - TR::VMAccessCriticalSection getClassFromConstantPool(fej9()); + TR::VMAccessCriticalSection getClassFromConstantPool(fej9); TR_OpaqueClassBlock *result = 0; - INCREMENT_COUNTER(_fe, totalClassRefs); + INCREMENT_COUNTER(fej9, totalClassRefs); J9Class * resolvedClass; if (cpIndex != -1 && - !((_fe->_jitConfig->runtimeFlags & J9JIT_RUNTIME_RESOLVE) && + !((fej9->_jitConfig->runtimeFlags & J9JIT_RUNTIME_RESOLVE) && !comp->ilGenRequest().details().isMethodHandleThunk() && // cmvc 195373 performTransformation(comp, "Setting as unresolved class from CP cpIndex=%d\n",cpIndex) )&& - (resolvedClass = _fe->_vmFunctionTable->resolveClassRef(_fe->vmThread(), cp(), cpIndex, J9_RESOLVE_FLAG_JIT_COMPILE_TIME))) + (resolvedClass = fej9->_vmFunctionTable->resolveClassRef(fej9->vmThread(), cp, cpIndex, J9_RESOLVE_FLAG_JIT_COMPILE_TIME))) { - result = _fe->convertClassPtrToClassOffset(resolvedClass); + result = fej9->convertClassPtrToClassOffset(resolvedClass); } else { - INCREMENT_COUNTER(_fe, unresolvedClassRefs); + INCREMENT_COUNTER(fej9, unresolvedClassRefs); } return result; } +TR_OpaqueClassBlock * +TR_ResolvedJ9Method::getClassFromConstantPool(TR::Compilation * comp, uint32_t cpIndex, bool) + { + return getClassFromCP(fej9(), cp(), comp, cpIndex); + } + /* TR_OpaqueClassBlock * TR_ResolvedJ9Method::getClassFromConstantPoolForCheckcast(TR::Compilation *comp, uint32_t cpIndex) @@ -6137,6 +6262,58 @@ TR_ResolvedJ9Method::isCompilable(TR_Memory * trMemory) return true; } +static bool +isInvokePrivateVTableOffset(UDATA vTableOffset) + { +#if defined(J9VM_OPT_VALHALLA_NESTMATES) + return vTableOffset == J9VTABLE_INVOKE_PRIVATE_OFFSET; +#else + return false; +#endif + } + +TR_OpaqueMethodBlock * +TR_ResolvedJ9Method::getVirtualMethod(TR_J9VMBase *fej9, J9ConstantPool *cp, I_32 cpIndex, UDATA *vTableOffset, bool *unresolvedInCP) + { + J9RAMConstantPoolItem *literals = (J9RAMConstantPoolItem *)cp; + J9Method * ramMethod = NULL; + + *vTableOffset = (((J9RAMVirtualMethodRef*) literals)[cpIndex]).methodIndexAndArgCount; + *vTableOffset >>= 8; + if (J9VTABLE_INITIAL_VIRTUAL_OFFSET == *vTableOffset) + { + TR::VMAccessCriticalSection resolveVirtualMethodRef(fej9); + *vTableOffset = fej9->_vmFunctionTable->resolveVirtualMethodRefInto(fej9->vmThread(), cp, cpIndex, J9_RESOLVE_FLAG_JIT_COMPILE_TIME, &ramMethod, NULL); + } + else if (!isInvokePrivateVTableOffset(*vTableOffset)) + { + // go fishing for the J9Method... + uint32_t classIndex = ((J9ROMMethodRef *) cp->romConstantPool)[cpIndex].classRefCPIndex; + J9Class * classObject = (((J9RAMClassRef*) literals)[classIndex]).value; + ramMethod = *(J9Method **)((char *)classObject + *vTableOffset); + if (unresolvedInCP) + *unresolvedInCP = false; + } + + if (isInvokePrivateVTableOffset(*vTableOffset)) + ramMethod = (((J9RAMVirtualMethodRef*) literals)[cpIndex]).method; + + return (TR_OpaqueMethodBlock *)ramMethod; + } + +TR_OpaqueClassBlock * +TR_ResolvedJ9Method::getInterfaceITableIndexFromCP(TR_J9VMBase *fej9, J9ConstantPool *cp, int32_t cpIndex, UDATA *pITableIndex) + { + INCREMENT_COUNTER(fej9, totalInterfaceMethodRefs); + INCREMENT_COUNTER(fej9, unresolvedInterfaceMethodRefs); + + if (cpIndex == -1) + return NULL; + + TR::VMAccessCriticalSection getResolvedInterfaceMethod(fej9); + return (TR_OpaqueClassBlock *)jitGetInterfaceITableIndexFromCP(fej9->vmThread(), cp, cpIndex, pITableIndex); + } + TR_OpaqueClassBlock * TR_ResolvedJ9Method::getResolvedInterfaceMethod(I_32 cpIndex, UDATA *pITableIndex) { @@ -6147,12 +6324,13 @@ TR_ResolvedJ9Method::getResolvedInterfaceMethod(I_32 cpIndex, UDATA *pITableInde return 0; #else - INCREMENT_COUNTER(_fe, totalInterfaceMethodRefs); - INCREMENT_COUNTER(_fe, unresolvedInterfaceMethodRefs); + result = getInterfaceITableIndexFromCP(fej9(), cp(), cpIndex, pITableIndex); + TR::Compilation *comp = TR::comp(); + if (comp && comp->compileRelocatableCode() && comp->getOption(TR_UseSymbolValidationManager)) { - TR::VMAccessCriticalSection getResolvedInterfaceMethod(fej9()); - result = (TR_OpaqueClassBlock *)jitGetInterfaceITableIndexFromCP(_fe->vmThread(), cp(), cpIndex, pITableIndex); + if (!comp->getSymbolValidationManager()->addClassFromITableIndexCPRecord(result, cp(), cpIndex)) + result = NULL; } return result; @@ -6204,6 +6382,12 @@ TR_ResolvedJ9Method::getResolvedImproperInterfaceMethod(TR::Compilation * comp, j9method = jitGetImproperInterfaceMethodFromCP(_fe->vmThread(), cp(), cpIndex); } + if (comp->getOption(TR_UseSymbolValidationManager) && j9method) + { + if (!comp->getSymbolValidationManager()->addImproperInterfaceMethodFromCPRecord((TR_OpaqueMethodBlock *)j9method, cp(), cpIndex)) + j9method = NULL; + } + if (j9method == NULL) return NULL; else @@ -6269,6 +6453,12 @@ TR_ResolvedJ9Method::getResolvedStaticMethod(TR::Compilation * comp, I_32 cpInde ramMethod = jitResolveStaticMethodRef(_fe->vmThread(), cp(), cpIndex, J9_RESOLVE_FLAG_JIT_COMPILE_TIME); } + if (comp->compileRelocatableCode() && comp->getOption(TR_UseSymbolValidationManager) && ramMethod) + { + if (!comp->getSymbolValidationManager()->addStaticMethodFromCPRecord((TR_OpaqueMethodBlock *)ramMethod, cp(), cpIndex)) + ramMethod = NULL; + } + bool skipForDebugging = doResolveAtRuntime(ramMethod, cpIndex, comp); if (isArchetypeSpecimen()) { @@ -6339,10 +6529,19 @@ TR_ResolvedJ9Method::getResolvedSpecialMethod(TR::Compilation * comp, I_32 cpInd ramMethod = jitResolveSpecialMethodRef(_fe->vmThread(), cp(), cpIndex, J9_RESOLVE_FLAG_JIT_COMPILE_TIME); if (ramMethod) { + bool createResolvedMethod = true; + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (!comp->getSymbolValidationManager()->addSpecialMethodFromCPRecord((TR_OpaqueMethodBlock *)ramMethod, cp(), cpIndex)) + createResolvedMethod = false; + } + TR_AOTInliningStats *aotStats = NULL; if (comp->getOption(TR_EnableAOTStats)) aotStats = & (((TR_JitPrivateConfig *)_fe->_jitConfig->privateConfig)->aotStats->specialMethods); - resolvedMethod = createResolvedMethodFromJ9Method(comp, cpIndex, 0, ramMethod, unresolvedInCP, aotStats); + if (createResolvedMethod) + resolvedMethod = createResolvedMethodFromJ9Method(comp, cpIndex, 0, ramMethod, unresolvedInCP, aotStats); if (unresolvedInCP) *unresolvedInCP = false; } @@ -6360,16 +6559,6 @@ TR_ResolvedJ9Method::getResolvedSpecialMethod(TR::Compilation * comp, I_32 cpInd return resolvedMethod; } -static bool -isInvokePrivateVTableOffset(UDATA vTableOffset) - { -#if defined(J9VM_OPT_VALHALLA_NESTMATES) - return vTableOffset == J9VTABLE_INVOKE_PRIVATE_OFFSET; -#else - return false; -#endif - } - TR_ResolvedMethod * TR_ResolvedJ9Method::getResolvedPossiblyPrivateVirtualMethod(TR::Compilation * comp, I_32 cpIndex, bool ignoreRtResolve, bool * unresolvedInCP) { @@ -6391,34 +6580,25 @@ TR_ResolvedJ9Method::getResolvedPossiblyPrivateVirtualMethod(TR::Compilation * c performTransformation(comp, "Setting as unresolved virtual call cpIndex=%d\n",cpIndex) ) || ignoreRtResolve) { // only call the resolve if unresolved - J9Method * ramMethod = 0; - UDATA vTableOffset = (((J9RAMVirtualMethodRef*) literals())[cpIndex]).methodIndexAndArgCount; - vTableOffset >>= 8; - if (J9VTABLE_INITIAL_VIRTUAL_OFFSET == vTableOffset) + UDATA vTableOffset; + J9Method * ramMethod = (J9Method *)getVirtualMethod(_fe, cp(), cpIndex, &vTableOffset, unresolvedInCP); + bool createResolvedMethod = true; + + if (comp->compileRelocatableCode() && ramMethod && comp->getOption(TR_UseSymbolValidationManager)) { - TR::VMAccessCriticalSection resolveVirtualMethodRef(fej9()); - vTableOffset = _fe->_vmFunctionTable->resolveVirtualMethodRefInto(_fe->vmThread(), cp(), cpIndex, J9_RESOLVE_FLAG_JIT_COMPILE_TIME, &ramMethod, NULL); + if (!comp->getSymbolValidationManager()->addVirtualMethodFromCPRecord((TR_OpaqueMethodBlock *)ramMethod, cp(), cpIndex)) + createResolvedMethod = false; } - else if (!isInvokePrivateVTableOffset(vTableOffset)) - { - // go fishing for the J9Method... - uint32_t classIndex = ((J9ROMMethodRef *) cp()->romConstantPool)[cpIndex].classRefCPIndex; - J9Class * classObject = (((J9RAMClassRef*) literals())[classIndex]).value; - ramMethod = *(J9Method **)((char *)classObject + vTableOffset); - if (unresolvedInCP) - *unresolvedInCP = false; - } - - if (isInvokePrivateVTableOffset(vTableOffset)) - ramMethod = (((J9RAMVirtualMethodRef*) literals())[cpIndex]).method; if (vTableOffset) { TR_AOTInliningStats *aotStats = NULL; if (comp->getOption(TR_EnableAOTStats)) aotStats = & (((TR_JitPrivateConfig *)_fe->_jitConfig->privateConfig)->aotStats->virtualMethods); - resolvedMethod = createResolvedMethodFromJ9Method(comp, cpIndex, vTableOffset, ramMethod, unresolvedInCP, aotStats); + if (createResolvedMethod) + resolvedMethod = createResolvedMethodFromJ9Method(comp, cpIndex, vTableOffset, ramMethod, unresolvedInCP, aotStats); } + } if (resolvedMethod == NULL) @@ -6892,7 +7072,7 @@ TR_J9VMBase::getResolvedVirtualMethod(TR_OpaqueClassBlock * classObject, I_32 vi } TR_OpaqueMethodBlock * -TR_J9VMBase::getResolvedInterfaceMethod(TR_OpaqueMethodBlock *interfaceMethod, TR_OpaqueClassBlock * classObject, I_32 cpIndex) +TR_J9VMBase::getResolvedInterfaceMethod(J9ConstantPool *ownerCP, TR_OpaqueClassBlock * classObject, int32_t cpIndex) { TR::VMAccessCriticalSection getResolvedInterfaceMethod(this); TR_ASSERT(cpIndex != -1, "cpIndex shouldn't be -1"); @@ -6904,13 +7084,67 @@ TR_J9VMBase::getResolvedInterfaceMethod(TR_OpaqueMethodBlock *interfaceMethod, T INCREMENT_COUNTER(this, totalInterfaceMethodRefs); J9Method * ramMethod = jitGetInterfaceMethodFromCP(vmThread(), - (J9ConstantPool *)(J9_CP_FROM_METHOD((J9Method*)interfaceMethod)), + ownerCP, cpIndex, TR::Compiler->cls.convertClassOffsetToClassPtr(classObject)); return (TR_OpaqueMethodBlock *)ramMethod; } +TR_OpaqueMethodBlock * +TR_J9VMBase::getResolvedInterfaceMethod(TR_OpaqueMethodBlock *interfaceMethod, TR_OpaqueClassBlock * classObject, I_32 cpIndex) + { + return getResolvedInterfaceMethod((J9ConstantPool *)(J9_CP_FROM_METHOD((J9Method*)interfaceMethod)), + classObject, + cpIndex); + + } + +TR_OpaqueMethodBlock * +TR_J9SharedCacheVM::getResolvedVirtualMethod(TR_OpaqueClassBlock * classObject, I_32 virtualCallOffset, bool ignoreRtResolve) + { + TR_OpaqueMethodBlock *ramMethod = TR_J9VMBase::getResolvedVirtualMethod(classObject, virtualCallOffset, ignoreRtResolve); + TR::Compilation *comp = TR::comp(); + if (comp && comp->getOption(TR_UseSymbolValidationManager)) + { + if (!comp->getSymbolValidationManager()->addVirtualMethodFromOffsetRecord(ramMethod, classObject, virtualCallOffset, ignoreRtResolve)) + return NULL; + } + + return ramMethod; + } + +TR_OpaqueMethodBlock * +TR_J9SharedCacheVM::getResolvedInterfaceMethod(TR_OpaqueMethodBlock *interfaceMethod, TR_OpaqueClassBlock * classObject, I_32 cpIndex) + { + TR_OpaqueMethodBlock *ramMethod = TR_J9VMBase::getResolvedInterfaceMethod(interfaceMethod, classObject, cpIndex); + TR::Compilation *comp = TR::comp(); + if (comp && comp->getOption(TR_UseSymbolValidationManager)) + { + if (!comp->getSymbolValidationManager()->addInterfaceMethodFromCPRecord(ramMethod, + (TR_OpaqueClassBlock *)J9_CLASS_FROM_METHOD((J9Method*)interfaceMethod), + classObject, + cpIndex)) + { + return NULL; + } + } + return ramMethod; + } + +TR_OpaqueClassBlock * +TR_ResolvedRelocatableJ9Method::getDeclaringClassFromFieldOrStatic(TR::Compilation *comp, int32_t cpIndex) + { + TR_OpaqueClassBlock *definingClass = TR_ResolvedJ9MethodBase::getDeclaringClassFromFieldOrStatic(comp, cpIndex); + if (comp->getOption(TR_UseSymbolValidationManager)) + { + if (!comp->getSymbolValidationManager()->addDeclaringClassFromFieldOrStaticRecord(definingClass, cp(), cpIndex)) + return NULL; + } + return definingClass; + } + + J9UTF8 * getSignatureFromTR_VMMethod(TR_OpaqueMethodBlock *vmMethod) { TR_ASSERT(0, "I don't think these are used"); diff --git a/runtime/compiler/env/j9method.h b/runtime/compiler/env/j9method.h index dac301243bb..7482c072d60 100644 --- a/runtime/compiler/env/j9method.h +++ b/runtime/compiler/env/j9method.h @@ -291,6 +291,7 @@ class TR_ResolvedJ9Method : public TR_J9Method, public TR_ResolvedJ9MethodBase virtual bool isFinal(); virtual bool isStrictFP(); virtual bool isInterpreted(); + virtual bool isInterpretedForHeuristics(); virtual bool hasBackwardBranches(); virtual bool isObjectConstructor(); virtual bool isNonEmptyObjectConstructor(); @@ -318,6 +319,9 @@ class TR_ResolvedJ9Method : public TR_J9Method, public TR_ResolvedJ9MethodBase virtual TR_OpaqueClassBlock * containingClass(); + static TR_OpaqueClassBlock * getClassFromCP(TR_J9VMBase *fej9, J9ConstantPool *cp, TR::Compilation *comp, uint32_t cpIndex); + static TR_OpaqueClassBlock * getClassOfStaticFromCP(TR_J9VMBase *fej9, J9ConstantPool *cp, int32_t cpIndex); + virtual void * ramConstantPool(); virtual void * constantPool(); virtual TR_OpaqueClassBlock * getClassFromConstantPool( TR::Compilation *, uint32_t cpIndex, bool returnClassForAot=false); @@ -414,6 +418,9 @@ class TR_ResolvedJ9Method : public TR_J9Method, public TR_ResolvedJ9MethodBase virtual bool isCompilable(TR_Memory *); + static TR_OpaqueMethodBlock * getVirtualMethod(TR_J9VMBase *fej9, J9ConstantPool *cp, I_32 cpIndex, UDATA *vTableOffset, bool *unresolvedInCP); + static TR_OpaqueClassBlock * getInterfaceITableIndexFromCP(TR_J9VMBase *fej9, J9ConstantPool *cp, int32_t cpIndex, uintptrj_t *pITableIndex); + virtual TR_ResolvedMethod * getResolvedStaticMethod ( TR::Compilation *, int32_t cpIndex, bool * unresolvedInCP); virtual TR_ResolvedMethod * getResolvedSpecialMethod( TR::Compilation *, int32_t cpIndex, bool * unresolvedInCP); virtual TR_ResolvedMethod * getResolvedVirtualMethod( TR::Compilation *, int32_t cpIndex, bool ignoreRtResolve, bool * unresolvedInCP); @@ -502,6 +509,7 @@ class TR_ResolvedRelocatableJ9Method : public TR_ResolvedJ9Method virtual bool isStrictFP(); virtual bool isInterpreted(); + virtual bool isInterpretedForHeuristics(); virtual bool hasBackwardBranches(); virtual bool isObjectConstructor(); virtual bool isNonEmptyObjectConstructor(); @@ -545,6 +553,8 @@ class TR_ResolvedRelocatableJ9Method : public TR_ResolvedJ9Method virtual TR_OpaqueMethodBlock *getNonPersistentIdentifier(); virtual uint8_t * allocateException(uint32_t, TR::Compilation*); + virtual TR_OpaqueClassBlock *getDeclaringClassFromFieldOrStatic( TR::Compilation *comp, int32_t cpIndex); + private: virtual TR_ResolvedMethod * createResolvedMethodFromJ9Method(TR::Compilation *comp, int32_t cpIndex, uint32_t vTableSlot, J9Method *j9Method, bool * unresolvedInCP, TR_AOTInliningStats *aotStats); diff --git a/runtime/compiler/exceptions/AOTFailure.hpp b/runtime/compiler/exceptions/AOTFailure.hpp index e1a92b7334a..ad5b748060f 100644 --- a/runtime/compiler/exceptions/AOTFailure.hpp +++ b/runtime/compiler/exceptions/AOTFailure.hpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corp. and others + * Copyright (c) 2000, 2018 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 @@ -70,6 +70,16 @@ class AOTRelocationFailed : public virtual RuntimeFailure virtual const char* what() const throw() { return "AOT Relocation Failed"; } }; +/** + * AOT Symbol Validation Failure exception type. + * + * Thrown when an AOT validation record that should succeed fails. + */ +class AOTSymbolValidationManagerFailure : public virtual TR::CompilationException + { + virtual const char* what() const throw() { return "AOT Symbol Validation Manager Failure"; } + }; + } #endif // AOT_FAILURE_HPP diff --git a/runtime/compiler/il/J9Node.cpp b/runtime/compiler/il/J9Node.cpp index b59597fd6cc..9d3945923e1 100644 --- a/runtime/compiler/il/J9Node.cpp +++ b/runtime/compiler/il/J9Node.cpp @@ -988,7 +988,8 @@ J9::Node::getTypeSignature(int32_t & len, TR_AllocationKind allocKind, bool parm TR::Symbol *sym = symRef->getSymbol(); if (parmAsAuto && sym->isParm()) return 0; - TR_PersistentClassInfo * classInfo = c->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(c->getCurrentMethod()->containingClass(), c); + bool allowForAOT = c->getOption(TR_UseSymbolValidationManager); + TR_PersistentClassInfo * classInfo = c->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(c->getCurrentMethod()->containingClass(), c, allowForAOT); TR::Node * node = self(); TR_PersistentFieldInfo * fieldInfo = classInfo && classInfo->getFieldInfo() ? classInfo->getFieldInfo()->findFieldInfo(c, node, false) : 0; if (fieldInfo && fieldInfo->isTypeInfoValid() && fieldInfo->getNumChars() > 0) diff --git a/runtime/compiler/il/J9SymbolReference.cpp b/runtime/compiler/il/J9SymbolReference.cpp index c0106330bb4..acf8549e3b4 100644 --- a/runtime/compiler/il/J9SymbolReference.cpp +++ b/runtime/compiler/il/J9SymbolReference.cpp @@ -180,6 +180,7 @@ const char * SymbolReference::getTypeSignature(int32_t & len, TR_AllocationKind allocKind, bool *isFixed) { TR::Compilation * comp = TR::comp(); + bool allowForAOT = comp->getOption(TR_UseSymbolValidationManager); TR_PersistentClassInfo * persistentClassInfo = NULL; switch (_symbol->getKind()) @@ -190,7 +191,7 @@ SymbolReference::getTypeSignature(int32_t & len, TR_AllocationKind allocKind, bo case TR::Symbol::IsShadow: persistentClassInfo = (comp->getPersistentInfo()->getPersistentCHTable() == NULL) ? NULL : - comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(comp->getCurrentMethod()->containingClass(), comp); + comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(comp->getCurrentMethod()->containingClass(), comp, allowForAOT); if (persistentClassInfo && persistentClassInfo->getFieldInfo() && persistentClassInfo->getFieldInfo()->getFirst() && @@ -241,12 +242,12 @@ SymbolReference::getTypeSignature(int32_t & len, TR_AllocationKind allocKind, bo { TR::StaticSymbol * symbol = _symbol->castToStaticSymbol(); TR::DataType type = symbol->getDataType(); - TR_OpaqueClassBlock * classOfStatic = self()->getOwningMethod(comp)->classOfStatic(_cpIndex); + TR_OpaqueClassBlock * classOfStatic = self()->getOwningMethod(comp)->classOfStatic(_cpIndex, allowForAOT); bool isClassInitialized = false; TR_PersistentClassInfo * classInfo = (comp->getPersistentInfo()->getPersistentCHTable() == NULL) ? NULL : - comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(classOfStatic, comp); + comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(classOfStatic, comp, allowForAOT); if (classInfo && classInfo->isInitialized()) { if (classInfo->getFieldInfo() && !classInfo->cannotTrustStaticFinal()) @@ -255,7 +256,6 @@ SymbolReference::getTypeSignature(int32_t & len, TR_AllocationKind allocKind, bo if ((classOfStatic != comp->getSystemClassPointer() && isClassInitialized && - !comp->getOption(TR_AOT) && (type == TR::Address))) { TR::VMAccessCriticalSection vmAccessCriticalSection(comp->fej9(), @@ -336,7 +336,7 @@ SymbolReference::getTypeSignature(int32_t & len, TR_AllocationKind allocKind, bo persistentClassInfo = (comp->getPersistentInfo()->getPersistentCHTable() == NULL) ? NULL : - comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(comp->getCurrentMethod()->containingClass(), comp); + comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(comp->getCurrentMethod()->containingClass(), comp, allowForAOT); if (persistentClassInfo && persistentClassInfo->getFieldInfo() && persistentClassInfo->getFieldInfo()->getFirst() && diff --git a/runtime/compiler/ilgen/ClassLookahead.cpp b/runtime/compiler/ilgen/ClassLookahead.cpp index ffd202d463d..b2a5959b51c 100644 --- a/runtime/compiler/ilgen/ClassLookahead.cpp +++ b/runtime/compiler/ilgen/ClassLookahead.cpp @@ -62,8 +62,9 @@ TR_ClassLookahead::perform() bool isClassInitialized = false; bool seenFirstInitializerMethod = false; + bool allowForAOT = comp()->getOption(TR_UseSymbolValidationManager); TR_PersistentClassInfo * classInfo = - comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(_classPointer, comp()); + comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(_classPointer, comp(), allowForAOT); if (classInfo && classInfo->isInitialized()) isClassInitialized = true; diff --git a/runtime/compiler/ilgen/IlGenerator.cpp b/runtime/compiler/ilgen/IlGenerator.cpp index 632247e2b22..691c0663cdd 100644 --- a/runtime/compiler/ilgen/IlGenerator.cpp +++ b/runtime/compiler/ilgen/IlGenerator.cpp @@ -73,7 +73,8 @@ TR_J9ByteCodeIlGenerator::TR_J9ByteCodeIlGenerator( ((comp->getMethodHotness() >= scorching) || (comp->couldBeRecompiled() && (comp->getMethodHotness() >= hot )))))) { - _classInfo = comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(method()->containingClass(), comp); + bool allowForAOT = comp->getOption(TR_UseSymbolValidationManager); + _classInfo = comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(method()->containingClass(), comp, allowForAOT); } else { diff --git a/runtime/compiler/ilgen/Walker.cpp b/runtime/compiler/ilgen/Walker.cpp index 0d0f66a5905..00a2b40b628 100644 --- a/runtime/compiler/ilgen/Walker.cpp +++ b/runtime/compiler/ilgen/Walker.cpp @@ -2767,8 +2767,7 @@ TR_J9ByteCodeIlGenerator::loadConstantValueIfPossible(TR::Node *topNode, uintptr bool canOptimizeFinalStatic = false; if (isResolved && symbol->isFinal() && !symRef->isUnresolved() && classOfStatic != comp()->getSystemClassPointer() && - isClassInitialized && - !comp()->compileRelocatableCode()) + isClassInitialized) { //if (symbol->getDataType() == TR::Address) { @@ -6137,8 +6136,7 @@ TR_J9ByteCodeIlGenerator::loadStatic(int32_t cpIndex) bool canOptimizeFinalStatic = false; if (isResolved && symbol->isFinal() && !symRef->isUnresolved() && classOfStatic != comp()->getSystemClassPointer() && - isClassInitialized && - !comp()->compileRelocatableCode()) + isClassInitialized) { //if (type == TR::Address) { @@ -6201,7 +6199,7 @@ TR_J9ByteCodeIlGenerator::loadStatic(int32_t cpIndex) else { TR::Node * load; - if (cg()->getAccessStaticsIndirectly() && isResolved && type != TR::Address && !comp()->compileRelocatableCode()) + if (cg()->getAccessStaticsIndirectly() && isResolved && type != TR::Address && (!comp()->compileRelocatableCode() || comp()->getOption(TR_UseSymbolValidationManager))) { TR::Node * statics = TR::Node::createWithSymRef(TR::loadaddr, 0, symRefTab()->findOrCreateClassStaticsSymbol(_methodSymbol, cpIndex)); load = TR::Node::createWithSymRef(comp()->il.opCodeForIndirectLoad(type), 1, 1, statics, symRef); @@ -7369,7 +7367,7 @@ TR_J9ByteCodeIlGenerator::storeStatic(int32_t cpIndex) node = TR::Node::createWithSymRef(TR::call, 2, 2, value, statics, volatileLongSymRef); } - else if (!symRef->isUnresolved() && cg()->getAccessStaticsIndirectly() && type != TR::Address && !comp()->compileRelocatableCode()) + else if (!symRef->isUnresolved() && cg()->getAccessStaticsIndirectly() && type != TR::Address && (!comp()->compileRelocatableCode() || comp()->getOption(TR_UseSymbolValidationManager))) { TR::Node * statics = TR::Node::createWithSymRef(TR::loadaddr, 0, symRefTab()->findOrCreateClassStaticsSymbol(_methodSymbol, cpIndex)); node = TR::Node::createWithSymRef(comp()->il.opCodeForIndirectStore(type), 2, 2, statics, value, symRef); @@ -7853,7 +7851,7 @@ void TR_J9ByteCodeIlGenerator::performClassLookahead(TR_PersistentClassInfo *cla if (comp()->getOption(TR_EnableHCR)) return; - if (comp()->compileRelocatableCode()) + if (comp()->compileRelocatableCode() && !comp()->getOption(TR_UseSymbolValidationManager)) return; _classLookaheadSymRefTab = new (trStackMemory())TR::SymbolReferenceTable(method()->maxBytecodeIndex(), comp()); diff --git a/runtime/compiler/optimizer/InlinerTempForJ9.cpp b/runtime/compiler/optimizer/InlinerTempForJ9.cpp index 138bd33ddce..5b090403118 100644 --- a/runtime/compiler/optimizer/InlinerTempForJ9.cpp +++ b/runtime/compiler/optimizer/InlinerTempForJ9.cpp @@ -941,7 +941,6 @@ TR_J9InlinerPolicy::genCodeForUnsafeGetPut(TR::Node* unsafeAddress, loadJavaLangClass->getByteCodeInfo().setZeroByteCodeIndex(); loadJavaLangClass->setIsClassPointerConstant(true); - TR::Node *isClassNode = TR::Node::createif(TR::ifacmpeq, vftLoad, loadJavaLangClass, NULL); isClassTreeTop = TR::TreeTop::create(comp(), isClassNode, NULL, NULL); isClassBlock = TR::Block::createEmptyBlock(vftLoad, comp(), directAccessBlock->getFrequency()); @@ -3498,6 +3497,7 @@ bool TR_MultipleCallTargetInliner::inlineCallTargets(TR::ResolvedMethodSymbol *c tracer()->dumpInline(&_callTargets, "inline script"); } } + if (prevCallStack == 0) { TR_InlinerDelimiter delimiter(tracer(),"inlineTransformation"); @@ -4223,12 +4223,12 @@ TR_MultipleCallTargetInliner::exceedsSizeThreshold(TR_CallSite *callSite, int by && (!trustedInterfaceRegex || !TR::SimpleRegex::match(trustedInterfaceRegex, callSite->_interfaceMethod->signature(trMemory()), false))) { TR_PersistentJittedBodyInfo *bodyInfo = NULL; - if (!calleeResolvedMethod->isInterpreted() && !calleeResolvedMethod->isJITInternalNative()) + if (!calleeResolvedMethod->isInterpretedForHeuristics() && !calleeResolvedMethod->isJITInternalNative()) { void *startPC = (void *)calleeResolvedMethod->startAddressForInterpreterOfJittedMethod(); bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(startPC); } - if (((!bodyInfo && !calleeResolvedMethod->isInterpreted() && !calleeResolvedMethod->isJITInternalNative()) //jitted method without bodyInfo must be scorching + if (((!bodyInfo && !calleeResolvedMethod->isInterpretedForHeuristics() && !calleeResolvedMethod->isJITInternalNative()) //jitted method without bodyInfo must be scorching || (bodyInfo && bodyInfo->getHotness() == scorching) || comp()->fej9()->isQueuedForVeryHotOrScorching(calleeResolvedMethod, comp())) && (comp()->getMethodHotness() == scorching)) diff --git a/runtime/compiler/optimizer/InterProceduralAnalyzer.cpp b/runtime/compiler/optimizer/InterProceduralAnalyzer.cpp index e96aeec2cce..d29e4e8c26c 100644 --- a/runtime/compiler/optimizer/InterProceduralAnalyzer.cpp +++ b/runtime/compiler/optimizer/InterProceduralAnalyzer.cpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corp. and others + * Copyright (c) 2000, 2018 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 @@ -302,7 +302,8 @@ List *TR::InterProceduralAnalyzer::analyzeCallGraph(TR:: } } - TR_PersistentClassInfo *classInfo = comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(clazz, comp()); + bool allowForAOT = comp()->getOption(TR_UseSymbolValidationManager); + TR_PersistentClassInfo *classInfo = comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(clazz, comp(), allowForAOT); if (classInfo) { TR_ScratchList subClasses(trMemory()); diff --git a/runtime/compiler/optimizer/J9Inliner.cpp b/runtime/compiler/optimizer/J9Inliner.cpp index 8172fecf264..87aeff5c19a 100644 --- a/runtime/compiler/optimizer/J9Inliner.cpp +++ b/runtime/compiler/optimizer/J9Inliner.cpp @@ -484,8 +484,9 @@ bool TR_J9VirtualCallSite::findCallSiteForAbstractClass(TR_InlinerBase* inliner) TR_PersistentCHTable *chTable = comp()->getPersistentInfo()->getPersistentCHTable(); TR_ResolvedMethod *implementer; - if (!comp()->compileRelocatableCode() && TR::Compiler->cls.isAbstractClass(comp(), _receiverClass) &&!comp()->getOption(TR_DisableAbstractInlining) && - (implementer = chTable->findSingleAbstractImplementer(_receiverClass, _vftSlot, _callerResolvedMethod, comp()))) + bool canInline = (!comp()->compileRelocatableCode() || comp()->getOption(TR_UseSymbolValidationManager)); + if (canInline && TR::Compiler->cls.isAbstractClass(comp(), _receiverClass) &&!comp()->getOption(TR_DisableAbstractInlining) && + (implementer = chTable->findSingleAbstractImplementer(_receiverClass, _vftSlot, _callerResolvedMethod, comp()))) { heuristicTrace(inliner->tracer(),"Found a single Abstract Implementer %p, signature = %s",implementer,inliner->tracer()->traceSignature(implementer)); TR_VirtualGuardSelection *guard = new (comp()->trHeapMemory()) TR_VirtualGuardSelection(TR_AbstractGuard, TR_MethodTest); @@ -812,6 +813,7 @@ void TR_ProfileableCallSite::findSingleProfiledReceiver(ListIterator_frequency; TR_OpaqueClassBlock* tempreceiverClass = (TR_OpaqueClassBlock *) profiledInfo->_value; + float val = (float)freq/(float)valueInfo->getTotalFrequency(); //x87 hardware rounds differently if you leave this division in compare @@ -847,7 +849,15 @@ void TR_ProfileableCallSite::findSingleProfiledReceiver(ListIteratorisInstanceOf (tempreceiverClass, callSiteClass, true, true, true) != TR_yes) + bool profiledClassIsNotInstanceOfCallSiteClass = true; + if (callSiteClass) + { + comp()->enterHeuristicRegion(); + profiledClassIsNotInstanceOfCallSiteClass = (fe()->isInstanceOf(tempreceiverClass, callSiteClass, true, true, true) != TR_yes); + comp()->exitHeuristicRegion(); + } + + if (profiledClassIsNotInstanceOfCallSiteClass) { inliner->tracer()->insertCounter(Not_Sane,_callNodeTreeTop); firstInstanceOfCheckFailed = true; @@ -858,7 +868,9 @@ void TR_ProfileableCallSite::findSingleProfiledReceiver(ListIteratorenterHeuristicRegion(); TR_ResolvedMethod* targetMethod = getResolvedMethod (tempreceiverClass); + comp()->exitHeuristicRegion(); if (!targetMethod) { @@ -871,6 +883,17 @@ void TR_ProfileableCallSite::findSingleProfiledReceiver(ListIteratorcompileRelocatableCode()) { + if (tempreceiverClass && comp()->getOption(TR_UseSymbolValidationManager)) + { + if (!comp()->getSymbolValidationManager()->addProfiledClassRecord(tempreceiverClass)) + continue; + /* call getResolvedMethod again to generate the validation records */ + TR_ResolvedMethod* target_method = getResolvedMethod (tempreceiverClass); + if (!comp()->getSymbolValidationManager()->addClassFromMethodRecord(target_method->classOfMethod(), target_method->getPersistentIdentifier())) + continue; + } + + TR_SharedCache *sharedCache = fej9->sharedCache(); if (!sharedCache->canRememberClass(tempreceiverClass) || !sharedCache->canRememberClass(callSiteClass)) @@ -947,6 +970,13 @@ void TR_ProfileableCallSite::findSingleProfiledMethod(ListIteratorcompileRelocatableCode()) { + if (clazz && comp()->getOption(TR_UseSymbolValidationManager)) + if (!comp()->getSymbolValidationManager()->addProfiledClassRecord(clazz)) + { + classValuesAreSane = false; + break; + } + TR_SharedCache *sharedCache = fej9->sharedCache(); if (!sharedCache->canRememberClass(clazz) || !sharedCache->canRememberClass(callSiteClass)) diff --git a/runtime/compiler/optimizer/J9ValuePropagation.cpp b/runtime/compiler/optimizer/J9ValuePropagation.cpp index 59fa3d26a9a..668348d4d1f 100644 --- a/runtime/compiler/optimizer/J9ValuePropagation.cpp +++ b/runtime/compiler/optimizer/J9ValuePropagation.cpp @@ -543,13 +543,16 @@ J9::ValuePropagation::constrainRecognizedMethod(TR::Node *node) node = TR::Node::recreateWithoutProperties(node, TR::aloadi, 1, arrayComponentClassPointer, comp()->getSymRefTab()->findOrCreateJavaLangClassFromClassSymbolRef()); TR::KnownObjectTable *knot = comp()->getOrCreateKnownObjectTable(); - TR::KnownObjectTable::Index knownObjectIndex = knot->getIndexAt((uintptrj_t*)(arrayComponentClass + comp()->fej9()->getOffsetOfJavaLangClassFromClassField())); - addBlockOrGlobalConstraint(node, - TR::VPClass::create(this, - TR::VPKnownObject::createForJavaLangClass(this, knownObjectIndex), - TR::VPNonNullObject::create(this), NULL, NULL, - TR::VPObjectLocation::create(this, TR::VPObjectLocation::JavaLangClassObject)), - classChildGlobal); + if (knot) + { + TR::KnownObjectTable::Index knownObjectIndex = knot->getIndexAt((uintptrj_t*)(arrayComponentClass + comp()->fej9()->getOffsetOfJavaLangClassFromClassField())); + addBlockOrGlobalConstraint(node, + TR::VPClass::create(this, + TR::VPKnownObject::createForJavaLangClass(this, knownObjectIndex), + TR::VPNonNullObject::create(this), NULL, NULL, + TR::VPObjectLocation::create(this, TR::VPObjectLocation::JavaLangClassObject)), + classChildGlobal); + } invalidateUseDefInfo(); invalidateValueNumberInfo(); @@ -617,13 +620,16 @@ J9::ValuePropagation::constrainRecognizedMethod(TR::Node *node) node = TR::Node::recreateWithoutProperties(node, TR::aloadi, 1, superClassPointer, comp()->getSymRefTab()->findOrCreateJavaLangClassFromClassSymbolRef()); TR::KnownObjectTable *knot = comp()->getOrCreateKnownObjectTable(); - TR::KnownObjectTable::Index knownObjectIndex = knot->getIndexAt((uintptrj_t*)(superClass + comp()->fej9()->getOffsetOfJavaLangClassFromClassField())); - addBlockOrGlobalConstraint(node, - TR::VPClass::create(this, - TR::VPKnownObject::createForJavaLangClass(this, knownObjectIndex), - TR::VPNonNullObject::create(this), NULL, NULL, - TR::VPObjectLocation::create(this, TR::VPObjectLocation::JavaLangClassObject)), - classChildGlobal); + if (knot) + { + TR::KnownObjectTable::Index knownObjectIndex = knot->getIndexAt((uintptrj_t*)(superClass + comp()->fej9()->getOffsetOfJavaLangClassFromClassField())); + addBlockOrGlobalConstraint(node, + TR::VPClass::create(this, + TR::VPKnownObject::createForJavaLangClass(this, knownObjectIndex), + TR::VPNonNullObject::create(this), NULL, NULL, + TR::VPObjectLocation::create(this, TR::VPObjectLocation::JavaLangClassObject)), + classChildGlobal); + } invalidateUseDefInfo(); invalidateValueNumberInfo(); diff --git a/runtime/compiler/optimizer/StringBuilderTransformer.cpp b/runtime/compiler/optimizer/StringBuilderTransformer.cpp index 7b9edd2c5be..9bb101ffc26 100644 --- a/runtime/compiler/optimizer/StringBuilderTransformer.cpp +++ b/runtime/compiler/optimizer/StringBuilderTransformer.cpp @@ -81,7 +81,7 @@ static const char* StringBuilderClassName = "java/lang/StringBuilder"; */ int32_t TR_StringBuilderTransformer::perform() { - if (comp()->getOption(TR_DisableStringBuilderTransformer) || comp()->compileRelocatableCode()) + if (comp()->getOption(TR_DisableStringBuilderTransformer) || (comp()->compileRelocatableCode() && !comp()->getOption(TR_UseSymbolValidationManager))) { return 0; } diff --git a/runtime/compiler/optimizer/StringPeepholes.cpp b/runtime/compiler/optimizer/StringPeepholes.cpp index cacd634a7e3..d6251944b98 100644 --- a/runtime/compiler/optimizer/StringPeepholes.cpp +++ b/runtime/compiler/optimizer/StringPeepholes.cpp @@ -229,7 +229,7 @@ int32_t TR_StringPeepholes::perform() { static char *skipitAtWarm = feGetEnv("TR_noPeepholeAtWarm"); if (comp()->getOption(TR_DisableStringPeepholes) - || !comp()->fej9()->doStringPeepholing() + || (!comp()->fej9()->doStringPeepholing() && !comp()->getOption(TR_UseSymbolValidationManager)) || (skipitAtWarm && comp()->getMethodHotness()==warm)) return 1; diff --git a/runtime/compiler/p/codegen/PPCPrivateLinkage.cpp b/runtime/compiler/p/codegen/PPCPrivateLinkage.cpp index e81ca67f461..d3a368da7a9 100644 --- a/runtime/compiler/p/codegen/PPCPrivateLinkage.cpp +++ b/runtime/compiler/p/codegen/PPCPrivateLinkage.cpp @@ -2451,7 +2451,8 @@ void TR::PPCPrivateLinkage::buildVirtualDispatch(TR::Node TR_OpaqueClassBlock *thisClass = refinedThisClass ? refinedThisClass : resolvedMethod->containingClass(); TR_PersistentCHTable *chTable = comp()->getPersistentInfo()->getPersistentCHTable(); - if (thisClass && TR::Compiler->cls.isAbstractClass(comp(), thisClass)) + /* Devirtualization is not currently supported for AOT compilations */ + if (thisClass && TR::Compiler->cls.isAbstractClass(comp(), thisClass) && !comp()->compileRelocatableCode()) { TR_ResolvedMethod *calleeMethod = chTable->findSingleAbstractImplementer(thisClass, methodSymRef->getOffset(), methodSymRef->getOwningMethod(comp()), comp()); if (calleeMethod && diff --git a/runtime/compiler/runtime/CMakeLists.txt b/runtime/compiler/runtime/CMakeLists.txt index 091c1ebeb5a..57fa261230d 100644 --- a/runtime/compiler/runtime/CMakeLists.txt +++ b/runtime/compiler/runtime/CMakeLists.txt @@ -49,6 +49,7 @@ j9jit_files( runtime/RuntimeAssumptions.cpp runtime/Runtime.cpp runtime/SignalHandler.c + runtime/SymbolValidationManager.cpp runtime/Trampoline.cpp runtime/ValueProfiler.cpp ) diff --git a/runtime/compiler/runtime/ClassUnloadAssumption.cpp b/runtime/compiler/runtime/ClassUnloadAssumption.cpp index 7da33354a49..8498442d285 100644 --- a/runtime/compiler/runtime/ClassUnloadAssumption.cpp +++ b/runtime/compiler/runtime/ClassUnloadAssumption.cpp @@ -1239,11 +1239,13 @@ J9::PersistentInfo::isUnloadedClass( bool J9::PersistentInfo::isObsoleteClass(void *v, TR_FrontEnd *fe) { + TR::Compilation *comp = TR::comp(); + bool allowForAOT = comp && comp->getOption(TR_UseSymbolValidationManager); if (isUnloadedClass(v, true)) return true; else if (!getPersistentCHTable()) return false; // HCR TODO: Support fixed opt levels - else if (!getPersistentCHTable()->findClassInfoAfterLocking((TR_OpaqueClassBlock*)v, fe)) + else if (!getPersistentCHTable()->findClassInfoAfterLocking((TR_OpaqueClassBlock*)v, fe, allowForAOT)) return false; // It's not a class, so it can't be a replaced class else return fe->classHasBeenReplaced((TR_OpaqueClassBlock*)v); diff --git a/runtime/compiler/runtime/IProfiler.cpp b/runtime/compiler/runtime/IProfiler.cpp index 62e61ca885a..fa47f979daa 100644 --- a/runtime/compiler/runtime/IProfiler.cpp +++ b/runtime/compiler/runtime/IProfiler.cpp @@ -2380,8 +2380,9 @@ TR_IProfiler::createIProfilingValueInfo (TR_ByteCodeInfo &bcInfo, TR::Compilatio // profiling information coming from this caller if (comp->getOption(TR_IProfilerPerformTimestampCheck) && method && !_compInfo->isCompiled((J9Method *)method))// method is interpreted { - TR_PersistentClassInfo *currentPersistentClassInfo = _compInfo->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(comp->getCurrentMethod()->containingClass(), comp); - TR_PersistentClassInfo *calleePersistentClassInfo = _compInfo->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking((TR_OpaqueClassBlock *)J9_CLASS_FROM_METHOD(((J9Method *)method)), comp); + bool allowForAOT = comp->getOption(TR_UseSymbolValidationManager); + TR_PersistentClassInfo *currentPersistentClassInfo = _compInfo->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(comp->getCurrentMethod()->containingClass(), comp, allowForAOT); + TR_PersistentClassInfo *calleePersistentClassInfo = _compInfo->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking((TR_OpaqueClassBlock *)J9_CLASS_FROM_METHOD(((J9Method *)method)), comp, allowForAOT); if (!currentPersistentClassInfo || !calleePersistentClassInfo) { diff --git a/runtime/compiler/runtime/J9Profiler.cpp b/runtime/compiler/runtime/J9Profiler.cpp index d8d7dde3fa6..098fe705a03 100644 --- a/runtime/compiler/runtime/J9Profiler.cpp +++ b/runtime/compiler/runtime/J9Profiler.cpp @@ -1808,7 +1808,7 @@ TR_BlockFrequencyInfo::getFrequencyInfo( { traceMsg(comp, " found frame for %s with no outter profiling info\n", resolvedMethodSymbol->signature(comp->trMemory())); // has this method been compiled so we might have had a chance to profile it? - if (!resolvedMethod->isInterpreted() + if (!resolvedMethod->isInterpretedForHeuristics() && !resolvedMethod->isNative() && !resolvedMethod->isJNINative()) { diff --git a/runtime/compiler/runtime/RelocationRecord.cpp b/runtime/compiler/runtime/RelocationRecord.cpp index e12fbeb442d..74e307f5ee7 100644 --- a/runtime/compiler/runtime/RelocationRecord.cpp +++ b/runtime/compiler/runtime/RelocationRecord.cpp @@ -42,6 +42,7 @@ #include "env/PersistentCHTable.hpp" #include "env/jittypes.h" #include "env/VMAccessCriticalSection.hpp" +#include "exceptions/AOTFailure.hpp" #include "il/symbol/StaticSymbol.hpp" #include "infra/SimpleRegex.hpp" #include "runtime/CodeCache.hpp" @@ -51,6 +52,7 @@ #include "runtime/RelocationRuntime.hpp" #include "runtime/RelocationRuntimeLogger.hpp" #include "runtime/RelocationTarget.hpp" +#include "runtime/SymbolValidationManager.hpp" #include "env/VMJ9.h" #include "control/rossa.h" @@ -66,169 +68,11 @@ extern "C" void _patchVirtualGuard(uint8_t *locationAddr, uint8_t *destinationAd extern "C" void ASM_CALL _patchVirtualGuard(uint8_t*, uint8_t*, uint32_t); #endif - -// These *BinaryTemplate structs describe the shape of the binary relocation records. -struct TR_RelocationRecordBinaryTemplate - { - uint8_t type(TR_RelocationTarget *reloTarget) { return reloTarget->loadUnsigned8b(&_type); } - - uint16_t _size; - uint8_t _type; - uint8_t _flags; - -#if defined(TR_HOST_64BIT) - uint32_t _extra; -#endif - }; - -// Generating 32-bit code on a 64-bit machine or vice-versa won't work because the alignment won't -// be right. Relying on inheritance in the structures here means padding is automatically inserted -// at each inheritance boundary: this inserted padding won't match across 32-bit and 64-bit platforms. -// Making as many fields as possible UDATA should minimize the differences and gives the most freedom -// in the hierarchy of binary relocation record structures, but the header definitely has an inheritance -// boundary at offset 4B. - -struct TR_RelocationRecordHelperAddressBinaryTemplate - { - uint16_t _size; - uint8_t _type; - uint8_t _flags; - uint32_t _helperID; - }; - -struct TR_RelocationRecordPicTrampolineBinaryTemplate - { - uint16_t _size; - uint8_t _type; - uint8_t _flags; - uint32_t _numTrampolines; - }; - -struct TR_RelocationRecordWithInlinedSiteIndexBinaryTemplate : public TR_RelocationRecordBinaryTemplate - { - UDATA _inlinedSiteIndex; - }; - -struct TR_RelocationRecordValidateArbitraryClassBinaryTemplate : public TR_RelocationRecordBinaryTemplate //public TR_RelocationRecordWithInlinedSiteIndexBinaryTemplate - { - UDATA _loaderClassChainOffset; - UDATA _classChainOffsetForClassBeingValidated; - }; - - -struct TR_RelocationRecordWithOffsetBinaryTemplate : public TR_RelocationRecordBinaryTemplate - { - UDATA _offset; - }; - -struct TR_RelocationRecordConstantPoolBinaryTemplate : public TR_RelocationRecordWithInlinedSiteIndexBinaryTemplate - { - UDATA _constantPool; - }; - -struct TR_RelocationRecordConstantPoolWithIndexBinaryTemplate : public TR_RelocationRecordConstantPoolBinaryTemplate - { - UDATA _index; - }; - -typedef TR_RelocationRecordConstantPoolWithIndexBinaryTemplate TR_RelocationRecordClassObjectBinaryTemplate; - -struct TR_RelocationRecordJ2IVirtualThunkPointerBinaryTemplate : public TR_RelocationRecordConstantPoolBinaryTemplate - { - IDATA _offsetToJ2IVirtualThunkPointer; - }; - -struct TR_RelocationRecordInlinedAllocationBinaryTemplate : public TR_RelocationRecordConstantPoolWithIndexBinaryTemplate - { - UDATA _branchOffset; - }; - -struct TR_RelocationRecordVerifyClassObjectForAllocBinaryTemplate : public TR_RelocationRecordInlinedAllocationBinaryTemplate - { - UDATA _allocationSize; - }; - -struct TR_RelocationRecordRomClassFromCPBinaryTemplate : public TR_RelocationRecordConstantPoolWithIndexBinaryTemplate - { - UDATA _romClassOffsetInSharedCache; - }; - -typedef TR_RelocationRecordRomClassFromCPBinaryTemplate TR_RelocationRecordInlinedMethodBinaryTemplate; - -struct TR_RelocationRecordNopGuardBinaryTemplate : public TR_RelocationRecordInlinedMethodBinaryTemplate - { - UDATA _destinationAddress; - }; - -typedef TR_RelocationRecordNopGuardBinaryTemplate TR_RelocationRecordInlinedStaticMethodWithNopGuardBinaryTemplate; -typedef TR_RelocationRecordNopGuardBinaryTemplate TR_RelocationRecordInlinedSpecialMethodWithNopGuardBinaryTemplate; -typedef TR_RelocationRecordNopGuardBinaryTemplate TR_RelocationRecordInlinedVirtualMethodWithNopGuardBinaryTemplate; -typedef TR_RelocationRecordNopGuardBinaryTemplate TR_RelocationRecordInlinedInterfaceMethodWithNopGuardBinaryTemplate; - - -struct TR_RelocationRecordProfiledInlinedMethodBinaryTemplate : TR_RelocationRecordInlinedMethodBinaryTemplate - { - UDATA _classChainIdentifyingLoaderOffsetInSharedCache; - UDATA _classChainForInlinedMethod; - UDATA _vTableSlot; - }; - -typedef TR_RelocationRecordProfiledInlinedMethodBinaryTemplate TR_RelocationRecordProfiledGuardBinaryTemplate; -typedef TR_RelocationRecordProfiledInlinedMethodBinaryTemplate TR_RelocationRecordProfiledClassGuardBinaryTemplate; -typedef TR_RelocationRecordProfiledInlinedMethodBinaryTemplate TR_RelocationRecordProfiledMethodGuardBinaryTemplate; - - -typedef TR_RelocationRecordBinaryTemplate TR_RelocationRecordRamMethodBinaryTemplate; - -typedef TR_RelocationRecordBinaryTemplate TR_RelocationRecordArrayCopyHelperTemplate; - -struct TR_RelocationRecordMethodTracingCheckBinaryTemplate : public TR_RelocationRecordBinaryTemplate - { - UDATA _destinationAddress; - }; - -struct TR_RelocationRecordValidateClassBinaryTemplate : public TR_RelocationRecordConstantPoolWithIndexBinaryTemplate - { - UDATA _classChainOffsetInSharedCache; - }; - -typedef TR_RelocationRecordRomClassFromCPBinaryTemplate TR_RelocationRecordValidateStaticFieldBinaryTemplate; - -struct TR_RelocationRecordDataAddressBinaryTemplate : public TR_RelocationRecordConstantPoolWithIndexBinaryTemplate - { - UDATA _offset; - }; - -struct TR_RelocationRecordPointerBinaryTemplate : TR_RelocationRecordWithInlinedSiteIndexBinaryTemplate - { - UDATA _classChainIdentifyingLoaderOffsetInSharedCache; - UDATA _classChainForInlinedMethod; - }; - -typedef TR_RelocationRecordPointerBinaryTemplate TR_RelocationRecordClassPointerBinaryTemplate; -struct TR_RelocationRecordMethodPointerBinaryTemplate : TR_RelocationRecordPointerBinaryTemplate - { - UDATA _vTableSlot; - }; -struct TR_RelocationRecordEmitClassBinaryTemplate : public TR_RelocationRecordWithInlinedSiteIndexBinaryTemplate - { - int32_t _bcIndex; -#if defined(TR_HOST_64BIT) - uint32_t _extra; -#endif - }; - -struct TR_RelocationRecordDebugCounterBinaryTemplate : public TR_RelocationRecordWithInlinedSiteIndexBinaryTemplate +uint8_t +TR_RelocationRecordBinaryTemplate::type(TR_RelocationTarget *reloTarget) { - UDATA _bcIndex; - UDATA _offsetOfNameString; - UDATA _delta; - UDATA _fidelity; - UDATA _staticDelta; - }; - - -typedef TR_RelocationRecordBinaryTemplate TR_RelocationRecordClassUnloadAssumptionBinaryTemplate; + return reloTarget->loadUnsigned8b(&_type); + } // TR_RelocationRecordGroup @@ -349,6 +193,9 @@ TR_RelocationRecord::create(TR_RelocationRecord *storage, TR_RelocationRuntime * case TR_InlinedInterfaceMethod: reloRecord = new (storage) TR_RelocationRecordInlinedInterfaceMethod(reloRuntime, record); break; + case TR_InlinedAbstractMethodWithNopGuard: + reloRecord = new (storage) TR_RelocationRecordInlinedAbstractMethodWithNopGuard(reloRuntime, record); + break; case TR_InlinedHCRMethod: reloRecord = new (storage) TR_RelocationRecordInlinedMethod(reloRuntime, record); break; @@ -469,6 +316,113 @@ TR_RelocationRecord::create(TR_RelocationRecord *storage, TR_RelocationRuntime * break; case TR_ClassUnloadAssumption: reloRecord = new (storage) TR_RelocationRecordClassUnloadAssumption(reloRuntime, record); + case TR_ValidateRootClass: + reloRecord = new (storage) TR_RelocationRecordValidateRootClass(reloRuntime, record); + break; + case TR_ValidateClassByName: + reloRecord = new (storage) TR_RelocationRecordValidateClassByName(reloRuntime, record); + break; + case TR_ValidateProfiledClass: + reloRecord = new (storage) TR_RelocationRecordValidateProfiledClass(reloRuntime, record); + break; + case TR_ValidateClassFromCP: + reloRecord = new (storage) TR_RelocationRecordValidateClassFromCP(reloRuntime, record); + break; + case TR_ValidateDefiningClassFromCP: + reloRecord = new (storage) TR_RelocationRecordValidateDefiningClassFromCP(reloRuntime, record); + break; + case TR_ValidateStaticClassFromCP: + reloRecord = new (storage) TR_RelocationRecordValidateStaticClassFromCP(reloRuntime, record); + break; + case TR_ValidateClassFromMethod: + reloRecord = new (storage) TR_RelocationRecordValidateClassFromMethod(reloRuntime, record); + break; + case TR_ValidateComponentClassFromArrayClass: + reloRecord = new (storage) TR_RelocationRecordValidateComponentClassFromArrayClass(reloRuntime, record); + break; + case TR_ValidateArrayClassFromComponentClass: + reloRecord = new (storage) TR_RelocationRecordValidateArrayClassFromComponentClass(reloRuntime, record); + break; + case TR_ValidateSuperClassFromClass: + reloRecord = new (storage) TR_RelocationRecordValidateSuperClassFromClass(reloRuntime, record); + break; + case TR_ValidateClassInstanceOfClass: + reloRecord = new (storage) TR_RelocationRecordValidateClassInstanceOfClass(reloRuntime, record); + break; + case TR_ValidateSystemClassByName: + reloRecord = new (storage) TR_RelocationRecordValidateSystemClassByName(reloRuntime, record); + break; + case TR_ValidateClassFromITableIndexCP: + reloRecord = new (storage) TR_RelocationRecordValidateClassFromITableIndexCP(reloRuntime, record); + break; + 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; + case TR_ValidateClassChain: + reloRecord = new (storage) TR_RelocationRecordValidateClassChain(reloRuntime, record); + break; + case TR_ValidateRomClass: + reloRecord = new (storage) TR_RelocationRecordValidateRomClass(reloRuntime, record); + break; + case TR_ValidatePrimitiveClass: + reloRecord = new (storage) TR_RelocationRecordValidatePrimitiveClass(reloRuntime, record); + break; + case TR_ValidateMethodFromInlinedSite: + reloRecord = new (storage) TR_RelocationRecordValidateMethodFromInlinedSite(reloRuntime, record); + break; + case TR_ValidateMethodByName: + reloRecord = new (storage) TR_RelocationRecordValidateMethodByName(reloRuntime, record); + break; + case TR_ValidateMethodFromClass: + reloRecord = new (storage) TR_RelocationRecordValidateMethodFromClass(reloRuntime, record); + break; + case TR_ValidateStaticMethodFromCP: + reloRecord = new (storage) TR_RelocationRecordValidateStaticMethodFromCP(reloRuntime, record); + break; + case TR_ValidateSpecialMethodFromCP: + reloRecord = new (storage) TR_RelocationRecordValidateSpecialMethodFromCP(reloRuntime, record); + break; + case TR_ValidateVirtualMethodFromCP: + reloRecord = new (storage) TR_RelocationRecordValidateVirtualMethodFromCP(reloRuntime, record); + break; + case TR_ValidateVirtualMethodFromOffset: + reloRecord = new (storage) TR_RelocationRecordValidateVirtualMethodFromOffset(reloRuntime, record); + break; + case TR_ValidateInterfaceMethodFromCP: + reloRecord = new (storage) TR_RelocationRecordValidateInterfaceMethodFromCP(reloRuntime, record); + break; + case TR_ValidateImproperInterfaceMethodFromCP: + reloRecord = new (storage) TR_RelocationRecordValidateImproperInterfaceMethodFromCP(reloRuntime, record); + break; + case TR_ValidateMethodFromClassAndSig: + reloRecord = new (storage) TR_RelocationRecordValidateMethodFromClassAndSig(reloRuntime, record); + break; + case TR_ValidateStackWalkerMaySkipFramesRecord: + reloRecord = new (storage) TR_RelocationRecordValidateStackWalkerMaySkipFrames(reloRuntime, record); + break; + case TR_ValidateArrayClassFromJavaVM: + reloRecord = new (storage) TR_RelocationRecordValidateArrayClassFromJavaVM(reloRuntime, record); + break; + case TR_ValidateClassInfoIsInitialized: + reloRecord = new (storage) TR_RelocationRecordValidateClassInfoIsInitialized(reloRuntime, record); + break; + case TR_ValidateMethodFromSingleImplementer: + reloRecord = new (storage) TR_RelocationRecordValidateMethodFromSingleImpl(reloRuntime, record); + break; + case TR_ValidateMethodFromSingleInterfaceImplementer: + reloRecord = new (storage) TR_RelocationRecordValidateMethodFromSingleInterfaceImpl(reloRuntime, record); + break; + case TR_ValidateMethodFromSingleAbstractImplementer: + reloRecord = new (storage) TR_RelocationRecordValidateMethodFromSingleAbstractImpl(reloRuntime, record); + break; + case TR_SymbolFromManager: + reloRecord = new (storage) TR_RelocationRecordSymbolFromManager(reloRuntime, record); break; default: // TODO: error condition @@ -1205,7 +1159,7 @@ TR_RelocationRecordConstantPoolWithIndex::getInterfaceMethodFromCP(TR_Relocation TR_PersistentCHTable * chTable = reloRuntime->getPersistentInfo()->getPersistentCHTable(); TR_ResolvedMethod *callerResolvedMethod = fe->createResolvedMethod(trMemory, callerMethod, NULL); - TR_ResolvedMethod *calleeResolvedMethod = chTable->findSingleInterfaceImplementer(interfaceClass, cpIndex, callerResolvedMethod, reloRuntime->comp()); + TR_ResolvedMethod *calleeResolvedMethod = chTable->findSingleInterfaceImplementer(interfaceClass, cpIndex, callerResolvedMethod, reloRuntime->comp(), false, false); if (calleeResolvedMethod) { @@ -1221,6 +1175,60 @@ TR_RelocationRecordConstantPoolWithIndex::getInterfaceMethodFromCP(TR_Relocation return calleeMethod; } +TR_OpaqueMethodBlock * +TR_RelocationRecordConstantPoolWithIndex::getAbstractMethodFromCP(TR_RelocationRuntime *reloRuntime, void *void_cp, int32_t cpIndex, TR_OpaqueMethodBlock *callerMethod) + { + TR_RelocationRuntimeLogger *reloLogger = reloRuntime->reloLogger(); + TR_RelocationRecordInlinedMethodPrivateData *reloPrivateData = &(privateData()->inlinedMethod); + + J9JavaVM *javaVM = reloRuntime->javaVM(); + TR_J9VMBase *fe = reloRuntime->fej9(); + TR_Memory *trMemory = reloRuntime->trMemory(); + + J9ConstantPool *cp = (J9ConstantPool *) void_cp; + J9ROMMethodRef *romMethodRef = (J9ROMMethodRef *)&cp->romConstantPool[cpIndex]; + + TR_OpaqueMethodBlock *calleeMethod = NULL; + TR_OpaqueClassBlock *abstractClass = NULL; + UDATA vTableOffset = (UDATA)-1; + J9Method *method = NULL; + + { + TR::VMAccessCriticalSection getAbstractlMethodFromCP(reloRuntime->fej9()); + abstractClass = (TR_OpaqueClassBlock *) javaVM->internalVMFunctions->resolveClassRef(reloRuntime->currentThread(), + cp, + romMethodRef->classRefCPIndex, + J9_RESOLVE_FLAG_AOT_LOAD_TIME); + + vTableOffset = javaVM->internalVMFunctions->resolveVirtualMethodRefInto(reloRuntime->currentThread(), + cp, + cpIndex, + J9_RESOLVE_FLAG_AOT_LOAD_TIME, + &method, + NULL); + } + + if (abstractClass && method) + { + int32_t vftSlot = (int32_t)(-(vTableOffset - J9JIT_INTERP_VTABLE_OFFSET)); + TR_PersistentCHTable * chTable = reloRuntime->getPersistentInfo()->getPersistentCHTable(); + TR_ResolvedMethod *callerResolvedMethod = fe->createResolvedMethod(trMemory, callerMethod, NULL); + + TR_ResolvedMethod *calleeResolvedMethod = chTable->findSingleAbstractImplementer(abstractClass, vftSlot, callerResolvedMethod, reloRuntime->comp(), false, false); + + if (calleeResolvedMethod) + { + if (!calleeResolvedMethod->virtualMethodIsOverridden()) + calleeMethod = calleeResolvedMethod->getPersistentIdentifier(); + else + RELO_LOG(reloLogger, 6, "\tgetMethodFromCP: callee method overridden\n"); + } + } + + reloPrivateData->_receiverClass = abstractClass; + return calleeMethod; + } + // TR_HelperAddress char * TR_RelocationRecordHelperAddress::name() @@ -1964,6 +1972,12 @@ TR_RelocationRecordInlinedAllocation::preparePrivateData(TR_RelocationRuntime *r TR_J9VMBase *fe = reloRuntime->fej9(); J9Class *clazz; + if (reloRuntime->comp()->getOption(TR_UseSymbolValidationManager)) + { + uint16_t classID = (uint16_t)cpIndex(reloTarget); + clazz = (J9Class *)reloRuntime->comp()->getSymbolValidationManager()->getSymbolFromID(classID); + } + else { TR::VMAccessCriticalSection preparePrivateData(fe); clazz = javaVM->internalVMFunctions->resolveClassRef(javaVM->internalVMFunctions->currentVMThread(javaVM), @@ -2197,7 +2211,34 @@ TR_RelocationRecordInlinedMethod::validateClassesSame(TR_RelocationRuntime *relo { J9JavaVM *javaVM = reloRuntime->jitConfig()->javaVM; void *romClass = reloRuntime->fej9()->sharedCache()->pointerFromOffsetInSharedCache((void *) romClassOffsetInSharedCache(reloTarget)); - J9Method *currentMethod = (J9Method *) getMethodFromCP(reloRuntime, cp, cpIndex(reloTarget), (TR_OpaqueMethodBlock *) callerMethod); + J9Method *currentMethod; + + TR_RelocationRecordInlinedMethodPrivateData *reloPrivateData = &(privateData()->inlinedMethod); + + if (reloRuntime->comp()->getOption(TR_UseSymbolValidationManager)) + { + TR_RelocationRecordInlinedMethodPrivateData *reloPrivateData = &(privateData()->inlinedMethod); + + uintptrj_t data = (uintptrj_t)cpIndex(reloTarget); + uint16_t methodID = (uint16_t)(data & 0xFFFF); + uint16_t receiverClassID = (uint16_t)((data >> 16) & 0xFFFF); + + currentMethod = (J9Method *)reloRuntime->comp()->getSymbolValidationManager()->getSymbolFromID(methodID); + reloPrivateData->_receiverClass = (TR_OpaqueClassBlock *)reloRuntime->comp()->getSymbolValidationManager()->getSymbolFromID(receiverClassID); + + if (reloFlags(reloTarget) != inlinedMethodIsStatic && reloFlags(reloTarget) != inlinedMethodIsSpecial) + { + TR_ResolvedMethod *calleeResolvedMethod = reloRuntime->fej9()->createResolvedMethod(reloRuntime->comp()->trMemory(), + (TR_OpaqueMethodBlock *)currentMethod, + NULL); + if (calleeResolvedMethod->virtualMethodIsOverridden()) + currentMethod = NULL; + } + } + else + { + currentMethod = (J9Method *) getMethodFromCP(reloRuntime, cp, cpIndex(reloTarget), (TR_OpaqueMethodBlock *) callerMethod); + } if (currentMethod != NULL && (reloRuntime->fej9()->isAnyMethodTracingEnabled((TR_OpaqueMethodBlock *) currentMethod) || @@ -2524,6 +2565,44 @@ TR_RelocationRecordInlinedInterfaceMethod::getMethodFromCP(TR_RelocationRuntime return getInterfaceMethodFromCP(reloRuntime, void_cp, cpIndex, callerMethod); } +// TR_InlinedAbstractMethodWithNopGuard +char * +TR_RelocationRecordInlinedAbstractMethodWithNopGuard::name() + { + return "TR_InlinedAbstractMethodWithNopGuard"; + } + +TR_OpaqueMethodBlock * +TR_RelocationRecordInlinedAbstractMethodWithNopGuard::getMethodFromCP(TR_RelocationRuntime *reloRuntime, void *void_cp, int32_t cpIndex, TR_OpaqueMethodBlock *callerMethod) + { + return getAbstractMethodFromCP(reloRuntime, void_cp, cpIndex, callerMethod); + } + +void +TR_RelocationRecordInlinedAbstractMethodWithNopGuard::createAssumptions(TR_RelocationRuntime *reloRuntime, uint8_t *reloLocation) + { + TR_RelocationRecordInlinedMethodPrivateData *reloPrivateData = &(privateData()->inlinedMethod); + TR_PersistentCHTable *table = reloRuntime->getPersistentInfo()->getPersistentCHTable(); + List sites(reloRuntime->comp()->trMemory()); + TR_VirtualGuardSite site; + site.setLocation(reloLocation); + site.setDestination(reloPrivateData->_destination); + sites.add(&site); + TR_ClassQueries::addAnAssumptionForEachSubClass(table, table->findClassInfo(reloPrivateData->_receiverClass), sites, reloRuntime->comp()); + } + +void +TR_RelocationRecordInlinedAbstractMethodWithNopGuard::updateFailedStats(TR_AOTStats *aotStats) + { + aotStats->abstractMethods.numFailedValidations++; + } + +void +TR_RelocationRecordInlinedAbstractMethodWithNopGuard::updateSucceededStats(TR_AOTStats *aotStats) + { + aotStats->abstractMethods.numSucceededValidations++; + } + // TR_ProfiledInlinedMethod char * TR_RelocationRecordProfiledInlinedMethod::name() @@ -3137,6 +3216,883 @@ TR_RelocationRecordValidateArbitraryClass::applyRelocation(TR_RelocationRuntime } +int32_t +TR_RelocationRecordValidateRootClass::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateRootClassBinaryTemplate *)_record)->_classID); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classID %d\n", classID); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateRootClassRecord(classID)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateClassByName::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassByNameBinaryTemplate *)_record)->_classID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassByNameBinaryTemplate *)_record)->_beholderID); + char primitiveType = (char)reloTarget->loadUnsigned8b((uint8_t *) &((TR_RelocationRecordValidateClassByNameBinaryTemplate *)_record)->_primitiveType); + void *romClassOffset = (void *)reloTarget->loadRelocationRecordValue((uintptrj_t *) &((TR_RelocationRecordValidateClassByNameBinaryTemplate *)_record)->_romClassOffsetInSCC); + void *romClass = reloRuntime->fej9()->sharedCache()->pointerFromOffsetInSharedCache(romClassOffset); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classID %d\n", classID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: primitiveType %c\n", primitiveType); + reloRuntime->reloLogger()->printf("\tapplyRelocation: romClass %p\n", romClass); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateClassByNameRecord(classID, beholderID, static_cast(romClass), primitiveType)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateProfiledClass::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateProfiledClassBinaryTemplate *)_record)->_classID); + char primitiveType = (char)reloTarget->loadUnsigned8b((uint8_t *) &((TR_RelocationRecordValidateProfiledClassBinaryTemplate *)_record)->_primitiveType); + + void *classChainForCLOffset = (void *)reloTarget->loadRelocationRecordValue((uintptrj_t *) &((TR_RelocationRecordValidateProfiledClassBinaryTemplate *)_record)->_classChainOffsetForCLInScc); + void *classChainForCL = reloRuntime->fej9()->sharedCache()->pointerFromOffsetInSharedCache(classChainForCLOffset); + + void *classChainOffset = (void *)reloTarget->loadRelocationRecordValue((uintptrj_t *) &((TR_RelocationRecordValidateProfiledClassBinaryTemplate *)_record)->_classChainOffsetInSCC); + void *classChain = reloRuntime->fej9()->sharedCache()->pointerFromOffsetInSharedCache(classChainOffset); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classID %d\n", classID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: primitiveType %c\n", primitiveType); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classChainForCL %p\n", classChainForCL); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classChain %p\n", classChain); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateProfiledClassRecord(classID, primitiveType, classChainForCL, classChain)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateClassFromCP::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassFromCPBinaryTemplate *)_record)->_classID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassFromCPBinaryTemplate *)_record)->_beholderID); + uint32_t cpIndex = reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateClassFromCPBinaryTemplate *)_record)->_cpIndex); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classID %d\n", classID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: cpIndex %d\n", cpIndex); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateClassFromCPRecord(classID, beholderID, cpIndex)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateDefiningClassFromCP::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateDefiningClassFromCPBinaryTemplate *)_record)->_classID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateDefiningClassFromCPBinaryTemplate *)_record)->_beholderID); + uint32_t cpIndex = reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateDefiningClassFromCPBinaryTemplate *)_record)->_cpIndex); + bool isStatic = (bool)reloTarget->loadUnsigned8b((uint8_t *) &((TR_RelocationRecordValidateDefiningClassFromCPBinaryTemplate *)_record)->_isStatic); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classID %d\n", classID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: cpIndex %d\n", cpIndex); + reloRuntime->reloLogger()->printf("\tapplyRelocation: isStatic %s\n", isStatic ? "true" : "false"); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateDefiningClassFromCPRecord(classID, beholderID, cpIndex, isStatic)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateStaticClassFromCP::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateStaticClassFromCPBinaryTemplate *)_record)->_classID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateStaticClassFromCPBinaryTemplate *)_record)->_beholderID); + uint32_t cpIndex = reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateStaticClassFromCPBinaryTemplate *)_record)->_cpIndex); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classID %d\n", classID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: cpIndex %d\n", cpIndex); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateStaticClassFromCPRecord(classID, beholderID, cpIndex)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateClassFromMethod::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassFromMethodBinaryTemplate *)_record)->_classID); + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassFromMethodBinaryTemplate *)_record)->_methodID); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classID %d\n", classID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateClassFromMethodRecord(classID, methodID)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateComponentClassFromArrayClass::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t componentClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateCompFromArrayBinaryTemplate *)_record)->_componentClassID); + uint16_t arrayClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateCompFromArrayBinaryTemplate *)_record)->_arrayClassID); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: componentClassID %d\n", componentClassID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: arrayClassID %d\n", arrayClassID); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateComponentClassFromArrayClassRecord(componentClassID, arrayClassID)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateArrayClassFromComponentClass::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t arrayClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateArrayFromCompBinaryTemplate *)_record)->_arrayClassID); + uint16_t componentClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateArrayFromCompBinaryTemplate *)_record)->_componentClassID); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: arrayClassID %d\n", arrayClassID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: componentClassID %d\n", componentClassID); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateArrayClassFromComponentClassRecord(arrayClassID, componentClassID)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateSuperClassFromClass::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t superClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateSuperClassFromClassBinaryTemplate *)_record)->_superClassID); + uint16_t childClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateSuperClassFromClassBinaryTemplate *)_record)->_childClassID); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: superClassID %d\n", superClassID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: childClassID %d\n", childClassID); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateSuperClassFromClassRecord(superClassID, childClassID)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateClassInstanceOfClass::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classOneID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassInstanceOfClassBinaryTemplate *)_record)->_classOneID); + uint16_t classTwoID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassInstanceOfClassBinaryTemplate *)_record)->_classTwoID); + bool objectTypeIsFixed = (bool)reloTarget->loadUnsigned8b((uint8_t *) &((TR_RelocationRecordValidateClassInstanceOfClassBinaryTemplate *)_record)->_objectTypeIsFixed); + bool castTypeIsFixed = (bool)reloTarget->loadUnsigned8b((uint8_t *) &((TR_RelocationRecordValidateClassInstanceOfClassBinaryTemplate *)_record)->_castTypeIsFixed); + bool isInstanceOf = (bool)reloTarget->loadUnsigned8b((uint8_t *) &((TR_RelocationRecordValidateClassInstanceOfClassBinaryTemplate *)_record)->_isInstanceOf); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classOneID %d\n", classOneID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classTwoID %d\n", classTwoID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: objectTypeIsFixed %s\n", objectTypeIsFixed ? "true" : "false'"); + reloRuntime->reloLogger()->printf("\tapplyRelocation: castTypeIsFixed %s\n", castTypeIsFixed ? "true" : "false'"); + reloRuntime->reloLogger()->printf("\tapplyRelocation: isInstanceOf %s\n", isInstanceOf ? "true" : "false'"); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateClassInstanceOfClassRecord(classOneID, classTwoID, objectTypeIsFixed, castTypeIsFixed, isInstanceOf)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateSystemClassByName::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t systemClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateSystemClassByNameBinaryTemplate *)_record)->_systemClassID); + void *romClassOffset = (void *)reloTarget->loadRelocationRecordValue((uintptrj_t *) &((TR_RelocationRecordValidateSystemClassByNameBinaryTemplate *)_record)->_romClassOffsetInSCC); + void *romClass = reloRuntime->fej9()->sharedCache()->pointerFromOffsetInSharedCache(romClassOffset); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: systemClassID %d\n", systemClassID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: romClass %p\n", romClass); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateSystemClassByNameRecord(systemClassID, static_cast(romClass))) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateClassFromITableIndexCP::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassFromITableIndexCPBinaryTemplate *)_record)->_classID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassFromITableIndexCPBinaryTemplate *)_record)->_beholderID); + uint32_t cpIndex = reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateClassFromITableIndexCPBinaryTemplate *)_record)->_cpIndex); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classID %d\n", classID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: cpIndex %d\n", cpIndex); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateClassFromITableIndexCPRecord(classID, beholderID, cpIndex)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateDeclaringClassFromFieldOrStatic::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateDeclaringClassFromFieldOrStaticBinaryTemplate *)_record)->_classID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateDeclaringClassFromFieldOrStaticBinaryTemplate *)_record)->_beholderID); + uint32_t cpIndex = reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateDeclaringClassFromFieldOrStaticBinaryTemplate *)_record)->_cpIndex); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classID %d\n", classID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: cpIndex %d\n", cpIndex); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateDeclaringClassFromFieldOrStaticRecord(classID, beholderID, cpIndex)) + return 0; + else + 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) + { + uint16_t childClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateConcreteSubFromClassBinaryTemplate *)_record)->_childClassID); + uint16_t superClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateConcreteSubFromClassBinaryTemplate *)_record)->_superClassID); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: childClassID %d\n", childClassID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: superClassID %d\n", superClassID); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateConcreteSubClassFromClassRecord(childClassID, superClassID)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateClassChain::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassChainBinaryTemplate *)_record)->_classID); + void *classChainOffset = (void *)reloTarget->loadRelocationRecordValue((uintptrj_t *) &((TR_RelocationRecordValidateClassChainBinaryTemplate *)_record)->_classChainOffsetInSCC); + void *classChain = reloRuntime->fej9()->sharedCache()->pointerFromOffsetInSharedCache(classChainOffset); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classID %d\n", classID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classChain %p\n", classChain); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateClassChainRecord(classID, classChain)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateRomClass::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateRomClassBinaryTemplate *)_record)->_classID); + void *romClassOffset = (void *)reloTarget->loadRelocationRecordValue((uintptrj_t *) &((TR_RelocationRecordValidateRomClassBinaryTemplate *)_record)->_romClassOffsetInSCC); + void *romClass = reloRuntime->fej9()->sharedCache()->pointerFromOffsetInSharedCache(romClassOffset); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classID %d\n", classID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: romClass %p\n", romClass); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateRomClassRecord(classID, static_cast(romClass))) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidatePrimitiveClass::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidatePrimitiveClassBinaryTemplate *)_record)->_classID); + char primitiveType = (char)reloTarget->loadUnsigned8b((uint8_t *) &((TR_RelocationRecordValidatePrimitiveClassBinaryTemplate *)_record)->_primitiveType); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classID %d\n", classID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: primitiveType %c\n", primitiveType); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validatePrimitiveClassRecord(classID, primitiveType)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateMethodFromInlinedSite::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromInlSiteBinaryTemplate *)_record)->_methodID); + uint32_t inlinedSiteIndex = reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateMethodFromInlSiteBinaryTemplate *)_record)->_inlinedSiteIndex); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: inlinedSiteIndex %d\n", inlinedSiteIndex); + } + + TR_InlinedCallSite *inlinedCallSite = (TR_InlinedCallSite *)getInlinedCallSiteArrayElement(reloRuntime->exceptionTable(), inlinedSiteIndex); + TR_OpaqueMethodBlock *method = inlinedCallSite->_methodInfo; + + if (reloRuntime->comp()->getSymbolValidationManager()->validateMethodFromInlinedSiteRecord(methodID, method)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateMethodByName::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodByNameBinaryTemplate *)_record)->_methodID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodByNameBinaryTemplate *)_record)->_beholderID); + + void *romClassOffset = (void *)reloTarget->loadRelocationRecordValue((uintptrj_t *) &((TR_RelocationRecordValidateMethodByNameBinaryTemplate *)_record)->_romClassOffsetInSCC); + void *romClass = reloRuntime->fej9()->sharedCache()->pointerFromOffsetInSharedCache(romClassOffset); + + void *romMethodOffset = (void *)reloTarget->loadRelocationRecordValue((uintptrj_t *) &((TR_RelocationRecordValidateMethodByNameBinaryTemplate *)_record)->_romMethodOffsetInSCC); + void *romMethod = reloRuntime->fej9()->sharedCache()->pointerFromOffsetInSharedCache(romMethodOffset); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: romClass %p\n", romClass); + reloRuntime->reloLogger()->printf("\tapplyRelocation: romMethod %p\n", romMethod); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateMethodByNameRecord(methodID, beholderID, static_cast(romClass), static_cast(romMethod))) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateMethodFromClass::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromClassBinaryTemplate *)_record)->_methodID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromClassBinaryTemplate *)_record)->_beholderID); + uint32_t index = reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateMethodFromClassBinaryTemplate *)_record)->_index); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: index %d\n", index); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateMethodFromClassRecord(methodID, beholderID, index)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateStaticMethodFromCP::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateStaticMethodFromCPBinaryTemplate *)_record)->_methodID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateStaticMethodFromCPBinaryTemplate *)_record)->_beholderID); + uint32_t cpIndex = reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateStaticMethodFromCPBinaryTemplate *)_record)->_cpIndex); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: cpIndex %d\n", cpIndex); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateStaticMethodFromCPRecord(methodID, beholderID, cpIndex)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateSpecialMethodFromCP::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateSpecialMethodFromCPBinaryTemplate *)_record)->_methodID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateSpecialMethodFromCPBinaryTemplate *)_record)->_beholderID); + uint32_t cpIndex = reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateSpecialMethodFromCPBinaryTemplate *)_record)->_cpIndex); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: cpIndex %d\n", cpIndex); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateSpecialMethodFromCPRecord(methodID, beholderID, cpIndex)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateVirtualMethodFromCP::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateVirtualMethodFromCPBinaryTemplate *)_record)->_methodID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateVirtualMethodFromCPBinaryTemplate *)_record)->_beholderID); + uint32_t cpIndex = reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateVirtualMethodFromCPBinaryTemplate *)_record)->_cpIndex); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: cpIndex %d\n", cpIndex); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateVirtualMethodFromCPRecord(methodID, beholderID, cpIndex)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateVirtualMethodFromOffset::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateVirtualMethodFromOffsetBinaryTemplate *)_record)->_methodID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateVirtualMethodFromOffsetBinaryTemplate *)_record)->_beholderID); + uint32_t virtualCallOffset = reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateVirtualMethodFromOffsetBinaryTemplate *)_record)->_virtualCallOffset); + bool ignoreRtResolve = (bool)reloTarget->loadUnsigned8b((uint8_t *) &((TR_RelocationRecordValidateVirtualMethodFromOffsetBinaryTemplate *)_record)->_ignoreRtResolve); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: virtualCallOffset %d\n", virtualCallOffset); + reloRuntime->reloLogger()->printf("\tapplyRelocation: ignoreRtResolve %s\n", ignoreRtResolve ? "true" : "false"); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateVirtualMethodFromOffsetRecord(methodID, beholderID, virtualCallOffset, ignoreRtResolve)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateInterfaceMethodFromCP::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateInterfaceMethodFromCPBinaryTemplate *)_record)->_methodID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateInterfaceMethodFromCPBinaryTemplate *)_record)->_beholderID); + uint16_t lookupID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateInterfaceMethodFromCPBinaryTemplate *)_record)->_lookupID); + uint32_t cpIndex = reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateInterfaceMethodFromCPBinaryTemplate *)_record)->_cpIndex); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: lookupID %d\n", lookupID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: cpIndex %d\n", cpIndex); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateInterfaceMethodFromCPRecord(methodID, beholderID, lookupID, cpIndex)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateImproperInterfaceMethodFromCP::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateImproperInterfaceMethodFromCPBinaryTemplate *)_record)->_methodID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateImproperInterfaceMethodFromCPBinaryTemplate *)_record)->_beholderID); + uint32_t cpIndex = reloTarget->loadUnsigned32b((uint8_t *) &((TR_RelocationRecordValidateImproperInterfaceMethodFromCPBinaryTemplate *)_record)->_cpIndex); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: cpIndex %d\n", cpIndex); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateImproperInterfaceMethodFromCPRecord(methodID, beholderID, cpIndex)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateMethodFromClassAndSig::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromClassAndSigBinaryTemplate *)_record)->_methodID); + uint16_t methodClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromClassAndSigBinaryTemplate *)_record)->_methodClassID); + uint16_t beholderID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromClassAndSigBinaryTemplate *)_record)->_beholderID); + + void *romMethodOffset = (void *)reloTarget->loadRelocationRecordValue((uintptrj_t *) &((TR_RelocationRecordValidateMethodFromClassAndSigBinaryTemplate *)_record)->_romMethodOffsetInSCC); + void *romMethod = reloRuntime->fej9()->sharedCache()->pointerFromOffsetInSharedCache(romMethodOffset); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodClassID %d\n", methodClassID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: beholderID %d\n", beholderID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: romMethod %p\n", romMethod); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateMethodFromClassAndSignatureRecord(methodID, methodClassID, beholderID, static_cast(romMethod))) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateStackWalkerMaySkipFrames::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateStackWalkerMaySkipFramesBinaryTemplate *)_record)->_methodID); + uint16_t methodClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateStackWalkerMaySkipFramesBinaryTemplate *)_record)->_methodClassID); + bool skipFrames = reloTarget->loadUnsigned8b((uint8_t *) &((TR_RelocationRecordValidateStackWalkerMaySkipFramesBinaryTemplate *)_record)->_skipFrames); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodClassID %d\n", methodClassID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: skipFrames %s\n", skipFrames ? "true" : "false"); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateStackWalkerMaySkipFramesRecord(methodID, methodClassID, skipFrames)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateArrayClassFromJavaVM::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t arrayClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateArrayClassFromJavaVMBinaryTemplate *)_record)->_arrayClassID); + int32_t arrayClassIndex = reloTarget->loadSigned32b((uint8_t *) &((TR_RelocationRecordValidateArrayClassFromJavaVMBinaryTemplate *)_record)->_arrayClassIndex); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: arrayClassID %d\n", arrayClassID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: arrayClassIndex %d\n", arrayClassIndex); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateArrayClassFromJavaVM(arrayClassID, arrayClassIndex)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateClassInfoIsInitialized::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t classID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateClassInfoIsInitializedBinaryTemplate *)_record)->_classID); + bool wasInitialized = (bool)reloTarget->loadUnsigned8b((uint8_t *) &((TR_RelocationRecordValidateClassInfoIsInitializedBinaryTemplate *)_record)->_isInitialized); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: classID %d\n", classID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: wasInitialized %s\n", wasInitialized ? "true" : "false"); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateClassInfoIsInitializedRecord(classID, wasInitialized)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateMethodFromSingleImpl::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromSingleImplBinaryTemplate *)_record)->_methodID); + uint16_t thisClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromSingleImplBinaryTemplate *)_record)->_thisClassID); + int32_t cpIndexOrVftSlot = reloTarget->loadSigned32b((uint8_t *) &((TR_RelocationRecordValidateMethodFromSingleImplBinaryTemplate *)_record)->_cpIndexOrVftSlot); + uint16_t callerMethodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromSingleImplBinaryTemplate *)_record)->_callerMethodID); + uint16_t useGetResolvedInterfaceMethod = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromSingleImplBinaryTemplate *)_record)->_useGetResolvedInterfaceMethod);; + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: thisClassID %d\n", thisClassID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: cpIndexOrVftSlot %d\n", cpIndexOrVftSlot); + reloRuntime->reloLogger()->printf("\tapplyRelocation: callerMethodID %d\n", callerMethodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: useGetResolvedInterfaceMethod %d\n", useGetResolvedInterfaceMethod); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateMethodFromSingleImplementerRecord(methodID, + thisClassID, + cpIndexOrVftSlot, + callerMethodID, + (TR_YesNoMaybe)useGetResolvedInterfaceMethod)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateMethodFromSingleInterfaceImpl::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromSingleInterfaceImplBinaryTemplate *)_record)->_methodID); + uint16_t thisClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromSingleInterfaceImplBinaryTemplate *)_record)->_thisClassID); + int32_t cpIndex = reloTarget->loadSigned32b((uint8_t *) &((TR_RelocationRecordValidateMethodFromSingleInterfaceImplBinaryTemplate *)_record)->_cpIndex); + uint16_t callerMethodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromSingleInterfaceImplBinaryTemplate *)_record)->_callerMethodID); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: thisClassID %d\n", thisClassID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: cpIndex %d\n", cpIndex); + reloRuntime->reloLogger()->printf("\tapplyRelocation: callerMethodID %d\n", callerMethodID); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateMethodFromSingleInterfaceImplementerRecord(methodID, + thisClassID, + cpIndex, + callerMethodID)) + return 0; + else + return compilationAotClassReloFailure; + } + +int32_t +TR_RelocationRecordValidateMethodFromSingleAbstractImpl::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + uint16_t methodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromSingleAbstractImplBinaryTemplate *)_record)->_methodID); + uint16_t thisClassID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromSingleAbstractImplBinaryTemplate *)_record)->_thisClassID); + int32_t vftSlot = reloTarget->loadSigned32b((uint8_t *) &((TR_RelocationRecordValidateMethodFromSingleAbstractImplBinaryTemplate *)_record)->_vftSlot); + uint16_t callerMethodID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateMethodFromSingleAbstractImplBinaryTemplate *)_record)->_callerMethodID); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tapplyRelocation: methodID %d\n", methodID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: thisClassID %d\n", thisClassID); + reloRuntime->reloLogger()->printf("\tapplyRelocation: vftSlot %d\n", vftSlot); + reloRuntime->reloLogger()->printf("\tapplyRelocation: callerMethodID %d\n", callerMethodID); + } + + if (reloRuntime->comp()->getSymbolValidationManager()->validateMethodFromSingleAbstractImplementerRecord(methodID, + thisClassID, + vftSlot, + callerMethodID)) + return 0; + else + return compilationAotClassReloFailure; + } + +void +TR_RelocationRecordSymbolFromManager::preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) + { + TR_RelocationSymbolFromManagerPrivateData *reloPrivateData = &(privateData()->symbolFromManager); + + uint16_t symbolID = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordSymbolFromManagerBinaryTemplate *)_record)->_symbolID); + uint16_t symbolType = reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordSymbolFromManagerBinaryTemplate *)_record)->_symbolType); + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tpreparePrivateData: symbolID %d\n", symbolID); + reloRuntime->reloLogger()->printf("\tpreparePrivateData: symbolType %d\n", symbolType); + } + + reloPrivateData->_symbol = reloRuntime->comp()->getSymbolValidationManager()->getSymbolFromID(symbolID); + reloPrivateData->_symbolType = symbolType; + } + +int32_t +TR_RelocationRecordSymbolFromManager::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + TR_RelocationSymbolFromManagerPrivateData *reloPrivateData = &(privateData()->symbolFromManager); + + void *symbol = reloPrivateData->_symbol; + + if (reloRuntime->reloLogger()->logEnabled()) + { + reloRuntime->reloLogger()->printf("%s\n", name()); + reloRuntime->reloLogger()->printf("\tpreparePrivateData: symbol %p\n", symbol); + } + + if (symbol) + { + reloTarget->storeAddressSequence((uint8_t *)symbol, reloLocation, reloFlags(reloTarget)); + activatePointer(reloRuntime, reloTarget, reloLocation); + } + else + { + return compilationAotClassReloFailure; + } + + return 0; + } + +bool +TR_RelocationRecordSymbolFromManager::needsUnloadAssumptions(TR::SymbolType symbolType) + { + bool needsAssumptions = false; + switch (symbolType) + { + case TR::SymbolType::typeClass: + case TR::SymbolType::typeMethod: + needsAssumptions = true; + default: + needsAssumptions = false; + } + return needsAssumptions; + } + +bool +TR_RelocationRecordSymbolFromManager::needsRedefinitionAssumption(TR_RelocationRuntime *reloRuntime, uint8_t *reloLocation, TR_OpaqueClassBlock *clazz, TR::SymbolType symbolType) + { + if (!reloRuntime->options()->getOption(TR_EnableHCR)) + return false; + + bool needsAssumptions = false; + switch (symbolType) + { + case TR::SymbolType::typeClass: + needsAssumptions = TR::CodeGenerator::wantToPatchClassPointer(reloRuntime->comp(), clazz, reloLocation); + case TR::SymbolType::typeMethod: + needsAssumptions = true; + default: + needsAssumptions = false; + } + return needsAssumptions; + } + +void +TR_RelocationRecordSymbolFromManager::activatePointer(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation) + { + TR_RelocationSymbolFromManagerPrivateData *reloPrivateData = &(privateData()->symbolFromManager); + TR::SymbolType symbolType = (TR::SymbolType)reloPrivateData->_symbolType; + + TR_OpaqueClassBlock *clazz = NULL; + if (symbolType == TR::SymbolType::typeClass) + { + clazz = (TR_OpaqueClassBlock *)reloPrivateData->_symbol; + } + else if (symbolType == TR::SymbolType::typeMethod) + { + clazz = (TR_OpaqueClassBlock *)J9_CLASS_FROM_METHOD((J9Method *)(reloPrivateData->_symbol)); + } + + if (needsUnloadAssumptions(symbolType)) + { + if (!clazz) + { + TR_ASSERT(false, "clazz must exist to add Unload Assumptions!\n"); + reloRuntime->comp()->failCompilation("Failed to validate in activatePointer"); + } + + reloTarget->addPICtoPatchPtrOnClassUnload(clazz, reloLocation); + } + if (needsRedefinitionAssumption(reloRuntime, reloLocation, clazz, symbolType)) + { + if (!clazz) + { + TR_ASSERT(false, "clazz must exist to add Redefinition Assumptions!\n"); + reloRuntime->comp()->failCompilation("Failed to validate in activatePointer"); + } + + createClassRedefinitionPicSite((void *)reloPrivateData->_symbol, (void *) reloLocation, sizeof(uintptrj_t), false, reloRuntime->comp()->getMetadataAssumptionList()); + reloRuntime->comp()->setHasClassRedefinitionAssumptions(); + } + } + + // TR_HCR char * TR_RelocationRecordHCR::name() diff --git a/runtime/compiler/runtime/RelocationRecord.hpp b/runtime/compiler/runtime/RelocationRecord.hpp index 4658dac7291..5d38d03032d 100644 --- a/runtime/compiler/runtime/RelocationRecord.hpp +++ b/runtime/compiler/runtime/RelocationRecord.hpp @@ -39,6 +39,392 @@ class TR_RelocationTarget; struct TR_RelocationRecordBinaryTemplate; typedef TR_ExternalRelocationTargetKind TR_RelocationRecordType; +// These *BinaryTemplate structs describe the shape of the binary relocation records. +struct TR_RelocationRecordBinaryTemplate + { + uint8_t type(TR_RelocationTarget *reloTarget); + + uint16_t _size; + uint8_t _type; + uint8_t _flags; + +#if defined(TR_HOST_64BIT) + uint32_t _extra; +#endif + }; + +// Generating 32-bit code on a 64-bit machine or vice-versa won't work because the alignment won't +// be right. Relying on inheritance in the structures here means padding is automatically inserted +// at each inheritance boundary: this inserted padding won't match across 32-bit and 64-bit platforms. +// Making as many fields as possible UDATA should minimize the differences and gives the most freedom +// in the hierarchy of binary relocation record structures, but the header definitely has an inheritance +// boundary at offset 4B. + +struct TR_RelocationRecordHelperAddressBinaryTemplate + { + uint16_t _size; + uint8_t _type; + uint8_t _flags; + uint32_t _helperID; + }; + +struct TR_RelocationRecordPicTrampolineBinaryTemplate + { + uint16_t _size; + uint8_t _type; + uint8_t _flags; + uint32_t _numTrampolines; + }; + +struct TR_RelocationRecordWithInlinedSiteIndexBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + UDATA _inlinedSiteIndex; + }; + +struct TR_RelocationRecordValidateArbitraryClassBinaryTemplate : public TR_RelocationRecordBinaryTemplate //public TR_RelocationRecordWithInlinedSiteIndexBinaryTemplate + { + UDATA _loaderClassChainOffset; + UDATA _classChainOffsetForClassBeingValidated; + }; + + +struct TR_RelocationRecordWithOffsetBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + UDATA _offset; + }; + +struct TR_RelocationRecordConstantPoolBinaryTemplate : public TR_RelocationRecordWithInlinedSiteIndexBinaryTemplate + { + UDATA _constantPool; + }; + +struct TR_RelocationRecordConstantPoolWithIndexBinaryTemplate : public TR_RelocationRecordConstantPoolBinaryTemplate + { + UDATA _index; + }; + +typedef TR_RelocationRecordConstantPoolWithIndexBinaryTemplate TR_RelocationRecordClassObjectBinaryTemplate; + +struct TR_RelocationRecordJ2IVirtualThunkPointerBinaryTemplate : public TR_RelocationRecordConstantPoolBinaryTemplate + { + IDATA _offsetToJ2IVirtualThunkPointer; + }; + +struct TR_RelocationRecordInlinedAllocationBinaryTemplate : public TR_RelocationRecordConstantPoolWithIndexBinaryTemplate + { + UDATA _branchOffset; + }; + +struct TR_RelocationRecordVerifyClassObjectForAllocBinaryTemplate : public TR_RelocationRecordInlinedAllocationBinaryTemplate + { + UDATA _allocationSize; + }; + +struct TR_RelocationRecordRomClassFromCPBinaryTemplate : public TR_RelocationRecordConstantPoolWithIndexBinaryTemplate + { + UDATA _romClassOffsetInSharedCache; + }; + +typedef TR_RelocationRecordRomClassFromCPBinaryTemplate TR_RelocationRecordInlinedMethodBinaryTemplate; + +struct TR_RelocationRecordNopGuardBinaryTemplate : public TR_RelocationRecordInlinedMethodBinaryTemplate + { + UDATA _destinationAddress; + }; + +typedef TR_RelocationRecordNopGuardBinaryTemplate TR_RelocationRecordInlinedStaticMethodWithNopGuardBinaryTemplate; +typedef TR_RelocationRecordNopGuardBinaryTemplate TR_RelocationRecordInlinedSpecialMethodWithNopGuardBinaryTemplate; +typedef TR_RelocationRecordNopGuardBinaryTemplate TR_RelocationRecordInlinedVirtualMethodWithNopGuardBinaryTemplate; +typedef TR_RelocationRecordNopGuardBinaryTemplate TR_RelocationRecordInlinedInterfaceMethodWithNopGuardBinaryTemplate; + + +struct TR_RelocationRecordProfiledInlinedMethodBinaryTemplate : TR_RelocationRecordInlinedMethodBinaryTemplate + { + UDATA _classChainIdentifyingLoaderOffsetInSharedCache; + UDATA _classChainForInlinedMethod; + UDATA _vTableSlot; + }; + +typedef TR_RelocationRecordProfiledInlinedMethodBinaryTemplate TR_RelocationRecordProfiledGuardBinaryTemplate; +typedef TR_RelocationRecordProfiledInlinedMethodBinaryTemplate TR_RelocationRecordProfiledClassGuardBinaryTemplate; +typedef TR_RelocationRecordProfiledInlinedMethodBinaryTemplate TR_RelocationRecordProfiledMethodGuardBinaryTemplate; + + +typedef TR_RelocationRecordBinaryTemplate TR_RelocationRecordRamMethodBinaryTemplate; + +typedef TR_RelocationRecordBinaryTemplate TR_RelocationRecordArrayCopyHelperTemplate; + +struct TR_RelocationRecordMethodTracingCheckBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + UDATA _destinationAddress; + }; + +struct TR_RelocationRecordValidateClassBinaryTemplate : public TR_RelocationRecordConstantPoolWithIndexBinaryTemplate + { + UDATA _classChainOffsetInSharedCache; + }; + +typedef TR_RelocationRecordRomClassFromCPBinaryTemplate TR_RelocationRecordValidateStaticFieldBinaryTemplate; + +struct TR_RelocationRecordDataAddressBinaryTemplate : public TR_RelocationRecordConstantPoolWithIndexBinaryTemplate + { + UDATA _offset; + }; + +struct TR_RelocationRecordPointerBinaryTemplate : TR_RelocationRecordWithInlinedSiteIndexBinaryTemplate + { + UDATA _classChainIdentifyingLoaderOffsetInSharedCache; + UDATA _classChainForInlinedMethod; + }; + +typedef TR_RelocationRecordPointerBinaryTemplate TR_RelocationRecordClassPointerBinaryTemplate; +struct TR_RelocationRecordMethodPointerBinaryTemplate : TR_RelocationRecordPointerBinaryTemplate + { + UDATA _vTableSlot; + }; +struct TR_RelocationRecordEmitClassBinaryTemplate : public TR_RelocationRecordWithInlinedSiteIndexBinaryTemplate + { + int32_t _bcIndex; +#if defined(TR_HOST_64BIT) + uint32_t _extra; +#endif + }; + +struct TR_RelocationRecordDebugCounterBinaryTemplate : public TR_RelocationRecordWithInlinedSiteIndexBinaryTemplate + { + UDATA _bcIndex; + UDATA _offsetOfNameString; + UDATA _delta; + UDATA _fidelity; + UDATA _staticDelta; + }; + +typedef TR_RelocationRecordBinaryTemplate TR_RelocationRecordClassUnloadAssumptionBinaryTemplate; + +struct TR_RelocationRecordValidateRootClassBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _classID; + }; + +struct TR_RelocationRecordValidateClassByNameBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _classID; + uint16_t _beholderID; + char _primitiveType; + UDATA _romClassOffsetInSCC; + }; + +struct TR_RelocationRecordValidateProfiledClassBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _classID; + char _primitiveType; + UDATA _classChainOffsetInSCC; + UDATA _classChainOffsetForCLInScc; + }; + +struct TR_RelocationRecordValidateClassFromCPBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _classID; + uint16_t _beholderID; + uint32_t _cpIndex; + }; + +struct TR_RelocationRecordValidateDefiningClassFromCPBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + bool _isStatic; + uint16_t _classID; + uint16_t _beholderID; + uint32_t _cpIndex; + }; + +typedef TR_RelocationRecordValidateClassFromCPBinaryTemplate TR_RelocationRecordValidateStaticClassFromCPBinaryTemplate; + +struct TR_RelocationRecordValidateClassFromMethodBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _classID; + uint16_t _methodID; + }; + +struct TR_RelocationRecordValidateCompFromArrayBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _componentClassID; + uint16_t _arrayClassID; + }; + +struct TR_RelocationRecordValidateArrayFromCompBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _arrayClassID; + uint16_t _componentClassID; + }; + +struct TR_RelocationRecordValidateSuperClassFromClassBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _superClassID; + uint16_t _childClassID; + }; + +struct TR_RelocationRecordValidateClassInstanceOfClassBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + bool _objectTypeIsFixed; + bool _castTypeIsFixed; + bool _isInstanceOf; + uint16_t _classOneID; + uint16_t _classTwoID; + }; + +struct TR_RelocationRecordValidateSystemClassByNameBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _systemClassID; + UDATA _romClassOffsetInSCC; + }; + +struct TR_RelocationRecordValidateClassFromITableIndexCPBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _classID; + uint16_t _beholderID; + uint32_t _cpIndex; + }; + +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; + uint16_t _superClassID; + }; + +struct TR_RelocationRecordValidateClassChainBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _classID; + UDATA _classChainOffsetInSCC; + }; + +struct TR_RelocationRecordValidateRomClassBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _classID; + UDATA _romClassOffsetInSCC; + }; + +struct TR_RelocationRecordValidatePrimitiveClassBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _classID; + char _primitiveType; + }; + +struct TR_RelocationRecordValidateMethodFromInlSiteBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + uint32_t _inlinedSiteIndex; + }; + +struct TR_RelocationRecordValidateMethodByNameBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + uint16_t _beholderID; + UDATA _romClassOffsetInSCC; + UDATA _romMethodOffsetInSCC; + }; + +struct TR_RelocationRecordValidateMethodFromClassBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + uint16_t _beholderID; + uint32_t _index; + }; + +struct TR_RelocationRecordValidateMethodFromCPBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + uint16_t _beholderID; + uint32_t _cpIndex; + }; + +typedef TR_RelocationRecordValidateMethodFromCPBinaryTemplate TR_RelocationRecordValidateStaticMethodFromCPBinaryTemplate; +typedef TR_RelocationRecordValidateMethodFromCPBinaryTemplate TR_RelocationRecordValidateSpecialMethodFromCPBinaryTemplate; +typedef TR_RelocationRecordValidateMethodFromCPBinaryTemplate TR_RelocationRecordValidateVirtualMethodFromCPBinaryTemplate; +typedef TR_RelocationRecordValidateMethodFromCPBinaryTemplate TR_RelocationRecordValidateImproperInterfaceMethodFromCPBinaryTemplate; + +struct TR_RelocationRecordValidateVirtualMethodFromOffsetBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + bool _ignoreRtResolve; + uint16_t _methodID; + uint16_t _beholderID; + uint32_t _virtualCallOffset; + }; + +struct TR_RelocationRecordValidateInterfaceMethodFromCPBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + uint16_t _beholderID; + uint16_t _lookupID; + uint32_t _cpIndex; + }; + +struct TR_RelocationRecordValidateMethodFromClassAndSigBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + uint16_t _methodClassID; + uint16_t _beholderID; + UDATA _romMethodOffsetInSCC; + }; + +struct TR_RelocationRecordValidateMethodFromSingleImplBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + uint16_t _thisClassID; + int32_t _cpIndexOrVftSlot; + uint16_t _callerMethodID; + uint16_t _useGetResolvedInterfaceMethod; + }; + +struct TR_RelocationRecordValidateMethodFromSingleInterfaceImplBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + uint16_t _thisClassID; + int32_t _cpIndex; + uint16_t _callerMethodID; + }; + +struct TR_RelocationRecordValidateMethodFromSingleAbstractImplBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + uint16_t _thisClassID; + int32_t _vftSlot; + uint16_t _callerMethodID; + }; + +struct TR_RelocationRecordValidateStackWalkerMaySkipFramesBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _methodID; + uint16_t _methodClassID; + bool _skipFrames; + }; + +struct TR_RelocationRecordValidateArrayClassFromJavaVMBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _arrayClassID; + int32_t _arrayClassIndex; + }; + +struct TR_RelocationRecordValidateClassInfoIsInitializedBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _classID; + bool _isInitialized; + }; + +struct TR_RelocationRecordSymbolFromManagerBinaryTemplate : public TR_RelocationRecordBinaryTemplate + { + uint16_t _symbolID; + uint16_t _symbolType; + }; + + extern char* AOTcgDiagOn; class TR_RelocationRecordGroup @@ -139,6 +525,12 @@ struct TR_RelocationRecordDebugCounterPrivateData const char *_name; }; +struct TR_RelocationSymbolFromManagerPrivateData + { + uint16_t _symbolType; + void *_symbol; + }; + union TR_RelocationRecordPrivateData { TR_RelocationRecordHelperAddressPrivateData helperAddress; @@ -152,6 +544,7 @@ union TR_RelocationRecordPrivateData TR_RelocationRecordMethodCallPrivateData methodCall; TR_RelocationRecordEmitClassPrivateData emitClass; TR_RelocationRecordDebugCounterPrivateData debugCounter; + TR_RelocationSymbolFromManagerPrivateData symbolFromManager; }; // TR_RelocationRecord is the base class for all relocation records. It is used for all queries on relocation @@ -176,6 +569,8 @@ class TR_RelocationRecord virtual void print(TR_RelocationRuntime *reloRuntime); virtual char *name() { return "TR_RelocationRecord"; } + virtual bool isValidationRecord() { return false; } + static TR_RelocationRecord *create(TR_RelocationRecord *storage, TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, TR_RelocationRecordBinaryTemplate *recordPointer); @@ -386,6 +781,7 @@ class TR_RelocationRecordConstantPoolWithIndex : public TR_RelocationRecordConst TR_OpaqueMethodBlock *getStaticMethodFromCP(TR_RelocationRuntime *reloRuntime, void *void_cp, int32_t cpIndex); TR_OpaqueMethodBlock *getSpecialMethodFromCP(TR_RelocationRuntime *reloRuntime, void *void_cp, int32_t cpIndex); TR_OpaqueMethodBlock *getInterfaceMethodFromCP(TR_RelocationRuntime *reloRuntime, void *void_cp, int32_t cpIndex, TR_OpaqueMethodBlock *callerMethod); + TR_OpaqueMethodBlock *getAbstractMethodFromCP(TR_RelocationRuntime *reloRuntime, void *void_cp, int32_t cpIndex, TR_OpaqueMethodBlock *callerMethod); virtual int32_t bytesInHeaderAndPayload(); }; @@ -814,6 +1210,19 @@ class TR_RelocationRecordInlinedInterfaceMethod: public TR_RelocationRecordInlin virtual TR_OpaqueMethodBlock *getMethodFromCP(TR_RelocationRuntime *reloRuntime, void *void_cp, int32_t cpindex, TR_OpaqueMethodBlock *callerMethod); }; +class TR_RelocationRecordInlinedAbstractMethodWithNopGuard : public TR_RelocationRecordNopGuard + { + public: + TR_RelocationRecordInlinedAbstractMethodWithNopGuard() {} + TR_RelocationRecordInlinedAbstractMethodWithNopGuard(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecordNopGuard(reloRuntime, record) {} + virtual char *name(); + private: + virtual TR_OpaqueMethodBlock *getMethodFromCP(TR_RelocationRuntime *reloRuntime, void *void_cp, int32_t cpindex, TR_OpaqueMethodBlock *callerMethod); + virtual void updateFailedStats(TR_AOTStats *aotStats); + virtual void updateSucceededStats(TR_AOTStats *aotStats); + virtual void createAssumptions(TR_RelocationRuntime *reloRuntime, uint8_t *reloLocation); + }; + class TR_RelocationRecordProfiledInlinedMethod : public TR_RelocationRecordInlinedMethod { public: @@ -1003,6 +1412,442 @@ class TR_RelocationRecordValidateArbitraryClass : public TR_RelocationRecord }; +/* SYMBOL VALIDATION MANAGER */ +class TR_RelocationRecordValidateRootClass : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateRootClass() {} + TR_RelocationRecordValidateRootClass(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateRootClass"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateRootClassBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateClassByName : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateClassByName() {} + TR_RelocationRecordValidateClassByName(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateClassByName"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateClassByNameBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateProfiledClass : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateProfiledClass() {} + TR_RelocationRecordValidateProfiledClass(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateProfiledClass"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateProfiledClassBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateClassFromCP : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateClassFromCP() {} + TR_RelocationRecordValidateClassFromCP(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateClassFromCP"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateClassFromCPBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateDefiningClassFromCP : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateDefiningClassFromCP() {} + TR_RelocationRecordValidateDefiningClassFromCP(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateDefiningClassFromCP"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateDefiningClassFromCPBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateStaticClassFromCP : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateStaticClassFromCP() {} + TR_RelocationRecordValidateStaticClassFromCP(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateStaticClassFromCP"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateStaticClassFromCPBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateClassFromMethod : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateClassFromMethod() {} + TR_RelocationRecordValidateClassFromMethod(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateClassFromMethod"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateClassFromMethodBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateComponentClassFromArrayClass : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateComponentClassFromArrayClass() {} + TR_RelocationRecordValidateComponentClassFromArrayClass(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateComponentClassFromArrayClass"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateCompFromArrayBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateArrayClassFromComponentClass : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateArrayClassFromComponentClass() {} + TR_RelocationRecordValidateArrayClassFromComponentClass(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateArrayClassFromComponentClass"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateArrayFromCompBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateSuperClassFromClass : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateSuperClassFromClass() {} + TR_RelocationRecordValidateSuperClassFromClass(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateSuperClassFromClass"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateSuperClassFromClassBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateClassInstanceOfClass : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateClassInstanceOfClass() {} + TR_RelocationRecordValidateClassInstanceOfClass(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateClassInstanceOfClass"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateClassInstanceOfClassBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateSystemClassByName : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateSystemClassByName() {} + TR_RelocationRecordValidateSystemClassByName(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateSystemClassByName"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateSystemClassByNameBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateClassFromITableIndexCP : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateClassFromITableIndexCP() {} + TR_RelocationRecordValidateClassFromITableIndexCP(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateClassFromITableIndexCP"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateClassFromITableIndexCPBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateDeclaringClassFromFieldOrStatic : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateDeclaringClassFromFieldOrStatic() {} + TR_RelocationRecordValidateDeclaringClassFromFieldOrStatic(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateDeclaringClassFromFieldOrStatic"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateDeclaringClassFromFieldOrStaticBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + 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: + TR_RelocationRecordValidateConcreteSubClassFromClass() {} + TR_RelocationRecordValidateConcreteSubClassFromClass(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateConcreteSubClassFromClass"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateConcreteSubFromClassBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateClassChain : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateClassChain() {} + TR_RelocationRecordValidateClassChain(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateClassChain"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateClassChainBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateRomClass : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateRomClass() {} + TR_RelocationRecordValidateRomClass(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateRomClass"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateRomClassBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidatePrimitiveClass : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidatePrimitiveClass() {} + TR_RelocationRecordValidatePrimitiveClass(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidatePrimitiveClass"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidatePrimitiveClassBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateMethodFromInlinedSite : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateMethodFromInlinedSite() {} + TR_RelocationRecordValidateMethodFromInlinedSite(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateMethodFromInlinedSite"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateMethodFromInlSiteBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateMethodByName : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateMethodByName() {} + TR_RelocationRecordValidateMethodByName(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateMethodByName"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateMethodByNameBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateMethodFromClass : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateMethodFromClass() {} + TR_RelocationRecordValidateMethodFromClass(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateMethodFromClass"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateMethodFromClassBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateStaticMethodFromCP : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateStaticMethodFromCP() {} + TR_RelocationRecordValidateStaticMethodFromCP(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateStaticMethodFromCP"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateStaticMethodFromCPBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateSpecialMethodFromCP : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateSpecialMethodFromCP() {} + TR_RelocationRecordValidateSpecialMethodFromCP(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateSpecialMethodFromCP"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateSpecialMethodFromCPBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateVirtualMethodFromCP : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateVirtualMethodFromCP() {} + TR_RelocationRecordValidateVirtualMethodFromCP(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateVirtualMethodFromCP"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateVirtualMethodFromCPBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateVirtualMethodFromOffset : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateVirtualMethodFromOffset() {} + TR_RelocationRecordValidateVirtualMethodFromOffset(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateVirtualMethodFromOffset"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateVirtualMethodFromOffsetBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateInterfaceMethodFromCP : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateInterfaceMethodFromCP() {} + TR_RelocationRecordValidateInterfaceMethodFromCP(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateInterfaceMethodFromCP"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateInterfaceMethodFromCPBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateImproperInterfaceMethodFromCP : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateImproperInterfaceMethodFromCP() {} + TR_RelocationRecordValidateImproperInterfaceMethodFromCP(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateImproperInterfaceMethodFromCP"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateImproperInterfaceMethodFromCPBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateMethodFromClassAndSig : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateMethodFromClassAndSig() {} + TR_RelocationRecordValidateMethodFromClassAndSig(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateMethodFromClassAndSig"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateMethodFromClassAndSigBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateStackWalkerMaySkipFrames : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateStackWalkerMaySkipFrames() {} + TR_RelocationRecordValidateStackWalkerMaySkipFrames(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateStackWalkerMaySkipFrames"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateStackWalkerMaySkipFramesBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateArrayClassFromJavaVM : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateArrayClassFromJavaVM() {} + TR_RelocationRecordValidateArrayClassFromJavaVM(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateArrayClassFromJavaVM"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateArrayClassFromJavaVMBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateClassInfoIsInitialized : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateClassInfoIsInitialized() {} + TR_RelocationRecordValidateClassInfoIsInitialized(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateClassInfoIsInitialized"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateClassInfoIsInitializedBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateMethodFromSingleImpl : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateMethodFromSingleImpl() {} + TR_RelocationRecordValidateMethodFromSingleImpl(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateMethodFromSingleImpl"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateMethodFromSingleImplBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateMethodFromSingleInterfaceImpl : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateMethodFromSingleInterfaceImpl() {} + TR_RelocationRecordValidateMethodFromSingleInterfaceImpl(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateMethodFromSingleInterfaceImpl"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateMethodFromSingleInterfaceImplBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordValidateMethodFromSingleAbstractImpl : public TR_RelocationRecord + { + public: + TR_RelocationRecordValidateMethodFromSingleAbstractImpl() {} + TR_RelocationRecordValidateMethodFromSingleAbstractImpl(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual bool isValidationRecord() { return true; } + virtual char *name() { return "TR_RelocationRecordValidateMethodFromSingleAbstractImpl"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordValidateMethodFromSingleAbstractImplBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget) {} + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + }; + +class TR_RelocationRecordSymbolFromManager : public TR_RelocationRecord + { + public: + TR_RelocationRecordSymbolFromManager() {} + TR_RelocationRecordSymbolFromManager(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecord(reloRuntime, record) {} + virtual char *name() { return "TR_RelocationRecordSymbolFromManager"; } + virtual int32_t bytesInHeaderAndPayload() { return sizeof(TR_RelocationRecordSymbolFromManagerBinaryTemplate); } + virtual void preparePrivateData(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget); + virtual int32_t applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + virtual void activatePointer(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation); + bool needsUnloadAssumptions(TR::SymbolType symbolType); + bool needsRedefinitionAssumption(TR_RelocationRuntime *reloRuntime, uint8_t *reloLocation, TR_OpaqueClassBlock *clazz, TR::SymbolType symbolType); + }; +/* SYMBOL VALIDATION MANAGER */ + class TR_RelocationRecordHCR : public TR_RelocationRecordWithOffset { public: diff --git a/runtime/compiler/runtime/RelocationRuntime.cpp b/runtime/compiler/runtime/RelocationRuntime.cpp index 19318327a5e..9d192af8aff 100644 --- a/runtime/compiler/runtime/RelocationRuntime.cpp +++ b/runtime/compiler/runtime/RelocationRuntime.cpp @@ -234,6 +234,12 @@ TR_RelocationRuntime::prepareRelocateAOTCodeAndData(J9VMThread* vmThread, } } + // Check the flags related to the symbol validation manager + if (_aotMethodHeaderEntry->flags & TR_AOTMethodHeader_UsesSymbolValidationManager) + { + comp->setOption(TR_UseSymbolValidationManager); + } + _exceptionTableCacheEntry = (J9JITDataCacheHeader *)((uint8_t *)cacheEntry + _aotMethodHeaderEntry->offsetToExceptionTable); if (_exceptionTableCacheEntry->type == J9_JIT_DCE_EXCEPTION_INFO) diff --git a/runtime/compiler/runtime/Runtime.hpp b/runtime/compiler/runtime/Runtime.hpp index 2133f3e8b01..3c7ca720b43 100644 --- a/runtime/compiler/runtime/Runtime.hpp +++ b/runtime/compiler/runtime/Runtime.hpp @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2017 IBM Corp. and others + * Copyright (c) 2000, 2018 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 @@ -169,6 +169,7 @@ typedef struct TR_AOTMethodHeader { #define TR_AOTMethodHeader_IsNotCapableOfMethodExitTracing 0x00000004 #define TR_AOTMethodHeader_UsesEnableStringCompressionFolding 0x00000008 #define TR_AOTMethodHeader_StringCompressionEnabled 0x00000010 +#define TR_AOTMethodHeader_UsesSymbolValidationManager 0x00000020 @@ -223,6 +224,7 @@ typedef struct TR_AOTStats TR_AOTInliningStats specialMethods; TR_AOTInliningStats virtualMethods; TR_AOTInliningStats interfaceMethods; + TR_AOTInliningStats abstractMethods; TR_AOTInliningStats profiledInlinedMethods; TR_AOTInliningStats profiledClassGuards; diff --git a/runtime/compiler/runtime/SymbolValidationManager.cpp b/runtime/compiler/runtime/SymbolValidationManager.cpp new file mode 100644 index 00000000000..55e1feb35bc --- /dev/null +++ b/runtime/compiler/runtime/SymbolValidationManager.cpp @@ -0,0 +1,2329 @@ +/******************************************************************************* + * Copyright (c) 2000, 2018 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 + *******************************************************************************/ + +#include +#include "env/VMJ9.h" +#include "env/ClassLoaderTable.hpp" +#include "env/PersistentCHTable.hpp" +#include "env/VMAccessCriticalSection.hpp" +#include "exceptions/AOTFailure.hpp" +#include "compile/Compilation.hpp" +#include "control/CompilationRuntime.hpp" +#include "control/CompilationThread.hpp" +#include "runtime/RelocationRuntime.hpp" +#include "runtime/SymbolValidationManager.hpp" + +#include "j9protos.h" + +static char getPrimitiveChar(J9UTF8 * primitiveClassName) + { + const char *name = reinterpret_cast(J9UTF8_DATA(primitiveClassName)); + int32_t length = J9UTF8_LENGTH(primitiveClassName); + + if (0 == strncmp(name,"int", length)) + return 'I'; + if (0 == strncmp(name,"boolean", length)) + return 'Z'; + if (0 == strncmp(name,"long", length)) + return 'J'; + if (0 == strncmp(name,"double", length)) + return 'D'; + if (0 == strncmp(name,"float", length)) + return 'F'; + if (0 == strncmp(name,"char", length)) + return 'C'; + if (0 == strncmp(name,"byte", length)) + return 'B'; + if (0 == strncmp(name,"short", length)) + return 'S'; + + return '\0'; + } + +TR::SymbolValidationManager::SymbolValidationManager(TR::Region ®ion, TR_ResolvedMethod *compilee) + : _symbolID(FIRST_ID), + _heuristicRegion(0), + _region(region), + _symbolValidationRecords(_region), + _symbolToIdMap((SymbolToIdComparator()), _region), + _idToSymbolsMap((IdToSymbolComparator()), _region), + _seenSymbolsSet((SeenSymbolsComparator()), _region) + { + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + struct J9Class ** arrayClasses = &fej9->getJ9JITConfig()->javaVM->booleanArrayClass; + uint16_t id; + for (int32_t i = 4; i <= 11; i++) + { + TR_OpaqueClassBlock *arrayClass = reinterpret_cast(arrayClasses[i - 4]); + TR_OpaqueClassBlock *component = fej9->getComponentClassFromArrayClass(arrayClass); + + id = getNewSymbolID(); + _symbolToIdMap.insert(std::make_pair(static_cast(arrayClass), id)); + _idToSymbolsMap.insert(std::make_pair(id, static_cast(arrayClass))); + + id = getNewSymbolID(); + _symbolToIdMap.insert(std::make_pair(static_cast(component), id)); + _idToSymbolsMap.insert(std::make_pair(id, static_cast(component))); + } + + id = getNewSymbolID(); + TR_OpaqueClassBlock *classOfMethod = compilee->classOfMethod(); + _symbolToIdMap.insert(std::make_pair(static_cast(classOfMethod), id)); + _idToSymbolsMap.insert(std::make_pair(id, static_cast(classOfMethod))); + + id = getNewSymbolID(); + TR_OpaqueMethodBlock *method = compilee->getPersistentIdentifier(); + _symbolToIdMap.insert(std::make_pair(static_cast(method), id)); + _idToSymbolsMap.insert(std::make_pair(id, static_cast(method))); + } + +uint16_t +TR::SymbolValidationManager::getNewSymbolID() + { + if (_symbolID == 0xFFFF) + { + TR_ASSERT(false, "_symbolID overflow\n"); + TR::comp()->failCompilation("Failed in getNewSymbolID"); + } + return _symbolID++; + } + +void * +TR::SymbolValidationManager::getSymbolFromID(uint16_t id) + { + IdToSymbolMap::iterator it = _idToSymbolsMap.find(id); + if (it == _idToSymbolsMap.end()) + return NULL; + else + return it->second; + } + +uint16_t +TR::SymbolValidationManager::getIDFromSymbol(void *symbol) + { + SymbolToIdMap::iterator it = _symbolToIdMap.find(symbol); + if (it == _symbolToIdMap.end()) + return NO_ID; + else + return it->second; + } + +TR_OpaqueClassBlock * +TR::SymbolValidationManager::getBaseComponentClass(TR_OpaqueClassBlock *clazz, int32_t &numDims) + { + numDims = 0; + if (!clazz) + return NULL; + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + while (fej9->isClassArray(clazz)) + { + TR_OpaqueClassBlock * componentClass = fej9->getComponentClassFromArrayClass(clazz); + numDims++; + clazz = componentClass; + } + + return clazz; + } + + +void * +TR::SymbolValidationManager::storeClassChain(TR_J9VMBase *fej9, TR_OpaqueClassBlock *clazz, bool isStatic) + { + void *classChain = NULL; + bool validated = false; + + classChain = fej9->sharedCache()->rememberClass(clazz); + if (classChain) + { + if (isStatic) + validated = addRomClassRecord(clazz); + else + validated = addClassChainRecord(clazz, classChain); + } + + if (validated) + return classChain; + else + return NULL; + } + +void +TR::SymbolValidationManager::storeRecord(void *symbol, TR::SymbolValidationRecord *record) + { + if (!getIDFromSymbol(symbol)) + { + _symbolToIdMap.insert(std::make_pair(symbol, getNewSymbolID())); + } + _symbolValidationRecords.push_front(record); + + record->printFields(); + traceMsg(TR::comp(), "\tkind=%d\n", record->_kind); + traceMsg(TR::comp(), "\tid=%d\n", (uint32_t)getIDFromSymbol(symbol)); + traceMsg(TR::comp(), "\n"); + } + +bool +TR::SymbolValidationManager::storeClassRecord(TR_OpaqueClassBlock *clazz, + TR::ClassValidationRecord *record, + int32_t arrayDimsToValidate, + bool isStatic, + bool storeCurrentRecord) + { + bool validated = false; + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + TR_AOTStats *aotStats = ((TR_JitPrivateConfig *)fej9->_jitConfig->privateConfig)->aotStats; + + if (storeCurrentRecord) + storeRecord(static_cast(clazz), record); + + if (fej9->isClassArray(clazz)) + { + validated = true; + } + else + { + if (fej9->isPrimitiveClass(clazz)) + { + validated = addPrimitiveClassRecord(clazz); + } + else + { + record->_classChain = storeClassChain(fej9, clazz, isStatic); + validated = (record->_classChain != NULL); + } + + if (validated) + { + int32_t arrayDims = 0; + TR_OpaqueClassBlock *componentClass = clazz; + while (validated && componentClass && arrayDims < arrayDimsToValidate) + { + TR_OpaqueClassBlock *arrayClass = fej9->getArrayClassFromComponentClass(componentClass); + + validated = addArrayClassFromComponentClassRecord(arrayClass, componentClass); + + componentClass = arrayClass; + arrayDims++; + } + + if (!(validated && (arrayDims == arrayDimsToValidate))) + { + TR_ASSERT(false, "Failed to validated clazz 0x%p\n", clazz); + comp->failCompilation("Failed to validate in storeClassRecord"); + } + } + } + + /* If we failed to store the class chain + * then it is because we failed to rememberClass; + * therefore, the last element in the list + * will be the one we added in this method and not + * the RomClassRecord or ClassChainRecord + */ + if (!validated) + _symbolValidationRecords.pop_front(); + + return validated; + } + +bool +TR::SymbolValidationManager::storeValidationRecordIfNecessary(void *symbol, + TR::SymbolValidationRecord *record, + int32_t arrayDimsToValidate, + bool isStatic) + { + bool existsInList = false; + bool validated = false; + + for (auto it = _symbolValidationRecords.begin(); it != _symbolValidationRecords.end(); it++) + { + if ((*it)->_kind == record->_kind && record->isEqual(*it)) + { + existsInList = true; + break; + } + } + + if (!existsInList || arrayDimsToValidate) + { + if (record->isClassValidationRecord()) + { + validated = storeClassRecord(static_cast(symbol), + reinterpret_cast(record), + arrayDimsToValidate, + isStatic, + !existsInList); + } + else + { + storeRecord(symbol, record); + validated = true; + } + } + + if (existsInList || !validated) + { + _region.deallocate(record); + } + + return (existsInList || validated); + } + +bool +TR::SymbolValidationManager::addRootClassRecord(TR_OpaqueClassBlock *clazz) + { + if (!clazz) + return false; + if (inHeuristicRegion()) + return true; + + int32_t arrayDims = 0; + clazz = getBaseComponentClass(clazz, arrayDims); + + SymbolValidationRecord *record = new (_region) RootClassRecord(clazz); + return storeValidationRecordIfNecessary(static_cast(clazz), record, arrayDims); + } + +bool +TR::SymbolValidationManager::addClassByNameRecord(TR_OpaqueClassBlock *clazz, TR_OpaqueClassBlock *beholder) + { + if (!clazz) + return false; + if (inHeuristicRegion()) + return true; + + TR::Compilation* comp = TR::comp(); + + if (getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(false, "beholder 0x%p should have already been validated\n", beholder); + comp->failCompilation("Failed to validate in addClassByNameRecord"); + } + + int32_t arrayDims = 0; + clazz = getBaseComponentClass(clazz, arrayDims); + char primitiveType = '\0'; + + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + if (fej9->isPrimitiveClass(clazz)) + { + J9ROMClass *romClass = reinterpret_cast(fej9->getPersistentClassPointerFromClassPointer(clazz)); + J9UTF8 * className = J9ROMCLASS_CLASSNAME(romClass); + primitiveType = getPrimitiveChar(className); + } + + SymbolValidationRecord *record = new (_region) ClassByNameRecord(clazz, beholder, primitiveType); + return storeValidationRecordIfNecessary(static_cast(clazz), record, arrayDims); + } + +bool +TR::SymbolValidationManager::addProfiledClassRecord(TR_OpaqueClassBlock *clazz) + { + if (!clazz) + return false; + if (inHeuristicRegion()) + return true; + + int32_t arrayDims = 0; + clazz = getBaseComponentClass(clazz, arrayDims); + char primitiveType = '\0'; + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + if (fej9->isPrimitiveClass(clazz)) + { + J9ROMClass *romClass = reinterpret_cast(fej9->getPersistentClassPointerFromClassPointer(clazz)); + J9UTF8 * className = J9ROMCLASS_CLASSNAME(romClass); + primitiveType = getPrimitiveChar(className); + } + + SymbolValidationRecord *record = new (_region) ProfiledClassRecord(clazz, primitiveType); + bool validated = storeValidationRecordIfNecessary(static_cast(clazz), record, arrayDims); + return validated; + } + +bool +TR::SymbolValidationManager::addClassFromCPRecord(TR_OpaqueClassBlock *clazz, J9ConstantPool *constantPoolOfBeholder, uint32_t cpIndex) + { + if (!clazz) + return false; + if (inHeuristicRegion()) + return true; + + int32_t arrayDims = 0; + clazz = getBaseComponentClass(clazz, arrayDims); + + TR_OpaqueClassBlock *beholder = reinterpret_cast(J9_CLASS_FROM_CP(constantPoolOfBeholder)); + + if (getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(false, "beholder 0x%p should have already been validated\n", beholder); + TR::comp()->failCompilation("Failed to validate in addClassFromCPRecord"); + } + + SymbolValidationRecord *record = new (_region) ClassFromCPRecord(clazz, beholder, cpIndex); + return storeValidationRecordIfNecessary(static_cast(clazz), record, arrayDims); + } + +bool +TR::SymbolValidationManager::addDefiningClassFromCPRecord(TR_OpaqueClassBlock *clazz, J9ConstantPool *constantPoolOfBeholder, uint32_t cpIndex, bool isStatic) + { + if (!clazz) + return false; + if (inHeuristicRegion()) + return true; + + int32_t arrayDims = 0; + clazz = getBaseComponentClass(clazz, arrayDims); + + TR_OpaqueClassBlock *beholder = reinterpret_cast(J9_CLASS_FROM_CP(constantPoolOfBeholder)); + + if (getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(false, "beholder 0x%p should have already been validated\n", beholder); + TR::comp()->failCompilation("Failed to validate in addDefiningClassFromCPRecord"); + } + + SymbolValidationRecord *record = new (_region) DefiningClassFromCPRecord(clazz, beholder, cpIndex, isStatic); + return storeValidationRecordIfNecessary(static_cast(clazz), record, arrayDims, isStatic); + } + +bool +TR::SymbolValidationManager::addStaticClassFromCPRecord(TR_OpaqueClassBlock *clazz, J9ConstantPool *constantPoolOfBeholder, uint32_t cpIndex) + { + if (!clazz) + return false; + if (inHeuristicRegion()) + return true; + + int32_t arrayDims = 0; + clazz = getBaseComponentClass(clazz, arrayDims); + + TR_OpaqueClassBlock *beholder = reinterpret_cast(J9_CLASS_FROM_CP(constantPoolOfBeholder)); + + if (getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(false, "beholder 0x%p should have already been validated\n", beholder); + TR::comp()->failCompilation("Failed to validate in addStaticClassFromCPRecord"); + } + + SymbolValidationRecord *record = new (_region) StaticClassFromCPRecord(clazz, beholder, cpIndex); + return storeValidationRecordIfNecessary(static_cast(clazz), record, arrayDims); + } + +bool +TR::SymbolValidationManager::addClassFromMethodRecord(TR_OpaqueClassBlock *clazz, TR_OpaqueMethodBlock *method) + { + if (!clazz) + return false; + if (inHeuristicRegion()) + return true; + + int32_t arrayDims = 0; + clazz = getBaseComponentClass(clazz, arrayDims); + + if (getIDFromSymbol(method) == 0) + { + TR_ASSERT(false, "method 0x%p should have already been validated\n", method); + TR::comp()->failCompilation("Failed to validate in addClassFromMethodRecord"); + } + + SymbolValidationRecord *record = new (_region) ClassFromMethodRecord(clazz, method); + return storeValidationRecordIfNecessary(static_cast(clazz), record); + } + +bool +TR::SymbolValidationManager::addComponentClassFromArrayClassRecord(TR_OpaqueClassBlock *componentClass, TR_OpaqueClassBlock *arrayClass) + { + if (!componentClass) + return false; + if (inHeuristicRegion()) + return true; + + if (getIDFromSymbol(arrayClass) == 0) + { + TR_ASSERT(false, "arrayClass 0x%p should have already been validated\n", arrayClass); + TR::comp()->failCompilation("Failed to validate in addComponentClassFromArrayClassRecord"); + } + + SymbolValidationRecord *record = new (_region) ComponentClassFromArrayClassRecord(componentClass, arrayClass); + return storeValidationRecordIfNecessary(static_cast(componentClass), record); + } + +bool +TR::SymbolValidationManager::addArrayClassFromComponentClassRecord(TR_OpaqueClassBlock *arrayClass, TR_OpaqueClassBlock *componentClass) + { + if (!arrayClass) + return false; + if (inHeuristicRegion()) + return true; + + if (getIDFromSymbol(componentClass) == 0) + { + TR_ASSERT(false, "componentClass 0x%p should have already been validated\n", componentClass); + TR::comp()->failCompilation("Failed to validate in addArrayClassFromComponentClassRecord"); + } + + SymbolValidationRecord *record = new (_region) ArrayClassFromComponentClassRecord(arrayClass, componentClass); + return storeValidationRecordIfNecessary(static_cast(arrayClass), record); + } + +bool +TR::SymbolValidationManager::addSuperClassFromClassRecord(TR_OpaqueClassBlock *superClass, TR_OpaqueClassBlock *childClass) + { + if (!superClass) + return false; + if (inHeuristicRegion()) + return true; + + int32_t arrayDims = 0; + superClass = getBaseComponentClass(superClass, arrayDims); + + if (getIDFromSymbol(childClass) == 0) + { + TR_ASSERT(false, "childClass 0x%p should have already been validated\n", childClass); + TR::comp()->failCompilation("Failed to validate in addSuperClassFromClassRecord"); + } + + SymbolValidationRecord *record = new (_region) SuperClassFromClassRecord(superClass, childClass); + return storeValidationRecordIfNecessary(static_cast(superClass), record, arrayDims); + } + +bool +TR::SymbolValidationManager::addClassInstanceOfClassRecord(TR_OpaqueClassBlock *classOne, TR_OpaqueClassBlock *classTwo, bool objectTypeIsFixed, bool castTypeIsFixed, bool isInstanceOf) + { + if (inHeuristicRegion()) + return true; + + if (getIDFromSymbol(classOne) == 0 || getIDFromSymbol(classTwo) == 0) + { + TR_ASSERT(getIDFromSymbol(classOne) != 0, "classOne 0x%p should have already been validated\n", classOne); + TR_ASSERT(getIDFromSymbol(classTwo) != 0, "classTwo 0x%p should have already been validated\n", classTwo); + TR::comp()->failCompilation("Failed to validate in addClassInstanceOfClassRecord"); + } + + SymbolValidationRecord *record = new (_region) ClassInstanceOfClassRecord(classOne, classTwo, objectTypeIsFixed, castTypeIsFixed, isInstanceOf); + return storeValidationRecordIfNecessary(static_cast(classOne), record); + } + +bool +TR::SymbolValidationManager::addSystemClassByNameRecord(TR_OpaqueClassBlock *systemClass) + { + if (!systemClass) + return false; + if (inHeuristicRegion()) + return true; + + int32_t arrayDims = 0; + systemClass = getBaseComponentClass(systemClass, arrayDims); + + SymbolValidationRecord *record = new (_region) SystemClassByNameRecord(systemClass); + return storeValidationRecordIfNecessary(static_cast(systemClass), record, arrayDims); + } + +bool +TR::SymbolValidationManager::addClassFromITableIndexCPRecord(TR_OpaqueClassBlock *clazz, J9ConstantPool *constantPoolOfBeholder, int32_t cpIndex) + { + if (!clazz) + return false; + if (inHeuristicRegion()) + return true; + + TR_OpaqueClassBlock *beholder = reinterpret_cast(J9_CLASS_FROM_CP(constantPoolOfBeholder)); + + if (getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(false, "beholder 0x%p should have already been validated\n", beholder); + TR::comp()->failCompilation("Failed to validate in addClassFromITableIndexCPRecord"); + } + + int32_t arrayDims = 0; + clazz = getBaseComponentClass(clazz, arrayDims); + + SymbolValidationRecord *record = new (_region) ClassFromITableIndexCPRecord(clazz, beholder, cpIndex); + return storeValidationRecordIfNecessary(static_cast(clazz), record, arrayDims); + } + +bool +TR::SymbolValidationManager::addDeclaringClassFromFieldOrStaticRecord(TR_OpaqueClassBlock *clazz, J9ConstantPool *constantPoolOfBeholder, int32_t cpIndex) + { + if (!clazz) + return false; + if (inHeuristicRegion()) + return true; + + TR_OpaqueClassBlock *beholder = reinterpret_cast(J9_CLASS_FROM_CP(constantPoolOfBeholder)); + + if (getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(false, "beholder 0x%p should have already been validated\n", beholder); + TR::comp()->failCompilation("Failed to validate in addDeclaringClassFromFieldOrStaticRecord"); + } + + int32_t arrayDims = 0; + clazz = getBaseComponentClass(clazz, arrayDims); + + SymbolValidationRecord *record = new (_region) DeclaringClassFromFieldOrStaticRecord(clazz, beholder, cpIndex); + return storeValidationRecordIfNecessary(static_cast(clazz), record, arrayDims); + } + +bool +TR::SymbolValidationManager::addClassClassRecord(TR_OpaqueClassBlock *classClass, TR_OpaqueClassBlock *objectClass) + { + if (!classClass) + return false; + if (inHeuristicRegion()) + return true; + + if (getIDFromSymbol(objectClass) == 0) + { + TR_ASSERT(false, "objectClass 0x%p should have already been validated\n", objectClass); + TR::comp()->failCompilation("Failed to validate in addClassClassRecord"); + } + + SymbolValidationRecord *record = new (_region) ClassClassRecord(classClass, objectClass); + return storeValidationRecordIfNecessary(static_cast(classClass), record); + } + +bool +TR::SymbolValidationManager::addConcreteSubClassFromClassRecord(TR_OpaqueClassBlock *childClass, TR_OpaqueClassBlock *superClass) + { + if (!superClass) + return false; + if (inHeuristicRegion()) + return true; + + int32_t arrayDims = 0; + childClass = getBaseComponentClass(childClass, arrayDims); + + if (getIDFromSymbol(superClass) == 0) + { + TR_ASSERT(false, "superClass 0x%p should have already been validated\n", superClass); + TR::comp()->failCompilation("Failed to validate in addConcreteSubClassFromClassRecord"); + } + + SymbolValidationRecord *record = new (_region) ConcreteSubClassFromClassRecord(childClass, superClass); + return storeValidationRecordIfNecessary(static_cast(childClass), record, arrayDims); + } + +bool +TR::SymbolValidationManager::addArrayClassFromJavaVM(TR_OpaqueClassBlock *arrayClass, int32_t arrayClassIndex) + { + if (!arrayClass) + return false; + if (inHeuristicRegion()) + return true; + + int32_t arrayDims = 0; + arrayClass = getBaseComponentClass(arrayClass, arrayDims); + + SymbolValidationRecord *record = new (_region) ArrayClassFromJavaVM(arrayClass, arrayClassIndex); + return storeValidationRecordIfNecessary(static_cast(arrayClass), record, arrayDims); + } + +bool +TR::SymbolValidationManager::addClassChainRecord(TR_OpaqueClassBlock *clazz, void *classChain) + { + if (!clazz) + return false; + if (inHeuristicRegion()) + return true; + + SymbolValidationRecord *record = new (_region) ClassChainRecord(clazz, classChain); + return storeValidationRecordIfNecessary(static_cast(clazz), record); + } + +bool +TR::SymbolValidationManager::addRomClassRecord(TR_OpaqueClassBlock *clazz) + { + if (!clazz) + return false; + if (inHeuristicRegion()) + return true; + + SymbolValidationRecord *record = new (_region) RomClassRecord(clazz); + return storeValidationRecordIfNecessary(static_cast(clazz), record); + } + +bool +TR::SymbolValidationManager::addPrimitiveClassRecord(TR_OpaqueClassBlock *clazz) + { + if (!clazz) + return false; + if (inHeuristicRegion()) + return true; + + TR::Compilation* comp = TR::comp(); + + if (getIDFromSymbol(clazz) == 0) + { + TR_ASSERT(false, "clazz 0x%p should have already been validated\n", clazz); + comp->failCompilation("Failed to validate in addPrimitiveClassRecord"); + } + + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + J9ROMClass *romClass = reinterpret_cast(fej9->getPersistentClassPointerFromClassPointer(clazz)); + J9UTF8 * className = J9ROMCLASS_CLASSNAME(romClass); + char primitiveType =getPrimitiveChar(className); + + if (primitiveType == '\0') + { + TR_ASSERT(false, "clazz 0x%p is not primitive\n", clazz); + comp->failCompilation("Failed to validate in addPrimitiveClassRecord"); + } + + SymbolValidationRecord *record = new (_region) PrimitiveClassRecord(clazz, primitiveType); + return storeValidationRecordIfNecessary(static_cast(clazz), record); + } + +bool +TR::SymbolValidationManager::addMethodFromInlinedSiteRecord(TR_OpaqueMethodBlock *method, + int32_t inlinedSiteIndex) + { + if (!method) + return false; + if (inHeuristicRegion()) + return true; + + SymbolValidationRecord *record = new (_region) MethodFromInlinedSiteRecord(method, inlinedSiteIndex); + return storeValidationRecordIfNecessary(static_cast(method), record); + } + +bool +TR::SymbolValidationManager::addMethodByNameRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *beholder) + { + if (!method) + return false; + if (inHeuristicRegion()) + return true; + + if (getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(false, "beholder 0x%p should have already been validated\n", beholder); + TR::comp()->failCompilation("Failed to validate in addMethodByNameRecord"); + } + + SymbolValidationRecord *record = new (_region) MethodByNameRecord(method, beholder); + bool valid = storeValidationRecordIfNecessary(static_cast(method), record); + + if (valid) + { + J9Class *methodClass = J9_CLASS_FROM_METHOD(reinterpret_cast(method)); + valid = addClassFromMethodRecord(reinterpret_cast(methodClass), method); + } + + return valid; + } + +bool +TR::SymbolValidationManager::addMethodFromClassRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *beholder, uint32_t index) + { + if (!method) + return false; + if (inHeuristicRegion()) + return true; + + TR::Compilation* comp = TR::comp(); + + if (index == static_cast(-1)) + { + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + J9Method * resolvedMethods = static_cast(fej9->getMethods(beholder)); + uint32_t numMethods = fej9->getNumMethods(beholder); + for (index = 0; index < numMethods ; index++) + { + if ((TR_OpaqueMethodBlock *) &(resolvedMethods[index]) == method) + break; + } + + if (index == numMethods) + { + TR_ASSERT(false, "Method 0x%p not found in class 0x%p\n", method, beholder); + return false; + } + } + + if (getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(false, "beholder 0x%p should have already been validated\n", beholder); + comp->failCompilation("Failed to validate in addMethodFromClassRecord"); + } + + SymbolValidationRecord *record = new (_region) MethodFromClassRecord(method, beholder, index); + return storeValidationRecordIfNecessary(static_cast(method), record); + } + +bool +TR::SymbolValidationManager::addStaticMethodFromCPRecord(TR_OpaqueMethodBlock *method, J9ConstantPool *cp, int32_t cpIndex) + { + if (!method) + return false; + if (inHeuristicRegion()) + return true; + + TR_OpaqueClassBlock *beholder = reinterpret_cast(J9_CLASS_FROM_CP(cp)); + + if (getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(false, "beholder 0x%p should have already been validated\n", beholder); + TR::comp()->failCompilation("Failed to validate in addStaticMethodFromCPRecord"); + } + + SymbolValidationRecord *record = new (_region) StaticMethodFromCPRecord(method, beholder, cpIndex); + bool valid = storeValidationRecordIfNecessary(static_cast(method), record); + + if (valid) + { + J9Class *methodClass = J9_CLASS_FROM_METHOD(reinterpret_cast(method)); + valid = addClassFromMethodRecord(reinterpret_cast(methodClass), method); + } + + return valid; + } + +bool +TR::SymbolValidationManager::addSpecialMethodFromCPRecord(TR_OpaqueMethodBlock *method, J9ConstantPool *cp, int32_t cpIndex) + { + if (!method) + return false; + if (inHeuristicRegion()) + return true; + + TR_OpaqueClassBlock *beholder = reinterpret_cast(J9_CLASS_FROM_CP(cp)); + + if (getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(false, "beholder 0x%p should have already been validated\n", beholder); + TR::comp()->failCompilation("Failed to validate in addSpecialMethodFromCPRecord"); + } + + SymbolValidationRecord *record = new (_region) SpecialMethodFromCPRecord(method, beholder, cpIndex); + bool valid = storeValidationRecordIfNecessary(static_cast(method), record); + + if (valid) + { + J9Class *methodClass = J9_CLASS_FROM_METHOD(reinterpret_cast(method)); + valid = addClassFromMethodRecord(reinterpret_cast(methodClass), method); + } + + return valid; + } + +bool +TR::SymbolValidationManager::addVirtualMethodFromCPRecord(TR_OpaqueMethodBlock *method, J9ConstantPool *cp, int32_t cpIndex) + { + if (!method) + return false; + if (inHeuristicRegion()) + return true; + + TR_OpaqueClassBlock *beholder = reinterpret_cast(J9_CLASS_FROM_CP(cp)); + + if (getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(false, "beholder 0x%p should have already been validated\n", beholder); + TR::comp()->failCompilation("Failed to validate in addVirtualMethodFromCPRecord"); + } + + SymbolValidationRecord *record = new (_region) VirtualMethodFromCPRecord(method, beholder, cpIndex); + bool valid = storeValidationRecordIfNecessary(static_cast(method), record); + + if (valid) + { + J9Class *methodClass = J9_CLASS_FROM_METHOD(reinterpret_cast(method)); + valid = addClassFromMethodRecord(reinterpret_cast(methodClass), method); + } + + return valid; + } + +bool +TR::SymbolValidationManager::addVirtualMethodFromOffsetRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *beholder, int32_t virtualCallOffset, bool ignoreRtResolve) + { + if (!method) + return false; + if (inHeuristicRegion()) + return true; + + if (getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(false, "beholder 0x%p should have already been validated\n", beholder); + TR::comp()->failCompilation("Failed to validate in addVirtualMethodFromOffsetRecord"); + } + + SymbolValidationRecord *record = new (_region) VirtualMethodFromOffsetRecord(method, beholder, virtualCallOffset, ignoreRtResolve); + bool valid = storeValidationRecordIfNecessary(static_cast(method), record); + + if (valid) + { + J9Class *methodClass = J9_CLASS_FROM_METHOD(reinterpret_cast(method)); + valid = addClassFromMethodRecord(reinterpret_cast(methodClass), method); + } + + return valid; + } + +bool +TR::SymbolValidationManager::addInterfaceMethodFromCPRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *beholder, TR_OpaqueClassBlock *lookup, int32_t cpIndex) + { + if (!method) + return false; + if (inHeuristicRegion()) + return true; + + if (getIDFromSymbol(beholder) == 0 || getIDFromSymbol(lookup) == 0) + { + TR_ASSERT(getIDFromSymbol(beholder) != 0, "beholder 0x%p should have already been validated\n", beholder); + TR_ASSERT(getIDFromSymbol(lookup) != 0, "lookup 0x%p should have already been validated\n", lookup); + TR::comp()->failCompilation("Failed to validate in addInterfaceMethodFromCPRecord"); + } + + SymbolValidationRecord *record = new (_region) InterfaceMethodFromCPRecord(method, beholder, lookup, cpIndex); + bool valid = storeValidationRecordIfNecessary(static_cast(method), record); + + if (valid) + { + J9Class *methodClass = J9_CLASS_FROM_METHOD(reinterpret_cast(method)); + valid = addClassFromMethodRecord(reinterpret_cast(methodClass), method); + } + + return valid; + } + +bool +TR::SymbolValidationManager::addImproperInterfaceMethodFromCPRecord(TR_OpaqueMethodBlock *method, J9ConstantPool *cp, int32_t cpIndex) + { + if (!method) + return false; + if (inHeuristicRegion()) + return true; + + TR_OpaqueClassBlock *beholder = reinterpret_cast(J9_CLASS_FROM_CP(cp)); + + if (getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(false, "beholder 0x%p should have already been validated\n", beholder); + TR::comp()->failCompilation("Failed to validate in addImproperInterfaceMethodFromCPRecord"); + } + + SymbolValidationRecord *record = new (_region) ImproperInterfaceMethodFromCPRecord(method, beholder, cpIndex); + bool valid = storeValidationRecordIfNecessary(static_cast(method), record); + + if (valid) + { + J9Class *methodClass = J9_CLASS_FROM_METHOD(reinterpret_cast(method)); + valid = addClassFromMethodRecord(reinterpret_cast(methodClass), method); + } + + return valid; + } + +bool +TR::SymbolValidationManager::addMethodFromClassAndSignatureRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass, TR_OpaqueClassBlock *beholder) + { + if (!method) + return false; + if (inHeuristicRegion()) + return true; + + if (getIDFromSymbol(methodClass) == 0 || getIDFromSymbol(beholder) == 0) + { + TR_ASSERT(getIDFromSymbol(methodClass) != 0, "methodClass 0x%p should have already been validated\n", methodClass); + TR_ASSERT(getIDFromSymbol(beholder) != 0, "beholder 0x%p should have already been validated\n", beholder); + TR::comp()->failCompilation("Failed to validate in addMethodFromClassAndSignatureRecord"); + } + + SymbolValidationRecord *record = new (_region) MethodFromClassAndSigRecord(method, methodClass, beholder); + return storeValidationRecordIfNecessary(static_cast(method), record); + } + +bool +TR::SymbolValidationManager::addMethodFromSingleImplementerRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *thisClass, + int32_t cpIndexOrVftSlot, + TR_OpaqueMethodBlock *callerMethod, + TR_YesNoMaybe useGetResolvedInterfaceMethod) + { + if (!method) + return false; + if (inHeuristicRegion()) + return true; + + if (getIDFromSymbol(thisClass) == 0 || getIDFromSymbol(callerMethod) == 0) + { + TR_ASSERT(getIDFromSymbol(thisClass) != 0, "thisClass 0x%p should have already been validated\n", thisClass); + TR_ASSERT(getIDFromSymbol(callerMethod) != 0, "callerMethod 0x%p should have already been validated\n", callerMethod); + TR::comp()->failCompilation("Failed to validate in addMethodFromSingleImplementerRecord"); + } + + SymbolValidationRecord *record = new (_region) MethodFromSingleImplementer(method, thisClass, cpIndexOrVftSlot, callerMethod, useGetResolvedInterfaceMethod); + bool valid = storeValidationRecordIfNecessary(static_cast(method), record); + + if (valid) + { + J9Class *methodClass = J9_CLASS_FROM_METHOD(reinterpret_cast(method)); + valid = addClassFromMethodRecord(reinterpret_cast(methodClass), method); + } + + return valid; + } + +bool +TR::SymbolValidationManager::addMethodFromSingleInterfaceImplementerRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *thisClass, + int32_t cpIndex, + TR_OpaqueMethodBlock *callerMethod) + { + if (!method) + return false; + if (inHeuristicRegion()) + return true; + + if (getIDFromSymbol(thisClass) == 0 || getIDFromSymbol(callerMethod) == 0) + { + TR_ASSERT(getIDFromSymbol(thisClass) != 0, "thisClass 0x%p should have already been validated\n", thisClass); + TR_ASSERT(getIDFromSymbol(callerMethod) != 0, "callerMethod 0x%p should have already been validated\n", callerMethod); + TR::comp()->failCompilation("Failed to validate in addMethodFromSingleInterfaceImplementerRecord"); + } + + SymbolValidationRecord *record = new (_region) MethodFromSingleInterfaceImplementer(method, thisClass, cpIndex, callerMethod); + bool valid = storeValidationRecordIfNecessary(static_cast(method), record); + + if (valid) + { + J9Class *methodClass = J9_CLASS_FROM_METHOD(reinterpret_cast(method)); + valid = addClassFromMethodRecord(reinterpret_cast(methodClass), method); + } + + return valid; + } + +bool +TR::SymbolValidationManager::addMethodFromSingleAbstractImplementerRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *thisClass, + int32_t vftSlot, + TR_OpaqueMethodBlock *callerMethod) + { + if (!method) + return false; + if (inHeuristicRegion()) + return true; + + if (getIDFromSymbol(thisClass) == 0 || getIDFromSymbol(callerMethod) == 0) + { + TR_ASSERT(getIDFromSymbol(thisClass) != 0, "thisClass 0x%p should have already been validated\n", thisClass); + TR_ASSERT(getIDFromSymbol(callerMethod) != 0, "callerMethod 0x%p should have already been validated\n", callerMethod); + TR::comp()->failCompilation("Failed to validate in addMethodFromSingleAbstractImplementerRecord"); + } + + SymbolValidationRecord *record = new (_region) MethodFromSingleAbstractImplementer(method, thisClass, vftSlot, callerMethod); + bool valid = storeValidationRecordIfNecessary(static_cast(method), record); + + if (valid) + { + J9Class *methodClass = J9_CLASS_FROM_METHOD(reinterpret_cast(method)); + valid = addClassFromMethodRecord(reinterpret_cast(methodClass), method); + } + + return valid; + } + +bool +TR::SymbolValidationManager::addStackWalkerMaySkipFramesRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass, bool skipFrames) + { + if (!method || !methodClass) + return false; + if (inHeuristicRegion()) + return true; + + if (getIDFromSymbol(method) == 0 || getIDFromSymbol(methodClass) == 0) + { + TR_ASSERT(getIDFromSymbol(method) != 0, "method 0x%p should have already been validated\n", method); + TR_ASSERT(getIDFromSymbol(methodClass) != 0, "methodClass 0x%p should have already been validated\n", methodClass); + TR::comp()->failCompilation("Failed to validate in addStackWalkerMaySkipFramesRecord"); + } + + SymbolValidationRecord *record = new (_region) StackWalkerMaySkipFramesRecord(method, methodClass, skipFrames); + return storeValidationRecordIfNecessary(static_cast(method), record); + } + +bool +TR::SymbolValidationManager::addClassInfoIsInitializedRecord(TR_OpaqueClassBlock *clazz, bool isInitialized) + { + if (!clazz) + return false; + if (inHeuristicRegion()) + return true; + + if (getIDFromSymbol(clazz) == 0) + { + TR_ASSERT(false, "clazz 0x%p should have already been validated\n", clazz); + TR::comp()->failCompilation("Failed to validate in addClassInfoIsInitializedRecord"); + } + + SymbolValidationRecord *record = new (_region) ClassInfoIsInitialized(clazz, isInitialized); + return storeValidationRecordIfNecessary(static_cast(clazz), record); + } + + + +bool +TR::SymbolValidationManager::validateSymbol(uint16_t idToBeValidated, void *validSymbol) + { + bool valid = false; + void *symbol = getSymbolFromID(idToBeValidated); + + if (validSymbol) + { + if (symbol == NULL) + { + if (_seenSymbolsSet.find(validSymbol) == _seenSymbolsSet.end()) + { + _idToSymbolsMap.insert(std::make_pair(idToBeValidated, validSymbol)); + _seenSymbolsSet.insert(validSymbol); + valid = true; + } + } + else + { + valid = (symbol == validSymbol); + } + } + + return valid; + } + +bool +TR::SymbolValidationManager::validateRootClassRecord(uint16_t classID) + { + TR::Compilation *comp = TR::comp(); + J9Class *rootClass = ((TR_ResolvedJ9Method *)comp->getMethodBeingCompiled())->constantPoolHdr(); + TR_OpaqueClassBlock *opaqueRootClass = reinterpret_cast(rootClass); + + int32_t arrayDims = 0; + opaqueRootClass = getBaseComponentClass(opaqueRootClass, arrayDims); + + return validateSymbol(classID, static_cast(opaqueRootClass)); + } + +bool +TR::SymbolValidationManager::validateClassByNameRecord(uint16_t classID, uint16_t beholderID, J9ROMClass *romClass, char primitiveType) + { + if (getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(false, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + J9Class *beholder = static_cast(getSymbolFromID(beholderID)); + J9ConstantPool *beholderCP = J9_CP_FROM_CLASS(beholder); + + if (primitiveType != '\0') + { + if (getSymbolFromID(classID) == NULL) + { + TR_ASSERT(false, "primitive classID %u should exist\n", classID); + return false; + } + return true; + } + + J9UTF8 * classNameData = J9ROMCLASS_CLASSNAME(romClass); + char *className = reinterpret_cast(J9UTF8_DATA(classNameData)); + uint32_t classNameLength = J9UTF8_LENGTH(classNameData); + + TR_OpaqueClassBlock *classByName = fej9->getClassFromSignature(className, classNameLength, beholderCP); + + if (!classByName) + return false; + + int32_t arrayDims = 0; + classByName = getBaseComponentClass(classByName, arrayDims); + + return validateSymbol(classID, static_cast(classByName)); + } + +bool +TR::SymbolValidationManager::validateProfiledClassRecord(uint16_t classID, char primitiveType, void *classChainIdentifyingLoader, void *classChainForClassBeingValidated) + { + TR::Compilation* comp = TR::comp(); + + if (primitiveType != '\0') + { + if (getSymbolFromID(classID) == NULL) + { + TR_ASSERT(false, "primitive classID %u should exist\n", classID); + return false; + } + return true; + } + + J9ClassLoader *classLoader = (J9ClassLoader *) comp->fej9()->sharedCache()->persistentClassLoaderTable()->lookupClassLoaderAssociatedWithClassChain(classChainIdentifyingLoader); + + if (classLoader) + { + TR_OpaqueClassBlock *clazz = comp->fej9()->sharedCache()->lookupClassFromChainAndLoader(static_cast(classChainForClassBeingValidated), classLoader); + + if (clazz) + { + int32_t arrayDims = 0; + clazz = getBaseComponentClass(clazz, arrayDims); + + return validateSymbol(classID, static_cast(clazz)); + } + } + + return false; + } + +bool +TR::SymbolValidationManager::validateClassFromCPRecord(uint16_t classID, uint16_t beholderID, uint32_t cpIndex) + { + if (getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(false, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + J9Class *beholder = static_cast(getSymbolFromID(beholderID)); + J9ConstantPool *beholderCP = J9_CP_FROM_CLASS(beholder); + TR_OpaqueClassBlock *classFromCP = TR_ResolvedJ9Method::getClassFromCP(fej9, beholderCP, comp, cpIndex); + + int32_t arrayDims = 0; + classFromCP = getBaseComponentClass(classFromCP, arrayDims); + + return validateSymbol(classID, static_cast(classFromCP)); + } + +bool +TR::SymbolValidationManager::validateDefiningClassFromCPRecord(uint16_t classID, uint16_t beholderID, uint32_t cpIndex, bool isStatic) + { + if (getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(false, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + TR::CompilationInfo *compInfo = TR::CompilationInfo::get(fej9->_jitConfig); + TR::CompilationInfoPerThreadBase *compInfoPerThreadBase = compInfo->getCompInfoForCompOnAppThread(); + TR_RelocationRuntime *reloRuntime; + if (compInfoPerThreadBase) + reloRuntime = compInfoPerThreadBase->reloRuntime(); + else + reloRuntime = compInfo->getCompInfoForThread(fej9->vmThread())->reloRuntime(); + + J9Class *beholder = static_cast(getSymbolFromID(beholderID)); + J9ConstantPool *beholderCP = J9_CP_FROM_CLASS(beholder); + TR_OpaqueClassBlock *classFromCP = reloRuntime->getClassFromCP(fej9->vmThread(), fej9->_jitConfig->javaVM, beholderCP, cpIndex, isStatic); + + int32_t arrayDims = 0; + classFromCP = getBaseComponentClass(classFromCP, arrayDims); + + return validateSymbol(classID, static_cast(classFromCP)); + } + +bool +TR::SymbolValidationManager::validateStaticClassFromCPRecord(uint16_t classID, uint16_t beholderID, uint32_t cpIndex) + { + if (getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(false, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + J9Class *beholder = static_cast(getSymbolFromID(beholderID)); + J9ConstantPool *beholderCP = J9_CP_FROM_CLASS(beholder); + TR_OpaqueClassBlock *classFromCP = TR_ResolvedJ9Method::getClassOfStaticFromCP(fej9, beholderCP, cpIndex); + + int32_t arrayDims = 0; + classFromCP = getBaseComponentClass(classFromCP, arrayDims); + + return validateSymbol(classID, static_cast(classFromCP)); + } + +bool +TR::SymbolValidationManager::validateClassFromMethodRecord(uint16_t classID, uint16_t methodID) + { + if (getSymbolFromID(methodID) == NULL) + { + TR_ASSERT(false, "methodID %u should exist\n", methodID); + return false; + } + + J9Method *method = static_cast(getSymbolFromID(methodID)); + TR_OpaqueClassBlock *classFromMethod = reinterpret_cast(J9_CLASS_FROM_METHOD(method)); + + int32_t arrayDims = 0; + classFromMethod = getBaseComponentClass(classFromMethod, arrayDims); + + return validateSymbol(classID, static_cast(classFromMethod)); + } + +bool +TR::SymbolValidationManager::validateComponentClassFromArrayClassRecord(uint16_t componentClassID, uint16_t arrayClassID) + { + if (getSymbolFromID(arrayClassID) == NULL) + { + TR_ASSERT(false, "arrayClassID %u should exist\n", arrayClassID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + TR_OpaqueClassBlock *arrayClass = static_cast(getSymbolFromID(arrayClassID)); + TR_OpaqueClassBlock *componentClass = fej9->getComponentClassFromArrayClass(arrayClass); + + return validateSymbol(componentClassID, static_cast(componentClass)); + } + +bool +TR::SymbolValidationManager::validateArrayClassFromComponentClassRecord(uint16_t arrayClassID, uint16_t componentClassID) + { + if (getSymbolFromID(componentClassID) == NULL) + { + TR_ASSERT(false, "componentClassID %u should exist\n", componentClassID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + TR_OpaqueClassBlock *componentClass = static_cast(getSymbolFromID(componentClassID)); + TR_OpaqueClassBlock *arrayClass = fej9->getArrayClassFromComponentClass(componentClass); + + return validateSymbol(arrayClassID, static_cast(arrayClass)); + } + +bool +TR::SymbolValidationManager::validateSuperClassFromClassRecord(uint16_t superClassID, uint16_t childClassID) + { + if (getSymbolFromID(childClassID) == NULL) + { + TR_ASSERT(false, "childClassID %u should exist\n", childClassID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + TR_OpaqueClassBlock *childClass = static_cast(getSymbolFromID(childClassID)); + TR_OpaqueClassBlock *superClass = fej9->getSuperClass(childClass); + + int32_t arrayDims = 0; + superClass = getBaseComponentClass(superClass, arrayDims); + + return validateSymbol(superClassID, static_cast(superClass)); + } + +bool +TR::SymbolValidationManager::validateClassInstanceOfClassRecord(uint16_t classOneID, uint16_t classTwoID, bool objectTypeIsFixed, bool castTypeIsFixed, bool wasInstanceOf) + { + if (getSymbolFromID(classOneID) == NULL || getSymbolFromID(classTwoID) == NULL) + { + TR_ASSERT(getSymbolFromID(classOneID) != 0, "classOneID %u should exist\n", classOneID); + TR_ASSERT(getSymbolFromID(classTwoID) != 0, "classTwoID %u should exist\n", classTwoID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + TR_OpaqueClassBlock *classOne = static_cast(getSymbolFromID(classOneID)); + TR_OpaqueClassBlock *classTwo = static_cast(getSymbolFromID(classTwoID)); + + TR_YesNoMaybe isInstanceOf = fej9->isInstanceOf(classOne, classTwo, objectTypeIsFixed, castTypeIsFixed); + + return (wasInstanceOf == isInstanceOf); + } + +bool +TR::SymbolValidationManager::validateSystemClassByNameRecord(uint16_t systemClassID, J9ROMClass *romClass) + { + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + J9UTF8 * className = J9ROMCLASS_CLASSNAME(romClass); + TR_OpaqueClassBlock *systemClassByName = fej9->getSystemClassFromClassName(reinterpret_cast(J9UTF8_DATA(className)), + J9UTF8_LENGTH(className)); + + int32_t arrayDims = 0; + systemClassByName = getBaseComponentClass(systemClassByName, arrayDims); + + return validateSymbol(systemClassID, static_cast(systemClassByName)); + } + +bool +TR::SymbolValidationManager::validateClassFromITableIndexCPRecord(uint16_t classID, uint16_t beholderID, uint32_t cpIndex) + { + if (getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(false, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + J9Class *beholder = static_cast(getSymbolFromID(beholderID)); + J9ConstantPool *beholderCP = J9_CP_FROM_CLASS(beholder); + uintptr_t pITableIndex; + TR_OpaqueClassBlock *clazz = TR_ResolvedJ9Method::getInterfaceITableIndexFromCP(fej9, beholderCP, cpIndex, &pITableIndex); + + int32_t arrayDims = 0; + clazz = getBaseComponentClass(clazz, arrayDims); + + return validateSymbol(classID, static_cast(clazz)); + } + +bool +TR::SymbolValidationManager::validateDeclaringClassFromFieldOrStaticRecord(uint16_t definingClassID, uint16_t beholderID, int32_t cpIndex) + { + if (getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(false, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + J9Class *beholder = static_cast(getSymbolFromID(beholderID)); + J9ROMClass *beholderRomClass = beholder->romClass; + J9ConstantPool *beholderCP = J9_CP_FROM_CLASS(beholder); + J9ROMFieldRef *romCPBase = (J9ROMFieldRef *)((UDATA)beholderRomClass + sizeof(J9ROMClass)); + + int32_t classCPIndexOfFieldOrStatic = -1; + if (cpIndex != -1) + classCPIndexOfFieldOrStatic = ((J9ROMFieldRef *)(&romCPBase[cpIndex]))->classRefCPIndex; + + J9Class *definingClass = NULL; + J9Class *cpClass = (J9Class*)TR_ResolvedJ9Method::getClassFromCP(fej9, beholderCP, comp, classCPIndexOfFieldOrStatic); + + if (cpClass) + { + TR::VMAccessCriticalSection getDeclaringClassFromFieldOrStatic(fej9); + + int32_t fieldLen; + char *field = cpIndex >= 0 ? utf8Data(J9ROMNAMEANDSIGNATURE_NAME(J9ROMFIELDREF_NAMEANDSIGNATURE(&romCPBase[cpIndex])), fieldLen) : 0; + + int32_t sigLen; + char *sig = cpIndex >= 0 ? utf8Data(J9ROMNAMEANDSIGNATURE_SIGNATURE(J9ROMFIELDREF_NAMEANDSIGNATURE(&romCPBase[cpIndex])), sigLen) : 0; + + vmThread->javaVM->internalVMFunctions->instanceFieldOffset(vmThread, + cpClass, + (U_8*)field, + fieldLen, + (U_8*)sig, + sigLen, + &definingClass, + NULL, + J9_LOOK_NO_JAVA); + } + else + { + return false; + } + + TR_OpaqueClassBlock *opaqueDefiningClass = reinterpret_cast(definingClass); + int32_t arrayDims = 0; + opaqueDefiningClass = getBaseComponentClass(opaqueDefiningClass, arrayDims); + + return validateSymbol(definingClassID, static_cast(opaqueDefiningClass)); + } + +bool +TR::SymbolValidationManager::validateClassClassRecord(uint16_t classClassID, uint16_t objectClassID) + { + if (getSymbolFromID(objectClassID) == NULL) + { + TR_ASSERT(false, "objectClassID %u should exist\n", objectClassID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + TR_OpaqueClassBlock *objectClass = static_cast(getSymbolFromID(objectClassID)); + TR_OpaqueClassBlock *classClass = fej9->getClassClassPointer(objectClass); + + return validateSymbol(classClassID, static_cast(classClass)); + } + +bool +TR::SymbolValidationManager::validateConcreteSubClassFromClassRecord(uint16_t childClassID, uint16_t superClassID) + { + if (getSymbolFromID(superClassID) == NULL) + { + TR_ASSERT(false, "superClassID %u should exist\n", superClassID); + return false; + } + + TR_OpaqueClassBlock *superClass = static_cast(getSymbolFromID(superClassID)); + + TR_PersistentCHTable * chTable = comp()->getPersistentInfo()->getPersistentCHTable(); + TR_OpaqueClassBlock *childClass = chTable->findSingleConcreteSubClass(superClass, TR::comp(), false); + + int32_t arrayDims = 0; + childClass = getBaseComponentClass(childClass, arrayDims); + + return validateSymbol(childClassID, static_cast(childClass)); + } + +bool +TR::SymbolValidationManager::validateArrayClassFromJavaVM(uint16_t arrayClassID, int32_t arrayClassIndex) + { + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + struct J9Class ** arrayClasses = &fej9->getJ9JITConfig()->javaVM->booleanArrayClass; + TR_OpaqueClassBlock *arrayClass = reinterpret_cast(arrayClasses[arrayClassIndex - 4]); + + int32_t arrayDims = 0; + arrayClass = getBaseComponentClass(arrayClass, arrayDims); + + return validateSymbol(arrayClassID, static_cast(arrayClass)); + } + +bool +TR::SymbolValidationManager::validateClassChainRecord(uint16_t classID, void *classChain) + { + if (getSymbolFromID(classID) == NULL) + { + TR_ASSERT(false, "classID %u should exist\n", classID); + return false; + } + + TR::Compilation* comp = TR::comp(); + TR_OpaqueClassBlock *definingClass = static_cast(getSymbolFromID(classID)); + + return comp->fej9()->sharedCache()->classMatchesCachedVersion(definingClass, (uintptrj_t *) classChain); + } + +bool +TR::SymbolValidationManager::validateRomClassRecord(uint16_t classID, J9ROMClass *romClass) + { + if (getSymbolFromID(classID) == NULL) + { + TR_ASSERT(false, "classID %u should exist\n", classID); + return false; + } + + J9Class *definingClass = static_cast(getSymbolFromID(classID)); + + return (definingClass->romClass == romClass); + } + +bool +TR::SymbolValidationManager::validatePrimitiveClassRecord(uint16_t classID, char primitiveType) + { + if (getSymbolFromID(classID) == NULL) + { + TR_ASSERT(false, "classID %u should exist\n", classID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + TR_OpaqueClassBlock *primitiveClass = static_cast(getSymbolFromID(classID)); + + J9ROMClass *romClass = reinterpret_cast(fej9->getPersistentClassPointerFromClassPointer(primitiveClass)); + J9UTF8 * className = J9ROMCLASS_CLASSNAME(romClass); + + return (primitiveType == getPrimitiveChar(className)); + } + +bool +TR::SymbolValidationManager::validateMethodFromInlinedSiteRecord(uint16_t methodID, TR_OpaqueMethodBlock *method) + { + return validateSymbol(methodID, static_cast(method)); + } + +bool +TR::SymbolValidationManager::validateMethodByNameRecord(uint16_t methodID, uint16_t beholderID, J9ROMClass *romClass, J9ROMMethod *romMethod) + { + if (getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(false, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VM *fej9 = reinterpret_cast(TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread)); + + J9Class *beholder = static_cast(getSymbolFromID(beholderID)); + J9ConstantPool *beholderCP = J9_CP_FROM_CLASS(beholder); + + J9UTF8 *methodNameData = J9ROMMETHOD_NAME(romMethod); + char *methodName = (char *)alloca(J9UTF8_LENGTH(methodNameData)+1); + strncpy(methodName, reinterpret_cast(J9UTF8_DATA(methodNameData)), J9UTF8_LENGTH(methodNameData)); + methodName[J9UTF8_LENGTH(methodNameData)] = '\0'; + + J9UTF8 *methodSigData = J9ROMMETHOD_SIGNATURE(romMethod); + char *methodSig = (char *)alloca(J9UTF8_LENGTH(methodSigData)+1); + strncpy(methodSig, reinterpret_cast(J9UTF8_DATA(methodSigData)), J9UTF8_LENGTH(methodSigData)); + methodSig[J9UTF8_LENGTH(methodSigData)] = '\0'; + + J9UTF8 * classNameData = J9ROMCLASS_CLASSNAME(romClass); + char *className = (char *)alloca(J9UTF8_LENGTH(classNameData)+1); + strncpy(className, reinterpret_cast(J9UTF8_DATA(classNameData)), J9UTF8_LENGTH(classNameData)); + className[J9UTF8_LENGTH(classNameData)] = '\0'; + + TR_OpaqueMethodBlock *method = fej9->getMethodFromName(className, methodName, methodSig, beholderCP); + + return validateSymbol(methodID, static_cast(method)); + } + +bool +TR::SymbolValidationManager::validateMethodFromClassRecord(uint16_t methodID, uint16_t beholderID, uint32_t index) + { + if (getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(false, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + TR_OpaqueClassBlock *beholder = static_cast(getSymbolFromID(beholderID)); + J9Method *method; + + { + TR::VMAccessCriticalSection getResolvedMethods(fej9); // Prevent HCR + J9Method *methods = static_cast(fej9->getMethods(beholder)); + uint32_t numMethods = fej9->getNumMethods(beholder); + if (index >= numMethods) + { + TR_ASSERT(false, "Index is not within the bounds of the ramMethods array\n"); + return false; + } + method = &(methods[index]); + } + + return validateSymbol(methodID, static_cast(method)); + } + +bool +TR::SymbolValidationManager::validateStaticMethodFromCPRecord(uint16_t methodID, uint16_t beholderID, int32_t cpIndex) + { + if (getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(false, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + J9Class *beholder = static_cast(getSymbolFromID(beholderID)); + J9ConstantPool *beholderCP = J9_CP_FROM_CLASS(beholder); + J9Method *ramMethod; + + { + TR::VMAccessCriticalSection getResolvedStaticMethod(fej9); + ramMethod = jitResolveStaticMethodRef(vmThread, beholderCP, cpIndex, J9_RESOLVE_FLAG_JIT_COMPILE_TIME); + } + + return validateSymbol(methodID, static_cast(ramMethod)); + } + +bool +TR::SymbolValidationManager::validateSpecialMethodFromCPRecord(uint16_t methodID, uint16_t beholderID, int32_t cpIndex) + { + if (getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(false, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + J9Class *beholder = static_cast(getSymbolFromID(beholderID)); + J9ConstantPool *beholderCP = J9_CP_FROM_CLASS(beholder); + J9Method *ramMethod; + + { + TR::VMAccessCriticalSection resolveSpecialMethodRef(fej9); + ramMethod = jitResolveSpecialMethodRef(vmThread, beholderCP, cpIndex, J9_RESOLVE_FLAG_JIT_COMPILE_TIME); + } + + return validateSymbol(methodID, static_cast(ramMethod)); + } + +bool +TR::SymbolValidationManager::validateVirtualMethodFromCPRecord(uint16_t methodID, uint16_t beholderID, int32_t cpIndex) + { + if (getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(false, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + J9Class *beholder = static_cast(getSymbolFromID(beholderID)); + J9ConstantPool *beholderCP = J9_CP_FROM_CLASS(beholder); + + UDATA vTableOffset; + bool unresolvedInCP; + TR_OpaqueMethodBlock * ramMethod = TR_ResolvedJ9Method::getVirtualMethod(fej9, beholderCP, cpIndex, &vTableOffset, &unresolvedInCP); + + return validateSymbol(methodID, static_cast(ramMethod)); + } + +bool +TR::SymbolValidationManager::validateVirtualMethodFromOffsetRecord(uint16_t methodID, uint16_t beholderID, int32_t virtualCallOffset, bool ignoreRtResolve) + { + if (getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(false, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + TR_OpaqueClassBlock *beholder = static_cast(getSymbolFromID(beholderID)); + + TR_OpaqueMethodBlock *ramMethod = fej9->getResolvedVirtualMethod(beholder, virtualCallOffset, ignoreRtResolve); + + return validateSymbol(methodID, static_cast(ramMethod)); + } + +bool +TR::SymbolValidationManager::validateInterfaceMethodFromCPRecord(uint16_t methodID, uint16_t beholderID, uint16_t lookupID, int32_t cpIndex) + { + if (getSymbolFromID(beholderID) == NULL || getSymbolFromID(lookupID) == NULL) + { + TR_ASSERT(getSymbolFromID(beholderID) != 0, "beholderID %u should exist\n", beholderID); + TR_ASSERT(getSymbolFromID(lookupID) != 0, "lookupID %u should exist\n", lookupID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + TR_OpaqueClassBlock *lookup = static_cast(getSymbolFromID(lookupID)); + + J9Class *beholder = static_cast(getSymbolFromID(beholderID)); + J9ConstantPool *beholderCP = J9_CP_FROM_CLASS(beholder); + + TR_OpaqueMethodBlock *ramMethod = fej9->getResolvedInterfaceMethod(beholderCP, lookup, cpIndex); + + return validateSymbol(methodID, static_cast(ramMethod)); + } + +bool +TR::SymbolValidationManager::validateImproperInterfaceMethodFromCPRecord(uint16_t methodID, uint16_t beholderID, int32_t cpIndex) + { + if (getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(false, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + J9Class *beholder = static_cast(getSymbolFromID(beholderID)); + J9ConstantPool *beholderCP = J9_CP_FROM_CLASS(beholder); + J9Method *ramMethod; + + { + TR::VMAccessCriticalSection resolveImproperMethodRef(fej9); + ramMethod = jitGetImproperInterfaceMethodFromCP(vmThread, beholderCP, cpIndex); + } + + return validateSymbol(methodID, static_cast(ramMethod)); + } + +bool +TR::SymbolValidationManager::validateMethodFromClassAndSignatureRecord(uint16_t methodID, uint16_t methodClassID, uint16_t beholderID, J9ROMMethod *romMethod) + { + if (getSymbolFromID(methodClassID) == NULL || getSymbolFromID(beholderID) == NULL) + { + TR_ASSERT(getSymbolFromID(methodClassID) != 0, "methodClassID %u should exist\n", methodClassID); + TR_ASSERT(getSymbolFromID(beholderID) != 0, "beholderID %u should exist\n", beholderID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + TR_OpaqueClassBlock *methodClass = static_cast(getSymbolFromID(methodClassID)); + TR_OpaqueClassBlock *beholder = static_cast(getSymbolFromID(beholderID)); + + J9UTF8 *methodNameData = J9ROMMETHOD_NAME(romMethod); + char *methodName = (char *)alloca(J9UTF8_LENGTH(methodNameData)+1); + strncpy(methodName, reinterpret_cast(J9UTF8_DATA(methodNameData)), J9UTF8_LENGTH(methodNameData)); + methodName[J9UTF8_LENGTH(methodNameData)] = '\0'; + + J9UTF8 *methodSigData = J9ROMMETHOD_SIGNATURE(romMethod); + char *methodSig = (char *)alloca(J9UTF8_LENGTH(methodSigData)+1); + strncpy(methodSig, reinterpret_cast(J9UTF8_DATA(methodSigData)), J9UTF8_LENGTH(methodSigData)); + methodSig[J9UTF8_LENGTH(methodSigData)] = '\0'; + + TR_OpaqueMethodBlock *method = fej9->getMethodFromClass(methodClass, methodName, methodSig, beholder); + + return validateSymbol(methodID, static_cast(method)); + } + +bool +TR::SymbolValidationManager::validateMethodFromSingleImplementerRecord(uint16_t methodID, + uint16_t thisClassID, + int32_t cpIndexOrVftSlot, + uint16_t callerMethodID, + TR_YesNoMaybe useGetResolvedInterfaceMethod) + { + if (getSymbolFromID(thisClassID) == NULL || getSymbolFromID(callerMethodID) == NULL) + { + TR_ASSERT(getSymbolFromID(thisClassID) != 0, "thisClassID %u should exist\n", thisClassID); + TR_ASSERT(getSymbolFromID(callerMethodID) != 0, "callerMethodID %u should exist\n", callerMethodID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + TR_Memory *trMemory = comp->trMemory(); + TR_PersistentCHTable * chTable = comp->getPersistentInfo()->getPersistentCHTable(); + + TR_OpaqueClassBlock *thisClass = static_cast(getSymbolFromID(thisClassID)); + TR_OpaqueMethodBlock *callerMethod = static_cast(getSymbolFromID(callerMethodID)); + + TR_ResolvedMethod *callerResolvedMethod = fej9->createResolvedMethod(trMemory, callerMethod, NULL); + TR_ResolvedMethod *calleeResolvedMethod = chTable->findSingleImplementer(thisClass, cpIndexOrVftSlot, callerResolvedMethod, comp, false, useGetResolvedInterfaceMethod, false); + + if (!calleeResolvedMethod) + return false; + + TR_OpaqueMethodBlock *method = calleeResolvedMethod->getPersistentIdentifier(); + + return validateSymbol(methodID, static_cast(method)); + } + +bool +TR::SymbolValidationManager::validateMethodFromSingleInterfaceImplementerRecord(uint16_t methodID, + uint16_t thisClassID, + int32_t cpIndex, + uint16_t callerMethodID) + { + if (getSymbolFromID(thisClassID) == NULL || getSymbolFromID(callerMethodID) == NULL) + { + TR_ASSERT(getSymbolFromID(thisClassID) != 0, "thisClassID %u should exist\n", thisClassID); + TR_ASSERT(getSymbolFromID(callerMethodID) != 0, "callerMethodID %u should exist\n", callerMethodID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + TR_Memory *trMemory = comp->trMemory(); + TR_PersistentCHTable * chTable = comp->getPersistentInfo()->getPersistentCHTable(); + + TR_OpaqueClassBlock *thisClass = static_cast(getSymbolFromID(thisClassID)); + TR_OpaqueMethodBlock *callerMethod = static_cast(getSymbolFromID(callerMethodID)); + + TR_ResolvedMethod *callerResolvedMethod = fej9->createResolvedMethod(trMemory, callerMethod, NULL); + TR_ResolvedMethod *calleeResolvedMethod = chTable->findSingleInterfaceImplementer(thisClass, cpIndex, callerResolvedMethod, comp, false, false); + + if (!calleeResolvedMethod) + return false; + + TR_OpaqueMethodBlock *method = calleeResolvedMethod->getPersistentIdentifier(); + + return validateSymbol(methodID, static_cast(method)); + } + +bool +TR::SymbolValidationManager::validateMethodFromSingleAbstractImplementerRecord(uint16_t methodID, + uint16_t thisClassID, + int32_t vftSlot, + uint16_t callerMethodID) + { + if (getSymbolFromID(thisClassID) == NULL || getSymbolFromID(callerMethodID) == NULL) + { + TR_ASSERT(getSymbolFromID(thisClassID) != 0, "thisClassID %u should exist\n", thisClassID); + TR_ASSERT(getSymbolFromID(callerMethodID) != 0, "callerMethodID %u should exist\n", callerMethodID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + TR_Memory *trMemory = comp->trMemory(); + TR_PersistentCHTable * chTable = comp->getPersistentInfo()->getPersistentCHTable(); + + TR_OpaqueClassBlock *thisClass = static_cast(getSymbolFromID(thisClassID)); + TR_OpaqueMethodBlock *callerMethod = static_cast(getSymbolFromID(callerMethodID)); + + TR_ResolvedMethod *callerResolvedMethod = fej9->createResolvedMethod(trMemory, callerMethod, NULL); + TR_ResolvedMethod *calleeResolvedMethod = chTable->findSingleAbstractImplementer(thisClass, vftSlot, callerResolvedMethod, comp, false, false); + + if (!calleeResolvedMethod) + return false; + + TR_OpaqueMethodBlock *method = calleeResolvedMethod->getPersistentIdentifier(); + + return validateSymbol(methodID, static_cast(method)); + } + +bool +TR::SymbolValidationManager::validateStackWalkerMaySkipFramesRecord(uint16_t methodID, uint16_t methodClassID, bool couldSkipFrames) + { + if (getSymbolFromID(methodID) == NULL || getSymbolFromID(methodClassID) == NULL) + { + TR_ASSERT(getSymbolFromID(methodID) != 0, "methodID %u should exist\n", methodID); + TR_ASSERT(getSymbolFromID(methodClassID) != 0, "methodClassID %u should exist\n", methodClassID); + return false; + } + + TR::Compilation* comp = TR::comp(); + J9VMThread *vmThread = comp->j9VMThread(); + TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread); + + TR_OpaqueMethodBlock *method = static_cast(getSymbolFromID(methodID)); + TR_OpaqueClassBlock *methodClass = static_cast(getSymbolFromID(methodClassID)); + + bool canSkipFrames = fej9->stackWalkerMaySkipFrames(method, methodClass); + + return (canSkipFrames == couldSkipFrames); + } + +bool +TR::SymbolValidationManager::validateClassInfoIsInitializedRecord(uint16_t classID, bool wasInitialized) + { + if (getSymbolFromID(classID) == NULL) + { + TR_ASSERT(getSymbolFromID(classID) != 0, "classID %u should exist\n", classID); + return false; + } + + TR::Compilation* comp = TR::comp(); + TR_OpaqueClassBlock *clazz = static_cast(getSymbolFromID(classID)); + + bool initialized = false; + + TR_PersistentClassInfo * classInfo = + comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(clazz, comp, true); + + if (classInfo) + initialized = classInfo->isInitialized(); + + bool valid = (!wasInitialized || initialized); + return valid; + } + + +static void printClass(TR_OpaqueClassBlock *clazz) + { + J9UTF8 *className = J9ROMCLASS_CLASSNAME(((J9Class *)clazz)->romClass); + traceMsg(TR::comp(), "\tclassName=%.*s\n", J9UTF8_LENGTH(className), J9UTF8_DATA(className)); + } + +void TR::ClassValidationRecord::printFields() + { + traceMsg(TR::comp(), "\t_classChain=0x%p\n", _classChain); + } + +void TR::RootClassRecord::printFields() + { + traceMsg(TR::comp(), "RootClassRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_class=0x%p\n", _class); + printClass(_class); + } + +void TR::ClassByNameRecord::printFields() + { + traceMsg(TR::comp(), "ClassByNameRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_class=0x%p\n", _class); + printClass(_class); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + traceMsg(TR::comp(), "\t_primitiveType=%c\n", _primitiveType); + } + +void TR::ProfiledClassRecord::printFields() + { + traceMsg(TR::comp(), "ProfiledClassRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_class=0x%p\n", _class); + printClass(_class); + traceMsg(TR::comp(), "\t_primitiveType=%c\n", _primitiveType); + } + +void TR::ClassFromCPRecord::printFields() + { + traceMsg(TR::comp(), "ClassFromCPRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_class=0x%p\n", _class); + printClass(_class); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + traceMsg(TR::comp(), "\t_cpIndex=%d\n", _cpIndex); + } + +void TR::DefiningClassFromCPRecord::printFields() + { + traceMsg(TR::comp(), "DefiningClassFromCPRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_class=0x%p\n", _class); + printClass(_class); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + traceMsg(TR::comp(), "\t_cpIndex=%d\n", _cpIndex); + traceMsg(TR::comp(), "\t_isStatic=%s\n", (_isStatic ? "true" : "false")); + } + +void TR::StaticClassFromCPRecord::printFields() + { + traceMsg(TR::comp(), "StaticClassFromCPRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_class=0x%p\n", _class); + printClass(_class); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + traceMsg(TR::comp(), "\t_cpIndex=%d\n", _cpIndex); + } + +void TR::ClassFromMethodRecord::printFields() + { + traceMsg(TR::comp(), "ClassFromMethodRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_class=0x%p\n", _class); + printClass(_class); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + } + +void TR::ComponentClassFromArrayClassRecord::printFields() + { + traceMsg(TR::comp(), "ComponentClassFromArrayClassRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_componentClass=0x%p\n", _componentClass); + printClass(_componentClass); + traceMsg(TR::comp(), "\t_arrayClass=0x%p\n", _arrayClass); + printClass(_arrayClass); + } + +void TR::ArrayClassFromComponentClassRecord::printFields() + { + traceMsg(TR::comp(), "ArrayClassFromComponentClassRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_arrayClass=0x%p\n", _arrayClass); + printClass(_arrayClass); + traceMsg(TR::comp(), "\t_componentClass=0x%p\n", _componentClass); + printClass(_componentClass); + } + +void TR::SuperClassFromClassRecord::printFields() + { + traceMsg(TR::comp(), "SuperClassFromClassRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_superClass=0x%p\n", _superClass); + printClass(_superClass); + traceMsg(TR::comp(), "\t_childClass=0x%p\n", _childClass); + printClass(_childClass); + } + +void TR::ClassInstanceOfClassRecord::printFields() + { + traceMsg(TR::comp(), "ClassInstanceOfClassRecord\n"); + traceMsg(TR::comp(), "\t_classOne=0x%p\n", _classOne); + printClass(_classOne); + traceMsg(TR::comp(), "\t_classTwo=0x%p\n", _classTwo); + printClass(_classTwo); + traceMsg(TR::comp(), "\t_objectTypeIsFixed=%s\n", _objectTypeIsFixed ? "true" : "false"); + traceMsg(TR::comp(), "\t_castTypeIsFixed=%s\n", _castTypeIsFixed ? "true" : "false"); + traceMsg(TR::comp(), "\t_isInstanceOf=%s\n", _isInstanceOf ? "true" : "false"); + } + +void TR::SystemClassByNameRecord::printFields() + { + traceMsg(TR::comp(), "SystemClassByNameRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_systemClass=0x%p\n", _systemClass); + printClass(_systemClass); + } + +void TR::ClassFromITableIndexCPRecord::printFields() + { + traceMsg(TR::comp(), "ClassFromITableIndexCPRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_class=0x%p\n", _class); + printClass(_class); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + traceMsg(TR::comp(), "\t_cpIndex=%d\n", _cpIndex); + } + +void TR::DeclaringClassFromFieldOrStaticRecord::printFields() + { + traceMsg(TR::comp(), "DeclaringClassFromFieldOrStaticRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_class=0x%p\n", _class); + printClass(_class); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + traceMsg(TR::comp(), "\t_cpIndex=%d\n", _cpIndex); + } + +void TR::ClassClassRecord::printFields() + { + traceMsg(TR::comp(), "ClassClassRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_classClass=0x%p\n", _classClass); + printClass(_classClass); + traceMsg(TR::comp(), "\t_objectClass=0x%p\n", _objectClass); + printClass(_objectClass); + } + +void TR::ConcreteSubClassFromClassRecord::printFields() + { + traceMsg(TR::comp(), "ConcreteSubClassFromClassRecord\n"); + TR::ClassValidationRecord::printFields(); + traceMsg(TR::comp(), "\t_childClass=0x%p\n", _childClass); + traceMsg(TR::comp(), "\t_superClass=0x%p\n", _superClass); + } + +void TR::ClassChainRecord::printFields() + { + traceMsg(TR::comp(), "ClassChainRecord\n"); + traceMsg(TR::comp(), "\t_classChain=0x%p\n", _classChain); + } + +void TR::RomClassRecord::printFields() + { + traceMsg(TR::comp(), "RomClassRecord\n"); + traceMsg(TR::comp(), "\t_class=0x%p\n", _class); + } + +void TR::PrimitiveClassRecord::printFields() + { + traceMsg(TR::comp(), "PrimitiveClassRecord\n"); + traceMsg(TR::comp(), "\t_class=0x%p\n", _class); + printClass(_class); + } + +void TR::MethodFromInlinedSiteRecord::printFields() + { + traceMsg(TR::comp(), "MethodFromInlinedSiteRecord\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_inlinedSiteIndex=%d\n", _inlinedSiteIndex); + } + +void TR::MethodByNameRecord::printFields() + { + traceMsg(TR::comp(), "MethodByNameRecord\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + } + +void TR::MethodFromClassRecord::printFields() + { + traceMsg(TR::comp(), "MethodFromClassRecord\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + traceMsg(TR::comp(), "\t_index=%u\n", _index); + } + +void TR::StaticMethodFromCPRecord::printFields() + { + traceMsg(TR::comp(), "StaticMethodFromCPRecord\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + traceMsg(TR::comp(), "\t_cpIndex=%d\n", _cpIndex); + } + +void TR::SpecialMethodFromCPRecord::printFields() + { + traceMsg(TR::comp(), "SpecialMethodFromCPRecord\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + traceMsg(TR::comp(), "\t_cpIndex=%d\n", _cpIndex); + } + +void TR::VirtualMethodFromCPRecord::printFields() + { + traceMsg(TR::comp(), "VirtualMethodFromCPRecord\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + traceMsg(TR::comp(), "\t_cpIndex=%d\n", _cpIndex); + } + +void TR::VirtualMethodFromOffsetRecord::printFields() + { + traceMsg(TR::comp(), "VirtualMethodFromOffsetRecord\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + traceMsg(TR::comp(), "\t_virtualCallOffset=%d\n", _virtualCallOffset); + traceMsg(TR::comp(), "\t_ignoreRtResolve=%s\n", _ignoreRtResolve ? "true" : "false"); + } + +void TR::InterfaceMethodFromCPRecord::printFields() + { + traceMsg(TR::comp(), "InterfaceMethodFromCPRecord\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + traceMsg(TR::comp(), "\t_lookup=0x%p\n", _lookup); + printClass(_lookup); + traceMsg(TR::comp(), "\t_cpIndex=%d\n", _cpIndex); + } + +void TR::MethodFromClassAndSigRecord::printFields() + { + traceMsg(TR::comp(), "MethodFromClassAndSigRecord\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_methodClass=0x%p\n", _methodClass); + printClass(_methodClass); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + } + +void TR::StackWalkerMaySkipFramesRecord::printFields() + { + traceMsg(TR::comp(), "StackWalkerMaySkipFramesRecord\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_methodClass=0x%p\n", _methodClass); + printClass(_methodClass); + traceMsg(TR::comp(), "\t_skipFrames=%sp\n", _skipFrames ? "true" : "false"); + } + +void TR::ArrayClassFromJavaVM::printFields() + { + traceMsg(TR::comp(), "ArrayClassFromJavaVM\n"); + traceMsg(TR::comp(), "\t_arrayClass=0x%p\n", _arrayClass); + printClass(_arrayClass); + traceMsg(TR::comp(), "\t_arrayClassIndex=%d\n", _arrayClassIndex); + } + +void TR::ClassInfoIsInitialized::printFields() + { + traceMsg(TR::comp(), "ClassInfoIsInitialized\n"); + traceMsg(TR::comp(), "\t_class=0x%p\n", _class); + printClass(_class); + traceMsg(TR::comp(), "\t_isInitialized=%sp\n", _isInitialized ? "true" : "false"); + } + +void TR::MethodFromSingleImplementer::printFields() + { + traceMsg(TR::comp(), "MethodFromSingleImplementer\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_thisClass=0x%p\n", _thisClass); + printClass(_thisClass); + traceMsg(TR::comp(), "\t_cpIndexOrVftSlot=%d\n", _cpIndexOrVftSlot); + traceMsg(TR::comp(), "\t_callerMethod=0x%p\n", _callerMethod); + traceMsg(TR::comp(), "\t_useGetResolvedInterfaceMethod=%d\n", _useGetResolvedInterfaceMethod); + } + +void TR::MethodFromSingleInterfaceImplementer::printFields() + { + traceMsg(TR::comp(), "MethodFromSingleInterfaceImplementer\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_thisClass=0x%p\n", _thisClass); + printClass(_thisClass); + traceMsg(TR::comp(), "\t_cpIndex=%d\n", _cpIndex); + traceMsg(TR::comp(), "\t_callerMethod=0x%p\n", _callerMethod); + } + +void TR::MethodFromSingleAbstractImplementer::printFields() + { + traceMsg(TR::comp(), "MethodFromSingleAbstractImplementer\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_thisClass=0x%p\n", _thisClass); + printClass(_thisClass); + traceMsg(TR::comp(), "\t_vftSlot=%d\n", _vftSlot); + traceMsg(TR::comp(), "\t_callerMethod=0x%p\n", _callerMethod); + } + +void TR::ImproperInterfaceMethodFromCPRecord::printFields() + { + traceMsg(TR::comp(), "ImproperInterfaceMethodFromCPRecord\n"); + traceMsg(TR::comp(), "\t_method=0x%p\n", _method); + traceMsg(TR::comp(), "\t_beholder=0x%p\n", _beholder); + printClass(_beholder); + traceMsg(TR::comp(), "\t_cpIndex=%d\n", _cpIndex); + } diff --git a/runtime/compiler/runtime/SymbolValidationManager.hpp b/runtime/compiler/runtime/SymbolValidationManager.hpp new file mode 100644 index 00000000000..23e2fc9e4c5 --- /dev/null +++ b/runtime/compiler/runtime/SymbolValidationManager.hpp @@ -0,0 +1,1345 @@ +/******************************************************************************* + * Copyright (c) 2000, 2018 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 + *******************************************************************************/ + +#ifndef SYMBOL_VALIDATION_MANAGER_INCL +#define SYMBOL_VALIDATION_MANAGER_INCL + +#include // for std::max, etc +#include +#include +#include // for NULL +#include // for int32_t, uint8_t, etc +#include "env/jittypes.h" // for uintptrj_t +#include "j9.h" +#include "j9nonbuilder.h" +#include "infra/TRlist.hpp" +#include "env/TRMemory.hpp" +#include "env/VMJ9.h" +#include "runtime/Runtime.hpp" + +#define SVM_ASSERT(manager, condition, format, ...) \ + do { (manager->inHeuristicRegion() && condition) ? (void)0 : TR::fatal_assertion(__FILE__, __LINE__, #condition, format, ##__VA_ARGS__); } while(0) + +namespace TR { + +struct SymbolValidationRecord + { + SymbolValidationRecord(TR_ExternalRelocationTargetKind kind) + : _kind(kind) + {} + + virtual bool isEqual(SymbolValidationRecord *other) = 0; + virtual void printFields() = 0; + + virtual bool isClassValidationRecord() { return false; } + + TR_ExternalRelocationTargetKind _kind; + }; + +struct ClassValidationRecord : public SymbolValidationRecord + { + ClassValidationRecord(TR_ExternalRelocationTargetKind kind) + : SymbolValidationRecord(kind), + _classChain(NULL) + {} + + virtual bool isEqual(SymbolValidationRecord *other) = 0; + virtual void printFields(); + + virtual bool isClassValidationRecord() { return true; } + + void * _classChain; + }; + +struct RootClassRecord : public ClassValidationRecord + { + RootClassRecord(TR_OpaqueClassBlock *clazz) + : ClassValidationRecord(TR_ValidateRootClass), + _class(clazz) + {} + + bool operator ==(const RootClassRecord &rhs) + { + if (_class == rhs._class) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock * _class; + }; + + +struct ClassByNameRecord : public ClassValidationRecord + { + ClassByNameRecord(TR_OpaqueClassBlock *clazz, + TR_OpaqueClassBlock *beholder, + char primitiveType) + : ClassValidationRecord(TR_ValidateClassByName), + _class(clazz), + _beholder(beholder), + _primitiveType(primitiveType) + {} + + bool operator ==(const ClassByNameRecord &rhs) + { + if (_class == rhs._class && + _beholder == rhs._beholder && + _primitiveType == rhs._primitiveType) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock * _class; + TR_OpaqueClassBlock * _beholder; + char _primitiveType; + }; + +struct ProfiledClassRecord : public ClassValidationRecord + { + ProfiledClassRecord(TR_OpaqueClassBlock *clazz, + char primitiveType) + : ClassValidationRecord(TR_ValidateProfiledClass), + _class(clazz), + _primitiveType(primitiveType) + {} + + bool operator ==(const ProfiledClassRecord &rhs) + { + if (_class == rhs._class && + _primitiveType == rhs._primitiveType) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock * _class; + char _primitiveType; + }; + +struct ClassFromCPRecord : public ClassValidationRecord + { + ClassFromCPRecord(TR_OpaqueClassBlock *clazz, TR_OpaqueClassBlock *beholder, uint32_t cpIndex) + : ClassValidationRecord(TR_ValidateClassFromCP), + _class(clazz), + _beholder(beholder), + _cpIndex(cpIndex) + {} + + bool operator ==(const ClassFromCPRecord &rhs) + { + if (_class == rhs._class && + _beholder == rhs._beholder && + _cpIndex == rhs._cpIndex) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock * _class; + TR_OpaqueClassBlock * _beholder; + uint32_t _cpIndex; + }; + +struct DefiningClassFromCPRecord : public ClassValidationRecord + { + DefiningClassFromCPRecord(TR_OpaqueClassBlock *clazz, TR_OpaqueClassBlock *beholder, uint32_t cpIndex, bool isStatic) + : ClassValidationRecord(TR_ValidateDefiningClassFromCP), + _class(clazz), + _beholder(beholder), + _cpIndex(cpIndex), + _isStatic(isStatic) + {} + + bool operator ==(const DefiningClassFromCPRecord &rhs) + { + if (_class == rhs._class && + _beholder == rhs._beholder && + _cpIndex == rhs._cpIndex && + _isStatic == rhs._isStatic) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock * _class; + TR_OpaqueClassBlock * _beholder; + uint32_t _cpIndex; + bool _isStatic; + }; + +struct StaticClassFromCPRecord : public ClassValidationRecord + { + StaticClassFromCPRecord(TR_OpaqueClassBlock *clazz, TR_OpaqueClassBlock *beholder, uint32_t cpIndex) + : ClassValidationRecord(TR_ValidateStaticClassFromCP), + _class(clazz), + _beholder(beholder), + _cpIndex(cpIndex) + {} + + bool operator ==(const StaticClassFromCPRecord &rhs) + { + if (_class == rhs._class && + _beholder == rhs._beholder && + _cpIndex == rhs._cpIndex) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock * _class; + TR_OpaqueClassBlock * _beholder; + uint32_t _cpIndex; + }; + +struct ClassFromMethodRecord : public ClassValidationRecord + { + ClassFromMethodRecord(TR_OpaqueClassBlock *clazz, TR_OpaqueMethodBlock *method) + : ClassValidationRecord(TR_ValidateClassFromMethod), + _class(clazz), + _method(method) + {} + + bool operator ==(const ClassFromMethodRecord &rhs) + { + if (_class == rhs._class && + _method == rhs._method) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock * _class; + TR_OpaqueMethodBlock *_method; + }; + +struct ComponentClassFromArrayClassRecord : public ClassValidationRecord + { + ComponentClassFromArrayClassRecord(TR_OpaqueClassBlock *componentClass, TR_OpaqueClassBlock *arrayClass) + : ClassValidationRecord(TR_ValidateComponentClassFromArrayClass), + _componentClass(componentClass), + _arrayClass(arrayClass) + {} + + bool operator ==(const ComponentClassFromArrayClassRecord &rhs) + { + if (_componentClass == rhs._componentClass && + _arrayClass == rhs._arrayClass) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock * _componentClass; + TR_OpaqueClassBlock * _arrayClass; + }; + +struct ArrayClassFromComponentClassRecord : public ClassValidationRecord + { + ArrayClassFromComponentClassRecord(TR_OpaqueClassBlock *arrayClass, TR_OpaqueClassBlock *componentClass) + : ClassValidationRecord(TR_ValidateArrayClassFromComponentClass), + _arrayClass(arrayClass), + _componentClass(componentClass) + {} + + bool operator ==(const ArrayClassFromComponentClassRecord &rhs) + { + if (_arrayClass == rhs._arrayClass && + _componentClass == rhs._componentClass) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock * _arrayClass; + TR_OpaqueClassBlock * _componentClass; + }; + +struct SuperClassFromClassRecord : public ClassValidationRecord + { + SuperClassFromClassRecord(TR_OpaqueClassBlock *superClass, TR_OpaqueClassBlock *childClass) + : ClassValidationRecord(TR_ValidateSuperClassFromClass), + _superClass(superClass), + _childClass(childClass) + {} + + bool operator ==(const SuperClassFromClassRecord &rhs) + { + if (_superClass == rhs._superClass && + _childClass == rhs._childClass) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock *_superClass; + TR_OpaqueClassBlock *_childClass; + }; + +struct ClassInstanceOfClassRecord : public SymbolValidationRecord + { + ClassInstanceOfClassRecord(TR_OpaqueClassBlock *classOne, TR_OpaqueClassBlock *classTwo, bool objectTypeIsFixed, bool castTypeIsFixed, bool isInstanceOf) + : SymbolValidationRecord(TR_ValidateClassInstanceOfClass), + _classOne(classOne), + _classTwo(classTwo), + _objectTypeIsFixed(objectTypeIsFixed), + _castTypeIsFixed(castTypeIsFixed), + _isInstanceOf(isInstanceOf) + {} + + bool operator ==(const ClassInstanceOfClassRecord &rhs) + { + if (_classOne == rhs._classOne && + _classTwo == rhs._classTwo && + _objectTypeIsFixed == rhs._objectTypeIsFixed && + _castTypeIsFixed == rhs._castTypeIsFixed && + _isInstanceOf == rhs._isInstanceOf) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock *_classOne; + TR_OpaqueClassBlock *_classTwo; + bool _objectTypeIsFixed; + bool _castTypeIsFixed; + bool _isInstanceOf; + }; + +struct SystemClassByNameRecord : public ClassValidationRecord + { + SystemClassByNameRecord(TR_OpaqueClassBlock *systemClass) + : ClassValidationRecord(TR_ValidateSystemClassByName), + _systemClass(systemClass) + {} + + bool operator ==(const SystemClassByNameRecord &rhs) + { + if (_systemClass == rhs._systemClass) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock *_systemClass; + }; + +struct ClassFromITableIndexCPRecord : public ClassValidationRecord + { + ClassFromITableIndexCPRecord(TR_OpaqueClassBlock *clazz, TR_OpaqueClassBlock *beholder, uint32_t cpIndex) + : ClassValidationRecord(TR_ValidateClassFromITableIndexCP), + _class(clazz), + _beholder(beholder), + _cpIndex(cpIndex) + {} + + bool operator ==(const ClassFromITableIndexCPRecord &rhs) + { + if (_class == rhs._class && + _beholder == rhs._beholder && + _cpIndex == rhs._cpIndex) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock * _class; + TR_OpaqueClassBlock * _beholder; + int32_t _cpIndex; + + }; + +struct DeclaringClassFromFieldOrStaticRecord : public ClassValidationRecord + { + DeclaringClassFromFieldOrStaticRecord(TR_OpaqueClassBlock *clazz, TR_OpaqueClassBlock *beholder, uint32_t cpIndex) + : ClassValidationRecord(TR_ValidateDeclaringClassFromFieldOrStatic), + _class(clazz), + _beholder(beholder), + _cpIndex(cpIndex) + {} + + bool operator ==(const DeclaringClassFromFieldOrStaticRecord &rhs) + { + if (_class == rhs._class && + _beholder == rhs._beholder && + _cpIndex == rhs._cpIndex) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock * _class; + TR_OpaqueClassBlock * _beholder; + uint32_t _cpIndex; + }; + +struct ClassClassRecord : public ClassValidationRecord + { + ClassClassRecord(TR_OpaqueClassBlock *classClass, TR_OpaqueClassBlock *objectClass) + : ClassValidationRecord(TR_ValidateClassClass), + _classClass(classClass), + _objectClass(objectClass) + {} + + bool operator ==(const ClassClassRecord &rhs) + { + if (_classClass == rhs._classClass && + _objectClass == rhs._objectClass) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock *_classClass; + TR_OpaqueClassBlock *_objectClass; + }; + +struct ConcreteSubClassFromClassRecord : public ClassValidationRecord + { + ConcreteSubClassFromClassRecord(TR_OpaqueClassBlock *childClass, TR_OpaqueClassBlock *superClass) + : ClassValidationRecord(TR_ValidateConcreteSubClassFromClass), + _childClass(childClass), + _superClass(superClass) + {} + + bool operator ==(const ConcreteSubClassFromClassRecord &rhs) + { + if (_childClass == rhs._childClass && + _superClass == rhs._superClass) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock *_childClass; + TR_OpaqueClassBlock *_superClass; + }; + +struct ClassChainRecord : public SymbolValidationRecord + { + ClassChainRecord(TR_OpaqueClassBlock *clazz, void *classChain) + : SymbolValidationRecord(TR_ValidateClassChain), + _class(clazz), + _classChain(classChain) + {} + + bool operator ==(const ClassChainRecord &rhs) + { + if (_class == rhs._class && + _classChain == rhs._classChain) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock *_class; + void *_classChain; + }; + +struct RomClassRecord : public SymbolValidationRecord + { + RomClassRecord(TR_OpaqueClassBlock *clazz) + : SymbolValidationRecord(TR_ValidateRomClass), + _class(clazz) + {} + + bool operator ==(const RomClassRecord &rhs) + { + if (_class == rhs._class) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock *_class; + }; + +struct PrimitiveClassRecord : public SymbolValidationRecord + { + PrimitiveClassRecord(TR_OpaqueClassBlock *clazz, char primitiveType) + : SymbolValidationRecord(TR_ValidatePrimitiveClass), + _class(clazz), + _primitiveType(primitiveType) + {} + + bool operator ==(const PrimitiveClassRecord &rhs) + { + if (_class == rhs._class && + _primitiveType == rhs._primitiveType) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock *_class; + char _primitiveType; + }; + +struct MethodFromInlinedSiteRecord : public SymbolValidationRecord + { + MethodFromInlinedSiteRecord(TR_OpaqueMethodBlock *method, + int32_t inlinedSiteIndex) + : SymbolValidationRecord(TR_ValidateMethodFromInlinedSite), + _method(method), + _inlinedSiteIndex(inlinedSiteIndex) + {} + + bool operator ==( const MethodFromInlinedSiteRecord &rhs) + { + if (_method == rhs._method && + _inlinedSiteIndex == rhs._inlinedSiteIndex) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + int32_t _inlinedSiteIndex; + }; + +struct MethodByNameRecord : public SymbolValidationRecord + { + MethodByNameRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *beholder) + : SymbolValidationRecord(TR_ValidateMethodByName), + _method(method), + _beholder(beholder) + {} + + bool operator ==( const MethodByNameRecord &rhs) + { + if (_method == rhs._method && + _beholder == rhs._beholder) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + TR_OpaqueClassBlock *_beholder; + }; + +struct MethodFromClassRecord : public SymbolValidationRecord + { + MethodFromClassRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *beholder, uint32_t index) + : SymbolValidationRecord(TR_ValidateMethodFromClass), + _method(method), + _beholder(beholder), + _index(index) + {} + + bool operator ==( const MethodFromClassRecord &rhs) + { + if (_method == rhs._method && + _beholder == rhs._beholder && + _index == rhs._index) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + TR_OpaqueClassBlock *_beholder; + uint32_t _index; + }; + +struct StaticMethodFromCPRecord : public SymbolValidationRecord + { + StaticMethodFromCPRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *beholder, + int32_t cpIndex) + : SymbolValidationRecord(TR_ValidateStaticMethodFromCP), + _method(method), + _beholder(beholder), + _cpIndex(cpIndex) + {} + + bool operator ==( const StaticMethodFromCPRecord &rhs) + { + if (_method == rhs._method && + _beholder == rhs._beholder && + _cpIndex == rhs._cpIndex) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + TR_OpaqueClassBlock *_beholder; + int32_t _cpIndex; + }; + +struct SpecialMethodFromCPRecord : public SymbolValidationRecord + { + SpecialMethodFromCPRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *beholder, + int32_t cpIndex) + : SymbolValidationRecord(TR_ValidateSpecialMethodFromCP), + _method(method), + _beholder(beholder), + _cpIndex(cpIndex) + {} + + bool operator ==( const SpecialMethodFromCPRecord &rhs) + { + if (_method == rhs._method && + _beholder == rhs._beholder && + _cpIndex == rhs._cpIndex) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + TR_OpaqueClassBlock *_beholder; + int32_t _cpIndex; + }; + +struct VirtualMethodFromCPRecord : public SymbolValidationRecord + { + VirtualMethodFromCPRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *beholder, + int32_t cpIndex) + : SymbolValidationRecord(TR_ValidateVirtualMethodFromCP), + _method(method), + _beholder(beholder), + _cpIndex(cpIndex) + {} + + bool operator ==( const VirtualMethodFromCPRecord &rhs) + { + if (_method == rhs._method && + _beholder == rhs._beholder && + _cpIndex == rhs._cpIndex) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + TR_OpaqueClassBlock *_beholder; + int32_t _cpIndex; + }; + +struct VirtualMethodFromOffsetRecord : public SymbolValidationRecord + { + VirtualMethodFromOffsetRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *beholder, + int32_t virtualCallOffset, + bool ignoreRtResolve) + : SymbolValidationRecord(TR_ValidateVirtualMethodFromOffset), + _method(method), + _beholder(beholder), + _virtualCallOffset(virtualCallOffset), + _ignoreRtResolve(ignoreRtResolve) + {} + + bool operator ==( const VirtualMethodFromOffsetRecord &rhs) + { + if (_method == rhs._method && + _beholder == rhs._beholder && + _virtualCallOffset == rhs._virtualCallOffset && + _ignoreRtResolve == rhs._ignoreRtResolve) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + TR_OpaqueClassBlock *_beholder; + int32_t _virtualCallOffset; + bool _ignoreRtResolve; + }; + +struct InterfaceMethodFromCPRecord : public SymbolValidationRecord + { + InterfaceMethodFromCPRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *beholder, + TR_OpaqueClassBlock *lookup, + int32_t cpIndex) + : SymbolValidationRecord(TR_ValidateInterfaceMethodFromCP), + _method(method), + _beholder(beholder), + _lookup(lookup), + _cpIndex(cpIndex) + {} + + bool operator ==( const InterfaceMethodFromCPRecord &rhs) + { + if (_method == rhs._method && + _beholder == rhs._beholder && + _lookup == rhs._lookup && + _cpIndex == rhs._cpIndex) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + TR_OpaqueClassBlock *_beholder; + TR_OpaqueClassBlock *_lookup; + int32_t _cpIndex; + }; + +struct MethodFromClassAndSigRecord : public SymbolValidationRecord + { + MethodFromClassAndSigRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *beholder, + TR_OpaqueClassBlock *methodClass) + : SymbolValidationRecord(TR_ValidateMethodFromClassAndSig), + _method(method), + _methodClass(methodClass), + _beholder(beholder) + {} + + bool operator ==( const MethodFromClassAndSigRecord &rhs) + { + if (_method == rhs._method && + _methodClass == rhs._methodClass && + _beholder == rhs._beholder) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + TR_OpaqueClassBlock *_methodClass; + TR_OpaqueClassBlock *_beholder; + }; + +struct StackWalkerMaySkipFramesRecord : public SymbolValidationRecord + { + StackWalkerMaySkipFramesRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *methodClass, + bool skipFrames) + : SymbolValidationRecord(TR_ValidateStackWalkerMaySkipFramesRecord), + _method(method), + _methodClass(methodClass), + _skipFrames(skipFrames) + {} + + bool operator ==( const StackWalkerMaySkipFramesRecord &rhs) + { + if (_method == rhs._method && + _methodClass == rhs._methodClass && + _skipFrames == rhs._skipFrames) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + TR_OpaqueClassBlock *_methodClass; + bool _skipFrames; + }; + +struct ArrayClassFromJavaVM : public ClassValidationRecord + { + ArrayClassFromJavaVM(TR_OpaqueClassBlock *arrayClass, int32_t arrayClassIndex) + : ClassValidationRecord(TR_ValidateArrayClassFromJavaVM), + _arrayClass(arrayClass), + _arrayClassIndex(arrayClassIndex) + {} + + bool operator ==(const ArrayClassFromJavaVM &rhs) + { + if (_arrayClass == rhs._arrayClass && + _arrayClassIndex == rhs._arrayClassIndex) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock *_arrayClass; + int32_t _arrayClassIndex; + }; + +struct ClassInfoIsInitialized : public SymbolValidationRecord + { + ClassInfoIsInitialized(TR_OpaqueClassBlock *clazz, bool isInitialized) + : SymbolValidationRecord(TR_ValidateClassInfoIsInitialized), + _class(clazz), + _isInitialized(isInitialized) + {} + + bool operator ==(const ClassInfoIsInitialized &rhs) + { + if (_class == rhs._class && + _isInitialized == rhs._isInitialized) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueClassBlock *_class; + bool _isInitialized; + }; + +struct MethodFromSingleImplementer : public SymbolValidationRecord + { + MethodFromSingleImplementer(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *thisClass, + int32_t cpIndexOrVftSlot, + TR_OpaqueMethodBlock *callerMethod, + TR_YesNoMaybe useGetResolvedInterfaceMethod) + : SymbolValidationRecord(TR_ValidateMethodFromSingleImplementer), + _method(method), + _thisClass(thisClass), + _cpIndexOrVftSlot(cpIndexOrVftSlot), + _callerMethod(callerMethod), + _useGetResolvedInterfaceMethod(useGetResolvedInterfaceMethod) + {} + + bool operator ==( const MethodFromSingleImplementer &rhs) + { + if (_method == rhs._method && + _thisClass == rhs._thisClass && + _cpIndexOrVftSlot == rhs._cpIndexOrVftSlot && + _callerMethod == rhs._callerMethod && + _useGetResolvedInterfaceMethod == rhs._useGetResolvedInterfaceMethod) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + TR_OpaqueClassBlock *_thisClass; + int32_t _cpIndexOrVftSlot; + TR_OpaqueMethodBlock *_callerMethod; + TR_YesNoMaybe _useGetResolvedInterfaceMethod; + }; + +struct MethodFromSingleInterfaceImplementer : public SymbolValidationRecord + { + MethodFromSingleInterfaceImplementer(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *thisClass, + int32_t cpIndex, + TR_OpaqueMethodBlock *callerMethod) + : SymbolValidationRecord(TR_ValidateMethodFromSingleInterfaceImplementer), + _method(method), + _thisClass(thisClass), + _cpIndex(cpIndex), + _callerMethod(callerMethod) + {} + + bool operator ==( const MethodFromSingleInterfaceImplementer &rhs) + { + if (_method == rhs._method && + _thisClass == rhs._thisClass && + _cpIndex == rhs._cpIndex && + _callerMethod == rhs._callerMethod) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + TR_OpaqueClassBlock *_thisClass; + int32_t _cpIndex; + TR_OpaqueMethodBlock *_callerMethod; + }; + +struct MethodFromSingleAbstractImplementer : public SymbolValidationRecord + { + MethodFromSingleAbstractImplementer(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *thisClass, + int32_t vftSlot, + TR_OpaqueMethodBlock *callerMethod) + : SymbolValidationRecord(TR_ValidateMethodFromSingleAbstractImplementer), + _method(method), + _thisClass(thisClass), + _vftSlot(vftSlot), + _callerMethod(callerMethod) + {} + + bool operator ==( const MethodFromSingleAbstractImplementer &rhs) + { + if (_method == rhs._method && + _thisClass == rhs._thisClass && + _vftSlot == rhs._vftSlot && + _callerMethod == rhs._callerMethod) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + TR_OpaqueClassBlock *_thisClass; + int32_t _vftSlot; + TR_OpaqueMethodBlock *_callerMethod; + }; + +struct ImproperInterfaceMethodFromCPRecord : public SymbolValidationRecord + { + ImproperInterfaceMethodFromCPRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *beholder, + int32_t cpIndex) + : SymbolValidationRecord(TR_ValidateImproperInterfaceMethodFromCP), + _method(method), + _beholder(beholder), + _cpIndex(cpIndex) + {} + + bool operator ==( const ImproperInterfaceMethodFromCPRecord &rhs) + { + if (_method == rhs._method && + _beholder == rhs._beholder && + _cpIndex == rhs._cpIndex) + return true; + else + return false; + } + + virtual bool isEqual(SymbolValidationRecord *other) + { + return (*this == *static_cast(other)); + } + + virtual void printFields(); + + TR_OpaqueMethodBlock *_method; + TR_OpaqueClassBlock *_beholder; + int32_t _cpIndex; + }; + +class SymbolValidationManager + { +public: + TR_ALLOC(TR_MemoryBase::SymbolValidationManager); + + SymbolValidationManager(TR::Region ®ion, TR_ResolvedMethod *compilee); + + void* getSymbolFromID(uint16_t id); + uint16_t getIDFromSymbol(void *symbol); + + bool isAlreadyValidated(void *symbol) { return (getIDFromSymbol(symbol) != 0); } + + bool addRootClassRecord(TR_OpaqueClassBlock *clazz); + bool addClassByNameRecord(TR_OpaqueClassBlock *clazz, TR_OpaqueClassBlock *beholder); + bool addProfiledClassRecord(TR_OpaqueClassBlock *clazz); + bool addClassFromCPRecord(TR_OpaqueClassBlock *clazz, J9ConstantPool *constantPoolOfBeholder, uint32_t cpIndex); + bool addDefiningClassFromCPRecord(TR_OpaqueClassBlock *clazz, J9ConstantPool *constantPoolOfBeholder, uint32_t cpIndex, bool isStatic = false); + bool addStaticClassFromCPRecord(TR_OpaqueClassBlock *clazz, J9ConstantPool *constantPoolOfBeholder, uint32_t cpIndex); + bool addClassFromMethodRecord(TR_OpaqueClassBlock *clazz, TR_OpaqueMethodBlock *method); + bool addComponentClassFromArrayClassRecord(TR_OpaqueClassBlock *componentClass, TR_OpaqueClassBlock *arrayClass); + bool addArrayClassFromComponentClassRecord(TR_OpaqueClassBlock *arrayClass, TR_OpaqueClassBlock *componentClass); + bool addSuperClassFromClassRecord(TR_OpaqueClassBlock *superClass, TR_OpaqueClassBlock *childClass); + bool addClassInstanceOfClassRecord(TR_OpaqueClassBlock *classOne, TR_OpaqueClassBlock *classTwo, bool objectTypeIsFixed, bool castTypeIsFixed, bool isInstanceOf); + bool addSystemClassByNameRecord(TR_OpaqueClassBlock *systemClass); + bool addClassFromITableIndexCPRecord(TR_OpaqueClassBlock *clazz, J9ConstantPool *constantPoolOfBeholder, int32_t cpIndex); + bool addDeclaringClassFromFieldOrStaticRecord(TR_OpaqueClassBlock *clazz, J9ConstantPool *constantPoolOfBeholder, int32_t cpIndex); + bool addClassClassRecord(TR_OpaqueClassBlock *classClass, TR_OpaqueClassBlock *objectClass); + bool addConcreteSubClassFromClassRecord(TR_OpaqueClassBlock *childClass, TR_OpaqueClassBlock *superClass); + bool addArrayClassFromJavaVM(TR_OpaqueClassBlock *arrayClass, int32_t arrayClassIndex); + + bool addClassChainRecord(TR_OpaqueClassBlock *clazz, void *classChain); + bool addRomClassRecord(TR_OpaqueClassBlock *clazz); + bool addPrimitiveClassRecord(TR_OpaqueClassBlock *clazz); + + bool addMethodFromInlinedSiteRecord(TR_OpaqueMethodBlock *method, int32_t inlinedSiteIndex); + bool addMethodByNameRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *beholder); + bool addMethodFromClassRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *beholder, uint32_t index); + bool addStaticMethodFromCPRecord(TR_OpaqueMethodBlock *method, J9ConstantPool *cp, int32_t cpIndex); + bool addSpecialMethodFromCPRecord(TR_OpaqueMethodBlock *method, J9ConstantPool *cp, int32_t cpIndex); + bool addVirtualMethodFromCPRecord(TR_OpaqueMethodBlock *method, J9ConstantPool *cp, int32_t cpIndex); + bool addVirtualMethodFromOffsetRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *beholder, int32_t virtualCallOffset, bool ignoreRtResolve); + bool addInterfaceMethodFromCPRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *beholder, TR_OpaqueClassBlock *lookup, int32_t cpIndex); + bool addImproperInterfaceMethodFromCPRecord(TR_OpaqueMethodBlock *method, J9ConstantPool *cp, int32_t cpIndex); + bool addMethodFromClassAndSignatureRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass, TR_OpaqueClassBlock *beholder); + bool addMethodFromSingleImplementerRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *thisClass, + int32_t cpIndexOrVftSlot, + TR_OpaqueMethodBlock *callerMethod, + TR_YesNoMaybe useGetResolvedInterfaceMethod); + bool addMethodFromSingleInterfaceImplementerRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *thisClass, + int32_t cpIndex, + TR_OpaqueMethodBlock *callerMethod); + bool addMethodFromSingleAbstractImplementerRecord(TR_OpaqueMethodBlock *method, + TR_OpaqueClassBlock *thisClass, + int32_t vftSlot, + TR_OpaqueMethodBlock *callerMethod); + + bool addStackWalkerMaySkipFramesRecord(TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *methodClass, bool skipFrames); + bool addClassInfoIsInitializedRecord(TR_OpaqueClassBlock *clazz, bool isInitialized); + + + + bool validateRootClassRecord(uint16_t classID); + bool validateClassByNameRecord(uint16_t classID, uint16_t beholderID, J9ROMClass *romClass, char primitiveType); + bool validateProfiledClassRecord(uint16_t classID, char primitiveType, void *classChainIdentifyingLoader, void *classChainForClassBeingValidated); + bool validateClassFromCPRecord(uint16_t classID, uint16_t beholderID, uint32_t cpIndex); + bool validateDefiningClassFromCPRecord(uint16_t classID, uint16_t beholderID, uint32_t cpIndex, bool isStatic); + bool validateStaticClassFromCPRecord(uint16_t classID, uint16_t beholderID, uint32_t cpIndex); + bool validateClassFromMethodRecord(uint16_t classID, uint16_t methodID); + bool validateComponentClassFromArrayClassRecord(uint16_t componentClassID, uint16_t arrayClassID); + bool validateArrayClassFromComponentClassRecord(uint16_t arrayClassID, uint16_t componentClassID); + bool validateSuperClassFromClassRecord(uint16_t superClassID, uint16_t childClassID); + bool validateClassInstanceOfClassRecord(uint16_t classOneID, uint16_t classTwoID, bool objectTypeIsFixed, bool castTypeIsFixed, bool wasInstanceOf); + bool validateSystemClassByNameRecord(uint16_t systemClassID, J9ROMClass *romClass); + bool validateClassFromITableIndexCPRecord(uint16_t classID, uint16_t beholderID, uint32_t cpIndex); + bool validateDeclaringClassFromFieldOrStaticRecord(uint16_t definingClassID, uint16_t beholderID, int32_t cpIndex); + bool validateClassClassRecord(uint16_t classClassID, uint16_t objectClassID); + bool validateConcreteSubClassFromClassRecord(uint16_t childClassID, uint16_t superClassID); + bool validateArrayClassFromJavaVM(uint16_t arrayClassID, int32_t arrayClassIndex); + + bool validateClassChainRecord(uint16_t classID, void *classChain); + bool validateRomClassRecord(uint16_t classID, J9ROMClass *romClass); + bool validatePrimitiveClassRecord(uint16_t classID, char primitiveType); + + bool validateMethodFromInlinedSiteRecord(uint16_t methodID, TR_OpaqueMethodBlock *method); + bool validateMethodByNameRecord(uint16_t methodID, uint16_t beholderID, J9ROMClass *romClass, J9ROMMethod *romMethod); + bool validateMethodFromClassRecord(uint16_t methodID, uint16_t beholderID, uint32_t index); + bool validateStaticMethodFromCPRecord(uint16_t methodID, uint16_t beholderID, int32_t cpIndex); + bool validateSpecialMethodFromCPRecord(uint16_t methodID, uint16_t beholderID, int32_t cpIndex); + bool validateVirtualMethodFromCPRecord(uint16_t methodID, uint16_t beholderID, int32_t cpIndex); + bool validateVirtualMethodFromOffsetRecord(uint16_t methodID, uint16_t beholderID, int32_t virtualCallOffset, bool ignoreRtResolve); + bool validateInterfaceMethodFromCPRecord(uint16_t methodID, uint16_t beholderID, uint16_t lookupID, int32_t cpIndex); + bool validateImproperInterfaceMethodFromCPRecord(uint16_t methodID, uint16_t beholderID, int32_t cpIndex); + bool validateMethodFromClassAndSignatureRecord(uint16_t methodID, uint16_t methodClassID, uint16_t beholderID, J9ROMMethod *romMethod); + bool validateMethodFromSingleImplementerRecord(uint16_t methodID, + uint16_t thisClassID, + int32_t cpIndexOrVftSlot, + uint16_t callerMethodID, + TR_YesNoMaybe useGetResolvedInterfaceMethod); + bool validateMethodFromSingleInterfaceImplementerRecord(uint16_t methodID, + uint16_t thisClassID, + int32_t cpIndex, + uint16_t callerMethodID); + bool validateMethodFromSingleAbstractImplementerRecord(uint16_t methodID, + uint16_t thisClassID, + int32_t vftSlot, + uint16_t callerMethodID); + + bool validateStackWalkerMaySkipFramesRecord(uint16_t methodID, uint16_t methodClassID, bool couldSkipFrames); + bool validateClassInfoIsInitializedRecord(uint16_t classID, bool wasInitialized); + + + static TR_OpaqueClassBlock *getBaseComponentClass(TR_OpaqueClassBlock *clazz, int32_t & numDims); + + typedef TR::list SymbolValidationRecordList; + + SymbolValidationRecordList& getValidationRecordList() { return _symbolValidationRecords; } + + void enterHeuristicRegion() { _heuristicRegion++; } + void exitHeuristicRegion() { _heuristicRegion--; } + bool inHeuristicRegion() { return (_heuristicRegion > 0); } + + bool verifySymbolHasBeenValidated(void *symbol) + { + if (inHeuristicRegion()) + return true; + else + return (getIDFromSymbol(symbol) != 0); + } + +private: + + static const uint16_t NO_ID = 0; + static const uint16_t FIRST_ID = 1; + + uint16_t getNewSymbolID(); + + void storeRecord(void *symbol, SymbolValidationRecord *record); + bool storeClassRecord(TR_OpaqueClassBlock *clazz, + ClassValidationRecord *record, + int32_t arrayDimsToValidate, + bool isStatic, + bool storeCurrentRecord); + bool storeValidationRecordIfNecessary(void *symbol, SymbolValidationRecord *record, int32_t arrayDimsToValidate = 0, bool isStatic = false); + void *storeClassChain(TR_J9VMBase *fej9, TR_OpaqueClassBlock *clazz, bool isStatic); + + bool validateSymbol(uint16_t idToBeValidated, void *validSymbol); + + + /* Monotonically increasing IDs */ + uint16_t _symbolID; + + uint32_t _heuristicRegion; + + TR::Region &_region; + + /* List of validation records to be written to the AOT buffer */ + SymbolValidationRecordList _symbolValidationRecords; + + typedef TR::typed_allocator, TR::Region&> SymbolToIdAllocator; + typedef std::less SymbolToIdComparator; + typedef std::map SymbolToIdMap; + + typedef TR::typed_allocator, TR::Region&> IdToSymbolAllocator; + typedef std::less IdToSymbolComparator; + typedef std::map IdToSymbolMap; + + typedef TR::typed_allocator SeenSymbolsAlloc; + typedef std::less SeenSymbolsComparator; + typedef std::set SeenSymbolsSet; + + /* Used for AOT Compile */ + SymbolToIdMap _symbolToIdMap; + + /* Used for AOT Load */ + IdToSymbolMap _idToSymbolsMap; + + SeenSymbolsSet _seenSymbolsSet; + }; + +} + +#endif //SYMBOL_VALIDATION_MANAGER_INCL diff --git a/runtime/compiler/x/codegen/CallSnippet.cpp b/runtime/compiler/x/codegen/CallSnippet.cpp index abc43c49699..475dd05907e 100644 --- a/runtime/compiler/x/codegen/CallSnippet.cpp +++ b/runtime/compiler/x/codegen/CallSnippet.cpp @@ -199,7 +199,7 @@ uint8_t *TR::X86PicDataSnippet::emitSnippetBody() } else { - TR_ASSERT(0, "Can't handle resolved IPICs here yet!"); + TR_ASSERT_FATAL(0, "Can't handle resolved IPICs here yet!"); } // Reserve space for resolved interface class and itable offset. @@ -312,7 +312,7 @@ uint8_t *TR::X86PicDataSnippet::emitSnippetBody() } else { - TR_ASSERT(0, "Can't handle resolved VPICs here yet!"); + TR_ASSERT_FATAL(0, "Can't handle resolved VPICs here yet!"); } _dispatchSymRef = cg()->symRefTab()->findOrCreateRuntimeHelper(TR_X86populateVPicVTableDispatch, false, false, false); @@ -428,6 +428,8 @@ TR_Debug::print(TR::FILE *pOutFile, TR::X86PicDataSnippet *snippet) if (pOutFile == NULL) return; + TR_J9VMBase *fej9 = (TR_J9VMBase *)(_cg->fe()); + uint8_t *bufferPos = snippet->getSnippetLabel()->getCodeLocation(); // Account for VPic data appearing before the actual entry label. @@ -473,7 +475,7 @@ TR_Debug::print(TR::FILE *pOutFile, TR::X86PicDataSnippet *snippet) printLabelInstruction(pOutFile, "jmp", snippet->getDoneLabel()); bufferPos += 5; - if (methodSymRef->isUnresolved()) + if (methodSymRef->isUnresolved() || fej9->forceUnresolvedDispatch()) { const char *op = (sizeof(uintptrj_t) == 4) ? "DD" : "DQ"; @@ -844,7 +846,11 @@ uint8_t *TR::X86CallSnippet::emitSnippetBody() } } - if (methodSymRef->isUnresolved() || fej9->forceUnresolvedDispatch()) + bool forceUnresolvedDispatch = fej9->forceUnresolvedDispatch(); + if (comp->getOption(TR_UseSymbolValidationManager)) + forceUnresolvedDispatch = false; + + if (methodSymRef->isUnresolved() || forceUnresolvedDispatch) { // Unresolved interpreted dispatch snippet shape: // @@ -868,7 +874,7 @@ uint8_t *TR::X86CallSnippet::emitSnippetBody() // (4) dd cpIndex // - TR_ASSERT(!isJitInduceOSRCall || !fej9->forceUnresolvedDispatch(), "calling jitInduceOSR is not supported yet under AOT\n"); + TR_ASSERT(!isJitInduceOSRCall || !forceUnresolvedDispatch, "calling jitInduceOSR is not supported yet under AOT\n"); cursor = alignCursorForCodePatching(cursor, TR::Compiler->target.is64Bit()); if (comp->getOption(TR_EnableHCR)) @@ -881,7 +887,7 @@ uint8_t *TR::X86CallSnippet::emitSnippetBody() getSnippetLabel()->setCodeLocation(cursor); } - TR_ASSERT((methodSymbol->isStatic() || methodSymbol->isSpecial() || fej9->forceUnresolvedDispatch()), "Unexpected unresolved dispatch"); + TR_ASSERT((methodSymbol->isStatic() || methodSymbol->isSpecial() || forceUnresolvedDispatch), "Unexpected unresolved dispatch"); // CALL interpreterUnresolved{Static|Special}Glue // @@ -1004,6 +1010,16 @@ uint8_t *TR::X86CallSnippet::emitSnippetBody() *(intptrj_t *)cursor = ramMethod; + if (comp->getOption(TR_UseSymbolValidationManager)) + { + cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor, + (uint8_t *)ramMethod, + (uint8_t *)TR::SymbolType::typeMethod, + TR_SymbolFromManager, + cg()), __FILE__, __LINE__, getNode()); + } + + // HCR in TR::X86CallSnippet::emitSnippetBody register the method address // if (comp->getOption(TR_EnableHCR)) @@ -1057,7 +1073,12 @@ uint32_t TR::X86CallSnippet::getLength(int32_t estimatedSnippetStart) length += codeSize; } - if (methodSymRef->isUnresolved() || fej9->forceUnresolvedDispatch()) + TR::Compilation *comp = cg()->comp(); + bool forceUnresolvedDispatch = fej9->forceUnresolvedDispatch(); + if (comp->getOption(TR_UseSymbolValidationManager)) + forceUnresolvedDispatch = false; + + if (methodSymRef->isUnresolved() || forceUnresolvedDispatch) { // +7 accounts for maximum length alignment padding. // diff --git a/runtime/compiler/x/codegen/J9AheadOfTimeCompile.cpp b/runtime/compiler/x/codegen/J9AheadOfTimeCompile.cpp index adcf4978091..c75a9edd4dc 100644 --- a/runtime/compiler/x/codegen/J9AheadOfTimeCompile.cpp +++ b/runtime/compiler/x/codegen/J9AheadOfTimeCompile.cpp @@ -39,6 +39,8 @@ #include "ras/DebugCounter.hpp" #include "runtime/CodeCacheConfig.hpp" #include "runtime/CodeCacheManager.hpp" +#include "runtime/RelocationRecord.hpp" +#include "runtime/SymbolValidationManager.hpp" #define NON_HELPER 0x00 @@ -95,6 +97,7 @@ uint8_t *J9::X86::AheadOfTimeCompile::initializeAOTRelocationHeader(TR::Iterated TR_J9VMBase *fej9 = (TR_J9VMBase *)(_cg->fe()); TR_SharedCache *sharedCache = fej9->sharedCache(); TR::Compilation * comp = _cg->comp(); + TR::SymbolValidationManager *symValManager = comp->getSymbolValidationManager(); uintptrj_t numTrampolines; TR::LabelSymbol *label; TR_ResolvedMethod *resolvedMethod; @@ -211,6 +214,7 @@ uint8_t *J9::X86::AheadOfTimeCompile::initializeAOTRelocationHeader(TR::Iterated case TR_InlinedStaticMethodWithNopGuard: case TR_InlinedSpecialMethodWithNopGuard: case TR_InlinedVirtualMethodWithNopGuard: + case TR_InlinedAbstractMethodWithNopGuard: case TR_InlinedVirtualMethod: case TR_InlinedInterfaceMethodWithNopGuard: case TR_InlinedInterfaceMethod: @@ -218,16 +222,13 @@ uint8_t *J9::X86::AheadOfTimeCompile::initializeAOTRelocationHeader(TR::Iterated { guard = (TR_VirtualGuard *)relocation->getTargetAddress2(); - if (relocation->getTargetKind() == TR_InlinedHCRMethod) - { - // Setup flags field with type of method that needs to be validated at relocation time - if (guard->getSymbolReference()->getSymbol()->getMethodSymbol()->isStatic()) - flags = inlinedMethodIsStatic; - if (guard->getSymbolReference()->getSymbol()->getMethodSymbol()->isSpecial()) - flags = inlinedMethodIsSpecial; - if (guard->getSymbolReference()->getSymbol()->getMethodSymbol()->isVirtual()) - flags = inlinedMethodIsVirtual; - } + // Setup flags field with type of method that needs to be validated at relocation time + if (guard->getSymbolReference()->getSymbol()->getMethodSymbol()->isStatic()) + flags = inlinedMethodIsStatic; + if (guard->getSymbolReference()->getSymbol()->getMethodSymbol()->isSpecial()) + flags = inlinedMethodIsSpecial; + if (guard->getSymbolReference()->getSymbol()->getMethodSymbol()->isVirtual()) + flags = inlinedMethodIsVirtual; TR_ASSERT((flags & RELOCATION_CROSS_PLATFORM_FLAGS_MASK) == 0, "reloFlags bits overlap cross-platform flags bits\n"); *flagsCursor |= (flags & RELOCATION_RELOC_FLAGS_MASK); @@ -238,11 +239,9 @@ uint8_t *J9::X86::AheadOfTimeCompile::initializeAOTRelocationHeader(TR::Iterated *(uintptrj_t *)cursor = (uintptrj_t)guard->getSymbolReference()->getOwningMethod(comp)->constantPool(); // record constant pool cursor += SIZEPOINTER; - *(uintptrj_t*)cursor = (uintptrj_t)guard->getSymbolReference()->getCPIndex(); // record cpIndex - cursor += SIZEPOINTER; - if (relocation->getTargetKind() == TR_InlinedInterfaceMethodWithNopGuard || - relocation->getTargetKind() == TR_InlinedInterfaceMethod) + relocation->getTargetKind() == TR_InlinedInterfaceMethod || + relocation->getTargetKind() == TR_InlinedAbstractMethodWithNopGuard) { TR_InlinedCallSite *inlinedCallSite = &comp->getInlinedCallSite(inlinedSiteIndex); TR_AOTMethodInfo *aotMethodInfo = (TR_AOTMethodInfo *)inlinedCallSite->_methodInfo; @@ -253,6 +252,23 @@ uint8_t *J9::X86::AheadOfTimeCompile::initializeAOTRelocationHeader(TR::Iterated resolvedMethod = guard->getSymbolReference()->getSymbol()->getResolvedMethodSymbol()->getResolvedMethod(); } + if (comp->getOption(TR_UseSymbolValidationManager)) + { + TR_OpaqueMethodBlock *method = resolvedMethod->getPersistentIdentifier(); + TR_OpaqueClassBlock *thisClass = guard->getThisClass(); + uint16_t methodID = symValManager->getIDFromSymbol(static_cast(method)); + uint16_t receiverClassID = symValManager->getIDFromSymbol(static_cast(thisClass)); + + uintptrj_t data = 0; + data = (((uintptrj_t)receiverClassID << 16) | (uintptrj_t)methodID); + *(uintptrj_t*)cursor = data; + } + else + { + *(uintptrj_t*)cursor = (uintptrj_t)guard->getSymbolReference()->getCPIndex(); // record cpIndex + } + cursor += SIZEPOINTER; + TR_OpaqueClassBlock *inlinedMethodClass = resolvedMethod->containingClass(); void *romClass = (void *)fej9->getPersistentClassPointerFromClassPointer(inlinedMethodClass); void *romClassOffsetInSharedCache = sharedCache->offsetInSharedCacheFromPointer(romClass); @@ -420,7 +436,7 @@ uint8_t *J9::X86::AheadOfTimeCompile::initializeAOTRelocationHeader(TR::Iterated cursor += SIZEPOINTER; } - break; + break; case TR_VerifyClassObjectForAlloc: { TR::SymbolReference * classSymRef = (TR::SymbolReference *) relocation->getTargetAddress(); @@ -434,8 +450,19 @@ uint8_t *J9::X86::AheadOfTimeCompile::initializeAOTRelocationHeader(TR::Iterated cursor += SIZEPOINTER; *(uintptrj_t *)cursor = (uintptrj_t) classSymRef->getOwningMethod(comp)->constantPool(); cursor += SIZEPOINTER; - *(uintptrj_t *)cursor = (uintptrj_t) classSymRef->getCPIndex(); // cp Index + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + TR_OpaqueClassBlock *classOfMethod = (TR_OpaqueClassBlock *)recordInfo->data5; + uintptrj_t classID = (uintptrj_t)symValManager->getIDFromSymbol(static_cast(classOfMethod)); + *(uintptrj_t *)cursor = classID; + } + else + { + *(uintptrj_t *)cursor = (uintptrj_t) classSymRef->getCPIndex(); // cp Index + } cursor += SIZEPOINTER; + *(uintptrj_t *)cursor = (uintptrj_t) branchOffset; cursor += SIZEPOINTER; *(uintptrj_t *)cursor = (uintptrj_t) recordInfo->data1; // allocation size. @@ -457,8 +484,19 @@ uint8_t *J9::X86::AheadOfTimeCompile::initializeAOTRelocationHeader(TR::Iterated cursor += SIZEPOINTER; *(uintptrj_t *)cursor = (uintptrj_t) classSymRef->getOwningMethod(comp)->constantPool(); cursor += SIZEPOINTER; - *(uintptrj_t *)cursor = (uintptrj_t) classSymRef->getCPIndex(); // cp Index + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + TR_OpaqueClassBlock *clazz = (TR_OpaqueClassBlock *)recordInfo->data5; + uintptrj_t classID = (uintptrj_t)symValManager->getIDFromSymbol(static_cast(clazz)); + *(uintptrj_t *)cursor = classID; + } + else + { + *(uintptrj_t *)cursor = (uintptrj_t) classSymRef->getCPIndex(); // cp Index + } cursor += SIZEPOINTER; + *(uintptrj_t *)cursor = (uintptrj_t) branchOffset; cursor += SIZEPOINTER; } @@ -540,6 +578,676 @@ uint8_t *J9::X86::AheadOfTimeCompile::initializeAOTRelocationHeader(TR::Iterated case TR_RamMethod: break; + case TR_ValidateRootClass: + { + TR::RootClassRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateRootClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_classID = symValManager->getIDFromSymbol(static_cast(record->_class)); + + cursor += sizeof(TR_RelocationRecordValidateRootClassBinaryTemplate); + } + break; + + case TR_ValidateClassByName: + { + TR::ClassByNameRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateClassByNameBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + // Store rom class to get name of class + void *romClass = reinterpret_cast(fej9->getPersistentClassPointerFromClassPointer(record->_class)); + void *romClassOffsetInSharedCache = sharedCache->offsetInSharedCacheFromPointer(romClass); + + binaryTemplate->_classID = symValManager->getIDFromSymbol(static_cast(record->_class)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_primitiveType = record->_primitiveType; + binaryTemplate->_romClassOffsetInSCC = reinterpret_cast(romClassOffsetInSharedCache); + + cursor += sizeof(TR_RelocationRecordValidateClassByNameBinaryTemplate); + } + break; + + case TR_ValidateProfiledClass: + { + TR::ProfiledClassRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateProfiledClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + TR_OpaqueClassBlock *classToValidate = record->_class; + char primitiveType = record->_primitiveType; + uintptrj_t classChainOffsetInSharedCacheForCL; + void* classChainOffsetInSharedCache; + + if (primitiveType != '\0') + { + classChainOffsetInSharedCacheForCL = 0; + classChainOffsetInSharedCache = NULL; + } + else + { + void *classChainForClassToValidate = record->_classChain; + + //store the classchain's offset for the classloader for the class + void *loaderForClazzToValidate = fej9->getClassLoader(classToValidate); + void *classChainIdentifyingLoaderForClazzToValidate = sharedCache->persistentClassLoaderTable()->lookupClassChainAssociatedWithClassLoader(loaderForClazzToValidate); + classChainOffsetInSharedCacheForCL = reinterpret_cast(sharedCache->offsetInSharedCacheFromPointer(classChainIdentifyingLoaderForClazzToValidate)); + + //store the classchain's offset for the class that needs to be validated in the second run + classChainOffsetInSharedCache = sharedCache->offsetInSharedCacheFromPointer(classChainForClassToValidate); + } + + binaryTemplate->_classID = symValManager->getIDFromSymbol(static_cast(classToValidate)); + binaryTemplate->_primitiveType = record->_primitiveType; + binaryTemplate->_classChainOffsetInSCC = reinterpret_cast(classChainOffsetInSharedCache); + binaryTemplate->_classChainOffsetForCLInScc = classChainOffsetInSharedCacheForCL; + + cursor += sizeof(TR_RelocationRecordValidateProfiledClassBinaryTemplate); + } + break; + + case TR_ValidateClassFromCP: + { + TR::ClassFromCPRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateClassFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_classID = symValManager->getIDFromSymbol(static_cast(record->_class)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_cpIndex = record->_cpIndex; + + cursor += sizeof(TR_RelocationRecordValidateClassFromCPBinaryTemplate); + } + break; + + case TR_ValidateDefiningClassFromCP: + { + TR::DefiningClassFromCPRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateDefiningClassFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_isStatic = record->_isStatic; + binaryTemplate->_classID = symValManager->getIDFromSymbol(static_cast(record->_class)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_cpIndex = record->_cpIndex; + + cursor += sizeof(TR_RelocationRecordValidateDefiningClassFromCPBinaryTemplate); + } + break; + + case TR_ValidateStaticClassFromCP: + { + TR::StaticClassFromCPRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateStaticClassFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_classID = symValManager->getIDFromSymbol(static_cast(record->_class)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_cpIndex = record->_cpIndex; + + cursor += sizeof(TR_RelocationRecordValidateStaticClassFromCPBinaryTemplate); + } + break; + + case TR_ValidateClassFromMethod: + { + TR::ClassFromMethodRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateClassFromMethodBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_classID = symValManager->getIDFromSymbol(static_cast(record->_class)); + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + + cursor += sizeof(TR_RelocationRecordValidateClassFromMethodBinaryTemplate); + } + break; + + case TR_ValidateComponentClassFromArrayClass: + { + TR::ComponentClassFromArrayClassRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateCompFromArrayBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_componentClassID = symValManager->getIDFromSymbol(static_cast(record->_componentClass)); + binaryTemplate->_arrayClassID = symValManager->getIDFromSymbol(static_cast(record->_arrayClass)); + + cursor += sizeof(TR_RelocationRecordValidateCompFromArrayBinaryTemplate); + } + break; + + case TR_ValidateArrayClassFromComponentClass: + { + TR::ArrayClassFromComponentClassRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateArrayFromCompBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_arrayClassID = symValManager->getIDFromSymbol(static_cast(record->_arrayClass)); + binaryTemplate->_componentClassID = symValManager->getIDFromSymbol(static_cast(record->_componentClass)); + + cursor += sizeof(TR_RelocationRecordValidateArrayFromCompBinaryTemplate); + } + break; + + case TR_ValidateSuperClassFromClass: + { + TR::SuperClassFromClassRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateSuperClassFromClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_superClassID = symValManager->getIDFromSymbol(static_cast(record->_superClass)); + binaryTemplate->_childClassID = symValManager->getIDFromSymbol(static_cast(record->_childClass)); + + cursor += sizeof(TR_RelocationRecordValidateSuperClassFromClassBinaryTemplate); + } + break; + + case TR_ValidateClassInstanceOfClass: + { + TR::ClassInstanceOfClassRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateClassInstanceOfClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_objectTypeIsFixed = record->_objectTypeIsFixed; + binaryTemplate->_castTypeIsFixed = record->_castTypeIsFixed; + binaryTemplate->_isInstanceOf = record->_isInstanceOf; + binaryTemplate->_classOneID = symValManager->getIDFromSymbol(static_cast(record->_classOne)); + binaryTemplate->_classTwoID = symValManager->getIDFromSymbol(static_cast(record->_classTwo)); + + cursor += sizeof(TR_RelocationRecordValidateClassInstanceOfClassBinaryTemplate); + } + break; + + case TR_ValidateSystemClassByName: + { + TR::SystemClassByNameRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateSystemClassByNameBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + // Store rom class to get name of class + void *romClass = reinterpret_cast(fej9->getPersistentClassPointerFromClassPointer(record->_systemClass)); + void *romClassOffsetInSharedCache = sharedCache->offsetInSharedCacheFromPointer(romClass); + + binaryTemplate->_systemClassID = symValManager->getIDFromSymbol(static_cast(record->_systemClass)); + binaryTemplate->_romClassOffsetInSCC = reinterpret_cast(romClassOffsetInSharedCache); + + cursor += sizeof(TR_RelocationRecordValidateSystemClassByNameBinaryTemplate); + } + break; + + case TR_ValidateClassFromITableIndexCP: + { + TR::ClassFromITableIndexCPRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateClassFromITableIndexCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_classID = symValManager->getIDFromSymbol(static_cast(record->_class)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_cpIndex = record->_cpIndex; + + cursor += sizeof(TR_RelocationRecordValidateClassFromITableIndexCPBinaryTemplate); + } + break; + + case TR_ValidateDeclaringClassFromFieldOrStatic: + { + TR::DeclaringClassFromFieldOrStaticRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateDeclaringClassFromFieldOrStaticBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_classID = symValManager->getIDFromSymbol(static_cast(record->_class)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_cpIndex = record->_cpIndex; + + cursor += sizeof(TR_RelocationRecordValidateDeclaringClassFromFieldOrStaticBinaryTemplate); + } + break; + + case TR_ValidateClassClass: + { + TR::ClassClassRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateClassClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_classClassID = symValManager->getIDFromSymbol(static_cast(record->_classClass)); + binaryTemplate->_objectClassID = symValManager->getIDFromSymbol(static_cast(record->_objectClass)); + + cursor += sizeof(TR_RelocationRecordValidateClassClassBinaryTemplate); + } + break; + + case TR_ValidateConcreteSubClassFromClass: + { + TR::ConcreteSubClassFromClassRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateConcreteSubFromClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_childClassID = symValManager->getIDFromSymbol(static_cast(record->_childClass)); + binaryTemplate->_superClassID = symValManager->getIDFromSymbol(static_cast(record->_superClass)); + + cursor += sizeof(TR_RelocationRecordValidateConcreteSubFromClassBinaryTemplate); + } + break; + + case TR_ValidateClassChain: + { + TR::ClassChainRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateClassChainBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + void *classToValidate = static_cast(record->_class); + void *classChainForClassToValidate = record->_classChain; + void *classChainOffsetInSharedCache = sharedCache->offsetInSharedCacheFromPointer(classChainForClassToValidate); + + binaryTemplate->_classID = symValManager->getIDFromSymbol(classToValidate); + binaryTemplate->_classChainOffsetInSCC = reinterpret_cast(classChainOffsetInSharedCache); + + cursor += sizeof(TR_RelocationRecordValidateClassChainBinaryTemplate); + } + break; + + case TR_ValidateRomClass: + { + TR::RomClassRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateRomClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + TR_OpaqueClassBlock *classToValidate = static_cast(record->_class); + + void *romClass = reinterpret_cast(fej9->getPersistentClassPointerFromClassPointer(classToValidate)); + void *romClassOffsetInSharedCache = sharedCache->offsetInSharedCacheFromPointer(romClass); + + binaryTemplate->_classID = symValManager->getIDFromSymbol(static_cast(classToValidate)); + binaryTemplate->_romClassOffsetInSCC = reinterpret_cast(romClassOffsetInSharedCache); + + cursor += sizeof(TR_RelocationRecordValidateRomClassBinaryTemplate); + } + break; + + case TR_ValidatePrimitiveClass: + { + TR::PrimitiveClassRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidatePrimitiveClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_classID = symValManager->getIDFromSymbol(static_cast(record->_class)); + binaryTemplate->_primitiveType = record->_primitiveType; + + cursor += sizeof(TR_RelocationRecordValidatePrimitiveClassBinaryTemplate); + } + break; + + case TR_ValidateMethodFromInlinedSite: + { + TR::MethodFromInlinedSiteRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateMethodFromInlSiteBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + binaryTemplate->_inlinedSiteIndex = static_cast(record->_inlinedSiteIndex); + + cursor += sizeof(TR_RelocationRecordValidateMethodFromInlSiteBinaryTemplate); + } + break; + + case TR_ValidateMethodByName: + { + TR::MethodByNameRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateMethodByNameBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + // Store rom method to get name of method + J9Method *methodToValidate = reinterpret_cast(record->_method); + J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(methodToValidate); + void *romMethodOffsetInSharedCache = sharedCache->offsetInSharedCacheFromPointer(romMethod); + + // Store rom class to get name of class + TR_OpaqueClassBlock *classOfMethod = reinterpret_cast(J9_CLASS_FROM_METHOD(methodToValidate)); + void *romClass = reinterpret_cast(fej9->getPersistentClassPointerFromClassPointer(classOfMethod)); + void *romClassOffsetInSharedCache = sharedCache->offsetInSharedCacheFromPointer(romClass); + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(methodToValidate)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_romClassOffsetInSCC = reinterpret_cast(romClassOffsetInSharedCache); + binaryTemplate->_romMethodOffsetInSCC = reinterpret_cast(romMethodOffsetInSharedCache); + + cursor += sizeof(TR_RelocationRecordValidateMethodByNameBinaryTemplate); + } + break; + + case TR_ValidateMethodFromClass: + { + TR::MethodFromClassRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateMethodFromClassBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_index = static_cast(record->_index); + + cursor += sizeof(TR_RelocationRecordValidateMethodFromClassBinaryTemplate); + } + break; + + case TR_ValidateStaticMethodFromCP: + { + TR::StaticMethodFromCPRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateStaticMethodFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_cpIndex = static_cast(record->_cpIndex); + + cursor += sizeof(TR_RelocationRecordValidateStaticMethodFromCPBinaryTemplate); + } + break; + + case TR_ValidateSpecialMethodFromCP: + { + TR::SpecialMethodFromCPRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateSpecialMethodFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_cpIndex = static_cast(record->_cpIndex); + + cursor += sizeof(TR_RelocationRecordValidateSpecialMethodFromCPBinaryTemplate); + } + break; + + case TR_ValidateVirtualMethodFromCP: + { + TR::VirtualMethodFromCPRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateVirtualMethodFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_cpIndex = static_cast(record->_cpIndex); + + cursor += sizeof(TR_RelocationRecordValidateVirtualMethodFromCPBinaryTemplate); + } + break; + + case TR_ValidateVirtualMethodFromOffset: + { + TR::VirtualMethodFromOffsetRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateVirtualMethodFromOffsetBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_virtualCallOffset = record->_virtualCallOffset; + binaryTemplate->_ignoreRtResolve = record->_ignoreRtResolve; + + cursor += sizeof(TR_RelocationRecordValidateVirtualMethodFromOffsetBinaryTemplate); + } + break; + + case TR_ValidateInterfaceMethodFromCP: + { + TR::InterfaceMethodFromCPRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateInterfaceMethodFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_lookupID = symValManager->getIDFromSymbol(static_cast(record->_lookup)); + binaryTemplate->_cpIndex = static_cast(record->_cpIndex); + + cursor += sizeof(TR_RelocationRecordValidateInterfaceMethodFromCPBinaryTemplate); + } + break; + + case TR_ValidateImproperInterfaceMethodFromCP: + { + TR::ImproperInterfaceMethodFromCPRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateImproperInterfaceMethodFromCPBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_cpIndex = static_cast(record->_cpIndex); + + cursor += sizeof(TR_RelocationRecordValidateImproperInterfaceMethodFromCPBinaryTemplate); + } + break; + + case TR_ValidateMethodFromClassAndSig: + { + TR::MethodFromClassAndSigRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateMethodFromClassAndSigBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + // Store rom method to get name of method + J9Method *methodToValidate = reinterpret_cast(record->_method); + J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(methodToValidate); + void *romMethodOffsetInSharedCache = sharedCache->offsetInSharedCacheFromPointer(romMethod); + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + binaryTemplate->_methodClassID = symValManager->getIDFromSymbol(static_cast(record->_methodClass)); + binaryTemplate->_beholderID = symValManager->getIDFromSymbol(static_cast(record->_beholder)); + binaryTemplate->_romMethodOffsetInSCC = reinterpret_cast(romMethodOffsetInSharedCache); + + cursor += sizeof(TR_RelocationRecordValidateMethodFromClassAndSigBinaryTemplate); + } + break; + + case TR_ValidateMethodFromSingleImplementer: + { + TR::MethodFromSingleImplementer *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateMethodFromSingleImplBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + binaryTemplate->_thisClassID = symValManager->getIDFromSymbol(static_cast(record->_thisClass)); + binaryTemplate->_cpIndexOrVftSlot = record->_cpIndexOrVftSlot; + binaryTemplate->_callerMethodID = symValManager->getIDFromSymbol(static_cast(record->_callerMethod)); + binaryTemplate->_useGetResolvedInterfaceMethod = (uint16_t)record->_useGetResolvedInterfaceMethod; + + cursor += sizeof(TR_RelocationRecordValidateMethodFromSingleImplBinaryTemplate); + } + break; + + case TR_ValidateMethodFromSingleInterfaceImplementer: + { + TR::MethodFromSingleInterfaceImplementer *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateMethodFromSingleInterfaceImplBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + binaryTemplate->_thisClassID = symValManager->getIDFromSymbol(static_cast(record->_thisClass)); + binaryTemplate->_cpIndex = record->_cpIndex; + binaryTemplate->_callerMethodID = symValManager->getIDFromSymbol(static_cast(record->_callerMethod)); + + cursor += sizeof(TR_RelocationRecordValidateMethodFromSingleInterfaceImplBinaryTemplate); + } + break; + + case TR_ValidateMethodFromSingleAbstractImplementer: + { + TR::MethodFromSingleAbstractImplementer *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateMethodFromSingleAbstractImplBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + binaryTemplate->_thisClassID = symValManager->getIDFromSymbol(static_cast(record->_thisClass)); + binaryTemplate->_vftSlot = record->_vftSlot; + binaryTemplate->_callerMethodID = symValManager->getIDFromSymbol(static_cast(record->_callerMethod)); + + cursor += sizeof(TR_RelocationRecordValidateMethodFromSingleAbstractImplBinaryTemplate); + } + break; + + case TR_ValidateStackWalkerMaySkipFramesRecord: + { + TR::StackWalkerMaySkipFramesRecord *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateStackWalkerMaySkipFramesBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_methodID = symValManager->getIDFromSymbol(static_cast(record->_method)); + binaryTemplate->_methodClassID = symValManager->getIDFromSymbol(static_cast(record->_methodClass)); + binaryTemplate->_skipFrames = record->_skipFrames; + + cursor += sizeof(TR_RelocationRecordValidateStackWalkerMaySkipFramesBinaryTemplate); + } + break; + + case TR_ValidateArrayClassFromJavaVM: + { + TR::ArrayClassFromJavaVM *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateArrayClassFromJavaVMBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_arrayClassID = symValManager->getIDFromSymbol(static_cast(record->_arrayClass)); + binaryTemplate->_arrayClassIndex = record->_arrayClassIndex; + + cursor += sizeof(TR_RelocationRecordValidateArrayClassFromJavaVMBinaryTemplate); + } + break; + + case TR_ValidateClassInfoIsInitialized: + { + TR::ClassInfoIsInitialized *record = reinterpret_cast(relocation->getTargetAddress()); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordValidateClassInfoIsInitializedBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_classID = symValManager->getIDFromSymbol(static_cast(record->_class)); + binaryTemplate->_isInitialized = record->_isInitialized; + + cursor += sizeof(TR_RelocationRecordValidateClassInfoIsInitializedBinaryTemplate); + } + break; + + case TR_SymbolFromManager: + { + uint8_t *symbol = relocation->getTargetAddress(); + uint16_t symbolID = comp->getSymbolValidationManager()->getIDFromSymbol(static_cast(symbol)); + + uint16_t symbolType = (uint16_t)(uintptrj_t)relocation->getTargetAddress2(); + + cursor -= sizeof(TR_RelocationRecordBinaryTemplate); + + TR_RelocationRecordSymbolFromManagerBinaryTemplate *binaryTemplate = + reinterpret_cast(cursor); + + binaryTemplate->_symbolID = symbolID; + binaryTemplate->_symbolType = symbolType; + + cursor += sizeof(TR_RelocationRecordSymbolFromManagerBinaryTemplate); + } + break; + case TR_ValidateClass: case TR_ValidateInstanceField: { @@ -632,7 +1340,7 @@ uint8_t *J9::X86::AheadOfTimeCompile::initializeAOTRelocationHeader(TR::Iterated break; default: - return cursor; + return cursor; } return cursor; } @@ -704,6 +1412,43 @@ uint32_t J9::X86::AheadOfTimeCompile::_relocationTargetTypeToHeaderSizeMap[TR_Nu 56, // TR_DebugCounter = 59 8, // TR_ClassUnloadAssumption = 60 32, // TR_J2IVirtualThunkPointer = 61, + 48, // TR_InlinedAbstractMethodWithNopGuard = 62, + sizeof(TR_RelocationRecordValidateRootClassBinaryTemplate), // TR_ValidateRootClass = 63, + sizeof(TR_RelocationRecordValidateClassByNameBinaryTemplate), // TR_ValidateClassByName = 64, + sizeof(TR_RelocationRecordValidateProfiledClassBinaryTemplate), // TR_ValidateProfiledClass = 65, + sizeof(TR_RelocationRecordValidateClassFromCPBinaryTemplate), // TR_ValidateClassFromCP = 66, + sizeof(TR_RelocationRecordValidateDefiningClassFromCPBinaryTemplate),//TR_ValidateDefiningClassFromCP = 67, + sizeof(TR_RelocationRecordValidateStaticClassFromCPBinaryTemplate), // TR_ValidateStaticClassFromCP = 68, + sizeof(TR_RelocationRecordValidateClassFromMethodBinaryTemplate), // TR_ValidateClassFromMethod = 69, + sizeof(TR_RelocationRecordValidateCompFromArrayBinaryTemplate), // TR_ValidateComponentClassFromArrayClass= 70, + sizeof(TR_RelocationRecordValidateArrayFromCompBinaryTemplate), // TR_ValidateArrayClassFromComponentClass= 71, + sizeof(TR_RelocationRecordValidateSuperClassFromClassBinaryTemplate),//TR_ValidateSuperClassFromClass = 72, + sizeof(TR_RelocationRecordValidateClassInstanceOfClassBinaryTemplate),//TR_ValidateClassInstanceOfClass = 73, + sizeof(TR_RelocationRecordValidateSystemClassByNameBinaryTemplate), //TR_ValidateSystemClassByName = 74, + sizeof(TR_RelocationRecordValidateClassFromITableIndexCPBinaryTemplate),//TR_ValidateClassFromITableIndexCP = 75, + sizeof(TR_RelocationRecordValidateDeclaringClassFromFieldOrStaticBinaryTemplate),//TR_ValidateDeclaringClassFromFieldOrStatic=76, + sizeof(TR_RelocationRecordValidateClassClassBinaryTemplate), // TR_ValidateClassClass = 77, + sizeof(TR_RelocationRecordValidateConcreteSubFromClassBinaryTemplate),//TR_ValidateConcreteSubClassFromClass = 78, + sizeof(TR_RelocationRecordValidateClassChainBinaryTemplate), // TR_ValidateClassChain = 79, + sizeof(TR_RelocationRecordValidateRomClassBinaryTemplate), // TR_ValidateRomClass = 80, + sizeof(TR_RelocationRecordValidatePrimitiveClassBinaryTemplate), // TR_ValidatePrimitiveClass = 81, + sizeof(TR_RelocationRecordValidateMethodFromInlSiteBinaryTemplate), // TR_ValidateMethodFromInlinedSite = 82, + sizeof(TR_RelocationRecordValidateMethodByNameBinaryTemplate), // TR_ValidatedMethodByName = 83, + sizeof(TR_RelocationRecordValidateMethodFromClassBinaryTemplate), // TR_ValidatedMethodFromClass = 84, + sizeof(TR_RelocationRecordValidateStaticMethodFromCPBinaryTemplate),// TR_ValidateStaticMethodFromCP = 85, + sizeof(TR_RelocationRecordValidateSpecialMethodFromCPBinaryTemplate),//TR_ValidateSpecialMethodFromCP = 86, + sizeof(TR_RelocationRecordValidateVirtualMethodFromCPBinaryTemplate),//TR_ValidateVirtualMethodFromCP = 87, + sizeof(TR_RelocationRecordValidateVirtualMethodFromOffsetBinaryTemplate),//TR_ValidateVirtualMethodFromOffset = 88, + sizeof(TR_RelocationRecordValidateInterfaceMethodFromCPBinaryTemplate),//TR_ValidateInterfaceMethodFromCP = 89, + sizeof(TR_RelocationRecordValidateMethodFromClassAndSigBinaryTemplate),//TR_ValidateMethodFromClassAndSig = 90, + sizeof(TR_RelocationRecordValidateStackWalkerMaySkipFramesBinaryTemplate),//TR_ValidateStackWalkerMaySkipFramesRecord= 91, + sizeof(TR_RelocationRecordValidateArrayClassFromJavaVMBinaryTemplate), //TR_ValidateArrayClassFromJavaVM = 92, + sizeof(TR_RelocationRecordValidateClassInfoIsInitializedBinaryTemplate),//TR_ValidateClassInfoIsInitialized = 93, + sizeof(TR_RelocationRecordValidateMethodFromSingleImplBinaryTemplate),//TR_ValidateMethodFromSingleImplementer= 94, + sizeof(TR_RelocationRecordValidateMethodFromSingleInterfaceImplBinaryTemplate),//TR_ValidateMethodFromSingleInterfaceImplementer= 95, + sizeof(TR_RelocationRecordValidateMethodFromSingleAbstractImplBinaryTemplate),//TR_ValidateMethodFromSingleAbstractImplementer= 96, + sizeof(TR_RelocationRecordValidateImproperInterfaceMethodFromCPBinaryTemplate),//TR_ValidateImproperInterfaceMethodFromCP= 97, + sizeof(TR_RelocationRecordSymbolFromManagerBinaryTemplate), // TR_SymbolFromManager = 98, #else 12, // TR_ConstantPool = 0 @@ -768,6 +1513,7 @@ uint32_t J9::X86::AheadOfTimeCompile::_relocationTargetTypeToHeaderSizeMap[TR_Nu 28, // TR_DebugCounter = 59 4, // TR_ClassUnloadAssumption = 60 16, // TR_J2IVirtualThunkPointer = 61, + 24, // TR_InlinedAbstractMethodWithNopGuard = 62, #endif }; diff --git a/runtime/compiler/x/codegen/J9TreeEvaluator.cpp b/runtime/compiler/x/codegen/J9TreeEvaluator.cpp index 2af7c3db825..c705765d9cb 100644 --- a/runtime/compiler/x/codegen/J9TreeEvaluator.cpp +++ b/runtime/compiler/x/codegen/J9TreeEvaluator.cpp @@ -3630,7 +3630,9 @@ inline void generateInlinedCheckCastOrInstanceOfForInterface(TR::Node* node, TR_ { TR_ASSERT(clazz && TR::Compiler->cls.isInterfaceClass(cg->comp(), clazz), "Not a compile-time known Interface."); - auto use64BitClasses = TR::Compiler->target.is64Bit() && !TR::Compiler->om.generateCompressedObjectHeaders(); + auto use64BitClasses = TR::Compiler->target.is64Bit() && + (!TR::Compiler->om.generateCompressedObjectHeaders() || + (cg->comp()->compileRelocatableCode() && cg->comp()->getOption(TR_UseSymbolValidationManager))); auto j9class = cg->allocateRegister(); auto tmp = use64BitClasses ? cg->allocateRegister() : NULL; @@ -3679,6 +3681,11 @@ inline void generateInlinedCheckCastOrInstanceOfForInterface(TR::Node* node, TR_ guessClass = (uintptrj_t)guessClassArray[i]; } } + + if (cg->comp()->compileRelocatableCode() && cg->comp()->getOption(TR_UseSymbolValidationManager)) + if (!cg->comp()->getSymbolValidationManager()->addProfiledClassRecord((TR_OpaqueClassBlock *)guessClass)) + guessClass = NULL; + // Call site cache auto cache = sizeof(J9Class*) == 4 ? cg->create4ByteData(node, (uint32_t)guessClass) : cg->create8ByteData(node, (uint64_t)guessClass); cache->setClassAddress(true); @@ -3767,7 +3774,9 @@ inline void generateInlinedCheckCastOrInstanceOfForInterface(TR::Node* node, TR_ inline void generateInlinedCheckCastOrInstanceOfForClass(TR::Node* node, TR_OpaqueClassBlock* clazz, TR::CodeGenerator* cg, bool isCheckCast) { auto fej9 = (TR_J9VMBase*)(cg->fe()); - auto use64BitClasses = TR::Compiler->target.is64Bit() && !TR::Compiler->om.generateCompressedObjectHeaders(); + auto use64BitClasses = TR::Compiler->target.is64Bit() && + (!TR::Compiler->om.generateCompressedObjectHeaders() || + (cg->comp()->compileRelocatableCode() && cg->comp()->getOption(TR_UseSymbolValidationManager))); auto clazzData = use64BitClasses ? cg->create8ByteData(node, (uint64_t)(uintptr_t)clazz) : NULL; if (clazzData) @@ -3928,7 +3937,7 @@ TR::Register *J9::X86::TreeEvaluator::checkcastinstanceofEvaluator(TR::Node *nod auto clazz = TR::TreeEvaluator::getCastClassAddress(node->getChild(1)); if (clazz && !TR::Compiler->cls.isClassArray(cg->comp(), clazz) && // not yet optimized - !cg->comp()->compileRelocatableCode() && // TODO subsequent PR will support AOT + (!cg->comp()->compileRelocatableCode() || cg->comp()->getOption(TR_UseSymbolValidationManager)) && !cg->comp()->getOption(TR_DisableInlineCheckCast) && !cg->comp()->getOption(TR_DisableInlineInstanceOf)) { @@ -6548,7 +6557,9 @@ static void genInitObjectHeader(TR::Node *node, TR::Compilation *comp = cg->comp(); TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe()); - bool use64BitClasses = TR::Compiler->target.is64Bit() && !TR::Compiler->om.generateCompressedObjectHeaders(); + bool use64BitClasses = TR::Compiler->target.is64Bit() && + (!TR::Compiler->om.generateCompressedObjectHeaders() || + (cg->comp()->compileRelocatableCode() && cg->comp()->getOption(TR_UseSymbolValidationManager))); // This code was moved to this point so that the romClass can be used by the AOT // portion without calling the method again. @@ -6568,7 +6579,7 @@ static void genInitObjectHeader(TR::Node *node, TR::Register * clzReg = classReg; // TODO: should be able to use a TR_ClassPointer relocation without this stuff (along with class validation) - if (cg->needClassAndMethodPointerRelocations()) + if (cg->needClassAndMethodPointerRelocations() && !comp->getOption(TR_UseSymbolValidationManager)) { TR::Register *vmThreadReg = cg->getVMThreadRegister(); if (node->getOpCodeValue() == TR::newarray) @@ -6609,7 +6620,10 @@ static void genInitObjectHeader(TR::Node *node, TR::Instruction *instr = NULL; if (use64BitClasses) { - instr = generateRegImm64Instruction(MOV8RegImm64, node, tempReg, ((intptrj_t)clazz|orFlagsClass), cg); + if (cg->needClassAndMethodPointerRelocations() && comp->getOption(TR_UseSymbolValidationManager)) + instr = generateRegImm64Instruction(MOV8RegImm64, node, tempReg, ((intptrj_t)clazz|orFlagsClass), cg, TR_ClassPointer); + else + instr = generateRegImm64Instruction(MOV8RegImm64, node, tempReg, ((intptrj_t)clazz|orFlagsClass), cg); generateMemRegInstruction(S8MemReg, node, generateX86MemoryReference(objectReg, TR::Compiler->om.offsetOfObjectVftField(), cg), tempReg, cg); } else @@ -7707,12 +7721,15 @@ J9::X86::TreeEvaluator::VMnewEvaluator( node->getOpCodeValue() == TR::anewarray) ) { startInstr = startInstr->getNext(); + TR_OpaqueClassBlock *classToValidate = clazz; + TR_RelocationRecordInformation *recordInfo = (TR_RelocationRecordInformation *) comp->trMemory()->allocateMemory(sizeof(TR_RelocationRecordInformation), heapAlloc); recordInfo->data1 = allocationSize; recordInfo->data2 = node->getInlinedSiteIndex(); recordInfo->data3 = (uintptr_t) failLabel; recordInfo->data4 = (uintptr_t) startInstr; + TR::SymbolReference * classSymRef; TR_ExternalRelocationTargetKind reloKind; @@ -7725,6 +7742,15 @@ J9::X86::TreeEvaluator::VMnewEvaluator( { classSymRef = node->getSecondChild()->getSymbolReference(); reloKind = TR_VerifyRefArrayForAlloc; + + if (comp->getOption(TR_UseSymbolValidationManager)) + classToValidate = comp->fej9()->getComponentClassFromArrayClass(classToValidate); + } + + if (comp->getOption(TR_UseSymbolValidationManager)) + { + TR_ASSERT(classToValidate, "classToValidate should not be NULL, clazz=%p\n", clazz); + recordInfo->data5 = (uintptr_t)classToValidate; } cg->addExternalRelocation(new (cg->trHeapMemory()) TR::BeforeBinaryEncodingExternalRelocation(startInstr, diff --git a/runtime/compiler/x/codegen/X86PrivateLinkage.cpp b/runtime/compiler/x/codegen/X86PrivateLinkage.cpp index ecc7317f69e..cd25d1769a8 100644 --- a/runtime/compiler/x/codegen/X86PrivateLinkage.cpp +++ b/runtime/compiler/x/codegen/X86PrivateLinkage.cpp @@ -1329,7 +1329,8 @@ void TR::X86CallSite::setupVirtualGuardInfo() TR::SymbolReference *methodSymRef = getSymbolReference(); TR_PersistentCHTable * chTable = comp()->getPersistentInfo()->getPersistentCHTable(); - if (thisClass && TR::Compiler->cls.isAbstractClass(comp(), thisClass)) + /* Devirtualization is not currently supported for AOT compilations */ + if (thisClass && TR::Compiler->cls.isAbstractClass(comp(), thisClass) && !comp()->compileRelocatableCode()) { TR_ResolvedMethod * method = chTable->findSingleAbstractImplementer(thisClass, methodSymRef->getOffset(), methodSymRef->getOwningMethod(comp()), comp()); if (method && diff --git a/runtime/compiler/z/codegen/J9S390PrivateLinkage.cpp b/runtime/compiler/z/codegen/J9S390PrivateLinkage.cpp index cf8d14873b1..5a64a7f1280 100644 --- a/runtime/compiler/z/codegen/J9S390PrivateLinkage.cpp +++ b/runtime/compiler/z/codegen/J9S390PrivateLinkage.cpp @@ -2026,7 +2026,8 @@ TR::S390PrivateLinkage::buildVirtualDispatch(TR::Node * callNode, TR::RegisterDe } TR_PersistentCHTable * chTable = comp()->getPersistentInfo()->getPersistentCHTable(); - if (thisClass && TR::Compiler->cls.isAbstractClass(comp(), thisClass)) + /* Devirtualization is not currently supported for AOT compilations */ + if (thisClass && TR::Compiler->cls.isAbstractClass(comp(), thisClass) && !comp()->compileRelocatableCode()) { TR_ResolvedMethod * method = chTable->findSingleAbstractImplementer(thisClass, methodSymRef->getOffset(), methodSymRef->getOwningMethod(comp()), comp());