Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/optimizer/HotFieldMarking.cpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2020, 2021 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/HotFieldMarking.hpp"
24
#include "env/j9method.h"
25
#include "il/Block.hpp"
26
#include "il/Node.hpp"
27
#include "il/Node_inlines.hpp"
28
#include "il/SymbolReference.hpp"
29
#include "il/TreeTop.hpp"
30
#include "infra/ILWalk.hpp"
31
#include "optimizer/Optimizer.hpp"
32
#include "optimizer/Optimization.hpp"
33
#include "optimizer/Optimization_inlines.hpp"
34
#include "optimizer/OptimizationManager.hpp"
35
36
#include <map>
37
38
/**
39
* @struct that represents the statistics related to each field during a compilation
40
* Member '_count' contains the number of blocks within the compilation that contributes to the frequency score value of the field
41
* Member '_score' contains the combined block frequency score of the field for the compilation
42
* Member '_clazz' contains the class of the field
43
*/
44
struct SymStats
45
{
46
int32_t _count;
47
int32_t _score;
48
int32_t _fieldNameLength;
49
char* _fieldName;
50
int32_t _fieldSigLength;
51
char* _fieldSig;
52
TR_OpaqueClassBlock *_clazz;
53
SymStats(int32_t count, int32_t score, int32_t fieldNameLength, char* fieldName, int32_t fieldSigLength, char* fieldSig, TR_OpaqueClassBlock *clazz) :
54
_count(count), _score(score), _fieldNameLength(fieldNameLength), _fieldName(fieldName), _fieldSigLength(fieldSigLength), _fieldSig(fieldSig), _clazz(clazz) {}
55
};
56
57
typedef TR::typed_allocator<std::pair<TR::Symbol* const, SymStats *>, TR::Region&> SymAggMapAllocator;
58
typedef std::less<TR::Symbol *> SymAggMapComparator;
59
typedef std::map<TR::Symbol *, SymStats *, SymAggMapComparator, SymAggMapAllocator> SymAggMap;
60
typedef int32_t(*BlockFrequencyReducer)(int32_t, int32_t, int32_t);
61
62
static int32_t getReducedFrequencySum(int32_t currentValue, int32_t count, int32_t newFrequency)
63
{
64
return (currentValue + newFrequency);
65
}
66
67
static int32_t getReducedFrequencyAverage(int32_t currentValue, int32_t count, int32_t newFrequency)
68
{
69
return ((currentValue * count) + newFrequency) / (count + 1);
70
}
71
72
static int32_t getReducedFrequencyMax(int32_t currentValue, int32_t count, int32_t newFrequency)
73
{
74
return (currentValue < newFrequency) ? newFrequency : currentValue;
75
}
76
77
int32_t TR_HotFieldMarking::perform()
78
{
79
if (!TR::Compiler->om.isHotReferenceFieldRequired())
80
{
81
if (trace())
82
traceMsg(comp(), "Skipping hot field marking since dynamic breadth first scan ordering is disabled\n");
83
return 0;
84
}
85
86
SymAggMap stats((SymAggMapComparator()), SymAggMapAllocator(comp()->trMemory()->currentStackRegion()));
87
TR::Block *block = NULL;
88
89
static BlockFrequencyReducer getReducedFrequency;
90
if(TR::Options::getReductionAlgorithm(TR_HotFieldReductionAlgorithmSum))
91
{
92
getReducedFrequency = getReducedFrequencySum;
93
}
94
else if(TR::Options::getReductionAlgorithm(TR_HotFieldReductionAlgorithmMax))
95
{
96
getReducedFrequency = getReducedFrequencyMax;
97
}
98
else
99
{
100
getReducedFrequency = getReducedFrequencyAverage;
101
}
102
103
for (TR::PostorderNodeIterator it(comp()->getStartTree(), comp()); it != NULL; ++it)
104
{
105
TR::Node * const node = it.currentNode();
106
if (node->getOpCodeValue() == TR::BBStart)
107
{
108
block = node->getBlock();
109
}
110
else if ((node->getOpCode().isLoadIndirect() || node->getOpCode().isStoreIndirect())
111
&& node->getOpCode().hasSymbolReference()
112
&& !node->getSymbolReference()->isUnresolved()
113
&& node->getSymbolReference()->getSymbol()->isShadow()
114
&& !node->isInternalPointer()
115
&& !node->getOpCode().isArrayLength()
116
&& node->getSymbolReference()->getSymbol()->isCollectedReference()
117
)
118
{
119
TR::SymbolReference *symRef = node->getSymbolReference();
120
if (symRef->getCPIndex() >= 0 && !symRef->getSymbol()->isArrayShadowSymbol())
121
{
122
auto itr = stats.find(symRef->getSymbol());
123
if (itr != stats.end())
124
{
125
itr->second->_score = getReducedFrequency(itr->second->_score, itr->second->_count, block->getFrequency());
126
itr->second->_count += 1;
127
continue;
128
}
129
130
TR::ResolvedMethodSymbol *rms = comp()->getOwningMethodSymbol(symRef->getOwningMethodIndex());
131
TR_ResolvedMethod *method = rms->getResolvedMethod();
132
133
int32_t fieldNameLength = 0;
134
char *fieldName = method->fieldNameChars(symRef->getCPIndex(), fieldNameLength);
135
int32_t fieldSigLength = 0;
136
char *fieldSig = method->fieldSignatureChars(symRef->getCPIndex(), fieldSigLength);
137
bool isStatic = false;
138
TR_OpaqueClassBlock *containingClass = static_cast<TR_ResolvedJ9Method*>(method)->definingClassFromCPFieldRef(comp(), symRef->getCPIndex(), isStatic);
139
if (isStatic)
140
continue;
141
142
stats[symRef->getSymbol()] = new (trStackMemory()) SymStats(1, block->getFrequency(), fieldNameLength, fieldName, fieldSigLength, fieldSig, containingClass);
143
}
144
}
145
}
146
147
for (auto itr = stats.begin(), end = stats.end(); itr != end; ++itr)
148
{
149
if (itr->second->_score >= TR::Options::_hotFieldThreshold)
150
{
151
uint32_t fieldOffset = (comp()->fej9()->getInstanceFieldOffset(itr->second->_clazz, itr->second->_fieldName, itr->second->_fieldNameLength, itr->second->_fieldSig, itr->second->_fieldSigLength) + TR::Compiler->om.objectHeaderSizeInBytes()) / TR::Compiler->om.sizeofReferenceField();
152
153
if (!comp()->fej9()->isAnonymousClass(itr->second->_clazz) && performTransformation(comp(), "%sUpdate hot field info for hot field. fieldSignature: %s; fieldName: %s; frequencyScore = %d\n", optDetailString(), itr->second->_fieldSig, itr->second->_fieldName, itr->second->_score) && (fieldOffset < U_8_MAX))
154
{
155
comp()->fej9()->reportHotField(getUtilization(), TR::Compiler->cls.convertClassOffsetToClassPtr(itr->second->_clazz), (uint8_t)fieldOffset, itr->second->_score);
156
if (comp()->getOption(TR_TraceMarkingOfHotFields))
157
{
158
int32_t classNameLength = 0;
159
char *className = comp()->fej9()->getClassNameChars(itr->second->_clazz, classNameLength);
160
traceMsg(comp(), "<traceMarkingOfHotFields\n"
161
"\tmethodSignature=\"%s\"\n"
162
"\tmethodHotness=\"%s\"\n"
163
"\tclassName=\"%s\"\n"
164
"\tfieldName=\"%s\""
165
"\tfieldSig=\"%s\""
166
"\tfrequencyScore=%d"
167
"\tfieldOffset=%d>\n",
168
comp()->signature(), comp()->getHotnessName(comp()->getMethodHotness()), className, itr->second->_fieldName, itr->second->_fieldSig, itr->second->_score, fieldOffset);
169
}
170
}
171
}
172
}
173
return 1;
174
}
175
176
int32_t TR_HotFieldMarking::getUtilization()
177
{
178
static const char *hotFieldMarkingUtilizationWarmAndBelow;
179
static int32_t hotFieldMarkingUtilizationWarmAndBelowValue = (hotFieldMarkingUtilizationWarmAndBelow = feGetEnv("TR_hotFieldMarkingUtilizationWarmAndBelow")) ? atoi(hotFieldMarkingUtilizationWarmAndBelow) : 1;
180
181
static const char *hotFieldMarkingUtilizationHot;
182
static int32_t hotFieldMarkingUtilizationHotValue = (hotFieldMarkingUtilizationHot = feGetEnv("TR_hotFieldMarkingUtilizationHot")) ? atoi(hotFieldMarkingUtilizationHot) : 10;
183
184
static const char *hotFieldMarkingUtilizationScorching;
185
static int32_t hotFieldMarkingUtilizationScorchingValue = (hotFieldMarkingUtilizationScorching = feGetEnv("TR_hotFieldMarkingUtilizationScorching")) ? atoi(hotFieldMarkingUtilizationScorching) : 100;
186
187
switch (comp()->getMethodHotness())
188
{
189
case noOpt:
190
case cold:
191
case warm:
192
return hotFieldMarkingUtilizationWarmAndBelowValue;
193
case hot:
194
return hotFieldMarkingUtilizationHotValue;
195
case veryHot:
196
case scorching:
197
return hotFieldMarkingUtilizationScorchingValue;
198
default:
199
TR_ASSERT(false, "Unable handled hotness for utilization calculation");
200
}
201
return 0;
202
}
203
204
const char *
205
TR_HotFieldMarking::optDetailString() const throw()
206
{
207
return "O^O HOT FIELD MARKING: ";
208
}
209
210