Path: blob/master/runtime/compiler/optimizer/EscapeAnalysisTools.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2019, 2020 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/EscapeAnalysisTools.hpp"23#include "il/Block.hpp"24#include "il/Node.hpp"25#include "il/Node_inlines.hpp"26#include "il/TreeTop.hpp"27#include "il/SymbolReference.hpp"28#include "il/AutomaticSymbol.hpp"2930TR_EscapeAnalysisTools::TR_EscapeAnalysisTools(TR::Compilation *comp)31{32_loads = NULL;33_comp = comp;34}3536void TR_EscapeAnalysisTools::insertFakeEscapeForLoads(TR::Block *block, TR::Node *node, NodeDeque *loads)37{38//TR::Node *fakePrepare = TR::Node::createWithSymRef(node, TR::call, loads->size(), _comp->getSymRefTab()->findOrCreateRuntimeHelper(TR_prepareForOSR, false, false, true));39TR::Node *fakePrepare = TR::Node::createEAEscapeHelperCall(node, loads->size());40int idx = 0;41for (auto itr = loads->begin(), end = loads->end(); itr != end; ++itr)42{43(*itr)->setByteCodeInfo(node->getByteCodeInfo());44fakePrepare->setAndIncChild(idx++, *itr);45}46dumpOptDetails(_comp, " Adding fake prepare n%dn to OSR induction block_%d\n", fakePrepare->getGlobalIndex(), block->getNumber());47block->getLastRealTreeTop()->insertBefore(48TR::TreeTop::create(_comp, TR::Node::create(node, TR::treetop, 1, fakePrepare)));49}5051void TR_EscapeAnalysisTools::insertFakeEscapeForOSR(TR::Block *block, TR::Node *induceCall)52{53if (_loads == NULL)54_loads = new (_comp->trMemory()->currentStackRegion()) NodeDeque(NodeDequeAllocator(_comp->trMemory()->currentStackRegion()));55else56_loads->clear();5758TR_ByteCodeInfo &bci = induceCall->getByteCodeInfo();5960int32_t inlinedIndex = bci.getCallerIndex();61int32_t byteCodeIndex = bci.getByteCodeIndex();62TR_OSRCompilationData *osrCompilationData = _comp->getOSRCompilationData();6364// The symrefs provided through OSR liveness data are only valid at the65// point of the OSR liveness analysis. After transformations have been66// applied to the trees, stores to those original symbols might have been67// eliminated, so they cannot be relied upon directly on the eaEscapeHelper68// call. Instead, we use the DefiningMaps which provide a map from each69// symref in the OSR liveness data to the symrefs whose definitions in the70// current trees correspond to the definition of the original symref at the71// point of the OSR liveness analysis.72//73// Setting the TR_DisableEAEscapeHelperDefiningMap environment variable74// prevents the use of DefiningMaps in setting up the eaEscapeHelper call.75// This might be used to help identify problems in the DefiningMaps, but76// setting it will fall back to using the original OSR liveness data77// instead, which itself may very well be incorrect. Setting this78// environment variable should not be relied upon as a work around.79//80TR_OSRMethodData *osrMethodData = _comp->getOSRCompilationData()->getOSRMethodDataArray()[inlinedIndex + 1];81static char *disableEADefiningMap = feGetEnv("TR_DisableEAEscapeHelperDefiningMap");82DefiningMap *induceDefiningMap = !disableEADefiningMap ? osrMethodData->getDefiningMap() : NULL;8384if (_comp->trace(OMR::escapeAnalysis) && induceDefiningMap)85{86traceMsg(_comp, "definingMap at induceCall n%dn %d:%d\n", induceCall->getGlobalIndex(), induceCall->getByteCodeInfo().getCallerIndex(), induceCall->getByteCodeInfo().getByteCodeIndex());87_comp->getOSRCompilationData()->printMap(induceDefiningMap);88}8990// Gather all live autos and pending pushes at this point for inlined methods in _loads91// This ensures objects that EA can stack allocate will be heapified if OSR is induced92while (inlinedIndex > -1)93{94TR::ResolvedMethodSymbol *rms = _comp->getInlinedResolvedMethodSymbol(inlinedIndex);95TR_ASSERT_FATAL(rms, "Unknown resolved method during escapetools");96TR_OSRMethodData *methodData = osrCompilationData->findOSRMethodData(inlinedIndex, rms);97processAutosAndPendingPushes(rms, induceDefiningMap, methodData, byteCodeIndex);98byteCodeIndex = _comp->getInlinedCallSite(inlinedIndex)._byteCodeInfo.getByteCodeIndex();99inlinedIndex = _comp->getInlinedCallSite(inlinedIndex)._byteCodeInfo.getCallerIndex();100}101102// handle the outermost method103{104TR_OSRMethodData *methodData = osrCompilationData->findOSRMethodData(-1, _comp->getMethodSymbol());105processAutosAndPendingPushes(_comp->getMethodSymbol(), induceDefiningMap, methodData, byteCodeIndex);106}107insertFakeEscapeForLoads(block, induceCall, _loads);108}109110void TR_EscapeAnalysisTools::processAutosAndPendingPushes(TR::ResolvedMethodSymbol *rms, DefiningMap *induceDefiningMap, TR_OSRMethodData *methodData, int32_t byteCodeIndex)111{112processSymbolReferences(rms->getAutoSymRefs(), induceDefiningMap, methodData->getLiveRangeInfo(byteCodeIndex));113processSymbolReferences(rms->getPendingPushSymRefs(), induceDefiningMap, methodData->getPendingPushLivenessInfo(byteCodeIndex));114}115116void TR_EscapeAnalysisTools::processSymbolReferences(TR_Array<List<TR::SymbolReference>> *symbolReferences, DefiningMap *induceDefiningMap, TR_BitVector *deadSymRefs)117{118for (int i = 0; symbolReferences && i < symbolReferences->size(); i++)119{120List<TR::SymbolReference> autosList = (*symbolReferences)[i];121ListIterator<TR::SymbolReference> autosIt(&autosList);122for (TR::SymbolReference* symRef = autosIt.getFirst(); symRef; symRef = autosIt.getNext())123{124TR::Symbol *p = symRef->getSymbol();125if ((p->isAuto() || p->isParm()) && p->getDataType() == TR::Address)126{127// If no DefiningMap is available for the current sym ref, or the128// DefiningMap is empty, simply use the sym ref on the129// eaEscapeHelper if it's live. Otherwise, walk through the130// DefiningMap and place all the sym refs for autos and parameters131// whose definitions map to the sym ref from the OSR132// liveness data that we're currently looking at.133if (!induceDefiningMap134|| induceDefiningMap->find(symRef->getReferenceNumber()) == induceDefiningMap->end())135{136if (deadSymRefs == NULL || !deadSymRefs->isSet(symRef->getReferenceNumber()))137{138_loads->push_back(TR::Node::createWithSymRef(TR::aload, 0, symRef));139}140}141else142{143TR_BitVector *definingSyms = (*induceDefiningMap)[symRef->getReferenceNumber()];144TR_BitVectorIterator definingSymsIt(*definingSyms);145while (definingSymsIt.hasMoreElements())146{147int32_t definingSymRefNum = definingSymsIt.getNextElement();148TR::SymbolReference *definingSymRef = _comp->getSymRefTab()->getSymRef(definingSymRefNum);149TR::Symbol *definingSym = definingSymRef->getSymbol();150151if ((definingSym->isAuto() || definingSym->isParm())152&& (deadSymRefs == NULL || !deadSymRefs->isSet(definingSymRefNum)))153{154_loads->push_back(TR::Node::createWithSymRef(TR::aload, 0, definingSymRef));155}156}157}158}159}160}161}162163164