Path: blob/master/runtime/compiler/ilgen/J9ByteCodeIteratorWithState.hpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 2019 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 "infra/Flags.hpp"23#include "infra/Link.hpp"24#include "infra/Stack.hpp"25#include "ilgen/J9ByteCode.hpp"26#include "ilgen/J9ByteCodeIterator.hpp"27#include "ilgen/ByteCodeIteratorWithState.hpp"28#include "il/Node.hpp"29#include "il/Node_inlines.hpp"30#include "il/ParameterSymbol.hpp"31#include "il/TreeTop.hpp"32#include "compiler/il/OMRTreeTop_inlines.hpp"3334class TR_J9ByteCodeIteratorWithState :35public TR_ByteCodeIteratorWithState<TR_J9ByteCode, J9BCunknown, TR_J9ByteCodeIterator, TR::Node *>36{37typedef TR_ByteCodeIteratorWithState<TR_J9ByteCode, J9BCunknown, TR_J9ByteCodeIterator, TR::Node *> Base;3839public:40TR_J9ByteCodeIteratorWithState(TR::ResolvedMethodSymbol * methodSymbol, TR_J9VMBase * fe, TR::Compilation * comp)41: Base(methodSymbol, comp),42_replacedSymRefs(NULL)43{44TR_J9ByteCodeIterator::initialize(static_cast<TR_ResolvedJ9Method *>(methodSymbol->getResolvedMethod()), fe);45}4647protected:4849void initialize()50{51Base::initialize();52}5354void markAnySpecialBranchTargets(TR_J9ByteCode bc)55{56int32_t i = bcIndex();57if (bc == J9BCtableswitch)58{59int32_t index = defaultTargetIndex();60markTarget(i, nextSwitchValue(index));61int32_t low = nextSwitchValue(index);62int32_t high = nextSwitchValue(index) - low + 1;63for (int32_t j = 0; j < high; ++j)64markTarget(i, nextSwitchValue(index));65}66else if (bc == J9BClookupswitch)67{68int32_t index = defaultTargetIndex();69markTarget(i, nextSwitchValue(index));70int32_t tableSize = nextSwitchValue(index);71for (int32_t j = 0; j < tableSize; ++j)72{73index += 4; // match value74markTarget(i, nextSwitchValue(index));75}76}77}7879void findAndMarkExceptionRanges()80{81int32_t handlerIndex=0;82for (;handlerIndex < method()->numberOfExceptionHandlers(); handlerIndex++)83{84int32_t start, end, type;85int32_t handler = method()->exceptionData(handlerIndex, &start, &end, &type);86markExceptionRange(handlerIndex, start, end, handler, type);87}8889if (handlerIndex > 0)90_methodSymbol->setEHAware();91}9293virtual void saveStack(int32_t) = 0;9495void patchPartialInliningCallBack(int32_t slot, TR::SymbolReference *symRef, TR::SymbolReference *tempRef, TR::TreeTop *tt2) //TR::Block *restartBlock)96{97//printf("patchPartialInliningCallBack. Searching for Children with symref = %p\n",symRef);98TR::TreeTop *tt = tt2->getNextRealTreeTop(); //restartBlock->getEntry();99TR::Node *ttnode = tt->getNode();100TR::Node *callNode = ttnode->getFirstChild();101TR::Node *child = NULL;102103for(int32_t i = 0 ; i < callNode->getNumChildren() ; i++)104{105child = callNode->getChild(i);106if(child->getSymbolReference() == symRef)107{108child->setSymbolReference(tempRef);109//printf("patchPartialInliningCallBack: setting Child %d %p symRef %p to tempRef %p\n",i,child,symRef,tempRef);110}111112}113}114void addTempForPartialInliningCallBack(int32_t slot,TR::SymbolReference *tempRef, int32_t numParms)115{116//printf("addTempForPartialINliningCallBack. (Haven't generated CallBack yet.)\n");117118if(_replacedSymRefs == 0)119_replacedSymRefs = new (_compilation->trStackMemory()) TR_Array<TR::SymbolReference*>(_compilation->trMemory(), numParms , true, stackAlloc);120121(*_replacedSymRefs)[slot] = tempRef;122123//printf("addTempForPartialInliningCallBack : _replacedSYmRefs = %p _replacedSymRefs->isEmpty() = %d\n",_replacedSymRefs,_replacedSymRefs->isEmpty());124}125126TR::TreeTop *genPartialInliningCallBack(int32_t index, TR::TreeTop *callTreeTop)127{128// printf("Walker:genPartialInliningCallBack for index %d methodSymbol = %p\n",index, _methodSymbol);129genBBStart(index);130//printf("\tgenBBStart generated Block %p Block->getNumber %d\n",blocks(index),blocks(index)->getNumber());131132TR::Node *ttNode = TR::Node::create(TR::treetop, 1);133TR::Node *callNode =TR::Node::copy(callTreeTop->getNode()->getFirstChild());134callNode->setReferenceCount(1);135//TR_ASSERT(callNode->getOpCode().isCall(), "node %p isn't a call!\n",callTreeTop->getNode()->getFirstChild());136ttNode->setFirst(callNode); //copying callnode. will replace children shortly137138139ListIterator<TR::ParameterSymbol> li (&_methodSymbol->getParameterList());140TR::ParameterSymbol *si = NULL;141int32_t i;142for(si = li.getFirst(), i=0 ; si != NULL ; si = li.getNext(), i++ )143{144// printf("si = %p datatype = %d loadOpCode = %d, i = %d, symreftab = %p\n",si, si->getDataType(),_compilation->il.opCodeForDirectLoad(si->getDataType()),i,_compilation->getSymRefTab() );145TR::SymbolReference *ref = _compilation->getSymRefTab()->findOrCreateAutoSymbol(_methodSymbol,si->getSlot(),si->getDataType());146if(_replacedSymRefs && (*_replacedSymRefs)[si->getSlot()])147{148ref = (*_replacedSymRefs)[si->getSlot()];149//printf("genPartialInliningCallBack: Found a replaced symRef for slot %d\n",si->getSlot());150}151152if(callNode->getOpCode().isIndirect() && i==0) // need to generate vft offset & call153{154TR::Node *thisPointer = TR::Node::createWithSymRef(_compilation->il.opCodeForDirectLoad(si->getDataType()),0,ref);155callNode->setAndIncChild(0, TR::Node::createWithSymRef(TR::aloadi, 1, 1, thisPointer, _compilation->getSymRefTab()->findOrCreateVftSymbolRef()));156i++;157}158TR::Node *child = TR::Node::createWithSymRef(_compilation->il.opCodeForDirectLoad(si->getDataType()),0,ref);159callNode->setAndIncChild(i,child); //setChild doesn't modify the ref count. setAndIncChild() will properly inc the ref count.160}161blocks(index)->append(TR::TreeTop::create(_compilation, ttNode));162TR::Node *retNode = NULL;163if(TR::ILOpCode::returnOpCode(callNode->getDataType()) == TR::Return) //null return?164{165retNode = TR::Node::create(TR::ILOpCode::returnOpCode(callNode->getDataType()),0);166}167else168{169retNode = TR::Node::create(TR::ILOpCode::returnOpCode(callNode->getDataType()),1,callNode);170}171blocks(index)->append(TR::TreeTop::create(_compilation,retNode));172setIsGenerated(index);173return blocks(index)->getEntry();174}175176TR::TreeTop *genGotoPartialInliningCallBack(int32_t index, TR::TreeTop *gotoTreeTop)177{178//printf("Walker:genGotoPartialInliningCallBack for index %d\n",index);179genBBStart(index);180if(!isGenerated(index)) // could also consider blocks(index)->isEmptyBlock()181{182blocks(index)->append(TR::TreeTop::create(_compilation,TR::Node::create(TR::Goto, 0, gotoTreeTop)));183}184setIsGenerated(index);185return blocks(index)->getEntry();186//genTreeTop(TR::Node::create(TR::Goto, 0, genTarget(target)));187}188189bool hasExceptionHandlers()190{191return method()->numberOfExceptionHandlers() > 0;192}193194// how many bytes is the given operand stack element's result?195int32_t getSize(TR::Node * n)196{197return n->getSize();198}199200// what is the data type of the operand stack element's result?201TR::DataType getDataType(TR::Node * n)202{203return n->getDataType();204}205206// how many bytes are used on the operand stack to hold the operand stack element's result?207// size of addresses depends on the target platform (32- or 64-bit)208//209int32_t numberOfByteCodeStackSlots(TR::Node * n)210{211// note, getSize(TR::Address) = 8 on 64-bit platforms212if (getDataType(n) == TR::Address)213return 4;214else215return getSize(n);216}217218// duplicate the top two elements of the stack219void dup2()220{221TR::Node * &nWord1 = top();222223if (numberOfByteCodeStackSlots(nWord1) == 4)224shift(2,2);// i think this can be just "shift"225else226shift(1,1);// i think this can be just "shift"227}228229void dupx1()230{231shiftAndCopy(2, 1);232}233234void dup2x1()235{236TR::Node * &nWord1 = node(_stack->topIndex());237238if (numberOfByteCodeStackSlots(nWord1) == 4)239{240shiftAndCopy(3,2);241}242else243{244shiftAndCopy(2,1);245}246}247248void dupx2()249{250TR::Node * &nWord2 = node(_stack->topIndex()-1);251252if (numberOfByteCodeStackSlots(nWord2) == 4)253{254shiftAndCopy(3,1);255}256else257{258shiftAndCopy(2,1);259}260}261262void dup2x2()263{264TR::Node * &nWord1 = node(_stack->topIndex());265266if (numberOfByteCodeStackSlots(nWord1) == 4)267{268TR::Node * &nWord3 = node(_stack->topIndex() - 2);269270if (numberOfByteCodeStackSlots(nWord3) == 4)271{272shiftAndCopy(4,2);273}274else275{276shiftAndCopy(3,2);277}278}279else280{281TR::Node * &nWord2 = node(_stack->topIndex() - 1);282283if (numberOfByteCodeStackSlots(nWord2) == 4)284{285shiftAndCopy(3,1);286}287else288{289shiftAndCopy(2,1);290}291}292}293294TR_Array<TR::SymbolReference *> * _replacedSymRefs; //Partial Inlining295};296297298