Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/cpu/zero/stubGenerator_zero.cpp
40931 views
1
/*
2
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
3
* Copyright 2007, 2008, 2010, 2015 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 "asm/assembler.inline.hpp"
28
#include "interpreter/interpreter.hpp"
29
#include "nativeInst_zero.hpp"
30
#include "oops/instanceOop.hpp"
31
#include "oops/method.hpp"
32
#include "oops/objArrayKlass.hpp"
33
#include "oops/oop.inline.hpp"
34
#include "prims/methodHandles.hpp"
35
#include "runtime/frame.inline.hpp"
36
#include "runtime/handles.inline.hpp"
37
#include "runtime/sharedRuntime.hpp"
38
#include "runtime/stubCodeGenerator.hpp"
39
#include "runtime/stubRoutines.hpp"
40
#include "runtime/thread.inline.hpp"
41
#include "stack_zero.inline.hpp"
42
#ifdef COMPILER2
43
#include "opto/runtime.hpp"
44
#endif
45
46
// For SafeFetch we need POSIX tls and setjmp
47
#include <setjmp.h>
48
#include <pthread.h>
49
static pthread_key_t g_jmpbuf_key;
50
51
// return the currently active jump buffer for this thread
52
// - if there is any, NULL otherwise. Called from
53
// zero signal handlers.
54
extern sigjmp_buf* get_jmp_buf_for_continuation() {
55
return (sigjmp_buf*) pthread_getspecific(g_jmpbuf_key);
56
}
57
58
// Declaration and definition of StubGenerator (no .hpp file).
59
// For a more detailed description of the stub routine structure
60
// see the comment in stubRoutines.hpp
61
62
class StubGenerator: public StubCodeGenerator {
63
private:
64
// The call stub is used to call Java from C
65
static void call_stub(
66
JavaCallWrapper *call_wrapper,
67
intptr_t* result,
68
BasicType result_type,
69
Method* method,
70
address entry_point,
71
intptr_t* parameters,
72
int parameter_words,
73
TRAPS) {
74
JavaThread *thread = THREAD;
75
ZeroStack *stack = thread->zero_stack();
76
77
// Make sure we have no pending exceptions
78
assert(!HAS_PENDING_EXCEPTION, "call_stub called with pending exception");
79
80
// Set up the stack if necessary
81
bool stack_needs_teardown = false;
82
if (stack->needs_setup()) {
83
size_t zero_stack_size = stack->suggest_size(thread);
84
stack->setup(alloca(zero_stack_size), zero_stack_size);
85
stack_needs_teardown = true;
86
}
87
88
// Allocate and initialize our frame
89
EntryFrame *frame =
90
EntryFrame::build(parameters, parameter_words, call_wrapper, THREAD);
91
92
if (!HAS_PENDING_EXCEPTION) {
93
// Push the frame
94
thread->push_zero_frame(frame);
95
96
// Make the call
97
Interpreter::invoke_method(method, entry_point, THREAD);
98
99
// Store the result
100
if (!HAS_PENDING_EXCEPTION) {
101
switch (result_type) {
102
case T_INT:
103
*(jint *) result = *(jint *) stack->sp();
104
break;
105
case T_LONG:
106
*(jlong *) result = *(jlong *) stack->sp();
107
break;
108
case T_FLOAT:
109
*(jfloat *) result = *(jfloat *) stack->sp();
110
break;
111
case T_DOUBLE:
112
*(jdouble *) result = *(jdouble *) stack->sp();
113
break;
114
case T_OBJECT:
115
*(oop *) result = *(oop *) stack->sp();
116
break;
117
default:
118
ShouldNotReachHere();
119
}
120
}
121
122
// Unwind the frame
123
thread->pop_zero_frame();
124
}
125
126
// Tear down the stack if necessary
127
if (stack_needs_teardown)
128
stack->teardown();
129
}
130
131
// These stubs get called from some dumb test routine.
132
// I'll write them properly when they're called from
133
// something that's actually doing something.
134
static void fake_arraycopy_stub(address src, address dst, int count) {
135
assert(count == 0, "huh?");
136
}
137
138
void generate_arraycopy_stubs() {
139
// Call the conjoint generation methods immediately after
140
// the disjoint ones so that short branches from the former
141
// to the latter can be generated.
142
StubRoutines::_jbyte_disjoint_arraycopy = (address) fake_arraycopy_stub;
143
StubRoutines::_jbyte_arraycopy = (address) fake_arraycopy_stub;
144
145
StubRoutines::_jshort_disjoint_arraycopy = (address) fake_arraycopy_stub;
146
StubRoutines::_jshort_arraycopy = (address) fake_arraycopy_stub;
147
148
StubRoutines::_jint_disjoint_arraycopy = (address) fake_arraycopy_stub;
149
StubRoutines::_jint_arraycopy = (address) fake_arraycopy_stub;
150
151
StubRoutines::_jlong_disjoint_arraycopy = (address) fake_arraycopy_stub;
152
StubRoutines::_jlong_arraycopy = (address) fake_arraycopy_stub;
153
154
StubRoutines::_oop_disjoint_arraycopy = ShouldNotCallThisStub();
155
StubRoutines::_oop_arraycopy = ShouldNotCallThisStub();
156
157
StubRoutines::_checkcast_arraycopy = ShouldNotCallThisStub();
158
StubRoutines::_generic_arraycopy = ShouldNotCallThisStub();
159
160
// Shared code tests for "NULL" to discover the stub is not generated.
161
StubRoutines::_unsafe_arraycopy = NULL;
162
163
// We don't generate specialized code for HeapWord-aligned source
164
// arrays, so just use the code we've already generated
165
StubRoutines::_arrayof_jbyte_disjoint_arraycopy =
166
StubRoutines::_jbyte_disjoint_arraycopy;
167
StubRoutines::_arrayof_jbyte_arraycopy =
168
StubRoutines::_jbyte_arraycopy;
169
170
StubRoutines::_arrayof_jshort_disjoint_arraycopy =
171
StubRoutines::_jshort_disjoint_arraycopy;
172
StubRoutines::_arrayof_jshort_arraycopy =
173
StubRoutines::_jshort_arraycopy;
174
175
StubRoutines::_arrayof_jint_disjoint_arraycopy =
176
StubRoutines::_jint_disjoint_arraycopy;
177
StubRoutines::_arrayof_jint_arraycopy =
178
StubRoutines::_jint_arraycopy;
179
180
StubRoutines::_arrayof_jlong_disjoint_arraycopy =
181
StubRoutines::_jlong_disjoint_arraycopy;
182
StubRoutines::_arrayof_jlong_arraycopy =
183
StubRoutines::_jlong_arraycopy;
184
185
StubRoutines::_arrayof_oop_disjoint_arraycopy =
186
StubRoutines::_oop_disjoint_arraycopy;
187
StubRoutines::_arrayof_oop_arraycopy =
188
StubRoutines::_oop_arraycopy;
189
}
190
191
static int SafeFetch32(int *adr, int errValue) {
192
193
// set up a jump buffer; anchor the pointer to the jump buffer in tls; then
194
// do the pointer access. If pointer is invalid, we crash; in signal
195
// handler, we retrieve pointer to jmp buffer from tls, and jump back.
196
//
197
// Note: the jump buffer itself - which can get pretty large depending on
198
// the architecture - lives on the stack and that is fine, because we will
199
// not rewind the stack: either we crash, in which case signal handler
200
// frame is below us, or we don't crash, in which case it does not matter.
201
sigjmp_buf jb;
202
if (sigsetjmp(jb, 1)) {
203
// we crashed. clean up tls and return default value.
204
pthread_setspecific(g_jmpbuf_key, NULL);
205
return errValue;
206
} else {
207
// preparation phase
208
pthread_setspecific(g_jmpbuf_key, &jb);
209
}
210
211
int value = errValue;
212
value = *adr;
213
214
// all went well. clean tls.
215
pthread_setspecific(g_jmpbuf_key, NULL);
216
217
return value;
218
}
219
220
static intptr_t SafeFetchN(intptr_t *adr, intptr_t errValue) {
221
222
sigjmp_buf jb;
223
if (sigsetjmp(jb, 1)) {
224
// we crashed. clean up tls and return default value.
225
pthread_setspecific(g_jmpbuf_key, NULL);
226
return errValue;
227
} else {
228
// preparation phase
229
pthread_setspecific(g_jmpbuf_key, &jb);
230
}
231
232
intptr_t value = errValue;
233
value = *adr;
234
235
// all went well. clean tls.
236
pthread_setspecific(g_jmpbuf_key, NULL);
237
238
return value;
239
240
}
241
242
void generate_initial() {
243
// Generates all stubs and initializes the entry points
244
245
// entry points that exist in all platforms Note: This is code
246
// that could be shared among different platforms - however the
247
// benefit seems to be smaller than the disadvantage of having a
248
// much more complicated generator structure. See also comment in
249
// stubRoutines.hpp.
250
251
StubRoutines::_forward_exception_entry = ShouldNotCallThisStub();
252
StubRoutines::_call_stub_entry = (address) call_stub;
253
StubRoutines::_catch_exception_entry = ShouldNotCallThisStub();
254
255
// atomic calls
256
StubRoutines::_atomic_xchg_entry = ShouldNotCallThisStub();
257
StubRoutines::_atomic_xchg_long_entry = ShouldNotCallThisStub();
258
StubRoutines::_atomic_cmpxchg_entry = ShouldNotCallThisStub();
259
StubRoutines::_atomic_cmpxchg_byte_entry = ShouldNotCallThisStub();
260
StubRoutines::_atomic_cmpxchg_long_entry = ShouldNotCallThisStub();
261
StubRoutines::_atomic_add_entry = ShouldNotCallThisStub();
262
StubRoutines::_atomic_add_long_entry = ShouldNotCallThisStub();
263
StubRoutines::_fence_entry = ShouldNotCallThisStub();
264
}
265
266
void generate_all() {
267
// Generates all stubs and initializes the entry points
268
269
// These entry points require SharedInfo::stack0 to be set up in
270
// non-core builds and need to be relocatable, so they each
271
// fabricate a RuntimeStub internally.
272
StubRoutines::_throw_AbstractMethodError_entry =
273
ShouldNotCallThisStub();
274
275
StubRoutines::_throw_NullPointerException_at_call_entry =
276
ShouldNotCallThisStub();
277
278
StubRoutines::_throw_StackOverflowError_entry =
279
ShouldNotCallThisStub();
280
281
// support for verify_oop (must happen after universe_init)
282
StubRoutines::_verify_oop_subroutine_entry =
283
ShouldNotCallThisStub();
284
285
// arraycopy stubs used by compilers
286
generate_arraycopy_stubs();
287
288
// Safefetch stubs.
289
pthread_key_create(&g_jmpbuf_key, NULL);
290
StubRoutines::_safefetch32_entry = CAST_FROM_FN_PTR(address, StubGenerator::SafeFetch32);
291
StubRoutines::_safefetch32_fault_pc = NULL;
292
StubRoutines::_safefetch32_continuation_pc = NULL;
293
294
StubRoutines::_safefetchN_entry = CAST_FROM_FN_PTR(address, StubGenerator::SafeFetchN);
295
StubRoutines::_safefetchN_fault_pc = NULL;
296
StubRoutines::_safefetchN_continuation_pc = NULL;
297
}
298
299
public:
300
StubGenerator(CodeBuffer* code, bool all) : StubCodeGenerator(code) {
301
if (all) {
302
generate_all();
303
} else {
304
generate_initial();
305
}
306
}
307
};
308
309
void StubGenerator_generate(CodeBuffer* code, bool all) {
310
StubGenerator g(code, all);
311
}
312
313
EntryFrame *EntryFrame::build(const intptr_t* parameters,
314
int parameter_words,
315
JavaCallWrapper* call_wrapper,
316
TRAPS) {
317
318
ZeroStack *stack = THREAD->zero_stack();
319
stack->overflow_check(header_words + parameter_words, CHECK_NULL);
320
321
stack->push(0); // next_frame, filled in later
322
intptr_t *fp = stack->sp();
323
assert(fp - stack->sp() == next_frame_off, "should be");
324
325
stack->push(ENTRY_FRAME);
326
assert(fp - stack->sp() == frame_type_off, "should be");
327
328
stack->push((intptr_t) call_wrapper);
329
assert(fp - stack->sp() == call_wrapper_off, "should be");
330
331
for (int i = 0; i < parameter_words; i++)
332
stack->push(parameters[i]);
333
334
return (EntryFrame *) fp;
335
}
336
337