Path: blob/master/runtime/compiler/optimizer/InterProceduralAnalyzer.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 "optimizer/InterProceduralAnalyzer.hpp"2324#include <stdint.h>25#include <string.h>26#include "env/FrontEnd.hpp"27#include "compile/Compilation.hpp"28#include "compile/Method.hpp"29#include "compile/ResolvedMethod.hpp"30#include "compile/SymbolReferenceTable.hpp"31#include "control/Options.hpp"32#include "control/Options_inlines.hpp"33#include "env/CHTable.hpp"34#include "env/CompilerEnv.hpp"35#include "env/PersistentCHTable.hpp"36#include "env/PersistentInfo.hpp"37#include "env/TRMemory.hpp"38#include "env/jittypes.h"39#include "env/ClassTableCriticalSection.hpp"40#include "il/Block.hpp"41#include "il/DataTypes.hpp"42#include "il/ILOpCodes.hpp"43#include "il/ILOps.hpp"44#include "il/MethodSymbol.hpp"45#include "il/Node.hpp"46#include "il/Node_inlines.hpp"47#include "il/ResolvedMethodSymbol.hpp"48#include "il/Symbol.hpp"49#include "il/SymbolReference.hpp"50#include "il/TreeTop.hpp"51#include "il/TreeTop_inlines.hpp"52#include "infra/Link.hpp"53#include "infra/List.hpp"54#include "infra/Stack.hpp"55#include "ras/Debug.hpp"56#include "runtime/RuntimeAssumptions.hpp"5758#define MAX_SNIFF_BYTECODE_SIZE 100059#define MAX_SNIFF_DEPTH 1060#define MAX_SUB_METHODS 56162class TR_OpaqueClassBlock;63class TR_OpaqueMethodBlock;6465TR::InterProceduralAnalyzer::InterProceduralAnalyzer(TR::Compilation * c, bool trace)66:67_compilation(c),68_trMemory(c->trMemory()),69_maxSniffDepth(MAX_SNIFF_DEPTH),70_sniffDepth(0),71_maxSniffDepthExceeded(false),72_totalPeekedBytecodeSize(0),73_maxPeekedBytecodeSize(c->getMaxPeekedBytecodeSize()),74_trace(trace),75_fe(c->fe()),76_successfullyPeekedMethods(trMemory()),77_unsuccessfullyPeekedMethods(trMemory()),78_classesThatShouldNotBeLoadedInCurrentPeek(trMemory()),79_classesThatShouldNotBeNewlyExtendedInCurrentPeek(trMemory()),80_globalsWrittenInCurrentPeek(trMemory())81{82//TR_ScratchList<TR_ClassExtendCheck> _classesThatShouldNotBeNewlyExtendedInCurrentPeekHT[1+ CLASSHASHTABLE_SIZE];83_classesThatShouldNotBeNewlyExtendedInCurrentPeekHT =84(TR_ScratchList<TR_ClassExtendCheck> *)85trMemory()->allocateHeapMemory(sizeof(TR_ScratchList<TR_ClassExtendCheck>) * (CLASSHASHTABLE_SIZE + 1));8687memset(_classesThatShouldNotBeNewlyExtendedInCurrentPeekHT, 0, sizeof(TR_ScratchList<TR_ClassExtendCheck>) * (CLASSHASHTABLE_SIZE + 1));88for (int32_t i = 0; i < CLASSHASHTABLE_SIZE + 1; ++i)89_classesThatShouldNotBeNewlyExtendedInCurrentPeekHT[i].setRegion(trMemory()->currentStackRegion());9091_classesThatShouldNotBeNewlyExtendedHT =92(TR_LinkHead<TR_ClassExtendCheck> *)93trMemory()->allocateHeapMemory(sizeof(TR_LinkHead<TR_ClassExtendCheck>) * (CLASSHASHTABLE_SIZE + 1));94memset(_classesThatShouldNotBeNewlyExtendedHT, 0, sizeof(TR_LinkHead<TR_ClassExtendCheck>) * (CLASSHASHTABLE_SIZE + 1));9596}979899int32_t100TR::InterProceduralAnalyzer::perform()101{102return 2;103}104105106107bool TR::InterProceduralAnalyzer::capableOfPeekingVirtualCalls()108{109if (comp()->performVirtualGuardNOPing() &&110!comp()->getOption(TR_DisableIPA))111return true;112return false;113}114115116117List<OMR::RuntimeAssumption> *TR::InterProceduralAnalyzer::analyzeCall(TR::Node *callNode)118{119if (comp()->isProfilingCompilation() ||120!capableOfPeekingVirtualCalls())121return 0;122123comp()->incVisitCount();124bool success = true;125_maxSniffDepthExceeded = false;126_sniffDepth = 0;127_prevCec = NULL;128_prevClc = NULL;129_classesThatShouldNotBeLoaded.setFirst(NULL);130_classesThatShouldNotBeNewlyExtended.setFirst(NULL);131int32_t i;132133for (i=0;i<CLASSHASHTABLE_SIZE;i++)134_classesThatShouldNotBeNewlyExtendedHT[i].setFirst(NULL);135136_globalsWritten.setFirst(NULL);137138List<OMR::RuntimeAssumption> *runtimeAssumptions = analyzeCallGraph(callNode, &success);139if (trace())140{141if (success)142{143traceMsg(comp(), "Ended peek which was successful\n");144traceMsg(comp(), "Number of unloaded classes are %d\n", _classesThatShouldNotBeLoaded.getSize());145traceMsg(comp(), "Number of classes that should not be newly extended are %d\n", _classesThatShouldNotBeNewlyExtended.getSize());146}147else148traceMsg(comp(), "Ended peek which was unsuccessful\n");149}150151ListElement<TR_ClassExtendCheck> *currCec = _classesThatShouldNotBeNewlyExtendedInCurrentPeek.getListHead();152while (currCec)153{154TR_PersistentClassInfo * cl = comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(currCec->getData()->_clazz, comp());155cl->resetShouldNotBeNewlyExtended(comp()->getCompThreadID());156currCec = currCec->getNextElement();157}158_classesThatShouldNotBeLoadedInCurrentPeek.deleteAll();159_classesThatShouldNotBeNewlyExtendedInCurrentPeek.deleteAll();160for (i=0;i<CLASSHASHTABLE_SIZE;i++)161_classesThatShouldNotBeNewlyExtendedInCurrentPeekHT[i].deleteAll();162_globalsWrittenInCurrentPeek.deleteAll();163164if (success)165return new (trStackMemory()) TR_ScratchList<OMR::RuntimeAssumption>(trMemory());166else167return NULL;168169//return runtimeAssumptions;170}171172List<OMR::RuntimeAssumption> *TR::InterProceduralAnalyzer::analyzeCallGraph(TR::Node *callNode, bool *success)173{174if (_sniffDepth >= _maxSniffDepth)175{176_maxSniffDepthExceeded = true;177*success = false;178179if (trace())180{181traceMsg(comp(), "High sniff depth made peek unsuccessful\n");182}183184return 0;185}186187TR::SymbolReference *symRef = callNode->getSymbolReference();188TR::MethodSymbol *methodSymbol = symRef->getSymbol()->castToMethodSymbol();189TR::ResolvedMethodSymbol * resolvedMethodSymbol = methodSymbol->getResolvedMethodSymbol();190TR_ResolvedMethod *owningMethod = symRef->getOwningMethod(comp());191192if (!resolvedMethodSymbol &&193!methodSymbol->isInterface())194{195*success = false;196if (trace())197{198traceMsg(comp(), "Unresolved non-interface call node %p made peek unsuccessful\n", callNode);199}200201return 0;202}203204if ((*success) &&205callNode->getOpCode().isIndirect() &&206!capableOfPeekingVirtualCalls())207{208*success = false;209return 0;210}211212TR_OpaqueClassBlock *clazz = NULL;213if (!resolvedMethodSymbol) // as per current logic, it is an interface method214{215int32_t cpIndex = symRef->getCPIndex();216TR::Method * originalMethod = methodSymbol->getMethod();217int32_t len = originalMethod->classNameLength();218char *s = TR::Compiler->cls.classNameToSignature(originalMethod->classNameChars(), len, comp());219clazz = fe()->getClassFromSignature(s, len, owningMethod);220if (!clazz)221{222// Add assumption here223//224if (!s)225{226*success = false;227if (trace())228{229traceMsg(comp(), "Found unresolved method call node %p while peeking whose class is unresolved and unable to add assumption -- peek unsuccessful\n", callNode);230}231}232else233{234addClassThatShouldNotBeLoaded(s, len);235236if (trace())237{238traceMsg(comp(), "Found unresolved method call node %p while peeking -- add assumption\n", callNode);239}240}241return 0;242}243}244else245{246TR_ResolvedMethod *method = resolvedMethodSymbol->getResolvedMethod();247if (!method)248{249*success = false;250return 0;251}252253analyzeMethod(callNode, method, success);254clazz = method->containingClass();255}256257258if ((*success) &&259callNode->getOpCode().isIndirect())260{261TR::Node *thisChild = callNode->getChild(callNode->getFirstArgumentIndex());262int32_t len;263const char *s = thisChild->getTypeSignature(len);264if (!s)265{266if (thisChild->getOpCodeValue() == TR::New)267s = thisChild->getFirstChild()->getTypeSignature(len);268}269270//traceMsg(comp(), "callNode %p thisChild %p\n", callNode, thisChild);271//if (s)272// traceMsg(comp(), "sig %s\n", s);273//else274// traceMsg(comp(), "sig is NULL\n");275276if (s)277{278TR_OpaqueClassBlock *thisClazz = fe()->getClassFromSignature(s, len, owningMethod);279if (thisClazz && (clazz != thisClazz))280{281TR_YesNoMaybe isInstance = fe()->isInstanceOf(thisClazz, clazz, true);282if (isInstance == TR_yes)283clazz = thisClazz;284}285}286287if (clazz)288{289if (!addClassThatShouldNotBeNewlyExtended(clazz))290{291if(trace())292traceMsg(comp(), "Could not add Class That should not be newly extended to assumptions list.\n");293294*success = false;295return 0;296}297298if (trace())299{300traceMsg(comp(), "Found class for this object -- add assumption that the class should not be newly extended\n");301}302}303304bool allowForAOT = comp()->getOption(TR_UseSymbolValidationManager);305TR_PersistentClassInfo *classInfo = comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(clazz, comp(), allowForAOT);306if (classInfo)307{308TR_ScratchList<TR_PersistentClassInfo> subClasses(trMemory());309TR_ClassQueries::getSubClasses(classInfo, subClasses, fe());310if (trace())311traceMsg(comp(), "Number of subclasses = %d\n", subClasses.getSize());312TR_ScratchList<TR_ResolvedMethod> subMethods(trMemory());313int32_t numSubMethods = 0;314ListIterator<TR_PersistentClassInfo> subClassesIt(&subClasses);315for (TR_PersistentClassInfo *subClassInfo = subClassesIt.getFirst(); subClassInfo; subClassInfo = subClassesIt.getNext())316{317TR_OpaqueClassBlock *subClass = (TR_OpaqueClassBlock *) subClassInfo->getClassId();318if (TR::Compiler->cls.isInterfaceClass(comp(), subClass))319continue;320TR_ResolvedMethod *subClassMethod;321if (methodSymbol->isInterface())322subClassMethod = owningMethod->getResolvedInterfaceMethod(comp(), subClass, symRef->getCPIndex());323else324subClassMethod = owningMethod->getResolvedVirtualMethod(comp(), subClass, symRef->getOffset());325int32_t length;326if (trace())327traceMsg(comp(), "Class name %s\n", TR::Compiler->cls.classNameChars(comp(), subClass, length));328if (subClassMethod && !subMethods.find(subClassMethod))329{330subMethods.add(subClassMethod);331numSubMethods++;332analyzeMethod(callNode, subClassMethod, success);333}334335if (numSubMethods > MAX_SUB_METHODS)336*success = false;337338if (!(*success))339break;340}341}342return 0;343}344345return 0;346}347348349List<OMR::RuntimeAssumption> *TR::InterProceduralAnalyzer::analyzeMethod(TR::Node *callNode, TR_ResolvedMethod *method, bool *success)350{351if (trace())352{353traceMsg(comp(), "Consider method %s for peek\n", method->signature(trMemory()));354}355356if (!method->isCompilable(trMemory()) || method->isJNINative())357{358*success = false;359return 0;360}361362bool successfulPriorPeek = true;363TR::PriorPeekInfo *priorPeek = NULL;364if (0 && alreadyPeekedMethod(method, &successfulPriorPeek, &priorPeek))365{366if (!successfulPriorPeek)367{368*success = false;369if (trace())370{371traceMsg(comp(), "Prior peek failure for method %s caused current peek to be unsuccessful\n", method->signature(trMemory()));372}373}374else375{376if (trace())377{378traceMsg(comp(), "Prior peek success for method %s caused current peek to be successful -- prior assumptions added\n", method->signature(trMemory()));379}380381for (TR_ClassLoadCheck * clc = priorPeek->_classesThatShouldNotBeLoaded.getFirst(); clc; clc = clc->getNext())382addClassThatShouldNotBeLoaded(clc->_name, clc->_length);383384for (TR_ClassExtendCheck * cec = priorPeek->_classesThatShouldNotBeNewlyExtended.getFirst(); cec; cec = cec->getNext())385addClassThatShouldNotBeNewlyExtended(cec->_clazz);386}387return 0;388}389390uint32_t bytecodeSize = method->maxBytecodeIndex();391if (bytecodeSize > MAX_SNIFF_BYTECODE_SIZE)392{393*success = false;394if (trace())395{396traceMsg(comp(), "Large bytecode size %d made peek unsuccessful\n", bytecodeSize);397}398399return 0;400}401402if (isOnPeekingStack(method))403return 0;404405if (trace())406traceMsg(comp(), "\nDepth %d sniffing into call at [%p] to %s\n", _sniffDepth, callNode, method->signature(trMemory()));407408TR::SymbolReference * symRef = callNode->getSymbolReference();409int32_t offset = symRef->getOffset();410TR::SymbolReference * newSymRef = NULL;411412if (method->isStatic())413newSymRef = comp()->getSymRefTab()->findOrCreateMethodSymbol(symRef->getOwningMethodIndex(), -1, method, TR::MethodSymbol::Static);414else415newSymRef = comp()->getSymRefTab()->findOrCreateMethodSymbol(symRef->getOwningMethodIndex(), -1, method, TR::MethodSymbol::Interface);416417newSymRef->copyAliasSets(symRef, comp()->getSymRefTab());418newSymRef->setOffset(offset);419TR::MethodSymbol *methodSymbol = newSymRef->getSymbol()->castToMethodSymbol();420TR::ResolvedMethodSymbol * resolvedMethodSymbol = methodSymbol->getResolvedMethodSymbol();421422vcount_t visitCount = comp()->getVisitCount();423if (!resolvedMethodSymbol->getFirstTreeTop())424{425int32_t firstArgIndex = callNode->getFirstArgumentIndex();426int32_t numRealArgs = callNode->getNumChildren() - firstArgIndex;427const char **argInfo = (const char **)trMemory()->allocateHeapMemory(numRealArgs*sizeof(char *)); // can stack allocate in some cases428memset(argInfo, 0, numRealArgs*sizeof(char *));429int32_t *lenInfo = (int32_t *) trMemory()->allocateHeapMemory(numRealArgs*sizeof(int32_t)); // can stack allocate in some cases430memset(lenInfo, 0xFF, numRealArgs*sizeof(int32_t));431432for (int32_t c = callNode->getNumChildren() - 1 ; c >= firstArgIndex; --c)433{434TR::Node *argument = callNode->getChild(c);435if (argument->getDataType() == TR::Address)436{437int32_t len;438const char *s = argument->getTypeSignature(len);439if (!s)440{441if (argument->getOpCodeValue() == TR::New)442s = argument->getFirstChild()->getTypeSignature(len);443}444445if (trace())446{447traceMsg(comp(), "callNode %p arg %p\n", callNode, argument);448if (s)449traceMsg(comp(), "sig %s\n", s);450else451traceMsg(comp(), "sig is NULL\n");452}453454if (s && (c == firstArgIndex))455{456TR_OpaqueClassBlock *argClazz = fe()->getClassFromSignature(s, len, symRef->getOwningMethod(comp()));457TR_OpaqueClassBlock *thisClazz = method->containingClass();458459if (!argClazz || !thisClazz)460{461*success = false;462if (trace())463{464traceMsg(comp(), "The call argument class is NULL, bailing out. (probably because of different class loaders)\n");465}466467return 0;468}469470if (argClazz != thisClazz)471{472TR_YesNoMaybe isInstance = fe()->isInstanceOf(thisClazz, argClazz, true);473if (isInstance == TR_yes)474{475s = TR::Compiler->cls.classSignature_DEPRECATED(comp(), thisClazz, len, trMemory());476}477}478}479480argInfo[c-firstArgIndex] = s;481lenInfo[c-firstArgIndex] = len;482}483}484485_totalPeekedBytecodeSize = _totalPeekedBytecodeSize + bytecodeSize;486if (_totalPeekedBytecodeSize > _maxPeekedBytecodeSize)487{488*success = false;489if (trace())490{491traceMsg(comp(), "Large bytecode size %d made peek unsuccessful\n", bytecodeSize);492}493494return 0;495}496497if (!performTransformation(comp(), "O^O INTERPROCEDURAL ANALYZER: Peeking into the IL for doing a limited form of interprocedural analysis \n"))498return 0;499500TR_PeekingArgInfo *peekInfo = (TR_PeekingArgInfo *) trMemory()->allocateStackMemory(sizeof(TR_PeekingArgInfo)); // can stack allocate in some cases501peekInfo->_args = argInfo;502peekInfo->_lengths = lenInfo;503peekInfo->_method = resolvedMethodSymbol->getResolvedMethod();504comp()->addPeekingArgInfo(peekInfo);505//comp()->setVisitCount(1);506507_currentPeekingSymRefTab = resolvedMethodSymbol->getResolvedMethod()->genMethodILForPeeking(resolvedMethodSymbol, comp());508//comp()->setVisitCount(visitCount);509comp()->removePeekingArgInfo();510511if (!_currentPeekingSymRefTab)512{513*success = false;514if (trace())515traceMsg(comp(), " (IL generation failed)\n");516return 0;517}518519if (trace())520{521//comp()->setVisitCount(1);522for (TR::TreeTop *tt = resolvedMethodSymbol->getFirstTreeTop(); tt; tt = tt->getNextTreeTop())523comp()->getDebug()->print(comp()->getOutFile(), tt);524//comp()->setVisitCount(visitCount);525}526}527else528{529if (trace())530traceMsg(comp(), " (trees already dumped)\n");531}532533++_sniffDepth;534535536ListElement<TR_ClassLoadCheck> *prevClc = NULL; //_classesThatShouldNotBeLoadedInCurrentPeek.getListHead();537ListElement<TR_ClassExtendCheck> *prevCec = NULL; //_classesThatShouldNotBeNewlyExtendedInCurrentPeek.getListHead();538ListElement<TR::GlobalSymbol> *prevSymRef = NULL; //_globalsWrittenInCurrentPeek.getListHead();539_prevClc = prevClc;540_prevCec = prevCec;541_prevSymRef = prevSymRef;542543544TR::TreeTop *treeTop = NULL;545TR::Node *node = NULL;546TR::Block *block = NULL;547for (treeTop = resolvedMethodSymbol->getFirstTreeTop(); treeTop; treeTop = treeTop->getNextTreeTop())548{549node = treeTop->getNode();550551if (node->getOpCodeValue() == TR::BBStart)552{553block = node->getBlock();554}555556if (node->getOpCode().isCheck() || node->getOpCodeValue() == TR::treetop)557node = node->getFirstChild();558559if (node->getOpCode().isCall() && node->getVisitCount() != visitCount)560{561_prevClc = prevClc;562_prevCec = prevCec;563_prevSymRef = prevSymRef;564565//node->setVisitCount(visitCount);566analyzeCallGraph(node, success);567}568569if (!*success)570{571if (trace())572{573traceMsg(comp(), "Node %p made peek unsuccessful\n", node);574}575break;576}577578if (analyzeNode(node, visitCount, success))579treeTop = block->getExit();580581if (!*success)582{583if (trace())584{585traceMsg(comp(), "Node %p made peek unsuccessful\n", node);586}587break;588}589}590591--_sniffDepth;592593if (0 && *success)594{595TR::PriorPeekInfo *priorPeek = (TR::PriorPeekInfo *) trMemory()->allocateHeapMemory(sizeof(TR::PriorPeekInfo));596priorPeek->_method = resolvedMethodSymbol->getResolvedMethod();597priorPeek->_classesThatShouldNotBeLoaded.setFirst(NULL);598priorPeek->_classesThatShouldNotBeNewlyExtended.setFirst(NULL);599priorPeek->_globalsWritten.setFirst(NULL);600ListElement<TR_ClassLoadCheck> *currClc = _classesThatShouldNotBeLoadedInCurrentPeek.getListHead();601ListElement<TR_ClassExtendCheck> *currCec = _classesThatShouldNotBeNewlyExtendedInCurrentPeek.getListHead();602ListElement<TR::GlobalSymbol> *currSymRef = _globalsWrittenInCurrentPeek.getListHead();603while (currClc != prevClc)604{605priorPeek->_classesThatShouldNotBeLoaded.add(new (trHeapMemory()) TR_ClassLoadCheck(currClc->getData()->_name, currClc->getData()->_length));606currClc = currClc->getNextElement();607}608609while (currCec != prevCec)610{611priorPeek->_classesThatShouldNotBeNewlyExtended.add(new (trHeapMemory()) TR_ClassExtendCheck(currCec->getData()->_clazz));612currCec = currCec->getNextElement();613}614615while (currSymRef != prevSymRef)616{617priorPeek->_globalsWritten.add(new (trHeapMemory()) TR::GlobalSymbol(currSymRef->getData()->_symRef));618currSymRef = currSymRef->getNextElement();619}620621_successfullyPeekedMethods.add(priorPeek);622if (trace())623{624traceMsg(comp(), "Method %s is successfully peeked\n", resolvedMethodSymbol->getResolvedMethod()->signature(trMemory()));625}626}627else628{629if (_sniffDepth == 0)630{631if (trace())632{633traceMsg(comp(), "1Method %s is unsuccessfully peeked\n", resolvedMethodSymbol->getResolvedMethod()->signature(trMemory()));634}635636_unsuccessfullyPeekedMethods.add(resolvedMethodSymbol->getResolvedMethod());637_maxSniffDepthExceeded = false;638}639else640{641if (!_maxSniffDepthExceeded)642{643if (trace())644{645traceMsg(comp(), "2Method %s is unsuccessfully peeked\n", resolvedMethodSymbol->getResolvedMethod()->signature(trMemory()));646}647_unsuccessfullyPeekedMethods.add(resolvedMethodSymbol->getResolvedMethod());648}649}650}651652653return 0;654}655656657bool TR::InterProceduralAnalyzer::isOnPeekingStack(TR_ResolvedMethod *method)658{659TR_Stack<TR_PeekingArgInfo *> *peekingStackInfo = comp()->getPeekingArgInfo();660int32_t topOfStack = peekingStackInfo->topIndex();661int32_t i;662for (i=0;i<=topOfStack;i++)663{664TR_PeekingArgInfo *peekInfo = peekingStackInfo->element(i);665if (peekInfo)666{667if (peekInfo->_method->isSameMethod(method))668return true;669/*670if ((nameLength(peekInfo->_method) == nameLength(method)) &&671!strncmp(nameChars(peekInfo->_method), nameChars(method), nameLength(method)) &&672(signatureLength(peekInfo->_method) == signatureLength(method)) &&673!strncmp(signatureChars(peekInfo->_method), signatureChars(method), signatureLength(method)))674{675TR_OpaqueClassBlock *peekedClazz = peekInfo->_method->containingClass();676TR_OpaqueClassBlock *clazz = method->containingClass();677TR_PersistentClassInfo *classInfo = comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(clazz, comp());678if (classInfo)679{680TR_ScratchList<TR_PersistentClassInfo> subClasses;681classInfo->getSubClasses(subClasses, comp());682if (trace())683traceMsg(comp(), "Number of subclasses = %d\n", subClasses.getSize());684ListIterator<TR_PersistentClassInfo> subClassesIt(&subClasses);685for (TR_PersistentClassInfo *subClassInfo = subClassesIt.getFirst(); subClassInfo; subClassInfo = subClassesIt.getNext())686{687TR_OpaqueClassBlock *subClass = subClassInfo->getClassId();688if (subClass == peekedClazz)689return true;690}691}692}693*/694}695}696697return false;698}699700701702bool TR::InterProceduralAnalyzer::alreadyPeekedMethod(TR_ResolvedMethod *method, bool *success, TR::PriorPeekInfo **priorPeek)703{704ListIterator<TR::PriorPeekInfo> priorPeekedMethodsIt(&_successfullyPeekedMethods);705TR::PriorPeekInfo *priorPeekedMethod = NULL;706for (priorPeekedMethod = priorPeekedMethodsIt.getFirst(); priorPeekedMethod; priorPeekedMethod = priorPeekedMethodsIt.getNext())707{708if (priorPeekedMethod->_method->isSameMethod(method))709{710*priorPeek = priorPeekedMethod;711//*success = true;712return true;713}714}715716//peekedMethodsIt.set(&_unsuccessfullyPeekedMethods);717ListIterator<TR_ResolvedMethod> peekedMethodsIt(&_unsuccessfullyPeekedMethods);718TR_ResolvedMethod *peekedMethod;719for (peekedMethod = peekedMethodsIt.getFirst(); peekedMethod; peekedMethod = peekedMethodsIt.getNext())720{721if (peekedMethod->isSameMethod(method))722{723*success = false;724return true;725}726}727728return false;729}730731732733bool734TR::InterProceduralAnalyzer::addClassThatShouldNotBeLoaded(char *name, int32_t len)735{736bool found = false;737738for (ListElement<TR_ClassLoadCheck> *currClc = _classesThatShouldNotBeLoadedInCurrentPeek.getListHead(); currClc != _prevClc; currClc = currClc->getNextElement())739{740if (currClc->getData()->_length == len && !strncmp(currClc->getData()->_name, name, len))741{742found = true;743break;744}745}746747if (!found)748_classesThatShouldNotBeLoadedInCurrentPeek.add(new (trStackMemory()) TR_ClassLoadCheck(name, len));749750for (TR_ClassLoadCheck * clc = _classesThatShouldNotBeLoaded.getFirst(); clc; clc = clc->getNext())751if (clc->_length == len && !strncmp(clc->_name, name, len))752return false;753754_classesThatShouldNotBeLoaded.add(new (trHeapMemory()) TR_ClassLoadCheck(name, len));755756return true;757}758759760761762763bool764TR::InterProceduralAnalyzer::addClassThatShouldNotBeNewlyExtended(TR_OpaqueClassBlock *clazz)765{766TR::ClassTableCriticalSection addClassThatShouldNotBeNewlyExtended(comp()->fe());767768TR_PersistentClassInfo * cl = comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(clazz, comp());769if(!cl)770return false;771772if (!cl->shouldNotBeNewlyExtended(comp()->getCompThreadID()))773addSingleClassThatShouldNotBeNewlyExtended(clazz);774775776cl->setShouldNotBeNewlyExtended(comp()->getCompThreadID());777TR_ScratchList<TR_PersistentClassInfo> subClasses(trMemory());778779TR_ClassQueries::collectAllSubClasses(cl, &subClasses, comp());780781ListIterator<TR_PersistentClassInfo> it(&subClasses);782TR_PersistentClassInfo *info = NULL;783for (info = it.getFirst(); info; info = it.getNext())784{785if (!info->shouldNotBeNewlyExtended(comp()->getCompThreadID()))786{787info->setShouldNotBeNewlyExtended(comp()->getCompThreadID());788TR_OpaqueClassBlock *subClass = info->getClassId();789addSingleClassThatShouldNotBeNewlyExtended(subClass);790}791}792793return true;794}795796797uint32_t TR::InterProceduralAnalyzer::hash(void * h, uint32_t size)798{799// 2654435761 is the golden ratio of 2^32.800//801return (((uint32_t)(uintptr_t)h >> 2) * 2654435761u) % size;802}803804805bool TR::InterProceduralAnalyzer::addSingleClassThatShouldNotBeNewlyExtended(TR_OpaqueClassBlock *clazz)806{807bool found = false;808uint32_t hashNum = hash(clazz, CLASSHASHTABLE_SIZE);809for (ListElement<TR_ClassExtendCheck> *currCec = _classesThatShouldNotBeNewlyExtendedInCurrentPeekHT[hashNum].getListHead(); currCec != _prevCec; currCec = currCec->getNextElement())810{811if (currCec->getData()->_clazz == clazz)812{813found = true;814break;815}816}817818if (!found)819{820_classesThatShouldNotBeNewlyExtendedInCurrentPeek.add(new (trStackMemory()) TR_ClassExtendCheck(clazz));821_classesThatShouldNotBeNewlyExtendedInCurrentPeekHT[hashNum].add(new (trStackMemory()) TR_ClassExtendCheck(clazz));822}823824found = false;825for (TR_ClassExtendCheck *clc = _classesThatShouldNotBeNewlyExtendedHT[hashNum].getFirst(); clc; clc = clc->getNext())826if (clc->_clazz == clazz)827{828found = true;829break;830//return false;831}832833if (!found)834{835_classesThatShouldNotBeNewlyExtended.add(new (trHeapMemory()) TR_ClassExtendCheck(clazz));836_classesThatShouldNotBeNewlyExtendedHT[hashNum].add(new (trHeapMemory()) TR_ClassExtendCheck(clazz));837}838return true;839}840841842843844bool845TR::InterProceduralAnalyzer::addWrittenGlobal(TR::SymbolReference *symRef)846{847char *sig = NULL;848int32_t length = 0;849if (symRef->getSymbol()->isStaticField())850sig = symRef->getOwningMethod(comp())->staticName(symRef->getCPIndex(), length, trMemory());851else if (symRef->getSymbol()->isShadow())852sig = symRef->getOwningMethod(comp())->fieldName(symRef->getCPIndex(), length, trMemory());853854bool found = false;855for (ListElement<TR::GlobalSymbol> *currSymRef = _globalsWrittenInCurrentPeek.getListHead(); currSymRef != _prevSymRef; currSymRef = currSymRef->getNextElement())856{857TR::SymbolReference *currSymReference = currSymRef->getData()->_symRef;858char *currSig = NULL;859int32_t currLength = 0;860if (currSymReference->getSymbol()->isStaticField())861currSig = currSymReference->getOwningMethod(comp())->staticName(currSymReference->getCPIndex(), currLength, trMemory());862else if (currSymReference->getSymbol()->isShadow())863currSig = currSymReference->getOwningMethod(comp())->fieldName(currSymReference->getCPIndex(), currLength, trMemory());864865if ((length == currLength) &&866(memcmp(sig, currSig, length) == 0))867{868found = true;869break;870}871}872873if (!found)874_globalsWrittenInCurrentPeek.add(new (trStackMemory()) TR::GlobalSymbol(symRef));875876for (TR::GlobalSymbol *currSym = _globalsWritten.getFirst(); currSym; currSym = currSym->getNext())877{878TR::SymbolReference *currSymReference = currSym->_symRef;879char *currSig = NULL;880int32_t currLength = 0;881if (currSymReference->getSymbol()->isStaticField())882currSig = currSymReference->getOwningMethod(comp())->staticName(currSymReference->getCPIndex(), currLength, trMemory());883else if (currSymReference->getSymbol()->isShadow())884currSig = currSymReference->getOwningMethod(comp())->fieldName(currSymReference->getCPIndex(), currLength, trMemory());885886if ((length == currLength) &&887(memcmp(sig, currSig, length) == 0))888return false;889}890891_globalsWritten.add(new (trHeapMemory()) TR::GlobalSymbol(symRef));892893return true;894}895896897898899bool900TR::InterProceduralAnalyzer::addMethodThatShouldNotBeNewlyOverridden(TR_OpaqueMethodBlock *method)901{902//903// Should check if method is overridden in future causing peeked call graph to904// change905//906// This check will be more precise than class extension check but907// will also be moe expensive at run-time. Implement if really required in908// the future909//910return true;911}912913914915916917