Path: blob/master/runtime/compiler/optimizer/HCRGuardAnalysis.cpp
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*******************************************************************************/21#include <stddef.h>22#include <stdint.h>23#include "optimizer/HCRGuardAnalysis.hpp"24#include "env/StackMemoryRegion.hpp"25#include "codegen/CodeGenerator.hpp"26#include "compile/Compilation.hpp"27#include "control/Options.hpp"28#include "control/Options_inlines.hpp"29#include "env/TRMemory.hpp"30#include "il/Node.hpp"31#include "il/Node_inlines.hpp"32#include "infra/Assert.hpp"33#include "infra/BitVector.hpp"34#include "infra/Checklist.hpp"35#include "optimizer/FearPointAnalysis.hpp"3637static bool containsPrepareForOSR(TR::Block *block)38{39for (TR::TreeTop *tt = block->getEntry(); tt != block->getExit(); tt = tt->getNextTreeTop())40{41if (tt->getNode()->getOpCode().isCheck() || tt->getNode()->getOpCodeValue() == TR::treetop)42{43if (tt->getNode()->getFirstChild()->getOpCode().isCall()44&& tt->getNode()->getFirstChild()->getSymbolReference()->getReferenceNumber() == TR_prepareForOSR)45return true;46}47}48return false;49}5051int32_t TR_HCRGuardAnalysis::getNumberOfBits() { return 1; }5253bool TR_HCRGuardAnalysis::supportsGenAndKillSets() { return true; }5455TR_DataFlowAnalysis::Kind TR_HCRGuardAnalysis::getKind() { return HCRGuardAnalysis; }5657void TR_HCRGuardAnalysis::analyzeNode(TR::Node *node, vcount_t visitCount, TR_BlockStructure *block, TR_SingleBitContainer *bv)58{59}6061void TR_HCRGuardAnalysis::analyzeTreeTopsInBlockStructure(TR_BlockStructure *block)62{63}6465TR_HCRGuardAnalysis::TR_HCRGuardAnalysis(TR::Compilation *comp, TR::Optimizer *optimizer, TR_Structure *rootStructure) :66TR_UnionSingleBitContainerAnalysis(comp, comp->getFlowGraph(), optimizer, false/*comp->getOption(TR_TraceFearPointAnalysis)*/)67{68//_traceFearPointAnalysis = comp->getOption(TR_TraceFearPointAnalysis);69if (comp->getVisitCount() > 8000)70comp->resetVisitCounts(1);7172// Allocate the block info before setting the stack mark - it will be used by73// the caller74//75initializeBlockInfo();7677{78TR::StackMemoryRegion stackMemoryRegion(*trMemory());79performAnalysis(rootStructure, false);80}8182}8384bool TR_HCRGuardAnalysis::shouldSkipBlock(TR::Block *block)85{86return block->isOSRCatchBlock() || block->isOSRCodeBlock() || containsPrepareForOSR(block);87}8889void TR_HCRGuardAnalysis::initializeGenAndKillSetInfo()90{91int32_t numBits = getNumberOfBits();92for (int32_t i = 0; i < comp()->getFlowGraph()->getNextNodeNumber(); ++i)93{94_regularGenSetInfo[i] = new (trStackMemory()) TR_SingleBitContainer(numBits,trMemory(), stackAlloc);95_exceptionGenSetInfo[i] = new (trStackMemory()) TR_SingleBitContainer(numBits,trMemory(), stackAlloc);96_regularKillSetInfo[i] = new (trStackMemory()) TR_SingleBitContainer(numBits,trMemory(), stackAlloc);97_exceptionKillSetInfo[i] = new (trStackMemory()) TR_SingleBitContainer(numBits,trMemory(), stackAlloc);98}99100TR::Block *currentBlock = NULL;101int32_t blockId = -1;102TR::NodeChecklist checklist(comp());103TR::NodeChecklist exceptionNodelist(comp());104bool isGen; /* If current state is gen */105bool isKill; /* If current state is kill */106bool hasExceptionGen; /* If there exists an exception that gens*/107bool hasExceptionKill; /* If there exists an exception that kills*/108bool hasExceptionNotKill; /* If there exists an exception that doesn't kill*/109bool isYieldPoint;110111TR_ByteCodeInfo nodeBCI;112nodeBCI.setCallerIndex(-1);113nodeBCI.setByteCodeIndex(0);114nodeBCI.setDoNotProfile(false);115currentBlock = comp()->getStartTree()->getEnclosingBlock();116if (!comp()->getMethodSymbol()->supportsInduceOSR(nodeBCI, currentBlock, comp()))117_regularGenSetInfo[currentBlock->getNumber()]->setAll(numBits);118119for (TR::TreeTop *treeTop = comp()->getStartTree(); treeTop; treeTop = treeTop->getNextTreeTop())120{121TR::Node* ttNode = treeTop->getNode();122TR::Node* osrNode = NULL;123isYieldPoint = false;124if (ttNode->getOpCodeValue() == TR::BBStart)125{126currentBlock = treeTop->getEnclosingBlock();127blockId = currentBlock->getNumber();128// Reset the walk state at the beginning of each block129isGen = false;130isKill = false;131hasExceptionGen = false;132hasExceptionKill = false;133hasExceptionNotKill = false;134if (shouldSkipBlock(currentBlock))135{136_regularKillSetInfo[blockId]->setAll(numBits);137_regularGenSetInfo[blockId]->empty();138_exceptionKillSetInfo[blockId]->setAll(numBits);139_exceptionGenSetInfo[blockId]->empty();140141treeTop = currentBlock->getExit();142}143continue;144}145else if (ttNode->getOpCodeValue() == TR::BBEnd)146{147// Gen and kill are exclusive, so isGen and isKill cannot be true at the same time148if (isGen)149{150TR_ASSERT(!isKill, "isGen and isKill cannot be true at the same time");151_regularGenSetInfo[blockId]->setAll(numBits);152_regularKillSetInfo[blockId]->empty();153}154else if (isKill)155{156TR_ASSERT(!isGen, "isGen and isKill cannot be true at the same time");157_regularKillSetInfo[blockId]->setAll(numBits);158_regularGenSetInfo[blockId]->empty();159}160161// Gen should win if there exists one exception point that is or can be reached by gen162if (hasExceptionGen)163{164_exceptionGenSetInfo[blockId]->setAll(numBits);165_exceptionKillSetInfo[blockId]->empty();166}167else if (hasExceptionKill && !hasExceptionNotKill) /* All exception points have to be kill in order to kill along the exception path */168{169_exceptionKillSetInfo[blockId]->setAll(numBits);170_exceptionGenSetInfo[blockId]->empty();171}172173continue;174}175176if (comp()->isPotentialOSRPoint(ttNode, &osrNode) && !checklist.contains(osrNode))177{178checklist.add(osrNode);179isYieldPoint = true;180bool supportsOSR = comp()->isPotentialOSRPointWithSupport(treeTop);181if (supportsOSR)182{183isKill = true;184isGen = false;185}186else187{188isGen = true;189isKill = false;190}191}192else if (ttNode->isTheVirtualGuardForAGuardedInlinedCall()193&& TR_FearPointAnalysis::virtualGuardsKillFear()194&& comp()->cg()->supportsMergingGuards())195{196TR_VirtualGuard *guardInfo = comp()->findVirtualGuardInfo(ttNode);197if (guardInfo->getKind() != TR_HCRGuard)198{199// Theoretically, the guard should only kill its inlined path. However, making it right require adding200// complications to the data flow and/or optimizations using the result of the analysis. Based on the201// fact that there is few optimization opportunities on the taken side and optimizing it has little benefit,202// we require optimizations that can generate fear stay away from taken side such that considering a guard203// to be a kill for the taken side is safe.204//205isKill = true;206isGen = false;207}208}209210bool canNodeRaiseException = false;211if (ttNode->getOpCode().canRaiseException())212{213canNodeRaiseException = true;214}215else216{217// Non-treetop nodes that can raise exceptions218if (ttNode->getOpCodeValue() == TR::treetop && ttNode->getNumChildren() > 0)219{220TR::Node* node = ttNode->getFirstChild();221if (!exceptionNodelist.contains(node) && node->getOpCode().canRaiseException())222{223canNodeRaiseException = true;224exceptionNodelist.add(node);225}226}227}228229if (canNodeRaiseException)230{231// If the exception point is also a yield point, it has to be a gen.232// It's possible for the tree to yield, allowing assumptions to be invalidated,233// and then throw afterward. An OSR guard (if one is necessary) would only run234// after non-exceptional completion of the tree, so it wouldn't stop control from235// reaching the exception handler.236if (isYieldPoint)237{238hasExceptionGen = true;239}240else241{242hasExceptionGen = hasExceptionGen || isGen;243hasExceptionKill = hasExceptionKill || isKill;244hasExceptionNotKill = hasExceptionNotKill || !isKill;245}246}247248}249}250251bool TR_HCRGuardAnalysis::postInitializationProcessing()252{253return true;254}255256257