Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/compiler/ImmutableOopMapSet.java
68559 views
1
/*
2
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
package sun.jvm.hotspot.compiler;
26
27
import java.util.*;
28
29
import sun.jvm.hotspot.code.*;
30
import sun.jvm.hotspot.debugger.*;
31
import sun.jvm.hotspot.runtime.*;
32
import sun.jvm.hotspot.types.*;
33
import sun.jvm.hotspot.utilities.*;
34
import sun.jvm.hotspot.utilities.Observable;
35
import sun.jvm.hotspot.utilities.Observer;
36
37
public class ImmutableOopMapSet extends VMObject {
38
private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.compiler.ImmutableOopMapSet.DEBUG") != null;
39
40
private static CIntegerField countField;
41
private static CIntegerField sizeField;
42
private static AddressField omDataField;
43
private static int REG_COUNT;
44
private static int SAVED_ON_ENTRY_REG_COUNT;
45
private static int C_SAVED_ON_ENTRY_REG_COUNT;
46
private static long classSize;
47
48
private static class MyVisitor implements OopMapVisitor {
49
private AddressVisitor addressVisitor;
50
51
public MyVisitor(AddressVisitor oopVisitor) {
52
setAddressVisitor(oopVisitor);
53
}
54
55
public void setAddressVisitor(AddressVisitor addressVisitor) {
56
this.addressVisitor = addressVisitor;
57
}
58
59
public void visitOopLocation(Address oopAddr) {
60
addressVisitor.visitAddress(oopAddr);
61
}
62
63
public void visitDerivedOopLocation(Address baseOopAddr, Address derivedOopAddr) {
64
if (VM.getVM().isClientCompiler()) {
65
Assert.that(false, "should not reach here");
66
} else if (VM.getVM().isServerCompiler() &&
67
VM.getVM().useDerivedPointerTable()) {
68
Assert.that(false, "FIXME: add derived pointer table");
69
}
70
}
71
72
public void visitNarrowOopLocation(Address narrowOopAddr) {
73
addressVisitor.visitCompOopAddress(narrowOopAddr);
74
}
75
}
76
77
static {
78
VM.registerVMInitializedObserver(new Observer() {
79
public void update(Observable o, Object data) {
80
initialize(VM.getVM().getTypeDataBase());
81
}
82
});
83
}
84
85
private static void initialize(TypeDataBase db) {
86
Type type = db.lookupType("ImmutableOopMapSet");
87
88
countField = type.getCIntegerField("_count");
89
sizeField = type.getCIntegerField("_size");
90
classSize = type.getSize();
91
92
if (!VM.getVM().isCore()) {
93
REG_COUNT = db.lookupIntConstant("REG_COUNT").intValue();
94
if (VM.getVM().isServerCompiler()) {
95
SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("SAVED_ON_ENTRY_REG_COUNT").intValue();
96
C_SAVED_ON_ENTRY_REG_COUNT = (int) db.lookupIntConstant("C_SAVED_ON_ENTRY_REG_COUNT").intValue();
97
}
98
}
99
}
100
101
public ImmutableOopMapSet(Address addr) {
102
super(addr);
103
}
104
105
/**
106
* Returns the number of OopMaps in this ImmutableOopMapSet
107
*/
108
public int getCount() { return (int) countField.getValue(addr); }
109
110
private Address dataStart() {
111
return (pairStart().addOffsetTo(ImmutableOopMapPair.classSize() * getCount()));
112
}
113
114
private Address pairStart() {
115
return addr.addOffsetTo(ImmutableOopMapSet.classSize);
116
}
117
118
public ImmutableOopMapPair pairAt(int index) {
119
Assert.that((index >= 0) && (index < getCount()), "bad index");
120
return new ImmutableOopMapPair(pairStart().addOffsetTo(index * ImmutableOopMapPair.classSize()));
121
}
122
123
/**
124
* returns the OopMap at a given index
125
*/
126
public ImmutableOopMap getMapAt(int index) {
127
if (Assert.ASSERTS_ENABLED) {
128
Assert.that((index >= 0) && (index <= getCount()), "bad index");
129
}
130
131
ImmutableOopMapPair immutableOopMapPair = pairAt(index);
132
return getMap(immutableOopMapPair);
133
}
134
135
public ImmutableOopMap findMapAtOffset(long pcOffset, boolean debugging) {
136
int i;
137
int len = getCount();
138
if (Assert.ASSERTS_ENABLED) {
139
Assert.that(len > 0, "must have pointer maps");
140
}
141
142
// Scan through oopmaps. Stop when current offset is either equal or greater
143
// than the one we are looking for.
144
for (i = 0; i < len; i++) {
145
if (pairAt(i).getPC() >= pcOffset) {
146
break;
147
}
148
}
149
150
if (!debugging) {
151
if (Assert.ASSERTS_ENABLED) {
152
Assert.that(i < len, "oopmap not found for pcOffset = " + pcOffset + "; len = " + len);
153
Assert.that(pairAt(i).getPC() == pcOffset, "oopmap not found");
154
}
155
} else {
156
if (i == len) {
157
if (DEBUG) {
158
System.out.println("can't find oopmap at " + pcOffset);
159
System.out.print("Oopmap offsets are [ ");
160
for (i = 0; i < len; i++) {
161
System.out.print(pairAt(i).getPC());
162
}
163
System.out.println("]");
164
}
165
i = len - 1;
166
return getMapAt(i);
167
}
168
}
169
170
ImmutableOopMap m = getMapAt(i);
171
return m;
172
}
173
174
/**
175
* Visitation -- iterates through the frame for a compiled method.
176
* This is a very generic mechanism that requires the Address to be
177
* dereferenced by the callee. Other, more specialized, visitation
178
* mechanisms are given below.
179
*/
180
public static void oopsDo(Frame fr, CodeBlob cb, RegisterMap regMap, AddressVisitor oopVisitor, boolean debugging) {
181
allDo(fr, cb, regMap, new MyVisitor(oopVisitor), debugging);
182
}
183
184
/**
185
* Note that there are 4 required AddressVisitors: one for oops,
186
* one for derived oops, one for values, and one for dead values
187
*/
188
public static void allDo(Frame fr, CodeBlob cb, RegisterMap regMap, OopMapVisitor visitor, boolean debugging) {
189
if (Assert.ASSERTS_ENABLED) {
190
CodeBlob tmpCB = VM.getVM().getCodeCache().findBlob(fr.getPC());
191
Assert.that(tmpCB != null && cb.equals(tmpCB), "wrong codeblob passed in");
192
}
193
194
ImmutableOopMapSet maps = cb.getOopMaps();
195
ImmutableOopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
196
if (Assert.ASSERTS_ENABLED) {
197
Assert.that(map != null, "no ptr map found");
198
}
199
200
// handle derived pointers first (otherwise base pointer may be
201
// changed before derived pointer offset has been collected)
202
OopMapValue omv;
203
{
204
for (OopMapStream oms = new OopMapStream(map); !oms.isDone(); oms.next()) {
205
omv = oms.getCurrent();
206
if (omv.getType() != OopMapValue.OopTypes.DERIVED_OOP_VALUE) {
207
continue;
208
}
209
if (VM.getVM().isClientCompiler()) {
210
Assert.that(false, "should not reach here");
211
}
212
Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);
213
if (loc != null) {
214
Address baseLoc = fr.oopMapRegToLocation(omv.getContentReg(), regMap);
215
Address derivedLoc = loc;
216
visitor.visitDerivedOopLocation(baseLoc, derivedLoc);
217
}
218
}
219
}
220
221
// We want narow oop and oop oop_types
222
{
223
for (OopMapStream oms = new OopMapStream(map); !oms.isDone(); oms.next()) {
224
omv = oms.getCurrent();
225
Address loc = fr.oopMapRegToLocation(omv.getReg(), regMap);
226
if (loc != null) {
227
if (omv.getType() == OopMapValue.OopTypes.OOP_VALUE) {
228
// This assert commented out because this will be useful
229
// to detect in the debugging system
230
// assert(Universe::is_heap_or_null(*loc), "found non oop pointer");
231
visitor.visitOopLocation(loc);
232
} else if (omv.getType() == OopMapValue.OopTypes.NARROWOOP_VALUE) {
233
visitor.visitNarrowOopLocation(loc);
234
}
235
}
236
}
237
}
238
}
239
240
/**
241
* Update callee-saved register info for the following frame.
242
* Should only be called in non-core builds.
243
*/
244
public static void updateRegisterMap(Frame fr, CodeBlob cb, RegisterMap regMap, boolean debugging) {
245
if (Assert.ASSERTS_ENABLED) {
246
Assert.that(!VM.getVM().isCore(), "non-core builds only");
247
}
248
249
if (!VM.getVM().isDebugging()) {
250
if (Assert.ASSERTS_ENABLED) {
251
ImmutableOopMapSet maps = cb.getOopMaps();
252
Assert.that((maps != null) && (maps.getCount() > 0), "found null or empty ImmutableOopMapSet for CodeBlob");
253
}
254
} else {
255
// Hack for some topmost frames that have been found with empty
256
// OopMapSets. (Actually have not seen the null case, but don't
257
// want to take any chances.) See HSDB.showThreadStackMemory().
258
ImmutableOopMapSet maps = cb.getOopMaps();
259
if ((maps == null) || (maps.getCount() == 0)) {
260
return;
261
}
262
}
263
264
// Check if caller must update oop argument
265
regMap.setIncludeArgumentOops(cb.callerMustGCArguments());
266
267
int nofCallee = 0;
268
Address[] locs = new Address[2 * REG_COUNT + 1];
269
VMReg[] regs = new VMReg[2 * REG_COUNT + 1];
270
// ("+1" because REG_COUNT might be zero)
271
272
// Scan through oopmap and find location of all callee-saved registers
273
// (we do not do update in place, since info could be overwritten)
274
ImmutableOopMap map = cb.getOopMapForReturnAddress(fr.getPC(), debugging);
275
if (Assert.ASSERTS_ENABLED) {
276
Assert.that(map != null, "no ptr map found");
277
}
278
279
OopMapValue omv = null;
280
for (OopMapStream oms = new OopMapStream(map); !oms.isDone(); oms.next()) {
281
omv = oms.getCurrent();
282
if (omv.getType() != OopMapValue.OopTypes.CALLEE_SAVED_VALUE) {
283
continue;
284
}
285
if (Assert.ASSERTS_ENABLED) {
286
Assert.that(nofCallee < 2 * REG_COUNT, "overflow");
287
}
288
regs[nofCallee] = omv.getContentReg();
289
locs[nofCallee] = fr.oopMapRegToLocation(omv.getReg(), regMap);
290
nofCallee++;
291
}
292
293
// Check that runtime stubs save all callee-saved registers
294
// After adapter frames were deleted C2 doesn't use callee save registers at present
295
if (Assert.ASSERTS_ENABLED) {
296
if (VM.getVM().isServerCompiler()) {
297
Assert.that(!cb.isRuntimeStub() ||
298
(nofCallee >= SAVED_ON_ENTRY_REG_COUNT || nofCallee >= C_SAVED_ON_ENTRY_REG_COUNT),
299
"must save all");
300
}
301
}
302
303
// Copy found callee-saved register to reg_map
304
for (int i = 0; i < nofCallee; i++) {
305
regMap.setLocation(regs[i], locs[i]);
306
}
307
}
308
309
public ImmutableOopMapPair getPairAt(int index) {
310
return pairAt(index);
311
}
312
313
private int getSize() {
314
return (int) sizeField.getValue(addr);
315
}
316
317
public ImmutableOopMap getMap(ImmutableOopMapPair pair) {
318
Assert.that(pair.getOffset() < getSize(), "boundary check: this: " + this + " offset: " + pair);
319
return new ImmutableOopMap(dataStart().addOffsetTo(pair.getOffset()));
320
}
321
322
public String toString() {
323
StringBuilder builder = new StringBuilder();
324
builder.append("Set{ ")
325
.append("addr = ").append(addr)
326
.append(", count = ").append(getCount())
327
.append(", size = ").append(getSize())
328
.append(", pairs = [");
329
330
for (int i = 0; i < getCount(); ++i) {
331
builder.append(getPairAt(i));
332
}
333
334
builder.append("]");
335
return builder.toString();
336
}
337
}
338
339