Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/hotspot/cpu/zero/frame_zero.cpp
64440 views
1
/*
2
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
3
* Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
4
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5
*
6
* This code is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License version 2 only, as
8
* published by the Free Software Foundation.
9
*
10
* This code is distributed in the hope that it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13
* version 2 for more details (a copy is included in the LICENSE file that
14
* accompanied this code).
15
*
16
* You should have received a copy of the GNU General Public License version
17
* 2 along with this work; if not, write to the Free Software Foundation,
18
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
*
20
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21
* or visit www.oracle.com if you need additional information or have any
22
* questions.
23
*
24
*/
25
26
#include "precompiled.hpp"
27
#include "gc/shared/collectedHeap.hpp"
28
#include "interpreter/interpreter.hpp"
29
#include "interpreter/interpreterRuntime.hpp"
30
#include "memory/resourceArea.hpp"
31
#include "memory/universe.hpp"
32
#include "oops/method.hpp"
33
#include "oops/oop.inline.hpp"
34
#include "runtime/frame.inline.hpp"
35
#include "runtime/handles.inline.hpp"
36
#include "runtime/signature.hpp"
37
#include "runtime/stackWatermarkSet.hpp"
38
#include "vmreg_zero.inline.hpp"
39
40
#ifdef ASSERT
41
void RegisterMap::check_location_valid() {
42
ShouldNotCallThis();
43
}
44
#endif
45
46
bool frame::is_interpreted_frame() const {
47
return zeroframe()->is_interpreter_frame();
48
}
49
50
bool frame::is_fake_stub_frame() const {
51
return zeroframe()->is_fake_stub_frame();
52
}
53
54
frame frame::sender_for_entry_frame(RegisterMap *map) const {
55
assert(zeroframe()->is_entry_frame(), "wrong type of frame");
56
assert(map != NULL, "map must be set");
57
assert(!entry_frame_is_first(), "next Java fp must be non zero");
58
assert(entry_frame_call_wrapper()->anchor()->last_Java_sp() == sender_sp(),
59
"sender should be next Java frame");
60
map->clear();
61
assert(map->include_argument_oops(), "should be set by clear");
62
return frame(zeroframe()->next(), sender_sp());
63
}
64
65
OptimizedEntryBlob::FrameData* OptimizedEntryBlob::frame_data_for_frame(const frame& frame) const {
66
ShouldNotCallThis();
67
return nullptr;
68
}
69
70
bool frame::optimized_entry_frame_is_first() const {
71
ShouldNotCallThis();
72
return false;
73
}
74
75
frame frame::sender_for_nonentry_frame(RegisterMap *map) const {
76
assert(zeroframe()->is_interpreter_frame() ||
77
zeroframe()->is_fake_stub_frame(), "wrong type of frame");
78
return frame(zeroframe()->next(), sender_sp());
79
}
80
81
frame frame::sender(RegisterMap* map) const {
82
// Default is not to follow arguments; the various
83
// sender_for_xxx methods update this accordingly.
84
map->set_include_argument_oops(false);
85
86
frame result = zeroframe()->is_entry_frame() ?
87
sender_for_entry_frame(map) :
88
sender_for_nonentry_frame(map);
89
90
if (map->process_frames()) {
91
StackWatermarkSet::on_iteration(map->thread(), result);
92
}
93
94
return result;
95
}
96
97
BasicObjectLock* frame::interpreter_frame_monitor_begin() const {
98
return get_interpreterState()->monitor_base();
99
}
100
101
BasicObjectLock* frame::interpreter_frame_monitor_end() const {
102
return (BasicObjectLock*) get_interpreterState()->stack_base();
103
}
104
105
void frame::patch_pc(Thread* thread, address pc) {
106
if (pc != NULL) {
107
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
108
_pc = pc;
109
_deopt_state = is_deoptimized;
110
} else {
111
// We borrow this call to set the thread pointer in the interpreter
112
// state; the hook to set up deoptimized frames isn't supplied it.
113
assert(pc == NULL, "should be");
114
get_interpreterState()->set_thread(thread->as_Java_thread());
115
}
116
}
117
118
bool frame::safe_for_sender(JavaThread *thread) {
119
ShouldNotCallThis();
120
return false;
121
}
122
123
bool frame::is_interpreted_frame_valid(JavaThread *thread) const {
124
ShouldNotCallThis();
125
return false;
126
}
127
128
BasicType frame::interpreter_frame_result(oop* oop_result,
129
jvalue* value_result) {
130
assert(is_interpreted_frame(), "interpreted frame expected");
131
Method* method = interpreter_frame_method();
132
BasicType type = method->result_type();
133
intptr_t* tos_addr = (intptr_t *) interpreter_frame_tos_address();
134
oop obj;
135
136
switch (type) {
137
case T_VOID:
138
break;
139
case T_BOOLEAN:
140
value_result->z = *(jboolean *) tos_addr;
141
break;
142
case T_BYTE:
143
value_result->b = *(jbyte *) tos_addr;
144
break;
145
case T_CHAR:
146
value_result->c = *(jchar *) tos_addr;
147
break;
148
case T_SHORT:
149
value_result->s = *(jshort *) tos_addr;
150
break;
151
case T_INT:
152
value_result->i = *(jint *) tos_addr;
153
break;
154
case T_LONG:
155
value_result->j = *(jlong *) tos_addr;
156
break;
157
case T_FLOAT:
158
value_result->f = *(jfloat *) tos_addr;
159
break;
160
case T_DOUBLE:
161
value_result->d = *(jdouble *) tos_addr;
162
break;
163
164
case T_OBJECT:
165
case T_ARRAY:
166
if (method->is_native()) {
167
obj = get_interpreterState()->oop_temp();
168
}
169
else {
170
oop* obj_p = (oop *) tos_addr;
171
obj = (obj_p == NULL) ? (oop) NULL : *obj_p;
172
}
173
assert(obj == NULL || Universe::heap()->is_in(obj), "sanity check");
174
*oop_result = obj;
175
break;
176
177
default:
178
ShouldNotReachHere();
179
}
180
181
return type;
182
}
183
184
int frame::frame_size(RegisterMap* map) const {
185
#ifdef PRODUCT
186
ShouldNotCallThis();
187
#endif // PRODUCT
188
return 0; // make javaVFrame::print_value work
189
}
190
191
intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
192
int index = (Interpreter::expr_offset_in_bytes(offset) / wordSize);
193
return &interpreter_frame_tos_address()[index];
194
}
195
196
void frame::zero_print_on_error(int frame_index,
197
outputStream* st,
198
char* buf,
199
int buflen) const {
200
// Divide the buffer between the field and the value
201
buflen >>= 1;
202
char *fieldbuf = buf;
203
char *valuebuf = buf + buflen;
204
205
// Print each word of the frame
206
for (intptr_t *addr = sp(); addr <= fp(); addr++) {
207
int offset = fp() - addr;
208
209
// Fill in default values, then try and improve them
210
snprintf(fieldbuf, buflen, "word[%d]", offset);
211
snprintf(valuebuf, buflen, PTR_FORMAT, *addr);
212
zeroframe()->identify_word(frame_index, offset, fieldbuf, valuebuf, buflen);
213
fieldbuf[buflen - 1] = '\0';
214
valuebuf[buflen - 1] = '\0';
215
216
// Print the result
217
st->print_cr(" " PTR_FORMAT ": %-21s = %s", p2i(addr), fieldbuf, valuebuf);
218
}
219
}
220
221
void ZeroFrame::identify_word(int frame_index,
222
int offset,
223
char* fieldbuf,
224
char* valuebuf,
225
int buflen) const {
226
switch (offset) {
227
case next_frame_off:
228
strncpy(fieldbuf, "next_frame", buflen);
229
break;
230
231
case frame_type_off:
232
strncpy(fieldbuf, "frame_type", buflen);
233
if (is_entry_frame())
234
strncpy(valuebuf, "ENTRY_FRAME", buflen);
235
else if (is_interpreter_frame())
236
strncpy(valuebuf, "INTERPRETER_FRAME", buflen);
237
else if (is_fake_stub_frame())
238
strncpy(valuebuf, "FAKE_STUB_FRAME", buflen);
239
break;
240
241
default:
242
if (is_entry_frame()) {
243
as_entry_frame()->identify_word(
244
frame_index, offset, fieldbuf, valuebuf, buflen);
245
}
246
else if (is_interpreter_frame()) {
247
as_interpreter_frame()->identify_word(
248
frame_index, offset, fieldbuf, valuebuf, buflen);
249
}
250
else if (is_fake_stub_frame()) {
251
as_fake_stub_frame()->identify_word(
252
frame_index, offset, fieldbuf, valuebuf, buflen);
253
}
254
}
255
}
256
257
void EntryFrame::identify_word(int frame_index,
258
int offset,
259
char* fieldbuf,
260
char* valuebuf,
261
int buflen) const {
262
switch (offset) {
263
case call_wrapper_off:
264
strncpy(fieldbuf, "call_wrapper", buflen);
265
break;
266
267
default:
268
snprintf(fieldbuf, buflen, "local[%d]", offset - 3);
269
}
270
}
271
272
void InterpreterFrame::identify_word(int frame_index,
273
int offset,
274
char* fieldbuf,
275
char* valuebuf,
276
int buflen) const {
277
interpreterState istate = interpreter_state();
278
bool is_valid = istate->self_link() == istate;
279
intptr_t *addr = addr_of_word(offset);
280
281
// Fixed part
282
if (addr >= (intptr_t *) istate) {
283
const char *field = istate->name_of_field_at_address((address) addr);
284
if (field) {
285
if (is_valid && !strcmp(field, "_method")) {
286
istate->method()->name_and_sig_as_C_string(valuebuf, buflen);
287
}
288
else if (is_valid && !strcmp(field, "_bcp") && istate->bcp()) {
289
snprintf(valuebuf, buflen, PTR_FORMAT " (bci %d)",
290
(intptr_t) istate->bcp(),
291
istate->method()->bci_from(istate->bcp()));
292
}
293
snprintf(fieldbuf, buflen, "%sistate->%s",
294
field[strlen(field) - 1] == ')' ? "(": "", field);
295
}
296
else if (addr == (intptr_t *) istate) {
297
strncpy(fieldbuf, "(vtable for istate)", buflen);
298
}
299
return;
300
}
301
302
// Variable part
303
if (!is_valid)
304
return;
305
306
// JNI stuff
307
if (istate->method()->is_native() && addr < istate->stack_base()) {
308
address hA = istate->method()->signature_handler();
309
if (hA != NULL) {
310
if (hA != (address) InterpreterRuntime::slow_signature_handler) {
311
InterpreterRuntime::SignatureHandler *handler =
312
InterpreterRuntime::SignatureHandler::from_handlerAddr(hA);
313
314
intptr_t *params = istate->stack_base() - handler->argument_count();
315
if (addr >= params) {
316
int param = addr - params;
317
const char *desc = "";
318
if (param == 0)
319
desc = " (JNIEnv)";
320
else if (param == 1) {
321
if (istate->method()->is_static())
322
desc = " (mirror)";
323
else
324
desc = " (this)";
325
}
326
snprintf(fieldbuf, buflen, "parameter[%d]%s", param, desc);
327
return;
328
}
329
330
for (int i = 0; i < handler->argument_count(); i++) {
331
if (params[i] == (intptr_t) addr) {
332
snprintf(fieldbuf, buflen, "unboxed parameter[%d]", i);
333
return;
334
}
335
}
336
}
337
}
338
return;
339
}
340
341
// Monitors and stack
342
identify_vp_word(frame_index, addr,
343
(intptr_t *) istate->monitor_base(),
344
istate->stack_base(),
345
fieldbuf, buflen);
346
}
347
348
void ZeroFrame::identify_vp_word(int frame_index,
349
intptr_t* addr,
350
intptr_t* monitor_base,
351
intptr_t* stack_base,
352
char* fieldbuf,
353
int buflen) const {
354
// Monitors
355
if (addr >= stack_base && addr < monitor_base) {
356
int monitor_size = frame::interpreter_frame_monitor_size();
357
int last_index = (monitor_base - stack_base) / monitor_size - 1;
358
int index = last_index - (addr - stack_base) / monitor_size;
359
intptr_t monitor = (intptr_t) (
360
(BasicObjectLock *) monitor_base - 1 - index);
361
intptr_t offset = (intptr_t) addr - monitor;
362
363
if (offset == BasicObjectLock::obj_offset_in_bytes())
364
snprintf(fieldbuf, buflen, "monitor[%d]->_obj", index);
365
else if (offset == BasicObjectLock::lock_offset_in_bytes())
366
snprintf(fieldbuf, buflen, "monitor[%d]->_lock", index);
367
368
return;
369
}
370
371
// Expression stack
372
if (addr < stack_base) {
373
snprintf(fieldbuf, buflen, "%s[%d]",
374
frame_index == 0 ? "stack_word" : "local",
375
(int) (stack_base - addr - 1));
376
return;
377
}
378
}
379
380
#ifndef PRODUCT
381
382
void frame::describe_pd(FrameValues& values, int frame_no) {
383
384
}
385
386
#endif
387
388
intptr_t *frame::initial_deoptimization_info() {
389
// unused... but returns fp() to minimize changes introduced by 7087445
390
return fp();
391
}
392
393
#ifndef PRODUCT
394
// This is a generic constructor which is only used by pns() in debug.cpp.
395
frame::frame(void* sp, void* fp, void* pc) {
396
Unimplemented();
397
}
398
399
void frame::pd_ps() {}
400
#endif
401
402