Path: blob/master/runtime/compiler/ilgen/ClassLookahead.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#include "ilgen/ClassLookahead.hpp"23#include "codegen/CodeGenerator.hpp"24#include "compile/Method.hpp"25#include "compile/ResolvedMethod.hpp"26#include "compiler/il/OMRTreeTop_inlines.hpp"27#include "env/ClassTableCriticalSection.hpp"28#include "env/IO.hpp"29#include "env/PersistentCHTable.hpp"30#include "il/Node.hpp"31#include "il/Node_inlines.hpp"32#include "il/TreeTop.hpp"33#include "ilgen/J9ByteCodeIlGenerator.hpp"34#include "ilgen/J9ByteCodeIterator.hpp"35#include "infra/Cfg.hpp"3637TR_ClassLookahead::TR_ClassLookahead(38TR_PersistentClassInfo * classInfo, TR_FrontEnd * fe, TR::Compilation * comp,39TR::SymbolReferenceTable * symRefTab)40:41_classPointer((TR_OpaqueClassBlock *) classInfo->getClassId()),42_compilation(comp),43_symRefTab(symRefTab),44_fe(fe),45_currentMethodSymbol(NULL)46{47_classFieldInfo = new (PERSISTENT_NEW) TR_PersistentClassInfoForFields;48_classInfo = classInfo;49_classFieldInfo->setFirst(0);50_traceIt = comp->getOption(TR_TraceLookahead);51}525354int32_t55TR_ClassLookahead::perform()56{57TR_J9VMBase *fej9 = (TR_J9VMBase *)fe();5859if ((fej9->getNumInnerClasses(_classPointer) > 0) ||60_classInfo->cannotTrustStaticFinal())61return 0;6263bool isClassInitialized = false;64bool seenFirstInitializerMethod = false;65bool allowForAOT = comp()->getOption(TR_UseSymbolValidationManager);66TR_PersistentClassInfo * classInfo =67comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(_classPointer, comp(), allowForAOT);68if (classInfo && classInfo->isInitialized())69isClassInitialized = true;7071if (!isClassInitialized)72return 0;7374TR_ScratchList<TR_ResolvedMethod> resolvedMethodsInClass(comp()->trMemory());75fej9->getResolvedMethods(comp()->trMemory(), _classPointer, &resolvedMethodsInClass);7677ListIterator<TR_ResolvedMethod> resolvedMethIt(&resolvedMethodsInClass);78TR_ResolvedMethod *resolvedMethod = NULL;79for (resolvedMethod = resolvedMethIt.getFirst(); resolvedMethod; resolvedMethod = resolvedMethIt.getNext())80{81if (resolvedMethod->isNative() ||82resolvedMethod->isJNINative() ||83resolvedMethod->isJITInternalNative())84{85_classInfo->setCannotTrustStaticFinal();86return 0;87}88}8990bool b = comp()->getNeedsClassLookahead();91comp()->setNeedsClassLookahead(false);9293int32_t len; char * name = fej9->getClassNameChars(_classPointer, len);9495if (_traceIt)96printf("ATTN: Doing classlookahead for %.*s\n", len, name);9798if (!performTransformation(comp(), "O^O CLASS LOOKAHEAD: Performing class lookahead for %s\n", name))99return 0;100101TR_ScratchList<TR::ResolvedMethodSymbol> initializerMethodsInClass(comp()->trMemory());102TR_ScratchList<TR::ResolvedMethodSymbol> resolvedMethodSyms(comp()->trMemory());103TR::ResolvedMethodSymbol *classInitializer = NULL;104105// check if peeking failed for any of the resolved methods106// if so, classLookahead cannot proceed107//108bool peekFailedForAnyMethod = false;109findInitializerMethods(&resolvedMethodsInClass, &initializerMethodsInClass, &resolvedMethodSyms, &classInitializer, &peekFailedForAnyMethod);110111if (peekFailedForAnyMethod)112{113comp()->setNeedsClassLookahead(b);114_classInfo->setCannotTrustStaticFinal();115return 0;116}117118_inClassInitializerMethod = false;119_inFirstInitializerMethod = false;120121if (classInitializer)122{123_currentMethodSymbol = classInitializer;124_inClassInitializerMethod = true;125_inInitializerMethod = true;126_inFirstBlock = true;127///fprintf(stderr, "looking at method %s\n", classInitializer->getResolvedMethod()->nameChars()); fflush(stderr);128129vcount_t visitCount = comp()->incVisitCount();130TR::TreeTop *tt;131comp()->resetVisitCounts(0, classInitializer->getFirstTreeTop());132for (tt = classInitializer->getFirstTreeTop(); tt; tt = tt->getNextTreeTop())133{134TR::Node *node = tt->getNode();135if (!examineNode(tt->getNextTreeTop(), NULL, NULL, -1, node, visitCount))136{137_classFieldInfo->setFirst(0);138_classInfo->setCannotTrustStaticFinal();139comp()->setNeedsClassLookahead(b);140return 2;141}142}143144_inClassInitializerMethod = false;145}146147148ListIterator<TR::ResolvedMethodSymbol> resolvedIt(&initializerMethodsInClass);149TR::ResolvedMethodSymbol *resolvedMethodSymbol = NULL;150resolvedMethod = NULL;151for (resolvedMethodSymbol = resolvedIt.getFirst(); resolvedMethodSymbol; resolvedMethodSymbol = resolvedIt.getNext())152{153_currentMethodSymbol = resolvedMethodSymbol;154resolvedMethod = resolvedMethodSymbol->getResolvedMethod();155if (strncmp(resolvedMethod->nameChars(), "<clinit>", 8))156{157//_inInitializerMethod = false;158//if (findMethod(&initializerMethodsInClass, resolvedMethodSymbol))159{160if (!seenFirstInitializerMethod)161{162_inFirstInitializerMethod = true;163seenFirstInitializerMethod = true;164}165166_inInitializerMethod = true;167if (!_inFirstInitializerMethod)168initializeFieldInfo();169}170171/////fprintf(stderr, "looking at method %s\n", resolvedMethod->nameChars()); fflush(stderr);172TR::TreeTop *startTree = resolvedMethodSymbol->getFirstTreeTop();173_inFirstBlock = true;174vcount_t visitCount = comp()->incVisitCount();175TR::TreeTop *tt;176comp()->resetVisitCounts(0, startTree);177for (tt = startTree; tt; tt = tt->getNextTreeTop())178{179TR::Node *node = tt->getNode();180//dumpOptDetails("Node = %p node vc %d comp vc %d\n", node, node->getVisitCount(), visitCount);181if (!examineNode(tt->getNextTreeTop(), NULL, NULL, -1, node, visitCount))182{183_classFieldInfo->setFirst(0);184_classInfo->setCannotTrustStaticFinal();185comp()->setNeedsClassLookahead(b);186return 2;187}188}189190if (_inInitializerMethod)191{192updateFieldInfo();193_inFirstInitializerMethod = false;194}195}196}197198resolvedIt.set(&resolvedMethodSyms);199resolvedMethodSymbol = NULL;200resolvedMethod = NULL;201for (resolvedMethodSymbol = resolvedIt.getFirst(); resolvedMethodSymbol; resolvedMethodSymbol = resolvedIt.getNext())202{203_currentMethodSymbol = resolvedMethodSymbol;204resolvedMethod = resolvedMethodSymbol->getResolvedMethod();205if (strncmp(resolvedMethod->nameChars(), "<clinit>", 8))206{207if (!findMethod(&initializerMethodsInClass, resolvedMethodSymbol))208{209////fprintf(stderr, "looking at method %s\n", resolvedMethod->nameChars()); fflush(stderr);210_inInitializerMethod = false;211_inFirstInitializerMethod = false;212213TR::TreeTop *startTree = resolvedMethodSymbol->getFirstTreeTop();214_inFirstBlock = true;215vcount_t visitCount = comp()->incVisitCount();216TR::TreeTop *tt;217comp()->resetVisitCounts(0, startTree);218for (tt = startTree; tt; tt = tt->getNextTreeTop())219{220TR::Node *node = tt->getNode();221//dumpOptDetails("Node = %p node vc %d comp vc %d\n", node, node->getVisitCount(), visitCount);222////fprintf(stderr, "looking at node in method %s\n", resolvedMethod->nameChars()); fflush(stderr);223if (!examineNode(tt->getNextTreeTop(), NULL, NULL, -1, node, visitCount))224{225_classFieldInfo->setFirst(0);226_classInfo->setCannotTrustStaticFinal();227comp()->setNeedsClassLookahead(b);228return 2;229}230}231}232}233}234235if (_classFieldInfo->getFirst())236makeInfoPersistent();237238classInfo->setFieldInfo(_classFieldInfo);239240comp()->setNeedsClassLookahead(b);241return 2;242}243244245static bool isCalledByNonConstructorMethodsInClass(TR_ResolvedMethod *calleeMethod, List<TR::ResolvedMethodSymbol> *resolvedMethodSyms)246{247ListIterator<TR::ResolvedMethodSymbol> resolvedIt(resolvedMethodSyms);248TR::ResolvedMethodSymbol *resolvedMethodSymbol;249for (resolvedMethodSymbol = resolvedIt.getFirst(); resolvedMethodSymbol; resolvedMethodSymbol = resolvedIt.getNext())250{251TR_ResolvedMethod *resolvedMethod = resolvedMethodSymbol->getResolvedMethod();252if (!resolvedMethod->isConstructor())253{254for (TR::TreeTop *tt = resolvedMethodSymbol->getFirstTreeTop(); tt; tt = tt->getNextTreeTop())255{256TR::Node *node = tt->getNode();257if (node->getNumChildren() > 0 &&258node->getFirstChild()->getOpCode().isCall() &&259!node->getFirstChild()->getOpCode().isIndirect())260{261TR::Method *calleeMethod1 = node->getFirstChild()->getSymbol()->getMethodSymbol()->getMethod();262if (calleeMethod1 &&263calleeMethod1->nameLength() == calleeMethod->nameLength() &&264calleeMethod1->signatureLength() == calleeMethod->signatureLength() &&265calleeMethod1->classNameLength() == calleeMethod->classNameLength() &&266!strncmp(calleeMethod1->nameChars(), calleeMethod->nameChars(), calleeMethod->nameLength()) &&267!strncmp(calleeMethod1->signatureChars(), calleeMethod->signatureChars(), calleeMethod->signatureLength()) &&268!strncmp(calleeMethod1->classNameChars(), calleeMethod->classNameChars(), calleeMethod->classNameLength()))269return true;270}271}272}273}274275return false;276}277278279280void281TR_ClassLookahead::findInitializerMethods(List<TR_ResolvedMethod> *resolvedMethodsInClass, List<TR::ResolvedMethodSymbol> *initializerMethodsInClass, List<TR::ResolvedMethodSymbol> *resolvedMethodSyms, TR::ResolvedMethodSymbol **classInitializer, bool *peekFailedForAnyMethod)282{283TR_IlGenerator *prevIlGen = comp()->getCurrentIlGenerator();284285ListIterator<TR_ResolvedMethod> resolvedIt(resolvedMethodsInClass);286TR_ResolvedMethod *resolvedMethod;287for (resolvedMethod = resolvedIt.getFirst(); resolvedMethod; resolvedMethod = resolvedIt.getNext())288{289TR::SymbolReference *methodSymRef;290if (resolvedMethod->isStatic())291methodSymRef = _symRefTab->findOrCreateMethodSymbol(JITTED_METHOD_INDEX, -1, resolvedMethod, TR::MethodSymbol::Static);292else293methodSymRef = _symRefTab->findOrCreateMethodSymbol(JITTED_METHOD_INDEX, -1, resolvedMethod, TR::MethodSymbol::Interface);294295TR::ResolvedMethodSymbol *resolvedMethodSymbol = methodSymRef->getSymbol()->castToResolvedMethodSymbol();296if (resolvedMethod->isCompilable(comp()->trMemory()) && !resolvedMethod->isNewInstanceImplThunk() && !resolvedMethod->isJNINative())297{298resolvedMethodSyms->add(resolvedMethodSymbol);299//printf("IL gen succeeded for %s resolvedMethod %x ramMethod %x\n", resolvedMethod->signature(), resolvedMethod, resolvedMethod->getPersistentIdentifier());300_symRefTab->addParameters(resolvedMethodSymbol);301//ilGenSuccess = (0 != TR_J9ByteCodeIlGenerator::genMethodILForPeeking(resolvedMethodSymbol, comp()));302*peekFailedForAnyMethod = (NULL == resolvedMethodSymbol->getResolvedMethod()->genMethodILForPeeking(resolvedMethodSymbol, comp(), true));303}304}305306if (*peekFailedForAnyMethod)307{308comp()->setCurrentIlGenerator(prevIlGen);309return;310}311312ListIterator<TR::ResolvedMethodSymbol> resolvedMethodSymsIt(resolvedMethodSyms);313TR::ResolvedMethodSymbol *resolvedMethodSymbol;314for (resolvedMethodSymbol = resolvedMethodSymsIt.getFirst(); resolvedMethodSymbol; resolvedMethodSymbol = resolvedMethodSymsIt.getNext())315{316resolvedMethod = resolvedMethodSymbol->getResolvedMethod();317if ((resolvedMethod->isConstructor() || (!strncmp(resolvedMethod->nameChars(), "<clinit>", 8))) && resolvedMethodSymbol->getFirstTreeTop())318{319if (!strncmp(resolvedMethod->nameChars(), "<clinit>", 8))320*classInitializer = resolvedMethodSymbol;321else322{323TR::ResolvedMethodSymbol *initializerMethodSymbol = resolvedMethodSymbol;324325TR::TreeTop * tt = resolvedMethodSymbol->getFirstTreeTop()->getNextRealTreeTop();326TR::Node *firstRealNode = tt->getNode();327if (firstRealNode->getOpCodeValue() == TR::treetop)328{329TR::Node *callChild = firstRealNode->getFirstChild();330if ((callChild->getOpCodeValue() == TR::call) &&331!callChild->getSymbolReference()->isUnresolved())332{333TR_ResolvedMethod *calleeMethod = callChild->getSymbol()->castToResolvedMethodSymbol()->getResolvedMethod();334if (!strncmp(calleeMethod->classNameChars(), "java/lang/Object", 16))335{336if (calleeMethod->isConstructor())337{338if (!strncmp(calleeMethod->signatureChars(), "()V", 3))339tt = tt->getNextRealTreeTop();340}341}342}343}344345TR::Node *node = tt->getNode();346if (node->getOpCode().isTreeTop() &&347(node->getNumChildren() > 0))348node = node->getFirstChild();349350if (node->getOpCode().isCall() &&351!node->getOpCode().isIndirect() &&352!node->getSymbolReference()->isUnresolved())353{354TR::ResolvedMethodSymbol *calleeSymbol = node->getSymbol()->castToResolvedMethodSymbol();355TR_ResolvedMethod *calleeMethod = calleeSymbol->getResolvedMethod();356if (calleeMethod->containingClass() == _classPointer &&357(!strncmp(calleeMethod->nameChars(), "<init>", 6) ||358(calleeMethod->isPrivate() &&359!isCalledByNonConstructorMethodsInClass(calleeMethod, resolvedMethodSyms))))360initializerMethodSymbol = calleeSymbol;361}362363//if (!initializerMethodsInClass->find(initializerMethodSymbol))364if (!findMethod(initializerMethodsInClass, initializerMethodSymbol))365initializerMethodsInClass->add(initializerMethodSymbol);366///initializerMethodsInClass->addAfter(initializerMethodSymbol, initializerMethodsInClass->getListHead());367}368}369}370371ListElement<TR::ResolvedMethodSymbol> *initMethodSymElem = initializerMethodsInClass->getListHead();372while (initMethodSymElem)373{374TR::ResolvedMethodSymbol *initMethodSym = initMethodSymElem->getData();375if (!resolvedMethodSyms->find(initMethodSym))376{377ListIterator<TR::ResolvedMethodSymbol> resolvedIt(resolvedMethodSyms);378TR::ResolvedMethodSymbol *resolvedMethodSym;379for (resolvedMethodSym = resolvedIt.getFirst(); resolvedMethodSym; resolvedMethodSym = resolvedIt.getNext())380{381if (resolvedMethodSym->getResolvedMethod()->isSameMethod(initMethodSym->getResolvedMethod()))382{383initMethodSymElem->setData(resolvedMethodSym);384break;385}386}387}388389initMethodSymElem = initMethodSymElem->getNextElement();390}391392comp()->setCurrentIlGenerator(prevIlGen);393}394395396397398399400401bool402TR_ClassLookahead::examineNode(TR::TreeTop *nextTree, TR::Node *grandParent, TR::Node *parent, int32_t childNum, TR::Node *node, vcount_t visitCount)403{404if (node->getVisitCount() == visitCount)405{406if (node->getOpCode().isLoadVar())407invalidateIfEscapingLoad(nextTree, grandParent, parent, childNum, node);408return true;409}410411if (node->getOpCode().isStore())412{413TR::SymbolReference *storedSymRef = node->getSymbolReference();414TR::Symbol *sym = storedSymRef->getSymbol();415//dumpOptDetails("Store node %p fieldInfo %p\n", node, fieldInfo);416417if (isProperFieldAccess(node))418{419//dumpOptDetails("Proper store node %p fieldInfo %p\n", node, fieldInfo);420int32_t childAdjust = (node->getOpCode().isWrtBar()) ? 2 : 1;421TR::Node *rhsOfStoreNode = node->getChild(node->getNumChildren() - childAdjust);422423bool isConstantLengthArrayAllocation = false;424bool isInitialized = false;425int32_t numberOfDimensions = -1;426int32_t firstDimensionChild = 0;427int32_t firstConstantLengthArrayDim = -1;428int32_t rhsNumChildren = rhsOfStoreNode->getNumChildren();429const char *sig = NULL;430int32_t length = 0;431bool isNewArray = true;432433if ((rhsOfStoreNode->getOpCodeValue() == TR::newarray) ||434(rhsOfStoreNode->getOpCodeValue() == TR::anewarray) ||435(rhsOfStoreNode->getOpCodeValue() == TR::multianewarray))436{437if (rhsOfStoreNode->getOpCodeValue() == TR::multianewarray)438{439firstDimensionChild = 1;440numberOfDimensions = rhsOfStoreNode->getFirstChild()->getInt();441}442else443{444numberOfDimensions = 1;445446if (rhsOfStoreNode->getOpCodeValue() == TR::anewarray)447{448// TODO: Do not consider types for arrays yet; have to449// be careful when appending '[' correct number of times450// for compatibility with constant propagation.451//452//453//sig = rhsOfStoreNode->getSecondChild()->getSymbolReference()->getTypeSignature(length);454}455}456457int32_t j;458for (j=firstDimensionChild;j<rhsNumChildren - 1;j++)459{460TR::Node *rhsChild = rhsOfStoreNode->getChild(j);461if (rhsChild->getOpCodeValue() == TR::iconst)462{463isConstantLengthArrayAllocation = true;464firstConstantLengthArrayDim = j;465break;466}467}468}469else if (rhsOfStoreNode->getOpCodeValue() == TR::New)470{471isNewArray = false;472sig = rhsOfStoreNode->getFirstChild()->getSymbolReference()->getTypeSignature(length);473}474else475isNewArray = false;476477// if this is a store to an arrayfield and a fieldInfo already478// exists (say created via a store seen in another ctor), then479// invalidate the fieldInfo480//481// check for stores of aconst null482//483bool canMorph = false;484if (rhsOfStoreNode->getOpCodeValue() == TR::aconst &&485rhsOfStoreNode->getInt() == 0)486canMorph = true;487488TR_PersistentFieldInfo *fieldInfo = NULL;489490if (isNewArray)491fieldInfo = getExistingArrayFieldInfo(sym, storedSymRef);492else493fieldInfo = getExistingFieldInfo(sym, storedSymRef, canMorph);494495//496// TODO: remove restriction on number of dimensions497//498if (fieldInfo &&499!storedSymRef->isUnresolved() &&500(sym->isPrivate() ||501sym->isFinal()))502{503if (fieldInfo->isTypeInfoValid())504{505bool isClassPtrInitialized = false;506bool classPtrSame = true;507if (_inFirstBlock &&508_inInitializerMethod)509{510int32_t oldNumChars = fieldInfo->getNumChars();511if (oldNumChars > -1)512{513if (length != oldNumChars)514classPtrSame = false;515else516classPtrSame = (memcmp(sig, fieldInfo->getClassPointer(), length) == 0);517}518else519{520isClassPtrInitialized = true;521}522}523else524classPtrSame = false;525526if (classPtrSame || isClassPtrInitialized)527{528if (isClassPtrInitialized)529{530//char *persistentSig = (char *)TR_Memory::jitPersistentAlloc(length);531//memcpy(persistentSig, sig, length);532//fieldInfo->setClassPointer(persistentSig);533fieldInfo->setClassPointer(sig);534}535536fieldInfo->setNumChars(length);537if (_inClassInitializerMethod)538{539if (_traceIt)540traceMsg(comp(), "CStatically initializing type info for symbol %x at node %x\n", sym, node);541fieldInfo->setIsTypeInfoValid(VALID_AND_INITIALIZED_STATICALLY);542}543else544{545if (fieldInfo->isTypeInfoValid() == VALID_AND_INITIALIZED_STATICALLY)546{547if (!_inFirstInitializerMethod &&548!sym->isStatic())549{550if (_traceIt)551traceMsg(comp(), "C0Not always initializing type info for symbol %x at node %x\n", sym, node);552fieldInfo->setIsTypeInfoValid(VALID_BUT_NOT_ALWAYS_INITIALIZED);553}554else555{556if (!sym->isStatic())557{558if (_traceIt)559traceMsg(comp(), "C0Always initializing type info for symbol %x at node %x\n", sym, node);560fieldInfo->setIsTypeInfoValid(VALID_AND_ALWAYS_INITIALIZED);561}562}563}564else565{566if (!sym->isStatic())567{568if (_traceIt)569traceMsg(comp(), "C1Always initializing type info for symbol %x at node %x\n", sym, node);570fieldInfo->setIsTypeInfoValid(VALID_AND_ALWAYS_INITIALIZED);571}572else573{574if (_traceIt)575traceMsg(comp(), "C0Invalidating type info for symbol %x at node %x\n", sym, node);576fieldInfo->setIsTypeInfoValid(INVALID);577}578}579}580}581else582{583if (_traceIt)584traceMsg(comp(), "C0Invalidating type info for symbol %x at node %x\n", sym, node);585fieldInfo->setIsTypeInfoValid(INVALID);586}587}588589TR_PersistentArrayFieldInfo *arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();590if (isNewArray &&591arrayFieldInfo &&592isConstantLengthArrayAllocation &&593(numberOfDimensions <= 2))594{595int32_t oldNumDimensions = arrayFieldInfo->getNumDimensions();596if (oldNumDimensions > -1)597{598if (arrayFieldInfo->isDimensionInfoValid())599{600if (oldNumDimensions != numberOfDimensions)601{602// Same field is assigned different dimension arrays603// at different program points within this class.604//605if (_traceIt)606traceMsg(comp(), "0Invalidating dimension info for symbol %x at node %x\n", sym, node);607arrayFieldInfo->setIsDimensionInfoValid(INVALID);608}609}610}611else612{613isInitialized = true;614arrayFieldInfo->prepareArrayFieldInfo(numberOfDimensions, comp());615}616617if (arrayFieldInfo->isDimensionInfoValid())618{619// Invalidate the dimensions that are known to be620// non constants at this stage621//622int32_t k;623for (k=0;k<firstConstantLengthArrayDim - firstDimensionChild;k++)624arrayFieldInfo->setDimensionInfo(k, -1);625626for (;k<(rhsNumChildren - 1 - firstDimensionChild);k++)627{628TR::Node *rhsChild = rhsOfStoreNode->getChild(k+firstDimensionChild);629if (_inFirstBlock &&630_inInitializerMethod &&631(rhsChild->getOpCodeValue() == TR::iconst) &&632((rhsChild->getInt() == arrayFieldInfo->getDimensionInfo(k)) ||633isInitialized))634{635arrayFieldInfo->setDimensionInfo(k, rhsChild->getInt());636if (_inClassInitializerMethod)637{638if (_traceIt)639traceMsg(comp(), "Statically initializing dimension info for symbol %x at node %x\n", sym, node);640arrayFieldInfo->setIsDimensionInfoValid(VALID_AND_INITIALIZED_STATICALLY);641}642else643{644if (arrayFieldInfo->isDimensionInfoValid() == VALID_AND_INITIALIZED_STATICALLY)645{646if (!_inFirstInitializerMethod &&647!sym->isStatic())648{649if (_traceIt)650traceMsg(comp(), "0Not always initializing dimension info for symbol %x at node %x\n", sym, node);651arrayFieldInfo->setIsDimensionInfoValid(VALID_BUT_NOT_ALWAYS_INITIALIZED);652}653else654{655if (!sym->isStatic())656{657if (_traceIt)658traceMsg(comp(), "0Always initializing dimension info for symbol %x at node %x\n", sym, node);659arrayFieldInfo->setIsDimensionInfoValid(VALID_AND_ALWAYS_INITIALIZED);660}661}662}663else664{665if (!sym->isStatic())666{667if (_traceIt)668traceMsg(comp(), "1Always initializing dimension info for symbol %x at node %x\n", sym, node);669arrayFieldInfo->setIsDimensionInfoValid(VALID_AND_ALWAYS_INITIALIZED);670}671else672{673if (_traceIt)674traceMsg(comp(), "C0Invalidating dimension info for symbol %x at node %x\n", sym, node);675arrayFieldInfo->setIsDimensionInfoValid(INVALID);676}677}678}679}680else681{682if (_traceIt)683traceMsg(comp(), "C1Invalidating dimension info for symbol %x at node %x\n", sym, node);684arrayFieldInfo->setIsDimensionInfoValid(INVALID);685arrayFieldInfo->setDimensionInfo(k, -1);686}687}688}689}690else if (arrayFieldInfo)691{692// Not a constant length allocation event693//694if (_traceIt)695traceMsg(comp(), "1Invalidating dimension info for symbol %x at node %x\n", sym, node);696arrayFieldInfo->setIsDimensionInfoValid(INVALID);697}698}699else if (fieldInfo)700{701// It is a store to this array field but not an allocation event702//703if (_traceIt)704traceMsg(comp(), "1Invalidating dimension and type info for symbol %x at node %x(%s)\n", sym, node, node->getOpCode().getName());705706fieldInfo->setIsTypeInfoValid(INVALID);707TR_PersistentArrayFieldInfo *arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();708if (arrayFieldInfo)709arrayFieldInfo->setIsDimensionInfoValid(INVALID);710else711fieldInfo->setCanChangeToArray(false);712}713}714else if ((sym->isShadow() ||715sym->isStatic()) &&716!storedSymRef->isUnresolved() &&717(sym->isPrivate() ||718sym->isFinal()))719{720TR_PersistentFieldInfo *fieldInfo = getExistingFieldInfo(sym, storedSymRef, false);721722if (fieldInfo)723{724if (_traceIt)725traceMsg(comp(), "2Invalidating dimension and type info for symbol %x at node %x\n", sym, node);726727fieldInfo->setIsTypeInfoValid(INVALID);728TR_PersistentArrayFieldInfo *arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();729if (arrayFieldInfo)730arrayFieldInfo->setIsDimensionInfoValid(INVALID);731}732}733734if (sym->isStatic() && sym->isFinal() && !_inClassInitializerMethod)735_classInfo->setCannotTrustStaticFinal();736737if (isPrivateFieldAccess(node) || isProperFieldAccess(node))738{739//int32_t length = 0;740//char *sig = TR_ClassLookahead::getFieldSignature(comp(), sym, storedSymRef, length);741742TR_PersistentFieldInfo *previousFieldInfo = _classFieldInfo->find(comp(), sym, storedSymRef);743TR_PersistentFieldInfo *fieldInfo = previousFieldInfo;744if (!fieldInfo)745{746fieldInfo = getExistingFieldInfo(sym, storedSymRef);747if (fieldInfo)748{749fieldInfo->setIsTypeInfoValid(INVALID);750TR_PersistentArrayFieldInfo *arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();751if (arrayFieldInfo)752arrayFieldInfo->setIsDimensionInfoValid(INVALID);753else754fieldInfo->setCanChangeToArray(false);755}756}757758//if (isProperFieldAccess(node))759{760if (fieldInfo)761{762if (!_inInitializerMethod && !_inClassInitializerMethod)763{764fieldInfo->setImmutable(false);765}766767int32_t childAdjust = (node->getOpCode().isWrtBar()) ? 2 : 1;768TR::Node *rhsOfStoreNode = node->getChild(node->getNumChildren() - childAdjust);769770int32_t length;771char *sig = getFieldSignature(comp(), sym, storedSymRef, length);772773if (rhsOfStoreNode->getOpCode().isCall() &&774rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol())775{776if (rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_valueOf)777{778//fprintf(stderr, "0Resetting big integer property for %s in %s\n", sig, _currentMethodSymbol->getResolvedMethod()->nameChars()); fflush(stderr);779fieldInfo->setBigIntegerType(false);780}781else if ((rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_add) ||782(rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_subtract) ||783(rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_multiply))784{785//fprintf(stderr, "1Resetting big integer property for %s in %s\n", sig, _currentMethodSymbol->getResolvedMethod()->nameChars()); fflush(stderr);786fieldInfo->setBigIntegerType(false);787}788else if ((rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigInteger_add) ||789(rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigInteger_subtract) ||790(rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigInteger_multiply))791{792fieldInfo->setBigDecimalType(false);793}794}795else796{797if (rhsOfStoreNode->getOpCode().isLoadVar() &&798rhsOfStoreNode->getSymbolReference()->getSymbol()->isStatic())799{800TR::Symbol::RecognizedField field = rhsOfStoreNode->getSymbolReference()->getSymbol()->getRecognizedField();801802if (field != TR::Symbol::Java_math_BigInteger_ZERO)803{804//fprintf(stderr, "2Resetting big integer property for %s in %s\n", sig, _currentMethodSymbol->getResolvedMethod()->nameChars()); fflush(stderr);805fieldInfo->setBigIntegerType(false);806}807else808{809//fprintf(stderr, "Found load of big integer ZERO in for %s (big integer type %d) in %s compiling %s\n", sig, fieldInfo->isBigIntegerType(), _currentMethodSymbol->getResolvedMethod()->nameChars(), comp()->signature()); fflush(stderr);810}811}812else813{814//fprintf(stderr, "3Resetting big integer property for %s in %s\n", sig, _currentMethodSymbol->getResolvedMethod()->nameChars()); fflush(stderr);815fieldInfo->setBigIntegerType(false);816}817818fieldInfo->setBigDecimalType(false);819}820}821}822}823}824else if (node->getOpCode().isLoadVar())825invalidateIfEscapingLoad(nextTree, grandParent, parent, childNum, node);826else if (node->getOpCodeValue() == TR::BBEnd)827_inFirstBlock = false;828829if (node->getOpCode().isCall())830{831TR::Method *calleeMethod = node->getSymbol()->castToMethodSymbol()->getMethod();832if (calleeMethod != NULL && !strncmp(calleeMethod->classNameChars(), "java/lang/reflect", 17))833return false;834}835836node->setVisitCount(visitCount);837838int32_t i;839int32_t numChildren = node->getNumChildren();840for (i=0;i<numChildren;i++)841{842if (!examineNode(nextTree, parent, node, i, node->getChild(i), visitCount))843return false;844}845846return true;847}848849850static bool isArithmeticForSameField(TR::Node *treeNode, TR::Node *grandParent, TR::Node *parent, TR::Node *node)851{852if ((node->getOpCodeValue() != TR::iloadi) &&853(node->getOpCodeValue() != TR::lloadi) &&854(node->getOpCodeValue() != TR::iload) &&855(node->getOpCodeValue() != TR::lload))856return false;857858if (parent->getReferenceCount() != 1)859return false;860861if (!grandParent)862return false;863864TR::Node *storeNode = NULL;865if (!grandParent->getOpCode().isStore())866{867if (grandParent->getOpCode().isConversion())868{869if (treeNode->getOpCodeValue() == TR::treetop ||870treeNode->getOpCode().isNullCheck())871treeNode = treeNode->getFirstChild();872873if (treeNode->getOpCode().isStore())874{875TR::Node *valueChild = NULL;876if (treeNode->getOpCode().isIndirect())877valueChild = treeNode->getSecondChild();878else879valueChild = treeNode->getFirstChild();880881if (valueChild->getOpCode().isConversion() &&882(valueChild->getReferenceCount() == 1) &&883valueChild->getFirstChild()->getOpCode().isConversion() &&884(valueChild->getFirstChild()->getReferenceCount() == 1) &&885(grandParent == valueChild->getFirstChild()) &&886(treeNode->getDataType() == parent->getDataType()))887{888// Tree matches for update of byte/char/short datatype889storeNode = treeNode;890}891else892return false;893}894else895return false;896}897else898return false;899}900else901{902if (grandParent->getOpCode().isIndirect() &&903(grandParent->getSecondChild() != parent))904return false;905906storeNode = grandParent;907}908909910if ((parent->getOpCodeValue() == TR::iadd) ||911(parent->getOpCodeValue() == TR::isub) ||912(parent->getOpCodeValue() == TR::imul))913{914if (node->getOpCodeValue() == TR::iloadi)915{916if (storeNode->getOpCodeValue() == TR::istorei)917{918if (storeNode->getSymbolReference() == node->getSymbolReference())919{920if (storeNode->getFirstChild()->getOpCodeValue() == node->getFirstChild()->getOpCodeValue())921{922if ((storeNode->getFirstChild() == node->getFirstChild()) ||923(storeNode->getFirstChild()->getSymbolReference() == node->getFirstChild()->getSymbolReference()))924return true;925}926}927}928}929else if ((node->getOpCodeValue() == TR::iload) &&930(storeNode->getOpCodeValue() == TR::istore) &&931(storeNode->getSymbolReference() == node->getSymbolReference()))932return true;933}934else if ((parent->getOpCodeValue() == TR::ladd) ||935(parent->getOpCodeValue() == TR::lsub) ||936(parent->getOpCodeValue() == TR::lmul))937{938if (node->getOpCodeValue() == TR::lloadi)939{940if (storeNode->getOpCodeValue() == TR::lstorei)941{942if (storeNode->getSymbolReference() == node->getSymbolReference())943{944if (storeNode->getFirstChild()->getOpCodeValue() == node->getFirstChild()->getOpCodeValue())945{946if ((storeNode->getFirstChild() == node->getFirstChild()) ||947(storeNode->getFirstChild()->getSymbolReference() == node->getFirstChild()->getSymbolReference()))948return true;949}950}951}952}953else if ((node->getOpCodeValue() == TR::lload) &&954(storeNode->getOpCodeValue() == TR::lstore) &&955(storeNode->getSymbolReference() == node->getSymbolReference()))956return true;957}958959return false;960}961962963static bool isPureBigDecimalMethod(TR::Node *node, TR::Compilation *comp, TR_PersistentFieldInfo *fieldInfo, bool & isBigDecimal, bool & isBigInteger)964{965if (!node)966return false;967968//fprintf(stderr, "0Calling isPure %s\n", node->getOpCode().getName()); fflush(stderr);969//if (node->getOpCodeValue() == TR::aloadi)970// {971// fprintf(stderr, "node sym ref %p offset %d vft %p\n", node->getSymbolReference(), node->getSymbolReference()->getOffset(), comp->getSymRefTab()->findVftSymbolRef());972// }973974975if (node->getOpCodeValue() != TR::acalli)976{977//fprintf(stderr, "1Returning false from isPure %s\n", node->getOpCode().getName()); fflush(stderr);978return false;979}980981if (node->getSymbolReference()->isUnresolved())982{983//fprintf(stderr, "2Returning false from isPure\n"); fflush(stderr);984return false;985}986987if ((fieldInfo->isBigDecimalType() &&988((node->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_add) ||989(node->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_subtract) ||990(node->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_multiply))))991{992isBigDecimal = true;993return true;994}995996997if ((fieldInfo->isBigIntegerType() &&998((node->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigInteger_add) ||999(node->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigInteger_subtract) ||1000(node->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigInteger_multiply))))1001{1002isBigInteger = true;1003return true;1004}10051006//fprintf(stderr, "is big decimal %d is big integer %d\n", fieldInfo->isBigDecimalType(), fieldInfo->isBigIntegerType());1007return false;1008}100910101011static bool isStoreToSameField(TR::Node *callNode, TR::Node *nextNode, TR::Node *loadNode)1012{1013if (callNode->getReferenceCount() == 2)1014{1015if (nextNode->getOpCodeValue() == TR::treetop ||1016nextNode->getOpCode().isNullCheck())1017nextNode = nextNode->getFirstChild();10181019if ((nextNode->getOpCodeValue() == TR::awrtbari) ||1020(nextNode->getOpCodeValue() == TR::astorei))1021{1022if (nextNode->getSymbolReference() == loadNode->getSymbolReference())1023{1024if (nextNode->getFirstChild()->getOpCodeValue() == loadNode->getFirstChild()->getOpCodeValue())1025{1026if ((nextNode->getFirstChild() == loadNode->getFirstChild()) ||1027(nextNode->getFirstChild()->getSymbolReference() == loadNode->getFirstChild()->getSymbolReference()))1028{1029if (nextNode->getSecondChild() == callNode)1030return true;1031}1032}1033}1034}1035else if ((nextNode->getOpCodeValue() == TR::awrtbar) ||1036(nextNode->getOpCodeValue() == TR::astore))1037{1038if (nextNode->getSymbolReference() == loadNode->getSymbolReference())1039{1040if (nextNode->getFirstChild() == callNode)1041return true;1042}1043}1044}10451046return false;1047}104810491050void TR_ClassLookahead::invalidateIfEscapingLoad(TR::TreeTop *nextTree, TR::Node *grandParent, TR::Node *parent, int32_t childNum, TR::Node *node)1051{1052TR::SymbolReference *storedSymRef = node->getSymbolReference();1053TR::Symbol *sym = storedSymRef->getSymbol();10541055//fprintf(stderr, "Check escaping load for node %s\n", node->getOpCode().getName()); fflush(stderr);10561057if ((sym->isShadow() ||1058sym->isStatic()) &&1059(storedSymRef->isUnresolved() ||1060(sym->isPrivate() ||1061sym->isFinal())))1062{1063//fprintf(stderr, "2Check escaping load for node %s\n", node->getOpCode().getName()); fflush(stderr);1064TR_PersistentFieldInfo *previousFieldInfo = _classFieldInfo->find(comp(), sym, storedSymRef);1065TR_PersistentFieldInfo *fieldInfo = previousFieldInfo;1066if (!fieldInfo)1067{1068fieldInfo = getExistingFieldInfo(sym, storedSymRef);1069//fprintf(stderr, "Check escaping load for fieldInfo %p\n", fieldInfo); fflush(stderr);1070if (fieldInfo)1071{1072fieldInfo->setIsTypeInfoValid(INVALID);1073TR_PersistentArrayFieldInfo *arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();1074if (arrayFieldInfo)1075arrayFieldInfo->setIsDimensionInfoValid(INVALID);1076else1077fieldInfo->setCanChangeToArray(false);1078}1079}10801081TR_PersistentArrayFieldInfo *arrayFieldInfo = NULL;1082if (fieldInfo)1083{1084int32_t length;1085char *sig = getFieldSignature(comp(), sym, storedSymRef, length);1086/////fprintf(stderr, "Check NOT read for field sig %s\n", sig); fflush(stderr);10871088bool knownRead = false;1089bool isBigDecimal = false;1090bool isBigInteger = false;10911092if (sym->isStatic() ||1093(sym->isShadow() &&1094node->getFirstChild()->isThisPointer()))1095{1096bool refCountMatches = false;1097int32_t refCount = 2;1098int32_t extraRefCount = comp()->useAnchors() ? 1 : 0;1099if ((node->getReferenceCount() == (refCount + extraRefCount)) ||1100(node->getReferenceCount() == (refCount + extraRefCount)))1101refCountMatches = true;11021103if (refCountMatches)1104{1105if (parent &&1106((parent->getOpCodeValue() == TR::treetop) || parent->getOpCode().isAnchor()))1107knownRead = true;11081109if (isPureBigDecimalMethod(parent, comp(), fieldInfo, isBigDecimal, isBigInteger) && (childNum == 1) &&1110(parent->getFirstChild()->getOpCodeValue() == TR::aloadi) &&1111(parent->getFirstChild()->getFirstChild() == node))1112{1113if ((parent->getReferenceCount() == 1) ||1114isStoreToSameField(parent, nextTree->getNode(), node))1115knownRead = true;1116}11171118if (parent && (parent->getOpCodeValue() == TR::aloadi) && comp()->getSymRefTab()->findVftSymbolRef() &&1119(parent->getSymbolReference()->getOffset() == comp()->getSymRefTab()->findVftSymbolRef()->getOffset()) &&1120isPureBigDecimalMethod(grandParent, comp(), fieldInfo, isBigDecimal, isBigInteger) &&1121(grandParent->getSecondChild() == node))1122{1123if ((grandParent->getReferenceCount() == 1) ||1124isStoreToSameField(grandParent, nextTree->getNode(), node))1125knownRead = true;1126}1127}1128else if (node->getReferenceCount() == 1)1129{1130if (isArithmeticForSameField(nextTree->getPrevTreeTop()->getNode(), grandParent, parent, node))1131knownRead = true;1132}1133}11341135if (!isBigDecimal)1136fieldInfo->setBigDecimalType(false);1137if (!isBigInteger)1138fieldInfo->setBigIntegerType(false);11391140if (!knownRead)1141{1142////int32_t length;1143////char *sig = getFieldSignature(comp(), sym, storedSymRef, length);1144////fprintf(stderr, "%s is read after all\n", sig); fflush(stderr);1145////traceMsg(comp(), "Field %s is read after all in node %p\n", sig, node);11461147fieldInfo->setNotRead(false);1148}1149else1150{1151if (isBigDecimal)1152fieldInfo->setBigDecimalAssumption(true);11531154if (isBigInteger)1155fieldInfo->setBigIntegerAssumption(true);1156}115711581159if (storedSymRef->isUnresolved() ||1160(sym->isPrivate() &&1161!sym->isFinal()))1162arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();1163}11641165if (arrayFieldInfo)1166{1167if (!parent ||1168((!parent->isInternalPointer()) &&1169(parent->getOpCodeValue() != TR::treetop) &&1170(!parent->getOpCode().isArrayLength()) &&1171(!parent->getOpCode().isAnchor()) &&1172(parent->getOpCodeValue() != TR::ArrayStoreCHK) &&1173((parent->getOpCodeValue() != TR::awrtbari) || (childNum != 2))))1174{1175if (_traceIt)1176traceMsg(comp(), "2Invalidating dimension and type info for symbol %x at node %x\n", sym, node);1177arrayFieldInfo->setIsDimensionInfoValid(INVALID);1178arrayFieldInfo->setIsTypeInfoValid(INVALID);1179}1180}1181}1182}1183118411851186bool TR_ClassLookahead::isProperFieldAccess(TR::Node *node)1187{1188TR::SymbolReference *storedSymRef = node->getSymbolReference();1189TR::Symbol *sym = storedSymRef->getSymbol();1190if (((sym->isShadow() &&1191node->getFirstChild()->isThisPointer()) ||1192(sym->isStatic() && sym->isFinal())) &&1193!storedSymRef->isUnresolved() &&1194(sym->isPrivate() ||1195sym->isFinal()))1196return true;11971198return false;1199}120012011202bool TR_ClassLookahead::isPrivateFieldAccess(TR::Node *node)1203{1204TR::SymbolReference *storedSymRef = node->getSymbolReference();1205TR::Symbol *sym = storedSymRef->getSymbol();1206if ((sym->isShadow() ||1207(sym->isStatic() && sym->isFinal())) &&1208!storedSymRef->isUnresolved() &&1209sym->isPrivate())1210return true;12111212return false;1213}121412151216bool TR_ClassLookahead::findMethod(List<TR::ResolvedMethodSymbol> *methodSyms, TR::ResolvedMethodSymbol *methodSym)1217{1218ListIterator<TR::ResolvedMethodSymbol> methodsIt(methodSyms);1219TR_ResolvedMethod *method = methodSym->getResolvedMethod();1220TR::ResolvedMethodSymbol *cursorMethodSym;1221for (cursorMethodSym = methodsIt.getFirst(); cursorMethodSym; cursorMethodSym = methodsIt.getNext())1222{1223if (cursorMethodSym->getResolvedMethod()->isSameMethod(method))1224return true;1225}1226return false;1227}122812291230char *TR_ClassLookahead::getFieldSignature(TR::Compilation *comp, TR::Symbol *sym, TR::SymbolReference *symRef, int32_t &length)1231{1232if (!symRef->isUnresolved() ||1233!sym->isStatic() ||1234!sym->isConstObjectRef())1235{1236char *sig = NULL;1237if (sym->isStatic())1238sig = symRef->getOwningMethod(comp)->staticName(symRef->getCPIndex(), length, comp->trMemory());1239else if (sym->isShadow())1240sig = symRef->getOwningMethod(comp)->fieldName(symRef->getCPIndex(), length, comp->trMemory());12411242return sig;1243}12441245length = -1;1246return NULL;1247}124812491250void TR_PersistentArrayFieldInfo::prepareArrayFieldInfo(int32_t numDimensions, TR::Compilation * comp)1251{1252setNumDimensions(numDimensions);1253//int32_t *newDimensionInfo = (int32_t *)jitPersistentAlloc(numDimensions*sizeof(int32_t));1254int32_t *newDimensionInfo = (int32_t *)comp->trMemory()->allocateHeapMemory(numDimensions*sizeof(int32_t));1255memset(newDimensionInfo, 0xFF, numDimensions*sizeof(int32_t));1256setDimensionInfo(newDimensionInfo);1257}12581259TR_PersistentArrayFieldInfo *TR_ClassLookahead::getExistingArrayFieldInfo(TR::Symbol *fieldSym, TR::SymbolReference *fieldSymRef)1260{1261TR::ClassTableCriticalSection getExistingArrayFieldInfo(comp()->fej9());12621263TR_PersistentFieldInfo *newFieldInfo = _classFieldInfo->find(comp(), fieldSym, fieldSymRef);1264TR_PersistentArrayFieldInfo *newArrayFieldInfo = NULL;1265if (newFieldInfo)1266newArrayFieldInfo = newFieldInfo->asPersistentArrayFieldInfo();12671268if (!newArrayFieldInfo /* &&1269(_inFirstInitializerMethod || _inClassInitializerMethod) */)1270{1271int32_t length = 0;1272char *sig = TR_ClassLookahead::getFieldSignature(comp(), fieldSym, fieldSymRef, length);1273if (length > -1)1274{1275//char *persistentSig = (char *)TR_Memory::jitPersistentAlloc(length);1276//memcpy(persistentSig, sig, length);1277//printf("Creating persistent info for array field %s\n", sig);1278//newArrayFieldInfo = new (PERSISTENT_NEW) TR_PersistentArrayFieldInfo(persistentSig, length);1279newArrayFieldInfo = new (comp()->trHeapMemory()) TR_PersistentArrayFieldInfo(sig, length);1280if (newFieldInfo)1281{1282if (newFieldInfo->canChangeToArray())1283{1284newArrayFieldInfo->copyData(newFieldInfo);1285_classFieldInfo->remove(newFieldInfo);1286}1287else1288{1289traceMsg(comp(), "fieldInfo %p exists already for array field %s, so cannot morph\n", newFieldInfo, sig);1290newArrayFieldInfo = NULL;1291newFieldInfo->setIsTypeInfoValid(INVALID);1292}1293}12941295if (newArrayFieldInfo)1296_classFieldInfo->add(newArrayFieldInfo);1297}1298}12991300return newArrayFieldInfo;1301}130213031304TR_PersistentFieldInfo *TR_ClassLookahead::getExistingFieldInfo(TR::Symbol *fieldSym, TR::SymbolReference *fieldSymRef, bool canMorph)1305{1306TR::ClassTableCriticalSection getExistingFieldInfo(comp()->fej9());13071308TR_PersistentFieldInfo *newFieldInfo = _classFieldInfo->find(comp(), fieldSym, fieldSymRef);1309if (!newFieldInfo /* &&1310(_inFirstInitializerMethod || _inClassInitializerMethod) */)1311{1312int32_t length = 0;1313char *sig = TR_ClassLookahead::getFieldSignature(comp(), fieldSym, fieldSymRef, length);1314if (length > -1)1315{1316//char *persistentSig = (char *)TR_Memory::jitPersistentAlloc(length);1317//memcpy(persistentSig, sig, length);1318//printf("Creating persistent info for field %s\n", sig);1319//newFieldInfo = new (PERSISTENT_NEW) TR_PersistentFieldInfo(persistentSig, length);1320newFieldInfo = new (comp()->trHeapMemory()) TR_PersistentFieldInfo(sig, length);1321if (!canMorph)1322newFieldInfo->setCanChangeToArray(false);1323_classFieldInfo->add(newFieldInfo);1324}1325}13261327return newFieldInfo;1328}132913301331void TR_ClassLookahead::makeInfoPersistent()1332{1333TR::ClassTableCriticalSection makeInfoPersistent(comp()->fej9());13341335TR_PersistentFieldInfo *fieldInfo = _classFieldInfo->getFirst();1336TR_PersistentFieldInfo *prevInfo = NULL;13371338while (fieldInfo)1339{1340bool isTypeInfoValid = fieldInfo->isTypeInfoValid();1341bool isDimensionInfoValid = false;1342TR_PersistentArrayFieldInfo *arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();1343if (arrayFieldInfo &&1344arrayFieldInfo->isDimensionInfoValid())1345isDimensionInfoValid = true;1346bool isImmutable = fieldInfo->isImmutable();1347bool isNotRead = fieldInfo->isNotRead();1348bool isBigDecimalType = fieldInfo->isBigDecimalType();1349bool isBigIntegerType = fieldInfo->isBigIntegerType();1350bool hasBigDecimalAssumption = fieldInfo->hasBigDecimalAssumption();1351bool hasBigIntegerAssumption = fieldInfo->hasBigIntegerAssumption();13521353TR_PersistentFieldInfo *newFieldInfo = NULL;1354if (isTypeInfoValid || isDimensionInfoValid || isImmutable || (isNotRead && ((!hasBigDecimalAssumption || isBigDecimalType) && (!hasBigIntegerAssumption || isBigIntegerType))))1355{1356//if (isImmutable &&1357// (!isTypeInfoValid && !isDimensionInfoValid))1358// {1359// printf("Type info and dimension info are invalid but field %s is immutable \n", fieldInfo->getFieldSignature());1360// fflush(stdout);1361// }13621363int32_t length = fieldInfo->getFieldSignatureLength();1364char *persistentSig = (char *)jitPersistentAlloc(length);1365memcpy(persistentSig, fieldInfo->getFieldSignature(), length);1366if (arrayFieldInfo)1367{1368if (_traceIt)1369printf("Creating persistent info for array field %s\n", persistentSig);1370newFieldInfo = new (PERSISTENT_NEW) TR_PersistentArrayFieldInfo(*arrayFieldInfo);1371}1372else1373{1374if (_traceIt)1375printf("Creating persistent info for field %s\n", persistentSig);1376newFieldInfo = new (PERSISTENT_NEW) TR_PersistentFieldInfo(*fieldInfo);1377}13781379newFieldInfo->setFieldSignature(persistentSig);1380newFieldInfo->setFieldSignatureLength(length);13811382char *persistentType = 0;1383if (isTypeInfoValid)1384{1385length = fieldInfo->getNumChars();1386persistentType = (char *)jitPersistentAlloc(length);1387memcpy(persistentType, fieldInfo->getClassPointer(), length);1388}1389newFieldInfo->setClassPointer(persistentType);13901391if (arrayFieldInfo)1392{1393TR_PersistentArrayFieldInfo *newArrayFieldInfo = newFieldInfo->asPersistentArrayFieldInfo();1394int32_t numDimensions = arrayFieldInfo->getNumDimensions();1395if (arrayFieldInfo->getDimensionInfo())1396{1397int32_t *newDimensionInfo = (int32_t *)jitPersistentAlloc(numDimensions*sizeof(int32_t));1398memcpy(newDimensionInfo, arrayFieldInfo->getDimensionInfo(), numDimensions*sizeof(int32_t));1399newArrayFieldInfo->setDimensionInfo(newDimensionInfo);1400}1401}14021403if (prevInfo)1404prevInfo->setNext(newFieldInfo);1405else1406_classFieldInfo->setFirst(newFieldInfo);1407prevInfo = newFieldInfo;1408}1409else1410{1411if (prevInfo)1412prevInfo->setNext(fieldInfo->getNext());1413else1414_classFieldInfo->setFirst(fieldInfo->getNext());1415}14161417fieldInfo = fieldInfo->getNext();1418}1419}142014211422TR_PersistentFieldInfo *TR_PersistentClassInfoForFields::find(TR::Compilation *comp, TR::Symbol *fieldSym, TR::SymbolReference *fieldSymRef)1423{1424int32_t length = 0;1425char *sig = TR_ClassLookahead::getFieldSignature(comp, fieldSym, fieldSymRef, length);14261427TR::ClassTableCriticalSection findFields(comp->fej9());1428for (TR_PersistentFieldInfo *fieldInfo = getFirst(); fieldInfo; fieldInfo = fieldInfo->getNext())1429{1430// Revisit1431//14321433if ((length == fieldInfo->getFieldSignatureLength()) &&1434(memcmp(sig, fieldInfo->getFieldSignature(), length) == 0))1435{1436return fieldInfo;1437}14381439//if ((fieldInfo->getFieldSymbol() == fieldSym) ||1440// (fieldInfo->getFieldSymRef() == fieldSymRef))1441// return fieldInfo;14421443/*1444else if (fieldSym->isShadow())1445{1446if (fieldsAreSame(fieldInfo->getOwningMethodSymbol()->getResolvedMethod(), fieldInfo->getFieldSymRef()->getCPIndex(), fieldSymRef->getOwningMethod(), fieldSymRef->getCPIndex()))1447return fieldInfo->asPersistentArrayFieldInfo();1448}1449else if (fieldSym->isStatic())1450{1451if (staticsAreSame(fieldInfo->getOwningMethodSymbol()->getResolvedMethod(), fieldInfo->getFieldSymRef()->getCPIndex(), fieldSymRef->getOwningMethod(), fieldSymRef->getCPIndex()))1452return fieldInfo->asPersistentArrayFieldInfo();1453}1454*/1455}14561457return 0;1458}14591460TR_PersistentFieldInfo *1461TR_PersistentClassInfoForFields::findFieldInfo(TR::Compilation *comp, TR::Node * & node, bool canBeArrayShadow)1462{1463if (!getFirst() || !node->getOpCode().hasSymbolReference())1464return 0;14651466TR::SymbolReference * symRef = node->getSymbolReference();1467if (symRef->isUnresolved())1468return 0;14691470TR::Symbol * sym = symRef->getSymbol();1471if (!sym->isPrivate() &&1472!sym->isFinal())1473return 0;14741475if (sym->isArrayShadowSymbol())1476{1477if (!canBeArrayShadow)1478return 0;1479TR::Node *firstChild = node->getFirstChild();1480if (firstChild->getNumChildren() > 0)1481firstChild = firstChild->getFirstChild();1482if (firstChild->getOpCode().hasSymbolReference())1483node = firstChild;1484}14851486if (sym->isStatic() ||1487(sym->isShadow() && node->getNumChildren() > 0 && node->getFirstChild()->isThisPointer()))1488return find(comp, sym, symRef);14891490return 0;1491}14921493void TR_ClassLookahead::initializeFieldInfo()1494{1495TR::ClassTableCriticalSection initializeFieldInfo(comp()->fej9());14961497TR_PersistentFieldInfo *fieldInfo = _classFieldInfo->getFirst();1498while (fieldInfo)1499{1500TR_PersistentArrayFieldInfo *arrayFieldInfo = NULL;1501arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();15021503if (arrayFieldInfo)1504{1505if (arrayFieldInfo->isDimensionInfoValid() == VALID_AND_ALWAYS_INITIALIZED)1506arrayFieldInfo->setIsDimensionInfoValid(VALID_BUT_NOT_ALWAYS_INITIALIZED);1507}15081509if (fieldInfo->isTypeInfoValid() == VALID_AND_ALWAYS_INITIALIZED)1510fieldInfo->setIsTypeInfoValid(VALID_BUT_NOT_ALWAYS_INITIALIZED);1511fieldInfo = fieldInfo->getNext();1512}1513}1514151515161517void TR_ClassLookahead::updateFieldInfo()1518{1519TR::ClassTableCriticalSection updateFieldInfo(comp()->fej9());15201521TR_PersistentFieldInfo *fieldInfo = _classFieldInfo->getFirst();1522while (fieldInfo)1523{1524TR_PersistentArrayFieldInfo *arrayFieldInfo = NULL;1525arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();15261527if (arrayFieldInfo)1528{1529if (arrayFieldInfo->isDimensionInfoValid() < VALID_AND_ALWAYS_INITIALIZED)1530arrayFieldInfo->setIsDimensionInfoValid(INVALID);1531}15321533if (fieldInfo->isTypeInfoValid() < VALID_AND_ALWAYS_INITIALIZED)1534{1535fieldInfo->setIsTypeInfoValid(INVALID);1536if (!arrayFieldInfo)1537fieldInfo->setCanChangeToArray(false);1538}15391540fieldInfo = fieldInfo->getNext();1541}1542}154315441545#ifdef DEBUG1546void TR_PersistentFieldInfo::dumpInfo(TR_FrontEnd *fe, TR::FILE *logFile)1547{1548trfprintf(logFile, "\n\nPersistentFieldInfo for (%s) : (next : %x)\n", _signature, getNext());15491550if (_isTypeInfoValid)1551{1552trfprintf(logFile, "Type info : %s\n", *_classPointer);1553}1554else1555trfprintf(logFile, "Type info INVALID\n");155615571558if (getNext())1559getNext()->dumpInfo(fe, logFile);1560}15611562void TR_PersistentArrayFieldInfo::dumpInfo(TR_FrontEnd *fe, TR::FILE *logFile)1563{1564TR_PersistentFieldInfo::dumpInfo(fe, logFile);15651566if (_isDimensionInfoValid)1567{1568trfprintf(logFile, "numDimensions : %d\n", _numDimensions);1569int32_t i;1570for (i=0;i<_numDimensions;i++)1571trfprintf(logFile, "_dimensionInfo[%d] : %d\n", i, _dimensionInfo[i]);1572}1573else1574trfprintf(logFile, "Dimension info INVALID\n");1575}15761577#endif1578157915801581