Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/optimizer/EscapeAnalysisTools.cpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2019, 2020 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* 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-exception
21
*******************************************************************************/
22
23
#include "optimizer/EscapeAnalysisTools.hpp"
24
#include "il/Block.hpp"
25
#include "il/Node.hpp"
26
#include "il/Node_inlines.hpp"
27
#include "il/TreeTop.hpp"
28
#include "il/SymbolReference.hpp"
29
#include "il/AutomaticSymbol.hpp"
30
31
TR_EscapeAnalysisTools::TR_EscapeAnalysisTools(TR::Compilation *comp)
32
{
33
_loads = NULL;
34
_comp = comp;
35
}
36
37
void TR_EscapeAnalysisTools::insertFakeEscapeForLoads(TR::Block *block, TR::Node *node, NodeDeque *loads)
38
{
39
//TR::Node *fakePrepare = TR::Node::createWithSymRef(node, TR::call, loads->size(), _comp->getSymRefTab()->findOrCreateRuntimeHelper(TR_prepareForOSR, false, false, true));
40
TR::Node *fakePrepare = TR::Node::createEAEscapeHelperCall(node, loads->size());
41
int idx = 0;
42
for (auto itr = loads->begin(), end = loads->end(); itr != end; ++itr)
43
{
44
(*itr)->setByteCodeInfo(node->getByteCodeInfo());
45
fakePrepare->setAndIncChild(idx++, *itr);
46
}
47
dumpOptDetails(_comp, " Adding fake prepare n%dn to OSR induction block_%d\n", fakePrepare->getGlobalIndex(), block->getNumber());
48
block->getLastRealTreeTop()->insertBefore(
49
TR::TreeTop::create(_comp, TR::Node::create(node, TR::treetop, 1, fakePrepare)));
50
}
51
52
void TR_EscapeAnalysisTools::insertFakeEscapeForOSR(TR::Block *block, TR::Node *induceCall)
53
{
54
if (_loads == NULL)
55
_loads = new (_comp->trMemory()->currentStackRegion()) NodeDeque(NodeDequeAllocator(_comp->trMemory()->currentStackRegion()));
56
else
57
_loads->clear();
58
59
TR_ByteCodeInfo &bci = induceCall->getByteCodeInfo();
60
61
int32_t inlinedIndex = bci.getCallerIndex();
62
int32_t byteCodeIndex = bci.getByteCodeIndex();
63
TR_OSRCompilationData *osrCompilationData = _comp->getOSRCompilationData();
64
65
// The symrefs provided through OSR liveness data are only valid at the
66
// point of the OSR liveness analysis. After transformations have been
67
// applied to the trees, stores to those original symbols might have been
68
// eliminated, so they cannot be relied upon directly on the eaEscapeHelper
69
// call. Instead, we use the DefiningMaps which provide a map from each
70
// symref in the OSR liveness data to the symrefs whose definitions in the
71
// current trees correspond to the definition of the original symref at the
72
// point of the OSR liveness analysis.
73
//
74
// Setting the TR_DisableEAEscapeHelperDefiningMap environment variable
75
// prevents the use of DefiningMaps in setting up the eaEscapeHelper call.
76
// This might be used to help identify problems in the DefiningMaps, but
77
// setting it will fall back to using the original OSR liveness data
78
// instead, which itself may very well be incorrect. Setting this
79
// environment variable should not be relied upon as a work around.
80
//
81
TR_OSRMethodData *osrMethodData = _comp->getOSRCompilationData()->getOSRMethodDataArray()[inlinedIndex + 1];
82
static char *disableEADefiningMap = feGetEnv("TR_DisableEAEscapeHelperDefiningMap");
83
DefiningMap *induceDefiningMap = !disableEADefiningMap ? osrMethodData->getDefiningMap() : NULL;
84
85
if (_comp->trace(OMR::escapeAnalysis) && induceDefiningMap)
86
{
87
traceMsg(_comp, "definingMap at induceCall n%dn %d:%d\n", induceCall->getGlobalIndex(), induceCall->getByteCodeInfo().getCallerIndex(), induceCall->getByteCodeInfo().getByteCodeIndex());
88
_comp->getOSRCompilationData()->printMap(induceDefiningMap);
89
}
90
91
// Gather all live autos and pending pushes at this point for inlined methods in _loads
92
// This ensures objects that EA can stack allocate will be heapified if OSR is induced
93
while (inlinedIndex > -1)
94
{
95
TR::ResolvedMethodSymbol *rms = _comp->getInlinedResolvedMethodSymbol(inlinedIndex);
96
TR_ASSERT_FATAL(rms, "Unknown resolved method during escapetools");
97
TR_OSRMethodData *methodData = osrCompilationData->findOSRMethodData(inlinedIndex, rms);
98
processAutosAndPendingPushes(rms, induceDefiningMap, methodData, byteCodeIndex);
99
byteCodeIndex = _comp->getInlinedCallSite(inlinedIndex)._byteCodeInfo.getByteCodeIndex();
100
inlinedIndex = _comp->getInlinedCallSite(inlinedIndex)._byteCodeInfo.getCallerIndex();
101
}
102
103
// handle the outermost method
104
{
105
TR_OSRMethodData *methodData = osrCompilationData->findOSRMethodData(-1, _comp->getMethodSymbol());
106
processAutosAndPendingPushes(_comp->getMethodSymbol(), induceDefiningMap, methodData, byteCodeIndex);
107
}
108
insertFakeEscapeForLoads(block, induceCall, _loads);
109
}
110
111
void TR_EscapeAnalysisTools::processAutosAndPendingPushes(TR::ResolvedMethodSymbol *rms, DefiningMap *induceDefiningMap, TR_OSRMethodData *methodData, int32_t byteCodeIndex)
112
{
113
processSymbolReferences(rms->getAutoSymRefs(), induceDefiningMap, methodData->getLiveRangeInfo(byteCodeIndex));
114
processSymbolReferences(rms->getPendingPushSymRefs(), induceDefiningMap, methodData->getPendingPushLivenessInfo(byteCodeIndex));
115
}
116
117
void TR_EscapeAnalysisTools::processSymbolReferences(TR_Array<List<TR::SymbolReference>> *symbolReferences, DefiningMap *induceDefiningMap, TR_BitVector *deadSymRefs)
118
{
119
for (int i = 0; symbolReferences && i < symbolReferences->size(); i++)
120
{
121
List<TR::SymbolReference> autosList = (*symbolReferences)[i];
122
ListIterator<TR::SymbolReference> autosIt(&autosList);
123
for (TR::SymbolReference* symRef = autosIt.getFirst(); symRef; symRef = autosIt.getNext())
124
{
125
TR::Symbol *p = symRef->getSymbol();
126
if ((p->isAuto() || p->isParm()) && p->getDataType() == TR::Address)
127
{
128
// If no DefiningMap is available for the current sym ref, or the
129
// DefiningMap is empty, simply use the sym ref on the
130
// eaEscapeHelper if it's live. Otherwise, walk through the
131
// DefiningMap and place all the sym refs for autos and parameters
132
// whose definitions map to the sym ref from the OSR
133
// liveness data that we're currently looking at.
134
if (!induceDefiningMap
135
|| induceDefiningMap->find(symRef->getReferenceNumber()) == induceDefiningMap->end())
136
{
137
if (deadSymRefs == NULL || !deadSymRefs->isSet(symRef->getReferenceNumber()))
138
{
139
_loads->push_back(TR::Node::createWithSymRef(TR::aload, 0, symRef));
140
}
141
}
142
else
143
{
144
TR_BitVector *definingSyms = (*induceDefiningMap)[symRef->getReferenceNumber()];
145
TR_BitVectorIterator definingSymsIt(*definingSyms);
146
while (definingSymsIt.hasMoreElements())
147
{
148
int32_t definingSymRefNum = definingSymsIt.getNextElement();
149
TR::SymbolReference *definingSymRef = _comp->getSymRefTab()->getSymRef(definingSymRefNum);
150
TR::Symbol *definingSym = definingSymRef->getSymbol();
151
152
if ((definingSym->isAuto() || definingSym->isParm())
153
&& (deadSymRefs == NULL || !deadSymRefs->isSet(definingSymRefNum)))
154
{
155
_loads->push_back(TR::Node::createWithSymRef(TR::aload, 0, definingSymRef));
156
}
157
}
158
}
159
}
160
}
161
}
162
}
163
164