Path: blob/master/runtime/compiler/il/J9Symbol.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/2122/**************************************************************************23Testarossa JIT Codegen2425File name: Symbol.cpp26Attributes: Platform independent, IL interface27Purpose: Implementation of the:28Symbol class2930**************************************************************************/3132#include <stddef.h>33#include <stdint.h>34#include <string.h>35#include "env/FrontEnd.hpp"36#include "compile/Compilation.hpp"37#include "compile/SymbolReferenceTable.hpp"38#include "env/TRMemory.hpp"39#include "env/VMJ9.h"40#include "il/DataTypes.hpp"41#include "il/StaticSymbol.hpp"42#include "il/StaticSymbol_inlines.hpp"43#include "il/Symbol.hpp"44#include "il/SymbolReference.hpp"45#include "infra/Assert.hpp"46#include "infra/Flags.hpp"47#include "ras/Debug.hpp"4849struct F50{51TR::Symbol::RecognizedField id;52// split "<class>.<field> <signature>"53const char *classStr; // "<class>"54uint16_t classLen;55const char *fieldStr; // "<field>"56uint16_t fieldLen;57const char *sigStr; // "<signature>"58uint16_t sigLen;59};60#define r(id, c, f, s) id, c, sizeof(c)-1, f, sizeof(f)-1, s, sizeof(s)-16162/*63* These recognized fields start with 'c' (like "com/...") as class name.64*/65static F recognizedFieldName_c[] =66{67{r(TR::Symbol::Com_ibm_gpu_Kernel_blockIdxX, "com/ibm/gpu/Kernel", "blockIdxX", "I")},68{r(TR::Symbol::Com_ibm_gpu_Kernel_blockIdxY, "com/ibm/gpu/Kernel", "blockIdxY", "I")},69{r(TR::Symbol::Com_ibm_gpu_Kernel_blockIdxZ, "com/ibm/gpu/Kernel", "blockIdxZ", "I")},70{r(TR::Symbol::Com_ibm_gpu_Kernel_blockDimX, "com/ibm/gpu/Kernel", "blockDimX", "I")},71{r(TR::Symbol::Com_ibm_gpu_Kernel_blockDimY, "com/ibm/gpu/Kernel", "blockDimY", "I")},72{r(TR::Symbol::Com_ibm_gpu_Kernel_blockDimZ, "com/ibm/gpu/Kernel", "blockDimZ", "I")},73{r(TR::Symbol::Com_ibm_gpu_Kernel_threadIdxX, "com/ibm/gpu/Kernel", "threadIdxX", "I")},74{r(TR::Symbol::Com_ibm_gpu_Kernel_threadIdxY, "com/ibm/gpu/Kernel", "threadIdxY", "I")},75{r(TR::Symbol::Com_ibm_gpu_Kernel_threadIdxZ, "com/ibm/gpu/Kernel", "threadIdxZ", "I")},76{r(TR::Symbol::Com_ibm_gpu_Kernel_syncThreads, "com/ibm/gpu/Kernel", "syncThreads", "I")},7778{r(TR::Symbol::Com_ibm_jit_JITHelpers_IS_32_BIT, "com/ibm/jit/JITHelpers", "IS_32_BIT", "Z")}, //2279{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9OBJECT_J9CLASS_OFFSET, "com/ibm/jit/JITHelpers", "J9OBJECT_J9CLASS_OFFSET", "I")}, //2280{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9OBJECT_FLAGS_MASK32, "com/ibm/jit/JITHelpers", "J9OBJECT_FLAGS_MASK32", "I")}, //2281{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9OBJECT_FLAGS_MASK64, "com/ibm/jit/JITHelpers", "J9OBJECT_FLAGS_MASK64", "I")}, //2282{r(TR::Symbol::Com_ibm_jit_JITHelpers_JLTHREAD_J9THREAD_OFFSET, "com/ibm/jit/JITHelpers", "JLTHREAD_J9THREAD_OFFSET", "I")}, //2283{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9THREAD_J9VM_OFFSET, "com/ibm/jit/JITHelpers", "J9THREAD_J9VM_OFFSET", "I")}, //2284{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9_GC_OBJECT_ALIGNMENT_SHIFT, "com/ibm/jit/JITHelpers", "J9_GC_OBJECT_ALIGNMENT_SHIFT", "I")}, //2285{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9ROMARRAYCLASS_ARRAYSHAPE_OFFSET, "com/ibm/jit/JITHelpers", "J9ROMARRAYCLASS_ARRAYSHAPE_OFFSET", "I")}, //2286{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9CLASS_BACKFILL_OFFSET_OFFSET, "com/ibm/jit/JITHelpers", "J9CLASS_BACKFILL_OFFSET_OFFSET", "I")}, //2287{r(TR::Symbol::Com_ibm_jit_JITHelpers_ARRAYSHAPE_ELEMENTCOUNT_MASK, "com/ibm/jit/JITHelpers", "ARRAYSHAPE_ELEMENTCOUNT_MASK", "I")}, //2288{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9CONTIGUOUSARRAY_HEADER_SIZE, "com/ibm/jit/JITHelpers", "J9CONTIGUOUSARRAY_HEADER_SIZE", "I")}, //2289{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9DISCONTIGUOUSARRAY_HEADER_SIZE, "com/ibm/jit/JITHelpers", "J9DISCONTIGUOUSARRAY_HEADER_SIZE", "I")}, //2290{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9OBJECT_CONTIGUOUS_LENGTH_OFFSET, "com/ibm/jit/JITHelpers", "J9OBJECT_CONTIGUOUS_LENGTH_OFFSET", "I")}, //2291{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9OBJECT_DISCONTIGUOUS_LENGTH_OFFSET, "com/ibm/jit/JITHelpers", "J9OBJECT_DISCONTIGUOUS_LENGTH_OFFSET", "I")}, //2292{r(TR::Symbol::Com_ibm_jit_JITHelpers_JLOBJECT_ARRAY_BASE_OFFSET, "com/ibm/jit/JITHelpers", "JLOBJECT_ARRAY_BASE_OFFSET", "I")}, //2293{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9CLASS_J9ROMCLASS_OFFSET, "com/ibm/jit/JITHelpers", "J9CLASS_J9ROMCLASS_OFFSET", "I")}, //2294{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9JAVAVM_IDENTITY_HASH_DATA_OFFSET, "com/ibm/jit/JITHelpers", "J9JAVAVM_IDENTITY_HASH_DATA_OFFSET","I")},95{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9IDENTITYHASHDATA_HASH_DATA1_OFFSET,"com/ibm/jit/JITHelpers", "J9IDENTITYHASHDATA_HASH_DATA1_OFFSET", "I")},96{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9IDENTITYHASHDATA_HASH_DATA2_OFFSET,"com/ibm/jit/JITHelpers", "J9IDENTITYHASHDATA_HASH_DATA2_OFFSET", "I")},97{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9IDENTITYHASHDATA_HASH_DATA3_OFFSET,"com/ibm/jit/JITHelpers", "J9IDENTITYHASHDATA_HASH_DATA3_OFFSET", "I")},98{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9IDENTITYHASHDATA_HASH_SALT_TABLE_OFFSET,"com/ibm/jit/JITHelpers","J9IDENTITYHASHDATA_HASH_SALT_TABLE_OFFSET", "I")},99{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9_IDENTITY_HASH_SALT_POLICY_STANDARD,"com/ibm/jit/JITHelpers","J9_IDENTITY_HASH_SALT_POLICY_STANDARD", "I")},100{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9_IDENTITY_HASH_SALT_POLICY_REGION,"com/ibm/jit/JITHelpers","J9_IDENTITY_HASH_SALT_POLICY_REGION", "I")},101{r(TR::Symbol::Com_ibm_jit_JITHelpers_J9_IDENTITY_HASH_SALT_POLICY_NONE,"com/ibm/jit/JITHelpers","J9_IDENTITY_HASH_SALT_POLICY_NONE", "I")},102{r(TR::Symbol::Com_ibm_jit_JITHelpers_IDENTITY_HASH_SALT_POLICY,"com/ibm/jit/JITHelpers","IDENTITY_HASH_SALT_POLICY", "I")},103{r(TR::Symbol::Com_ibm_oti_vm_VM_J9CLASS_CLASS_FLAGS_OFFSET,"com/ibm/oti/vm/VM","J9CLASS_CLASS_FLAGS_OFFSET", "I")},104{r(TR::Symbol::Com_ibm_oti_vm_VM_J9CLASS_INITIALIZE_STATUS_OFFSET,"com/ibm/oti/vm/VM","J9CLASS_INITIALIZE_STATUS_OFFSET", "I")},105{r(TR::Symbol::Com_ibm_oti_vm_VM_J9_JAVA_CLASS_RAM_SHAPE_SHIFT,"com/ibm/oti/vm/VM","J9AccClassRAMShapeShift", "I")},106{r(TR::Symbol::Com_ibm_oti_vm_VM_OBJECT_HEADER_SHAPE_MASK,"com/ibm/oti/vm/VM","OBJECT_HEADER_SHAPE_MASK", "I")},107{r(TR::Symbol::Com_ibm_oti_vm_VM_ADDRESS_SIZE,"com/ibm/oti/vm/VM","ADDRESS_SIZE", "I")},108{TR::Symbol::UnknownField}109};110111/*112* These recognized fields start with 'j' (like "java/...") as class name.113*/114static F recognizedFieldName_j[] =115{116/*117* NOTE: If you add a new class here, make sure its length is within118* minClassLength and maxClassLength of the corresponding FP struct.119*120* r(<enum>, "<class>" ,"<field>", "<sig>")121*/122{r(TR::Symbol::Java_io_ByteArrayOutputStream_count, "java/io/ByteArrayOutputStream", "count", "I")},123{r(TR::Symbol::Java_lang_J9VMInternals_jitHelpers, "java/lang/J9VMInternals", "jitHelpers", "Lcom/ibm/jit/JITHelpers;")},124{r(TR::Symbol::Java_lang_String_count, "java/lang/String", "count", "I")},125{r(TR::Symbol::Java_lang_String_enableCompression, "java/lang/String", "COMPACT_STRINGS", "Z") },126{r(TR::Symbol::Java_lang_String_hashCode, "java/lang/String", "hash", "I")},127{r(TR::Symbol::Java_lang_String_value, "java/lang/String", "value", "[B")},128{r(TR::Symbol::Java_lang_String_value, "java/lang/String", "value", "[C")},129{r(TR::Symbol::Java_lang_StringBuffer_count, "java/lang/StringBuffer", "count", "I")},130{r(TR::Symbol::Java_lang_StringBuffer_value, "java/lang/StringBuffer", "value", "[B")},131{r(TR::Symbol::Java_lang_StringBuffer_value, "java/lang/StringBuffer", "value", "[C")},132{r(TR::Symbol::Java_lang_StringBuilder_count, "java/lang/StringBuilder", "count", "I")},133{r(TR::Symbol::Java_lang_StringBuilder_value, "java/lang/StringBuilder", "value", "[B")},134{r(TR::Symbol::Java_lang_StringBuilder_value, "java/lang/StringBuilder", "value", "[C")},135{r(TR::Symbol::Java_lang_Throwable_stackTrace, "java/lang/Throwable", "stackTrace", "[Ljava/lang/StackTraceElement;")},136{r(TR::Symbol::Java_lang_invoke_BruteArgumentMoverHandle_extra,"java/lang/invoke/BruteArgumentMoverHandle", "extra", "[Ljava/lang/Object;")},137{r(TR::Symbol::Java_lang_invoke_DynamicInvokerHandle_site, "java/lang/invoke/DynamicInvokerHandle", "site", "Ljava/lang/invoke/CallSite;")},138{r(TR::Symbol::Java_lang_invoke_CallSite_target, "java/lang/invoke/CallSite", "target", "Ljava/lang/invoke/MethodHandle;")},139{r(TR::Symbol::Java_lang_invoke_LambdaForm_vmentry, "java/lang/invoke/LambdaForm", "vmentry", "Ljava/lang/invoke/MemberName;")},140{r(TR::Symbol::Java_lang_invoke_MutableCallSite_target, "java/lang/invoke/MutableCallSite", "target", "Ljava/lang/invoke/MethodHandle;")},141{r(TR::Symbol::Java_lang_invoke_MutableCallSiteDynamicInvokerHandle_mutableSite,"java/lang/invoke/MutableCallSiteDynamicInvokerHandle", "mutableSite", "Ljava/lang/invoke/MutableCallSite;")},142{r(TR::Symbol::Java_lang_invoke_MemberName_vmtarget, "java/lang/invoke/MemberName", "vmtarget", "J")},143{r(TR::Symbol::Java_lang_invoke_MemberName_vmindex, "java/lang/invoke/MemberName", "vmindex", "J")},144{r(TR::Symbol::Java_lang_invoke_MethodHandle_form, "java/lang/invoke/MethodHandle", "form", "Ljava/lang/invoke/LambdaForm;")},145{r(TR::Symbol::Java_lang_invoke_MethodHandle_thunks, "java/lang/invoke/MethodHandle", "thunks", "Ljava/lang/invoke/ThunkTuple;")},146{r(TR::Symbol::Java_lang_invoke_MethodHandle_type, "java/lang/invoke/MethodHandle", "type", "Ljava/lang/invoke/MethodType;")},147{r(TR::Symbol::Java_lang_invoke_MethodType_ptypes, "java/lang/invoke/MethodType", "ptypes", "[Ljava/lang/Class;")},148{r(TR::Symbol::Java_lang_invoke_PrimitiveHandle_rawModifiers, "java/lang/invoke/PrimitiveHandle", "rawModifiers", "I")},149{r(TR::Symbol::Java_lang_invoke_PrimitiveHandle_defc, "java/lang/invoke/PrimitiveHandle", "defc", "Ljava/lang/Class;")},150{r(TR::Symbol::Java_lang_invoke_ThunkTuple_invokeExactThunk, "java/lang/invoke/ThunkTuple", "invokeExactThunk", "J")},151{r(TR::Symbol::Java_util_Hashtable_elementCount, "java/util/Hashtable", "count", "I")},152{r(TR::Symbol::Java_math_BigInteger_ZERO, "java/math/BigInteger", "ZERO", "Ljava/math/BigInteger;")},153{r(TR::Symbol::Java_math_BigInteger_useLongRepresentation, "java/math/BigInteger", "useLongRepresentation", "Z")},154{r(TR::Symbol::Java_lang_ref_SoftReference_age, "java/lang/ref/SoftReference", "age", "I")},155{r(TR::Symbol::Java_lang_invoke_VarHandle_handleTable, "java/lang/invoke/VarHandle", "handleTable", "[Ljava/lang/invoke/MethodHandle;")},156{r(TR::Symbol::Java_lang_invoke_MethodHandleImpl_LoopClauses_clauses, "java/lang/invoke/MethodHandleImpl$LoopClauses", "clauses", "[[Ljava/lang/invoke/MethodHandle;")},157{r(TR::Symbol::Java_lang_Integer_value, "java/lang/Integer", "value", "I")},158{r(TR::Symbol::Java_lang_Long_value, "java/lang/Long", "value", "J")},159{r(TR::Symbol::Java_lang_Float_value, "java/lang/Float", "value", "F")},160{r(TR::Symbol::Java_lang_Double_value, "java/lang/Double", "value", "D")},161{r(TR::Symbol::Java_lang_Byte_value, "java/lang/Byte", "value", "B")},162{r(TR::Symbol::Java_lang_Character_value, "java/lang/Character", "value", "C")},163{r(TR::Symbol::Java_lang_Short_value, "java/lang/Short", "value", "S")},164{r(TR::Symbol::Java_lang_Boolean_value, "java/lang/Boolean", "value", "Z")},165{r(TR::Symbol::Java_lang_Class_enumVars, "java/lang/Class", "enumVars", "Ljava/lang/Class$EnumVars;")},166{r(TR::Symbol::Java_lang_ClassEnumVars_cachedEnumConstants, "java/lang/Class$EnumVars", "cachedEnumConstants", "[Ljava/lang/Object;")},167{TR::Symbol::UnknownField}168};169170TR::Symbol::RecognizedField171J9::Symbol::searchRecognizedField(TR::Compilation * comp, TR_ResolvedMethod * owningMethod, int32_t cpIndex, bool isStatic)172{173struct FP174{175struct F *fieldInfo;176uint16_t minClassLength;177uint16_t maxClassLength;178};179static FP fieldPrefixTable[] =180{181/*182* List is sorted by class name prefix183* The first prefix is 'c'184*/185{recognizedFieldName_c, 17, 22},186{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},187{recognizedFieldName_j, 14, 52}188};189190const char minClassPrefix = 'c';191const char maxClassPrefix = 'j';192193TR_OpaqueClassBlock *declaringClass = owningMethod->getDeclaringClassFromFieldOrStatic(comp, cpIndex);194195// $assertionDisabled fields are always foldable based on the Javadoc (setClassAssertionStatus196// "This method has no effect if the named class has already been initialized.197// (Once a class is initialized, its assertion status cannot change.)"198// So check if the field is final and check if it is this special field199if (isStatic)200{201int32_t totalLen;202char *fieldName;203fieldName = owningMethod->staticName(cpIndex, totalLen, comp->trMemory()); // totalLen = strlen("<class>" + "<field>" + "<sig>") + 3204static char *assertionsDisabledStr = "$assertionsDisabled Z";205//string will be of the form "<class>.$assertionsDisabled Z"206if (declaringClass207&& totalLen >= 22208&& comp->fej9()->isClassInitialized(declaringClass)209&& strncmp(&(fieldName[totalLen - 22]), assertionsDisabledStr, 21) == 0)210{211if (comp->getOption(TR_TraceCG))212traceMsg(comp, "Matched $assertionsDisabled Z\n");213return assertionsDisabled;214}215}216217/*218* quick check219*/220int32_t classLen;221char *className; // Note: not Null-terminated!222if (declaringClass)223className = comp->fej9()->getClassNameChars(declaringClass, classLen);224else225className = owningMethod->classNameOfFieldOrStatic(cpIndex, classLen); // classLen = strlen("<class>");226227if (!className ||228className[0] < minClassPrefix ||229className[0] > maxClassPrefix)230{231return TR::Symbol::UnknownField;232}233234FP * recognizedFieldPrefix = &fieldPrefixTable[className[0] - minClassPrefix];235if (!recognizedFieldPrefix ||236classLen < recognizedFieldPrefix->minClassLength || classLen > recognizedFieldPrefix->maxClassLength)237{238return TR::Symbol::UnknownField;239}240241F *recognizedFieldName = recognizedFieldPrefix->fieldInfo;242int32_t i;243F *knownField;244245int32_t fieldLen;246char* fieldName = isStatic ? owningMethod->staticNameChars(cpIndex, fieldLen) : owningMethod->fieldNameChars(cpIndex, fieldLen);247248int32_t sigLen;249char* fieldSig = isStatic ? owningMethod->staticSignatureChars(cpIndex, sigLen) : owningMethod->fieldSignatureChars(cpIndex, sigLen);250251for (i=0, knownField = &recognizedFieldName[i];252knownField->id != TR::Symbol::UnknownField;253knownField = &recognizedFieldName[++i])254{255if (classLen ==knownField->classLen &&256fieldLen == knownField->fieldLen &&257sigLen == knownField->sigLen &&258strncmp(knownField->fieldStr, fieldName, fieldLen) == 0 &&259strncmp(knownField->classStr, className, classLen) == 0)260{261// TODO (Filip): This is a workaround for Java 829 performance as we switched to using a byte[] backing array in String*. Remove this workaround once obsolete.262if (knownField->id != TR::Symbol::Java_lang_String_value &&263knownField->id != TR::Symbol::Java_lang_StringBuffer_value &&264knownField->id != TR::Symbol::Java_lang_StringBuilder_value)265{266TR_ASSERT(strncmp(knownField->sigStr, fieldSig, sigLen) == 0, "Signature is altered unexpectly!");267}268269return knownField->id;270}271}272273return TR::Symbol::UnknownField;274}275276TR::Symbol::RecognizedField277J9::Symbol::getRecognizedField()278{279if (self()->isRecognizedShadow())280return _recognizedField;281else if (self()->isRecognizedStatic())282return self()->getRecognizedStaticSymbol()->getRecognizedField();283else284return TR::Symbol::UnknownField;285}286287/**288* Return the owning class name of this recognized field.289* Return null if this symbol does not have a recognized field.290*/291const char *292J9::Symbol::owningClassNameCharsForRecognizedField(int32_t & length)293{294TR_ASSERT(isShadow(), "Must be a shadow symbol");295TR::Symbol::RecognizedField recognizedField = self()->getRecognizedField();296TR_ASSERT(TR::Symbol::UnknownField != recognizedField, "Symbol should have a valid recognized field");297for (int i = 0; recognizedFieldName_c[i].id != TR::Symbol::UnknownField; ++i)298{299F &knownField = recognizedFieldName_c[i];300if (knownField.id == recognizedField)301{302length = knownField.classLen;303return knownField.classStr;304}305}306for (int i = 0; recognizedFieldName_j[i].id != TR::Symbol::UnknownField; ++i)307{308F &knownField = recognizedFieldName_j[i];309if (knownField.id == recognizedField)310{311length = knownField.classLen;312return knownField.classStr;313}314}315316return NULL;317}318319/**320* Sets the data type of a symbol, and the size, if the size can be inferred321* from the data type.322*/323void324J9::Symbol::setDataType(TR::DataType dt)325{326if (dt.isBCD())327{328// do not infer a size for BCD types as their size varies329//Set data type but not size330_flags.setValue(DataTypeMask, dt);331}332else333{334OMR::SymbolConnector::setDataType(dt);335}336}337338uint32_t339J9::Symbol::convertTypeToSize(TR::DataType dt)340{341TR_ASSERT(!dt.isBCD(),"size for BCD type is not fixed\n");342return OMR::SymbolConnector::convertTypeToSize(dt);343}344345TR::Symbol *346J9::Symbol::getRecognizedShadowSymbol()347{348return self()->isRecognizedShadow() ? (TR::Symbol*)this : 0;349}350351template <typename AllocatorType>352TR::Symbol *353J9::Symbol::createRecognizedShadow(AllocatorType m, TR::DataType d, RecognizedField f)354{355auto * sym = createShadow(m, d);356sym->_recognizedField = f;357sym->_flags.set(RecognizedShadow);358if ((f == TR::Symbol::Java_lang_Class_enumVars) || (f == TR::Symbol::Java_lang_ClassEnumVars_cachedEnumConstants))359sym->_flags.set(RecognizedKnownObjectShadow);360return sym;361}362363template <typename AllocatorType>364TR::Symbol *365J9::Symbol::createRecognizedShadow(AllocatorType m, TR::DataType d, uint32_t s, RecognizedField f)366{367auto * sym = createShadow(m,d,s);368sym->_recognizedField = f;369sym->_flags.set(RecognizedShadow);370if ((f == TR::Symbol::Java_lang_Class_enumVars) || (f == TR::Symbol::Java_lang_ClassEnumVars_cachedEnumConstants))371sym->_flags.set(RecognizedKnownObjectShadow);372return sym;373}374375template <typename AllocatorType>376TR::Symbol *377J9::Symbol::createPossiblyRecognizedShadowWithFlags(378AllocatorType m,379TR::DataType type,380bool isVolatile,381bool isFinal,382bool isPrivate,383RecognizedField recognizedField)384{385TR::Symbol *fieldSymbol = NULL;386if (recognizedField != TR::Symbol::UnknownField)387fieldSymbol = TR::Symbol::createRecognizedShadow(m, type, recognizedField);388else389fieldSymbol = TR::Symbol::createShadow(m, type);390391if (isVolatile)392fieldSymbol->setVolatile();393394if (isFinal)395fieldSymbol->setFinal();396397if (isPrivate)398fieldSymbol->setPrivate();399400return fieldSymbol;401}402403template <typename AllocatorType>404TR::Symbol *405J9::Symbol::createPossiblyRecognizedShadowFromCP(406TR::Compilation *comp,407AllocatorType m,408TR_ResolvedMethod *owningMethod,409int32_t cpIndex,410TR::DataType *type, // can be determined accurately even for unresolved field refs411uint32_t *offset, // typically stored for some reason on symref (not Symbol)412bool needsAOTValidation)413{414*type = TR::NoType;415*offset = 0;416417const bool isStatic = false;418RecognizedField recognizedField =419TR::Symbol::searchRecognizedField(comp, owningMethod, cpIndex, isStatic);420421bool isVolatile, isFinal, isPrivate, isUnresolvedInCP;422423const bool isStore = false;424bool resolved = owningMethod->fieldAttributes(425comp,426cpIndex,427offset,428type,429&isVolatile,430&isFinal,431&isPrivate,432isStore,433&isUnresolvedInCP,434needsAOTValidation);435436if (!resolved)437return NULL;438439return createPossiblyRecognizedShadowWithFlags(440m, *type, isVolatile, isFinal, isPrivate, recognizedField);441}442443/*444* Explicit instantiation of factories for each TR_Memory type.445*/446447template TR::Symbol * J9::Symbol::createRecognizedShadow(TR_StackMemory, TR::DataType, RecognizedField);448template TR::Symbol * J9::Symbol::createRecognizedShadow(TR_HeapMemory, TR::DataType, RecognizedField);449450template TR::Symbol * J9::Symbol::createRecognizedShadow(TR_StackMemory, TR::DataType, uint32_t, RecognizedField);451template TR::Symbol * J9::Symbol::createRecognizedShadow(TR_HeapMemory, TR::DataType, uint32_t, RecognizedField);452453template TR::Symbol * J9::Symbol::createPossiblyRecognizedShadowWithFlags(TR_StackMemory, TR::DataType, bool, bool, bool, RecognizedField);454template TR::Symbol * J9::Symbol::createPossiblyRecognizedShadowWithFlags(TR_HeapMemory, TR::DataType, bool, bool, bool, RecognizedField);455456template TR::Symbol * J9::Symbol::createPossiblyRecognizedShadowFromCP(TR::Compilation*, TR_StackMemory, TR_ResolvedMethod*, int32_t, TR::DataType*, uint32_t*, bool);457template TR::Symbol * J9::Symbol::createPossiblyRecognizedShadowFromCP(TR::Compilation*, TR_HeapMemory, TR_ResolvedMethod*, int32_t, TR::DataType*, uint32_t*, bool);458459460