Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java
41161 views
1
/*
2
* Copyright (c) 2000, 2020, 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.runtime;
26
27
import java.util.*;
28
import sun.jvm.hotspot.code.*;
29
import sun.jvm.hotspot.debugger.*;
30
import sun.jvm.hotspot.oops.*;
31
import sun.jvm.hotspot.utilities.*;
32
33
/** FIXME: missing many accessors; all we have right now is the method
34
and BCI. NOTE that this has been modified from the VM's version to
35
handle NULL ScopeDescs for the debugging case. This simplifies
36
using code a great deal. */
37
38
public class CompiledVFrame extends JavaVFrame {
39
private ScopeDesc scope;
40
private boolean mayBeImprecise;
41
42
public CompiledVFrame(Frame fr, RegisterMap regMap, JavaThread thread, ScopeDesc scope, boolean mayBeImprecise) {
43
super(fr, regMap, thread);
44
this.scope = scope;
45
this.mayBeImprecise = mayBeImprecise;
46
if (!VM.getVM().isDebugging()) {
47
Assert.that(scope != null, "scope must be present");
48
}
49
}
50
51
public boolean isTop() {
52
if (VM.getVM().isDebugging()) {
53
return (getScope() == null || getScope().isTop());
54
} else {
55
return getScope().isTop();
56
}
57
}
58
59
public boolean isCompiledFrame() {
60
return true;
61
}
62
63
public boolean isDeoptimized() {
64
return fr.isDeoptimized();
65
}
66
67
public boolean mayBeImpreciseDbg() {
68
return mayBeImprecise;
69
}
70
71
/** Returns the active method */
72
public NMethod getCode() {
73
return VM.getVM().getCodeCache().findNMethod(fr.getPC());
74
}
75
76
/** Returns the active method. Does not perform a guarantee
77
regarding unloaded methods -- more suitable for debugging
78
system. */
79
public NMethod getCodeUnsafe() {
80
return VM.getVM().getCodeCache().findNMethodUnsafe(fr.getPC());
81
}
82
83
/** Returns the ScopeDesc */
84
public ScopeDesc getScope() {
85
return scope;
86
}
87
88
public Method getMethod() {
89
if (VM.getVM().isDebugging() && getScope() == null) {
90
return getCodeUnsafe().getMethod();
91
}
92
return getScope().getMethod();
93
}
94
95
public StackValueCollection getLocals() {
96
if (getScope() == null)
97
return new StackValueCollection();
98
List<ScopeValue> scvList = getScope().getLocals();
99
if (scvList == null)
100
return new StackValueCollection();
101
102
// scvList is the list of ScopeValues describing the JVM stack state.
103
// There is one scv_list entry for every JVM stack state in use.
104
int length = scvList.size();
105
StackValueCollection result = new StackValueCollection(length);
106
for( int i = 0; i < length; i++ )
107
result.add( createStackValue(scvList.get(i)) );
108
109
return result;
110
}
111
112
public StackValueCollection getExpressions() {
113
if (getScope() == null)
114
return new StackValueCollection();
115
List<ScopeValue> scvList = getScope().getExpressions();
116
if (scvList == null)
117
return new StackValueCollection();
118
119
// scvList is the list of ScopeValues describing the JVM stack state.
120
// There is one scv_list entry for every JVM stack state in use.
121
int length = scvList.size();
122
StackValueCollection result = new StackValueCollection(length);
123
for( int i = 0; i < length; i++ )
124
result.add( createStackValue(scvList.get(i)) );
125
126
return result;
127
}
128
129
public List<MonitorInfo> getMonitors() {
130
if (getScope() == null) {
131
return new ArrayList<>();
132
}
133
List<MonitorValue> monitors = getScope().getMonitors();
134
if (monitors == null) {
135
return new ArrayList<>();
136
}
137
List<MonitorInfo> result = new ArrayList<>(monitors.size());
138
for (int i = 0; i < monitors.size(); i++) {
139
MonitorValue mv = monitors.get(i);
140
ScopeValue ov = mv.owner();
141
StackValue ownerSV = createStackValue(ov); // it is an oop
142
if (ov.isObject()) { // The owner object was scalar replaced
143
Assert.that(mv.eliminated() && ownerSV.objIsScalarReplaced(), "monitor should be eliminated for scalar replaced object");
144
// Put klass for scalar replaced object.
145
ScopeValue kv = ((ObjectValue)ov).getKlass();
146
Assert.that(kv.isConstantOop(), "klass should be oop constant for scalar replaced object");
147
OopHandle k = ((ConstantOopReadValue)kv).getValue();
148
result.add(new MonitorInfo(k, resolveMonitorLock(mv.basicLock()), mv.eliminated(), true));
149
} else {
150
result.add(new MonitorInfo(ownerSV.getObject(), resolveMonitorLock(mv.basicLock()), mv.eliminated(), false));
151
}
152
}
153
return result;
154
}
155
156
public int getBCI() {
157
int raw = getRawBCI();
158
return ((raw == DebugInformationRecorder.SYNCHRONIZATION_ENTRY_BCI) ? 0 : raw);
159
}
160
161
/** Returns SynchronizationEntryBCI or bci() (used for synchronization) */
162
public int getRawBCI() {
163
if (VM.getVM().isDebugging() && getScope() == null) {
164
return 0; // No debugging information!
165
}
166
return getScope().getBCI();
167
}
168
169
/** Returns the sender vframe */
170
public VFrame sender() {
171
if (Assert.ASSERTS_ENABLED) {
172
Assert.that(isTop(), "just checking");
173
}
174
return sender(false);
175
}
176
177
public VFrame sender(boolean mayBeImprecise) {
178
if (!VM.getVM().isDebugging()) {
179
if (Assert.ASSERTS_ENABLED) {
180
Assert.that(scope != null, "When new stub generator is in place, then scope can never be NULL");
181
}
182
}
183
Frame f = (Frame) getFrame().clone();
184
return (isTop()
185
? super.sender(false)
186
: new CompiledVFrame(f, getRegisterMap(), getThread(), getScope().sender(), mayBeImprecise));
187
}
188
189
private StackValue createStackValue(ScopeValue sv) {
190
// FIXME: this code appears to be out-of-date with respect to the VM especially in 64-bit mode
191
if (sv.isLocation()) {
192
// Stack or register value
193
Location loc = ((LocationValue) sv).getLocation();
194
195
if (loc.isIllegal()) return new StackValue();
196
197
// First find address of value
198
Address valueAddr = loc.isRegister()
199
// Value was in a callee-save register
200
? getRegisterMap().getLocation(new VMReg(loc.getRegisterNumber()))
201
// Else value was directly saved on the stack. The frame's original stack pointer,
202
// before any extension by its callee (due to Compiler1 linkage on SPARC), must be used.
203
: ((Address)fr.getUnextendedSP()).addOffsetTo(loc.getStackOffset());
204
205
// Then package it right depending on type
206
if (loc.holdsFloat()) { // Holds a float in a double register?
207
// The callee has no clue whether the register holds a float,
208
// double or is unused. He always saves a double. Here we know
209
// a double was saved, but we only want a float back. Narrow the
210
// saved double to the float that the JVM wants.
211
if (Assert.ASSERTS_ENABLED) {
212
Assert.that( loc.isRegister(), "floats always saved to stack in 1 word" );
213
}
214
float value = (float) valueAddr.getJDoubleAt(0);
215
return new StackValue(Float.floatToIntBits(value) & 0xFFFFFFFF); // 64-bit high half is stack junk
216
} else if (loc.holdsInt()) { // Holds an int in a long register?
217
// The callee has no clue whether the register holds an int,
218
// long or is unused. He always saves a long. Here we know
219
// a long was saved, but we only want an int back. Narrow the
220
// saved long to the int that the JVM wants.
221
if (Assert.ASSERTS_ENABLED) {
222
Assert.that( loc.isRegister(), "ints always saved to stack in 1 word" );
223
}
224
return new StackValue(valueAddr.getJLongAt(0) & 0xFFFFFFFF);
225
} else if (loc.holdsNarrowOop()) { // Holds an narrow oop?
226
if (loc.isRegister() && VM.getVM().isBigEndian()) {
227
// The callee has no clue whether the register holds an narrow oop,
228
// long or is unused. He always saves a long. Here we know
229
// a long was saved, but we only want an narrow oop back. Narrow the
230
// saved long to the narrow oop that the JVM wants.
231
return new StackValue(valueAddr.getCompOopHandleAt(VM.getVM().getIntSize()), 0);
232
} else {
233
return new StackValue(valueAddr.getCompOopHandleAt(0), 0);
234
}
235
} else if( loc.holdsOop() ) { // Holds an oop?
236
return new StackValue(valueAddr.getOopHandleAt(0), 0);
237
} else if( loc.holdsDouble() ) {
238
// Double value in a single stack slot
239
return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF);
240
} else if(loc.holdsAddr()) {
241
if (Assert.ASSERTS_ENABLED) {
242
Assert.that(!VM.getVM().isServerCompiler(), "No address type for locations with C2 (jsr-s are inlined)");
243
}
244
// FIXME: not yet implemented (no access to safepoint state yet)
245
return new StackValue(0);
246
// intptr_t return_addr_tmp = *(intptr_t *)value_addr;
247
// int bci = -1;
248
// // Get the bci of the jsr that generated this returnAddress value.
249
// // If the destination of a jsr is a block that ends with a return or throw, then
250
// // the GraphBuilder converts the jsr into a direct goto. This has the side effect that
251
// // the return address for the jsr gets emitted as a bci instead of as a real pc
252
// if (code()->contains((address)return_addr_tmp)) {
253
// ScopeDesc* scope = code()->scope_desc_at((address)(return_addr_tmp - jsr_call_offset), false);
254
// bci = scope->bci();
255
// } else {
256
// bci = (int)return_addr_tmp;
257
// }
258
// // no need to lock method as this happens at Safepoint
259
// assert (SafepointSynchronize::is_at_safepoint(), "must be at safepoint, otherwise lock method()");
260
// // make sure bci points to jsr
261
// Bytecode* bytecode = Bytecode_at(method()->bcp_from(bci));
262
// Bytecodes::Code bc = bytecode->code();
263
// assert (bc == Bytecodes::_jsr || bc == Bytecodes::_jsr_w, "must be jsr");
264
//
265
// // the real returnAddress is the bytecode following the jsr
266
// return new StackValue((intptr_t)(bci + Bytecodes::length_for(bc)));
267
} else if (VM.getVM().isLP64() && loc.holdsLong()) {
268
if ( loc.isRegister() ) {
269
// Long value in two registers, high half in the first, low in the second
270
return new StackValue(((valueAddr.getJLongAt(0) & 0xFFFFFFFF) << 32) |
271
((valueAddr.getJLongAt(8) & 0xFFFFFFFF)));
272
} else {
273
// Long value in a single stack slot
274
return new StackValue(valueAddr.getJLongAt(0));
275
}
276
} else if( loc.isRegister() ) {
277
// At the moment, all non-oop values in registers are 4 bytes,
278
// including double and long halves (see Compile::FillLocArray() in
279
// opto/output.cpp). Haul them out as such and return a StackValue
280
// containing an image of the value as it appears in a stack slot.
281
// If this is a double or long half, the interpreter _must_ deal
282
// with doubles and longs as entities split across two stack slots.
283
// To change this so doubles and/or longs can live in one stack slot,
284
// a StackValue will have to understand that it can contain an
285
// undivided double or long, implying that a Location (and the debug
286
// info mechanism) and FillLocArray() will also have to understand it.
287
return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF);
288
} else {
289
return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF);
290
}
291
} else if (sv.isConstantInt()) {
292
// Constant int: treat same as register int.
293
return new StackValue(((ConstantIntValue) sv).getValue() & 0xFFFFFFFF);
294
} else if (sv.isConstantOop()) {
295
// constant oop
296
return new StackValue(((ConstantOopReadValue) sv).getValue(), 0);
297
} else if (sv.isConstantDouble()) {
298
// Constant double in a single stack slot
299
double d = ((ConstantDoubleValue) sv).getValue();
300
return new StackValue(Double.doubleToLongBits(d) & 0xFFFFFFFF);
301
} else if (VM.getVM().isLP64() && sv.isConstantLong()) {
302
// Constant long in a single stack slot
303
return new StackValue(((ConstantLongValue) sv).getValue() & 0xFFFFFFFF);
304
} else if (sv.isObject()) {
305
// Scalar replaced object in compiled frame
306
return new StackValue(((ObjectValue)sv).getValue(), 1);
307
}
308
309
// Unknown ScopeValue type
310
Assert.that(false, "Should not reach here");
311
return new StackValue(0); // dummy
312
}
313
314
private BasicLock resolveMonitorLock(Location location) {
315
if (Assert.ASSERTS_ENABLED) {
316
Assert.that(location.isStack(), "for now we only look at the stack");
317
}
318
int byteOffset = location.getStackOffset();
319
// (stack picture)
320
// high: [ ] byte_offset + wordSize
321
// low [ ] byte_offset
322
//
323
// sp-> [ ] 0
324
// the byte_offset is the distance from the stack pointer to the lowest address
325
// The frame's original stack pointer, before any extension by its callee
326
// (due to Compiler1 linkage on SPARC), must be used.
327
return new BasicLock(getFrame().getUnextendedSP().addOffsetTo(byteOffset));
328
}
329
}
330
331