1 /*
2 * Copyright (c) 1999, 2025, 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 #include "classfile/stringTable.hpp"
26 #include "classfile/symbolTable.hpp"
27 #include "classfile/systemDictionary.hpp"
28 #include "code/codeCache.hpp"
29 #include "compiler/compilerOracle.hpp"
30 #include "compiler/compileTask.hpp"
31 #include "gc/shared/barrierSet.hpp"
32 #include "gc/shared/barrierSetNMethod.hpp"
33 #include "jvm_io.h"
34 #include "jvmci/jniAccessMark.inline.hpp"
35 #include "jvmci/jvmciCompiler.hpp"
36 #include "jvmci/jvmciRuntime.hpp"
37 #include "memory/oopFactory.hpp"
38 #include "memory/resourceArea.hpp"
39 #include "memory/universe.hpp"
40 #include "oops/objArrayKlass.hpp"
41 #include "oops/typeArrayOop.inline.hpp"
42 #include "prims/jvmtiExport.hpp"
43 #include "runtime/arguments.hpp"
44 #include "runtime/deoptimization.hpp"
45 #include "runtime/fieldDescriptor.inline.hpp"
46 #include "runtime/javaCalls.hpp"
47 #include "runtime/jniHandles.inline.hpp"
48 #include "runtime/os.hpp"
49 #include "utilities/permitForbiddenFunctions.hpp"
50
51 JVMCICompileState::JVMCICompileState(CompileTask* task, JVMCICompiler* compiler):
52 _task(task),
53 _compiler(compiler),
54 _retryable(true),
55 _failure_reason(nullptr),
56 _failure_reason_on_C_heap(false) {
57 // Get Jvmti capabilities under lock to get consistent values.
58 MutexLocker mu(JvmtiThreadState_lock);
59 _jvmti_redefinition_count = JvmtiExport::redefinition_count();
60 _jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint() ? 1 : 0;
61 _jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables() ? 1 : 0;
62 _jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions() ? 1 : 0;
63 _jvmti_can_pop_frame = JvmtiExport::can_pop_frame() ? 1 : 0;
64 _target_method_is_old = _task != nullptr && _task->method()->is_old();
65 if (task->is_blocking()) {
66 task->set_blocking_jvmci_compile_state(this);
67 }
68 }
69
70 void JVMCICompileState::set_failure(bool retryable, const char* reason, bool reason_on_C_heap) {
71 if (_failure_reason != nullptr && _failure_reason_on_C_heap) {
72 os::free((void*) _failure_reason);
73 }
74 _failure_reason = reason;
75 _failure_reason_on_C_heap = reason_on_C_heap;
76 _retryable = retryable;
77 }
78
79 void JVMCICompileState::notify_libjvmci_oome() {
80 const char* msg = "Out of memory initializing libjvmci or attaching it to the current thread";
81 set_failure(true, msg);
82 _compiler->on_upcall(msg);
83 }
84
85 // Update global JVMCI compilation ticks after 512 thread-local JVMCI compilation ticks.
86 // This mitigates the overhead of the atomic operation used for the global update.
87 #define THREAD_TICKS_PER_GLOBAL_TICKS (2 << 9)
88 #define THREAD_TICKS_PER_GLOBAL_TICKS_MASK (THREAD_TICKS_PER_GLOBAL_TICKS - 1)
89
90 void JVMCICompileState::inc_compilation_ticks() {
91 if ((++_compilation_ticks & THREAD_TICKS_PER_GLOBAL_TICKS_MASK) == 0) {
92 _compiler->inc_global_compilation_ticks();
93 }
94 }
95
96 bool JVMCICompileState::jvmti_state_changed() const {
97 // Some classes were redefined
98 if (jvmti_redefinition_count() != JvmtiExport::redefinition_count()) {
99 return true;
100 }
101 if (!jvmti_can_access_local_variables() &&
102 JvmtiExport::can_access_local_variables()) {
103 return true;
104 }
105 if (!jvmti_can_hotswap_or_post_breakpoint() &&
106 JvmtiExport::can_hotswap_or_post_breakpoint()) {
107 return true;
108 }
109 if (!jvmti_can_post_on_exceptions() &&
110 JvmtiExport::can_post_on_exceptions()) {
111 return true;
112 }
113 if (!jvmti_can_pop_frame() &&
114 JvmtiExport::can_pop_frame()) {
115 return true;
116 }
117 return false;
118 }
119
120 void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) {
121 assert(thread != nullptr, "npe");
122 _env = nullptr;
123 _pop_frame_on_close = false;
124 _detach_on_close = false;
125 if (!UseJVMCINativeLibrary) {
126 // In HotSpot mode, JNI isn't used at all.
127 _runtime = JVMCI::java_runtime();
128 _is_hotspot = true;
129 return;
130 }
131
132 if (parent_env != nullptr) {
133 // If the parent JNI environment is non-null then figure out whether it
134 // is a HotSpot or shared library JNIEnv and set the state appropriately.
135 _is_hotspot = thread->jni_environment() == parent_env;
136 if (_is_hotspot) {
137 // Select the Java runtime
138 _runtime = JVMCI::java_runtime();
139 return;
140 }
141 _runtime = thread->libjvmci_runtime();
142 assert(_runtime != nullptr, "npe");
143 _env = parent_env;
144 return;
145 }
146
147 // Running in JVMCI shared library mode so ensure the shared library
148 // is loaded and initialized and get a shared library JNIEnv
149 _is_hotspot = false;
150
151 _runtime = JVMCI::compiler_runtime(thread);
152 _env = _runtime->init_shared_library_javavm(&_init_error, &_init_error_msg);
153 if (_env != nullptr) {
154 // Creating the JVMCI shared library VM also attaches the current thread
155 _detach_on_close = true;
156 } else if (_init_error != JNI_OK) {
157 // Caller creating this JVMCIEnv must handle the error.
158 JVMCI_event_1("[%s:%d] Error creating libjvmci (err: %d, %s)", _file, _line,
159 _init_error, _init_error_msg == nullptr ? "unknown" : _init_error_msg);
160 return;
161 } else {
162 _runtime->GetEnv(thread, (void**)&parent_env, JNI_VERSION_1_2);
163 if (parent_env != nullptr) {
164 // Even though there's a parent JNI env, there's no guarantee
165 // it was opened by a JVMCIEnv scope and thus may not have
166 // pushed a local JNI frame. As such, we use a new JNI local
167 // frame in this scope to ensure local JNI refs are collected
168 // in a timely manner after leaving this scope.
169 _env = parent_env;
170 } else {
171 ResourceMark rm; // Thread name is resource allocated
172 JavaVMAttachArgs attach_args;
173 attach_args.version = JNI_VERSION_1_2;
174 attach_args.name = const_cast<char*>(thread->name());
175 attach_args.group = nullptr;
176 _init_error = _runtime->AttachCurrentThread(thread, (void**) &_env, &attach_args);
177 if (_init_error == JNI_OK) {
178 _detach_on_close = true;
179 } else {
180 // Caller creating this JVMCIEnv must handle the error.
181 _env = nullptr;
182 JVMCI_event_1("[%s:%d] Error attaching to libjvmci (err: %d)", _file, _line, _init_error);
183 return;
184 }
185 }
186 }
187
188 assert(_env != nullptr, "missing env");
189 assert(_throw_to_caller == false, "must be");
190
191 JNIAccessMark jni(this, thread);
192 jint result = _env->PushLocalFrame(32);
193 if (result != JNI_OK) {
194 JVMCI_event_1("[%s:%d] Error pushing local JNI frame (err: %d)", _file, _line, result);
195 return;
196 }
197 _pop_frame_on_close = true;
198 }
199
200 JVMCIEnv::JVMCIEnv(JavaThread* thread, JVMCICompileState* compile_state, const char* file, int line):
201 _throw_to_caller(false), _file(file), _line(line), _init_error(JNI_OK), _init_error_msg(nullptr), _compile_state(compile_state) {
202 init_env_mode_runtime(thread, nullptr);
203 }
204
205 JVMCIEnv::JVMCIEnv(JavaThread* thread, const char* file, int line):
206 _throw_to_caller(false), _file(file), _line(line), _init_error(JNI_OK), _init_error_msg(nullptr), _compile_state(nullptr) {
207 init_env_mode_runtime(thread, nullptr);
208 }
209
210 JVMCIEnv::JVMCIEnv(JavaThread* thread, JNIEnv* parent_env, const char* file, int line):
211 _throw_to_caller(true), _file(file), _line(line), _init_error(JNI_OK), _init_error_msg(nullptr), _compile_state(nullptr) {
212 assert(parent_env != nullptr, "npe");
213 init_env_mode_runtime(thread, parent_env);
214 assert(_env == nullptr || parent_env == _env, "mismatched JNIEnvironment");
215 assert(_init_error == JNI_OK, "err: %d", _init_error);
216 }
217
218 void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, const char* file, int line) {
219 _compile_state = nullptr;
220 _throw_to_caller = false;
221 _file = file;
222 _line = line;
223 _init_error = JNI_OK;
224 _init_error_msg = nullptr;
225 if (is_hotspot) {
226 _env = nullptr;
227 _pop_frame_on_close = false;
228 _detach_on_close = false;
229 _is_hotspot = true;
230 _runtime = JVMCI::java_runtime();
231 } else {
232 init_env_mode_runtime(thread, nullptr);
233 }
234 }
235
236 void JVMCIEnv::check_init(JVMCI_TRAPS) {
237 guarantee(JVMCIENV != this, "must be");
238 if (_init_error == JNI_OK) {
239 return;
240 }
241 if (_init_error == JNI_ENOMEM) {
242 JVMCI_THROW_MSG(OutOfMemoryError, "JNI_ENOMEM creating or attaching to libjvmci");
243 }
244 stringStream st;
245 st.print("Error creating or attaching to libjvmci (err: %d, description: %s)",
246 _init_error, _init_error_msg == nullptr ? "unknown" : _init_error_msg);
247 JVMCI_THROW_MSG(InternalError, st.freeze());
248 }
249
250 void JVMCIEnv::check_init(TRAPS) {
251 if (_init_error == JNI_OK) {
252 return;
253 }
254 stringStream st;
255 st.print("Error creating or attaching to libjvmci (err: %d, description: %s)",
256 _init_error, _init_error_msg != nullptr ? _init_error_msg : (_init_error == JNI_ENOMEM ? "JNI_ENOMEM" : "none"));
257 THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), st.freeze());
258 }
259
260 // Prints a pending exception (if any) and its stack trace to st.
261 // Also partially logs the stack trace to the JVMCI event log.
262 void JVMCIEnv::describe_pending_exception(outputStream* st) {
263 ResourceMark rm;
264 char* stack_trace = nullptr;
265 if (pending_exception_as_string(nullptr, (const char**) &stack_trace)) {
266 st->print_raw_cr(stack_trace);
267
268 // Use up to half the lines of the JVMCI event log to
269 // show the stack trace.
270 char* cursor = stack_trace;
271 int line = 0;
272 const int max_lines = LogEventsBufferEntries / 2;
273 char* last_line = nullptr;
274 while (*cursor != '\0') {
275 char* eol = strchr(cursor, '\n');
276 if (eol == nullptr) {
277 if (line == max_lines - 1) {
278 last_line = cursor;
279 } else if (line < max_lines) {
280 JVMCI_event_1("%s", cursor);
281 }
282 cursor = cursor + strlen(cursor);
283 } else {
284 *eol = '\0';
285 if (line == max_lines - 1) {
286 last_line = cursor;
287 } else if (line < max_lines) {
288 JVMCI_event_1("%s", cursor);
289 }
290 cursor = eol + 1;
291 }
292 line++;
293 }
294 if (last_line != nullptr) {
295 if (line > max_lines) {
296 JVMCI_event_1("%s [elided %d more stack trace lines]", last_line, line - max_lines);
297 } else {
298 JVMCI_event_1("%s", last_line);
299 }
300 }
301 }
302 }
303
304 bool JVMCIEnv::pending_exception_as_string(const char** to_string, const char** stack_trace) {
305 JavaThread* THREAD = JavaThread::current(); // For exception macros.
306 JVMCIObject to_string_obj;
307 JVMCIObject stack_trace_obj;
308 bool had_nested_exception = false;
309 if (!is_hotspot()) {
310 JNIAccessMark jni(this, THREAD);
311 jthrowable ex = jni()->ExceptionOccurred();
312 if (ex != nullptr) {
313 jni()->ExceptionClear();
314 jobjectArray pair = (jobjectArray) jni()->CallStaticObjectMethod(
315 JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
316 JNIJVMCI::HotSpotJVMCIRuntime::exceptionToString_method(),
317 ex, to_string != nullptr, stack_trace != nullptr);
318 if (jni()->ExceptionCheck()) {
319 // As last resort, dump nested exception
320 jni()->ExceptionDescribe();
321 had_nested_exception = true;
322 } else {
323 guarantee(pair != nullptr, "pair is null");
324 int len = jni()->GetArrayLength(pair);
325 guarantee(len == 2, "bad len is %d", len);
326 if (to_string != nullptr) {
327 to_string_obj = JVMCIObject::create(jni()->GetObjectArrayElement(pair, 0), false);
328 }
329 if (stack_trace != nullptr) {
330 stack_trace_obj = JVMCIObject::create(jni()->GetObjectArrayElement(pair, 1), false);
331 }
332 }
333 } else {
334 return false;
335 }
336 } else {
337 if (HAS_PENDING_EXCEPTION) {
338 Handle exception(THREAD, PENDING_EXCEPTION);
339 CLEAR_PENDING_EXCEPTION;
340 JavaCallArguments jargs;
341 jargs.push_oop(exception);
342 jargs.push_int(to_string != nullptr);
343 jargs.push_int(stack_trace != nullptr);
344 JavaValue result(T_OBJECT);
345 JavaCalls::call_static(&result,
346 HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
347 vmSymbols::exceptionToString_name(),
348 vmSymbols::exceptionToString_signature(), &jargs, THREAD);
349 if (HAS_PENDING_EXCEPTION) {
350 Handle nested_exception(THREAD, PENDING_EXCEPTION);
351 CLEAR_PENDING_EXCEPTION;
352 java_lang_Throwable::print_stack_trace(nested_exception, tty);
353 // Clear and ignore any exceptions raised during printing
354 CLEAR_PENDING_EXCEPTION;
355 had_nested_exception = true;
356 } else {
357 oop pair = result.get_oop();
358 guarantee(pair->is_refArray(), "must be");
359 refArrayOop pair_arr = refArrayOop(pair);
360 int len = pair_arr->length();
361 guarantee(len == 2, "bad len is %d", len);
362 if (to_string != nullptr) {
363 to_string_obj = HotSpotJVMCI::wrap(pair_arr->obj_at(0));
364 }
365 if (stack_trace != nullptr) {
366 stack_trace_obj = HotSpotJVMCI::wrap(pair_arr->obj_at(1));
367 }
368 }
369 } else {
370 return false;
371 }
372 }
373 if (had_nested_exception) {
374 if (to_string != nullptr) {
375 *to_string = "nested exception occurred converting exception to string";
376 }
377 if (stack_trace != nullptr) {
378 *stack_trace = "nested exception occurred converting exception stack to string";
379 }
380 } else {
381 if (to_string_obj.is_non_null()) {
382 *to_string = as_utf8_string(to_string_obj);
383 }
384 if (stack_trace_obj.is_non_null()) {
385 *stack_trace = as_utf8_string(stack_trace_obj);
386 }
387 }
388 return true;
389 }
390
391
392 // Shared code for translating an exception from HotSpot to libjvmci or vice versa.
393 class ExceptionTranslation: public StackObj {
394 protected:
395 enum DecodeFormat {
396 _encoded_ok = 0, // exception was successfully encoded into buffer
397 _buffer_alloc_fail = 1, // native memory for buffer could not be allocated
398 _encode_oome_fail = 2, // OutOfMemoryError thrown during encoding
399 _encode_fail = 3, // some other problem occured during encoding. If buffer != 0,
400 // buffer contains a `struct { u4 len; char[len] desc}`
401 // describing the problem
402 _encode_oome_in_vm = 4 // an OutOfMemoryError thrown from within VM code on a
403 // thread that cannot call Java (OOME has no stack trace)
404 };
405
406 JVMCIEnv* _from_env; // Source of translation. Can be null.
407 JVMCIEnv* _to_env; // Destination of translation. Never null.
408
409 ExceptionTranslation(JVMCIEnv* from_env, JVMCIEnv* to_env) : _from_env(from_env), _to_env(to_env) {}
410
411 // Encodes the exception in `_from_env` into `buffer`.
412 // Where N is the number of bytes needed for the encoding, returns N if N <= `buffer_size`
413 // and the encoding was written to `buffer` otherwise returns -N.
414 virtual int encode(JavaThread* THREAD, jlong buffer, int buffer_size) = 0;
415
416 // Decodes the exception in `buffer` in `_to_env` and throws it.
417 virtual void decode(JavaThread* THREAD, DecodeFormat format, jlong buffer) = 0;
418
419 static bool debug_translated_exception() {
420 const char* prop_value = Arguments::get_property("jdk.internal.vm.TranslatedException.debug");
421 return prop_value != nullptr && strcmp("true", prop_value) == 0;
422 }
423
424 public:
425 void doit(JavaThread* THREAD) {
426 int buffer_size = 2048;
427 while (true) {
428 ResourceMark rm;
429 jlong buffer = (jlong) NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, jbyte, buffer_size);
430 if (buffer == 0L) {
431 JVMCI_event_1("error translating exception: translation buffer allocation failed");
432 decode(THREAD, _buffer_alloc_fail, 0L);
433 return;
434 }
435 int res = encode(THREAD, buffer, buffer_size);
436 if (_to_env->has_pending_exception()) {
437 // Propagate pending exception
438 return;
439 }
440 if (res < 0) {
441 int required_buffer_size = -res;
442 if (required_buffer_size > buffer_size) {
443 buffer_size = required_buffer_size;
444 }
445 } else {
446 decode(THREAD, _encoded_ok, buffer);
447 if (!_to_env->has_pending_exception()) {
448 _to_env->throw_InternalError("decodeAndThrowThrowable should have thrown an exception");
449 }
450 return;
451 }
452 }
453 }
454 };
455
456 // Translates an exception on the HotSpot heap to an exception on the shared library heap.
457 class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation {
458 private:
459 const Handle& _throwable;
460
461 char* print_throwable_to_buffer(Handle throwable, jlong buffer, int buffer_size) {
462 char* char_buffer = (char*) buffer + 4;
463 stringStream st(char_buffer, (size_t) buffer_size - 4);
464 java_lang_Throwable::print_stack_trace(throwable, &st);
465 u4 len = (u4) st.size();
466 *((u4*) buffer) = len;
467 return char_buffer;
468 }
469
470 bool handle_pending_exception(JavaThread* THREAD, jlong buffer, int buffer_size) {
471 if (HAS_PENDING_EXCEPTION) {
472 Handle throwable = Handle(THREAD, PENDING_EXCEPTION);
473 Symbol *ex_name = throwable->klass()->name();
474 CLEAR_PENDING_EXCEPTION;
475 if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) {
476 JVMCI_event_1("error translating exception: OutOfMemoryError");
477 decode(THREAD, _encode_oome_fail, 0L);
478 } else {
479 char* char_buffer = print_throwable_to_buffer(throwable, buffer, buffer_size);
480 JVMCI_event_1("error translating exception: %s", char_buffer);
481 decode(THREAD, _encode_fail, buffer);
482 }
483 return true;
484 }
485 return false;
486 }
487
488 int encode(JavaThread* THREAD, jlong buffer, int buffer_size) {
489 if (!THREAD->can_call_java()) {
490 Symbol *ex_name = _throwable->klass()->name();
491 if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) {
492 JVMCI_event_1("translating exception: OutOfMemoryError within VM code");
493 decode(THREAD, _encode_oome_in_vm, 0L);
494 return 0;
495 }
496 char* char_buffer = print_throwable_to_buffer(_throwable, buffer, buffer_size);
497 const char* detail = log_is_enabled(Info, exceptions) ? "" : " (-Xlog:exceptions may give more detail)";
498 JVMCI_event_1("cannot call Java to translate exception%s: %s", detail, char_buffer);
499 decode(THREAD, _encode_fail, buffer);
500 return 0;
501 }
502 Klass* vmSupport = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_VMSupport(), true, THREAD);
503 if (handle_pending_exception(THREAD, buffer, buffer_size)) {
504 return 0;
505 }
506 JavaCallArguments jargs;
507 jargs.push_oop(_throwable);
508 jargs.push_long(buffer);
509 jargs.push_int(buffer_size);
510 JavaValue result(T_INT);
511 JavaCalls::call_static(&result,
512 vmSupport,
513 vmSymbols::encodeThrowable_name(),
514 vmSymbols::encodeThrowable_signature(), &jargs, THREAD);
515 if (handle_pending_exception(THREAD, buffer, buffer_size)) {
516 return 0;
517 }
518 return result.get_jint();
519 }
520
521 void decode(JavaThread* THREAD, DecodeFormat format, jlong buffer) {
522 JVMCI_event_1("decoding exception from JVM heap (format: %d, buffer[%d]) ", format, buffer == 0L ? -1 : *((u4*) buffer));
523 JNIAccessMark jni(_to_env, THREAD);
524 jni()->CallStaticVoidMethod(JNIJVMCI::VMSupport::clazz(),
525 JNIJVMCI::VMSupport::decodeAndThrowThrowable_method(),
526 format, buffer, false, debug_translated_exception());
527 }
528 public:
529 HotSpotToSharedLibraryExceptionTranslation(JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, const Handle& throwable) :
530 ExceptionTranslation(hotspot_env, jni_env), _throwable(throwable) {}
531 };
532
533 // Translates an exception on the shared library heap to an exception on the HotSpot heap.
534 class SharedLibraryToHotSpotExceptionTranslation : public ExceptionTranslation {
535 private:
536 jthrowable _throwable;
537
538 int encode(JavaThread* THREAD, jlong buffer, int buffer_size) {
539 JNIAccessMark jni(_from_env, THREAD);
540 int res = jni()->CallStaticIntMethod(JNIJVMCI::VMSupport::clazz(),
541 JNIJVMCI::VMSupport::encodeThrowable_method(),
542 _throwable, buffer, buffer_size);
543 if (jni()->ExceptionCheck()) {
544 // Cannot get name of exception thrown as that can raise another exception.
545 jni()->ExceptionClear();
546 JVMCI_event_1("error translating exception: unknown error");
547 decode(THREAD, _encode_fail, 0L);
548 return 0;
549 }
550 return res;
551 }
552
553 void decode(JavaThread* THREAD, DecodeFormat format, jlong buffer) {
554 JVMCI_event_1("decoding exception to JVM heap (format: %d, buffer[%d]) ", format, buffer == 0L ? -1 : *((u4*) buffer));
555 Klass* vmSupport = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_VMSupport(), true, CHECK);
556 JavaCallArguments jargs;
557 jargs.push_int(format);
558 jargs.push_long(buffer);
559 jargs.push_int(true);
560 jargs.push_int(debug_translated_exception());
561 JavaValue result(T_VOID);
562 JavaCalls::call_static(&result,
563 vmSupport,
564 vmSymbols::decodeAndThrowThrowable_name(),
565 vmSymbols::decodeAndThrowThrowable_signature(), &jargs, THREAD);
566 }
567 public:
568 SharedLibraryToHotSpotExceptionTranslation(JVMCIEnv* hotspot_env, JVMCIEnv* jni_env, jthrowable throwable) :
569 ExceptionTranslation(jni_env, hotspot_env), _throwable(throwable) {}
570 };
571
572 void JVMCIEnv::translate_to_jni_exception(JavaThread* THREAD, const Handle& throwable, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env) {
573 HotSpotToSharedLibraryExceptionTranslation(hotspot_env, jni_env, throwable).doit(THREAD);
574 }
575
576 void JVMCIEnv::translate_from_jni_exception(JavaThread* THREAD, jthrowable throwable, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env) {
577 SharedLibraryToHotSpotExceptionTranslation(hotspot_env, jni_env, throwable).doit(THREAD);
578 }
579
580 jboolean JVMCIEnv::transfer_pending_exception_to_jni(JavaThread* THREAD, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env) {
581 if (HAS_PENDING_EXCEPTION) {
582 Handle throwable = Handle(THREAD, PENDING_EXCEPTION);
583 CLEAR_PENDING_EXCEPTION;
584 translate_to_jni_exception(THREAD, throwable, hotspot_env, jni_env);
585 return true;
586 }
587 return false;
588 }
589
590 jboolean JVMCIEnv::transfer_pending_exception(JavaThread* THREAD, JVMCIEnv* peer_env) {
591 if (is_hotspot()) {
592 return transfer_pending_exception_to_jni(THREAD, this, peer_env);
593 }
594 jthrowable ex = nullptr;
595 {
596 JNIAccessMark jni(this, THREAD);
597 ex = jni()->ExceptionOccurred();
598 if (ex != nullptr) {
599 jni()->ExceptionClear();
600 }
601 }
602 if (ex != nullptr) {
603 translate_from_jni_exception(THREAD, ex, peer_env, this);
604 return true;
605 }
606 return false;
607 }
608
609 JVMCIEnv::~JVMCIEnv() {
610 if (_init_error_msg != nullptr) {
611 // The memory allocated in libjvmci was not allocated with os::malloc
612 // so must not be freed with os::free.
613 permit_forbidden_function::free((void*)_init_error_msg);
614 }
615 if (_init_error != JNI_OK) {
616 return;
617 }
618 if (_throw_to_caller) {
619 if (is_hotspot()) {
620 // Nothing to do
621 } else {
622 Thread* thread = Thread::current();
623 if (thread->is_Java_thread()) {
624 JavaThread* THREAD = JavaThread::cast(thread); // For exception macros.
625 if (HAS_PENDING_EXCEPTION) {
626 Handle throwable = Handle(THREAD, PENDING_EXCEPTION);
627 CLEAR_PENDING_EXCEPTION;
628 translate_to_jni_exception(THREAD, throwable, nullptr, this);
629 }
630 }
631 }
632 } else {
633 if (_pop_frame_on_close) {
634 // Pop the JNI local frame that was pushed when entering this JVMCIEnv scope.
635 JNIAccessMark jni(this);
636 jni()->PopLocalFrame(nullptr);
637 }
638
639 if (has_pending_exception()) {
640 char message[256];
641 jio_snprintf(message, 256, "Uncaught exception exiting %s JVMCIEnv scope entered at %s:%d",
642 is_hotspot() ? "HotSpot" : "libjvmci", _file, _line);
643 JVMCIRuntime::fatal_exception(this, message);
644 }
645
646 if (_detach_on_close) {
647 _runtime->DetachCurrentThread(JavaThread::current());
648 }
649 }
650 }
651
652 jboolean JVMCIEnv::has_pending_exception() {
653 if (is_hotspot()) {
654 JavaThread* THREAD = JavaThread::current(); // For exception macros.
655 return HAS_PENDING_EXCEPTION;
656 } else {
657 JNIAccessMark jni(this);
658 return jni()->ExceptionCheck();
659 }
660 }
661
662 void JVMCIEnv::clear_pending_exception() {
663 if (is_hotspot()) {
664 JavaThread* THREAD = JavaThread::current(); // For exception macros.
665 CLEAR_PENDING_EXCEPTION;
666 } else {
667 JNIAccessMark jni(this);
668 jni()->ExceptionClear();
669 }
670 }
671
672 int JVMCIEnv::get_length(JVMCIArray array) {
673 if (is_hotspot()) {
674 return HotSpotJVMCI::resolve(array)->length();
675 } else {
676 JNIAccessMark jni(this);
677 return jni()->GetArrayLength(get_jarray(array));
678 }
679 }
680
681 JVMCIObject JVMCIEnv::get_object_at(JVMCIObjectArray array, int index, JVMCI_TRAPS) {
682 if (is_hotspot()) {
683 JavaThread* THREAD = JavaThread::current(); // For exception macros.
684 oop result = HotSpotJVMCI::resolve(array)->obj_at(index, CHECK_({}));
685 return wrap(result);
686 } else {
687 JNIAccessMark jni(this);
688 jobject result = jni()->GetObjectArrayElement(get_jobjectArray(array), index);
689 return wrap(result);
690 }
691 }
692
693 void JVMCIEnv::put_object_at(JVMCIObjectArray array, int index, JVMCIObject value) {
694 if (is_hotspot()) {
695 HotSpotJVMCI::resolve(array)->obj_at_put(index, HotSpotJVMCI::resolve(value));
696 } else {
697 JNIAccessMark jni(this);
698 jni()->SetObjectArrayElement(get_jobjectArray(array), index, get_jobject(value));
699 }
700 }
701
702 jboolean JVMCIEnv::get_bool_at(JVMCIPrimitiveArray array, int index) {
703 if (is_hotspot()) {
704 return HotSpotJVMCI::resolve(array)->bool_at(index);
705 } else {
706 JNIAccessMark jni(this);
707 jboolean result;
708 jni()->GetBooleanArrayRegion(array.as_jbooleanArray(), index, 1, &result);
709 return result;
710 }
711 }
712 void JVMCIEnv::put_bool_at(JVMCIPrimitiveArray array, int index, jboolean value) {
713 if (is_hotspot()) {
714 HotSpotJVMCI::resolve(array)->bool_at_put(index, value);
715 } else {
716 JNIAccessMark jni(this);
717 jni()->SetBooleanArrayRegion(array.as_jbooleanArray(), index, 1, &value);
718 }
719 }
720
721 jbyte JVMCIEnv::get_byte_at(JVMCIPrimitiveArray array, int index) {
722 if (is_hotspot()) {
723 return HotSpotJVMCI::resolve(array)->byte_at(index);
724 } else {
725 JNIAccessMark jni(this);
726 jbyte result;
727 jni()->GetByteArrayRegion(array.as_jbyteArray(), index, 1, &result);
728 return result;
729 }
730 }
731 void JVMCIEnv::put_byte_at(JVMCIPrimitiveArray array, int index, jbyte value) {
732 if (is_hotspot()) {
733 HotSpotJVMCI::resolve(array)->byte_at_put(index, value);
734 } else {
735 JNIAccessMark jni(this);
736 jni()->SetByteArrayRegion(array.as_jbyteArray(), index, 1, &value);
737 }
738 }
739
740 jint JVMCIEnv::get_int_at(JVMCIPrimitiveArray array, int index) {
741 if (is_hotspot()) {
742 return HotSpotJVMCI::resolve(array)->int_at(index);
743 } else {
744 JNIAccessMark jni(this);
745 jint result;
746 jni()->GetIntArrayRegion(array.as_jintArray(), index, 1, &result);
747 return result;
748 }
749 }
750 void JVMCIEnv::put_int_at(JVMCIPrimitiveArray array, int index, jint value) {
751 if (is_hotspot()) {
752 HotSpotJVMCI::resolve(array)->int_at_put(index, value);
753 } else {
754 JNIAccessMark jni(this);
755 jni()->SetIntArrayRegion(array.as_jintArray(), index, 1, &value);
756 }
757 }
758
759 jlong JVMCIEnv::get_long_at(JVMCIPrimitiveArray array, int index) {
760 if (is_hotspot()) {
761 return HotSpotJVMCI::resolve(array)->long_at(index);
762 } else {
763 JNIAccessMark jni(this);
764 jlong result;
765 jni()->GetLongArrayRegion(array.as_jlongArray(), index, 1, &result);
766 return result;
767 }
768 }
769 void JVMCIEnv::put_long_at(JVMCIPrimitiveArray array, int index, jlong value) {
770 if (is_hotspot()) {
771 HotSpotJVMCI::resolve(array)->long_at_put(index, value);
772 } else {
773 JNIAccessMark jni(this);
774 jni()->SetLongArrayRegion(array.as_jlongArray(), index, 1, &value);
775 }
776 }
777
778 void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length) {
779 if (length == 0) {
780 return;
781 }
782 if (is_hotspot()) {
783 memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), length);
784 } else {
785 JNIAccessMark jni(this);
786 jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, length, dest);
787 }
788 }
789 void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
790 if (length == 0) {
791 return;
792 }
793 if (is_hotspot()) {
794 memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, length);
795 } else {
796 JNIAccessMark jni(this);
797 jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, length, src);
798 }
799 }
800
801 void JVMCIEnv::copy_longs_from(jlong* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
802 if (length == 0) {
803 return;
804 }
805 if (is_hotspot()) {
806 memcpy(HotSpotJVMCI::resolve(dest)->long_at_addr(offset), src, length * sizeof(jlong));
807 } else {
808 JNIAccessMark jni(this);
809 jni()->SetLongArrayRegion(dest.as_jlongArray(), offset, length, src);
810 }
811 }
812
813 jboolean JVMCIEnv::is_boxing_object(BasicType type, JVMCIObject object) {
814 if (is_hotspot()) {
815 return java_lang_boxing_object::is_instance(HotSpotJVMCI::resolve(object), type);
816 } else {
817 JNIAccessMark jni(this);
818 return jni()->IsInstanceOf(get_jobject(object), JNIJVMCI::box_class(type));
819 }
820 }
821
822 // Get the primitive value from a Java boxing object. It's hard error to
823 // pass a non-primitive BasicType.
824 jvalue JVMCIEnv::get_boxed_value(BasicType type, JVMCIObject object) {
825 jvalue result;
826 if (is_hotspot()) {
827 if (java_lang_boxing_object::get_value(HotSpotJVMCI::resolve(object), &result) == T_ILLEGAL) {
828 ShouldNotReachHere();
829 }
830 } else {
831 JNIAccessMark jni(this);
832 jfieldID field = JNIJVMCI::box_field(type);
833 switch (type) {
834 case T_BOOLEAN: result.z = jni()->GetBooleanField(get_jobject(object), field); break;
835 case T_BYTE: result.b = jni()->GetByteField(get_jobject(object), field); break;
836 case T_SHORT: result.s = jni()->GetShortField(get_jobject(object), field); break;
837 case T_CHAR: result.c = jni()->GetCharField(get_jobject(object), field); break;
838 case T_INT: result.i = jni()->GetIntField(get_jobject(object), field); break;
839 case T_LONG: result.j = jni()->GetLongField(get_jobject(object), field); break;
840 case T_FLOAT: result.f = jni()->GetFloatField(get_jobject(object), field); break;
841 case T_DOUBLE: result.d = jni()->GetDoubleField(get_jobject(object), field); break;
842 default:
843 ShouldNotReachHere();
844 }
845 }
846 return result;
847 }
848
849 // Return the BasicType of the object if it's a boxing object, otherwise return T_ILLEGAL.
850 BasicType JVMCIEnv::get_box_type(JVMCIObject object) {
851 if (is_hotspot()) {
852 return java_lang_boxing_object::basic_type(HotSpotJVMCI::resolve(object));
853 } else {
854 JNIAccessMark jni(this);
855 jclass clazz = jni()->GetObjectClass(get_jobject(object));
856 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_BOOLEAN))) return T_BOOLEAN;
857 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_BYTE))) return T_BYTE;
858 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_SHORT))) return T_SHORT;
859 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_CHAR))) return T_CHAR;
860 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_INT))) return T_INT;
861 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_LONG))) return T_LONG;
862 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_FLOAT))) return T_FLOAT;
863 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_DOUBLE))) return T_DOUBLE;
864 return T_ILLEGAL;
865 }
866 }
867
868 // Create a boxing object of the appropriate primitive type.
869 JVMCIObject JVMCIEnv::create_box(BasicType type, jvalue* value, JVMCI_TRAPS) {
870 switch (type) {
871 case T_BOOLEAN:
872 case T_BYTE:
873 case T_CHAR:
874 case T_SHORT:
875 case T_INT:
876 case T_LONG:
877 case T_FLOAT:
878 case T_DOUBLE:
879 break;
880 default:
881 JVMCI_THROW_MSG_(IllegalArgumentException, "Only boxes for primitive values can be created", JVMCIObject());
882 }
883 JavaThread* THREAD = JavaThread::current(); // For exception macros.
884 if (is_hotspot()) {
885 oop box = java_lang_boxing_object::create(type, value, CHECK_(JVMCIObject()));
886 return HotSpotJVMCI::wrap(box);
887 } else {
888 JNIAccessMark jni(this, THREAD);
889 jobject box = jni()->NewObjectA(JNIJVMCI::box_class(type), JNIJVMCI::box_constructor(type), value);
890 assert(box != nullptr, "");
891 return wrap(box);
892 }
893 }
894
895 const char* JVMCIEnv::as_utf8_string(JVMCIObject str) {
896 if (is_hotspot()) {
897 return java_lang_String::as_utf8_string(HotSpotJVMCI::resolve(str));
898 } else {
899 JNIAccessMark jni(this);
900 jstring jstr = str.as_jstring();
901 int length = jni()->GetStringLength(jstr);
902 int utf8_length = jni()->GetStringUTFLength(jstr);
903 char* result = NEW_RESOURCE_ARRAY(char, utf8_length + 1);
904 jni()->GetStringUTFRegion(jstr, 0, length, result);
905 return result;
906 }
907 }
908
909 #define DO_THROW(name) \
910 void JVMCIEnv::throw_##name(const char* msg) { \
911 if (is_hotspot()) { \
912 JavaThread* THREAD = JavaThread::current(); \
913 THROW_MSG(HotSpotJVMCI::name::symbol(), msg); \
914 } else { \
915 JNIAccessMark jni(this); \
916 jni()->ThrowNew(JNIJVMCI::name::clazz(), msg); \
917 } \
918 }
919
920 DO_THROW(InternalError)
921 DO_THROW(ArrayIndexOutOfBoundsException)
922 DO_THROW(IllegalStateException)
923 DO_THROW(NullPointerException)
924 DO_THROW(IllegalArgumentException)
925 DO_THROW(InvalidInstalledCodeException)
926 DO_THROW(UnsatisfiedLinkError)
927 DO_THROW(UnsupportedOperationException)
928 DO_THROW(OutOfMemoryError)
929 DO_THROW(NoClassDefFoundError)
930
931 #undef DO_THROW
932
933 void JVMCIEnv::fthrow_error(const char* file, int line, const char* format, ...) {
934 const int max_msg_size = 1024;
935 va_list ap;
936 va_start(ap, format);
937 char msg[max_msg_size];
938 (void) os::vsnprintf(msg, max_msg_size, format, ap);
939 va_end(ap);
940 JavaThread* THREAD = JavaThread::current();
941 if (is_hotspot()) {
942 Handle h_loader;
943 Exceptions::_throw_msg(THREAD, file, line, vmSymbols::jdk_vm_ci_common_JVMCIError(), msg, h_loader );
944 } else {
945 JNIAccessMark jni(this, THREAD);
946 jni()->ThrowNew(JNIJVMCI::JVMCIError::clazz(), msg);
947 }
948 }
949
950 jboolean JVMCIEnv::call_HotSpotJVMCIRuntime_isGCSupported (JVMCIObject runtime, jint gcIdentifier) {
951 JavaThread* THREAD = JavaThread::current(); // For exception macros.
952 if (is_hotspot()) {
953 JavaCallArguments jargs;
954 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
955 jargs.push_int(gcIdentifier);
956 JavaValue result(T_BOOLEAN);
957 JavaCalls::call_special(&result,
958 HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
959 vmSymbols::isGCSupported_name(),
960 vmSymbols::int_bool_signature(), &jargs, CHECK_0);
961 return result.get_jboolean();
962 } else {
963 JNIAccessMark jni(this, THREAD);
964 jboolean result = jni()->CallNonvirtualBooleanMethod(runtime.as_jobject(),
965 JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
966 JNIJVMCI::HotSpotJVMCIRuntime::isGCSupported_method(),
967 gcIdentifier);
968 if (jni()->ExceptionCheck()) {
969 return false;
970 }
971 return result;
972 }
973 }
974
975 jboolean JVMCIEnv::call_HotSpotJVMCIRuntime_isIntrinsicSupported (JVMCIObject runtime, jint intrinsicIdentifier) {
976 JavaThread* THREAD = JavaThread::current(); // For exception macros.
977 if (is_hotspot()) {
978 JavaCallArguments jargs;
979 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
980 jargs.push_int(intrinsicIdentifier);
981 JavaValue result(T_BOOLEAN);
982 JavaCalls::call_special(&result,
983 HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
984 vmSymbols::isIntrinsicSupported_name(),
985 vmSymbols::int_bool_signature(), &jargs, CHECK_0);
986 return result.get_jboolean();
987 } else {
988 JNIAccessMark jni(this, THREAD);
989 jboolean result = jni()->CallNonvirtualBooleanMethod(runtime.as_jobject(),
990 JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
991 JNIJVMCI::HotSpotJVMCIRuntime::isIntrinsicSupported_method(),
992 intrinsicIdentifier);
993 if (jni()->ExceptionCheck()) {
994 return false;
995 }
996 return result;
997 }
998 }
999
1000 JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtime, JVMCIObject method, int entry_bci,
1001 jlong compile_state, int id) {
1002 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1003 if (is_hotspot()) {
1004 JavaCallArguments jargs;
1005 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
1006 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(method)));
1007 jargs.push_int(entry_bci);
1008 jargs.push_long(compile_state);
1009 jargs.push_int(id);
1010 JavaValue result(T_OBJECT);
1011 JavaCalls::call_special(&result,
1012 HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
1013 vmSymbols::compileMethod_name(),
1014 vmSymbols::compileMethod_signature(), &jargs, CHECK_(JVMCIObject()));
1015 return wrap(result.get_oop());
1016 } else {
1017 JNIAccessMark jni(this, THREAD);
1018 jobject result = jni()->CallNonvirtualObjectMethod(runtime.as_jobject(),
1019 JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
1020 JNIJVMCI::HotSpotJVMCIRuntime::compileMethod_method(),
1021 method.as_jobject(), entry_bci, compile_state, id);
1022 if (jni()->ExceptionCheck()) {
1023 return JVMCIObject();
1024 }
1025 return wrap(result);
1026 }
1027 }
1028
1029 void JVMCIEnv::call_HotSpotJVMCIRuntime_bootstrapFinished (JVMCIObject runtime, JVMCIEnv* JVMCIENV) {
1030 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1031 if (is_hotspot()) {
1032 JavaCallArguments jargs;
1033 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
1034 JavaValue result(T_VOID);
1035 JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::bootstrapFinished_name(), vmSymbols::void_method_signature(), &jargs, CHECK);
1036 } else {
1037 JNIAccessMark jni(this, THREAD);
1038 jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::bootstrapFinished_method());
1039
1040 }
1041 }
1042
1043 void JVMCIEnv::call_HotSpotJVMCIRuntime_shutdown (JVMCIObject runtime) {
1044 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1045 HandleMark hm(THREAD);
1046 if (is_hotspot()) {
1047 JavaCallArguments jargs;
1048 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
1049 JavaValue result(T_VOID);
1050 JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::shutdown_name(), vmSymbols::void_method_signature(), &jargs, THREAD);
1051 } else {
1052 JNIAccessMark jni(this, THREAD);
1053 jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::shutdown_method());
1054 }
1055 if (has_pending_exception()) {
1056 // This should never happen as HotSpotJVMCIRuntime.shutdown() should
1057 // handle all exceptions.
1058 describe_pending_exception(tty);
1059 }
1060 }
1061
1062 JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) {
1063 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1064 if (is_hotspot()) {
1065 JavaCallArguments jargs;
1066 JavaValue result(T_OBJECT);
1067 JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::runtime_name(), vmSymbols::runtime_signature(), &jargs, CHECK_(JVMCIObject()));
1068 return wrap(result.get_oop());
1069 } else {
1070 JNIAccessMark jni(this, THREAD);
1071 jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::runtime_method());
1072 if (jni()->ExceptionCheck()) {
1073 return JVMCIObject();
1074 }
1075 return wrap(result);
1076 }
1077 }
1078
1079 JVMCIObject JVMCIEnv::call_JVMCI_getRuntime (JVMCIEnv* JVMCIENV) {
1080 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1081 if (is_hotspot()) {
1082 JavaCallArguments jargs;
1083 JavaValue result(T_OBJECT);
1084 JavaCalls::call_static(&result, HotSpotJVMCI::JVMCI::klass(), vmSymbols::getRuntime_name(), vmSymbols::getRuntime_signature(), &jargs, CHECK_(JVMCIObject()));
1085 return wrap(result.get_oop());
1086 } else {
1087 JNIAccessMark jni(this, THREAD);
1088 jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::JVMCI::clazz(), JNIJVMCI::JVMCI::getRuntime_method());
1089 if (jni()->ExceptionCheck()) {
1090 return JVMCIObject();
1091 }
1092 return wrap(result);
1093 }
1094 }
1095
1096 JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime, JVMCIEnv* JVMCIENV) {
1097 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1098 if (is_hotspot()) {
1099 JavaCallArguments jargs;
1100 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
1101 JavaValue result(T_OBJECT);
1102 JavaCalls::call_virtual(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::getCompiler_name(), vmSymbols::getCompiler_signature(), &jargs, CHECK_(JVMCIObject()));
1103 return wrap(result.get_oop());
1104 } else {
1105 JNIAccessMark jni(this, THREAD);
1106 jobject result = jni()->CallObjectMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::getCompiler_method());
1107 if (jni()->ExceptionCheck()) {
1108 return JVMCIObject();
1109 }
1110 return wrap(result);
1111 }
1112 }
1113
1114 void JVMCIEnv::call_HotSpotJVMCIRuntime_postTranslation(JVMCIObject object, JVMCIEnv* JVMCIENV) {
1115 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1116 if (is_hotspot()) {
1117 JavaCallArguments jargs;
1118 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(object)));
1119 JavaValue result(T_VOID);
1120 JavaCalls::call_static(&result,
1121 HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
1122 vmSymbols::postTranslation_name(),
1123 vmSymbols::object_void_signature(), &jargs, CHECK);
1124 } else {
1125 JNIAccessMark jni(this, THREAD);
1126 jni()->CallStaticVoidMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
1127 JNIJVMCI::HotSpotJVMCIRuntime::postTranslation_method(),
1128 object.as_jobject());
1129 }
1130 }
1131
1132 JVMCIObject JVMCIEnv::call_JavaConstant_forPrimitive(jchar type_char, jlong value, JVMCI_TRAPS) {
1133 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1134 if (is_hotspot()) {
1135 JavaCallArguments jargs;
1136 jargs.push_int(type_char);
1137 jargs.push_long(value);
1138 JavaValue result(T_OBJECT);
1139 JavaCalls::call_static(&result,
1140 HotSpotJVMCI::JavaConstant::klass(),
1141 vmSymbols::forPrimitive_name(),
1142 vmSymbols::forPrimitive_signature(), &jargs, CHECK_(JVMCIObject()));
1143 return wrap(result.get_oop());
1144 } else {
1145 JNIAccessMark jni(this, THREAD);
1146 jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(),
1147 JNIJVMCI::JavaConstant::forPrimitive_method(),
1148 type_char, value);
1149 if (jni()->ExceptionCheck()) {
1150 return JVMCIObject();
1151 }
1152 return wrap(result);
1153 }
1154 }
1155
1156 JVMCIObject JVMCIEnv::get_jvmci_primitive_type(BasicType type, JVMCI_TRAPS) {
1157 JVMCIObjectArray primitives = get_HotSpotResolvedPrimitiveType_primitives();
1158 JVMCIObject result = get_object_at(primitives, type, JVMCI_CHECK_({}));
1159 return result;
1160 }
1161
1162 JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci, JVMCI_TRAPS) {
1163 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1164 Symbol* file_name_sym;
1165 int line_number;
1166 java_lang_StackTraceElement::decode(method, bci, file_name_sym, line_number, CHECK_(JVMCIObject()));
1167
1168 Symbol* method_name_sym = method->name();
1169 InstanceKlass* holder = method->method_holder();
1170 const char* declaring_class_str = holder->external_name();
1171
1172 if (is_hotspot()) {
1173 HotSpotJVMCI::StackTraceElement::klass()->initialize(CHECK_(JVMCIObject()));
1174 oop objOop = HotSpotJVMCI::StackTraceElement::klass()->allocate_instance(CHECK_(JVMCIObject()));
1175 Handle obj = Handle(THREAD, objOop);
1176
1177 oop declaring_class = StringTable::intern((char*) declaring_class_str, CHECK_(JVMCIObject()));
1178 HotSpotJVMCI::StackTraceElement::set_declaringClass(this, obj(), declaring_class);
1179
1180 oop method_name = StringTable::intern(method_name_sym, CHECK_(JVMCIObject()));
1181 HotSpotJVMCI::StackTraceElement::set_methodName(this, obj(), method_name);
1182
1183 if (file_name_sym != nullptr) {
1184 oop file_name = StringTable::intern(file_name_sym, CHECK_(JVMCIObject()));
1185 HotSpotJVMCI::StackTraceElement::set_fileName(this, obj(), file_name);
1186 }
1187 HotSpotJVMCI::StackTraceElement::set_lineNumber(this, obj(), line_number);
1188 return wrap(obj());
1189 } else {
1190 JNIAccessMark jni(this, THREAD);
1191 jobject declaring_class = jni()->NewStringUTF(declaring_class_str);
1192 if (jni()->ExceptionCheck()) {
1193 return JVMCIObject();
1194 }
1195 jobject method_name = jni()->NewStringUTF(method_name_sym->as_C_string());
1196 if (jni()->ExceptionCheck()) {
1197 return JVMCIObject();
1198 }
1199 jobject file_name = nullptr;
1200 if (file_name_sym != nullptr) {
1201 file_name = jni()->NewStringUTF(file_name_sym->as_C_string());
1202 if (jni()->ExceptionCheck()) {
1203 return JVMCIObject();
1204 }
1205 }
1206
1207 jobject result = jni()->NewObject(JNIJVMCI::StackTraceElement::clazz(),
1208 JNIJVMCI::StackTraceElement::constructor(),
1209 declaring_class, method_name, file_name, line_number);
1210 return wrap(result);
1211 }
1212 }
1213
1214 JVMCIObject JVMCIEnv::new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jboolean profileDeopt, jlong compileId, JVMCI_TRAPS) {
1215 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1216
1217 JVMCIObject methodObject = get_jvmci_method(method, JVMCI_CHECK_(JVMCIObject()));
1218
1219 if (is_hotspot()) {
1220 InstanceKlass* ik = InstanceKlass::cast(HotSpotJVMCI::HotSpotNmethod::klass());
1221 if (ik->should_be_initialized()) {
1222 ik->initialize(CHECK_(JVMCIObject()));
1223 }
1224 oop obj = ik->allocate_instance(CHECK_(JVMCIObject()));
1225 Handle obj_h(THREAD, obj);
1226 Handle nameStr = java_lang_String::create_from_str(name, CHECK_(JVMCIObject()));
1227
1228 // Call constructor
1229 JavaCallArguments jargs;
1230 jargs.push_oop(obj_h);
1231 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(methodObject)));
1232 jargs.push_oop(nameStr);
1233 jargs.push_int(isDefault);
1234 jargs.push_int(profileDeopt);
1235 jargs.push_long(compileId);
1236 JavaValue result(T_VOID);
1237 JavaCalls::call_special(&result, ik,
1238 vmSymbols::object_initializer_name(),
1239 vmSymbols::method_string_bool_bool_long_signature(),
1240 &jargs, CHECK_(JVMCIObject()));
1241 return wrap(obj_h());
1242 } else {
1243 JNIAccessMark jni(this, THREAD);
1244 jobject nameStr = name == nullptr ? nullptr : jni()->NewStringUTF(name);
1245 if (jni()->ExceptionCheck()) {
1246 return JVMCIObject();
1247 }
1248
1249 jobject result = jni()->NewObject(JNIJVMCI::HotSpotNmethod::clazz(),
1250 JNIJVMCI::HotSpotNmethod::constructor(),
1251 methodObject.as_jobject(), nameStr, isDefault);
1252 return wrap(result);
1253 }
1254 }
1255
1256 JVMCIObject JVMCIEnv::make_local(JVMCIObject object) {
1257 if (object.is_null()) {
1258 return JVMCIObject();
1259 }
1260 if (is_hotspot()) {
1261 return wrap(JNIHandles::make_local(HotSpotJVMCI::resolve(object)));
1262 } else {
1263 JNIAccessMark jni(this);
1264 return wrap(jni()->NewLocalRef(object.as_jobject()));
1265 }
1266 }
1267
1268 JVMCIObject JVMCIEnv::make_global(JVMCIObject object) {
1269 if (object.is_null()) {
1270 return JVMCIObject();
1271 }
1272 if (is_hotspot()) {
1273 return wrap(JNIHandles::make_global(Handle(Thread::current(), HotSpotJVMCI::resolve(object))));
1274 } else {
1275 JNIAccessMark jni(this);
1276 return wrap(jni()->NewGlobalRef(object.as_jobject()));
1277 }
1278 }
1279
1280 void JVMCIEnv::destroy_local(JVMCIObject object) {
1281 if (is_hotspot()) {
1282 JNIHandles::destroy_local(object.as_jobject());
1283 } else {
1284 JNIAccessMark jni(this);
1285 jni()->DeleteLocalRef(object.as_jobject());
1286 }
1287 }
1288
1289 void JVMCIEnv::destroy_global(JVMCIObject object) {
1290 if (is_hotspot()) {
1291 JNIHandles::destroy_global(object.as_jobject());
1292 } else {
1293 JNIAccessMark jni(this);
1294 jni()->DeleteGlobalRef(object.as_jobject());
1295 }
1296 }
1297
1298 const char* JVMCIEnv::klass_name(JVMCIObject object) {
1299 if (is_hotspot()) {
1300 return HotSpotJVMCI::resolve(object)->klass()->signature_name();
1301 } else {
1302 JVMCIObject name;
1303 {
1304 JNIAccessMark jni(this);
1305 jclass jcl = jni()->GetObjectClass(object.as_jobject());
1306 jobject result = jni()->CallObjectMethod(jcl, JNIJVMCI::Class_getName_method());
1307 name = JVMCIObject::create(result, is_hotspot());
1308 }
1309 return as_utf8_string(name);
1310 }
1311 }
1312
1313 JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS) {
1314 JVMCIObject method_object;
1315 if (method() == nullptr) {
1316 return method_object;
1317 }
1318 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1319 JVMCIKlassHandle holder_klass(THREAD, method->method_holder());
1320 JVMCIObject holder = get_jvmci_type(holder_klass, JVMCI_CHECK_(JVMCIObject()));
1321
1322 CompilerOracle::tag_blackhole_if_possible(method);
1323
1324 jmetadata handle = _runtime->allocate_handle(method);
1325 jboolean exception = false;
1326 if (is_hotspot()) {
1327 JavaValue result(T_OBJECT);
1328 JavaCallArguments args;
1329 args.push_long((jlong) handle);
1330 args.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(holder)));
1331 JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotResolvedJavaMethodImpl::klass(),
1332 vmSymbols::fromMetaspace_name(),
1333 vmSymbols::method_fromMetaspace_signature(), &args, THREAD);
1334 if (HAS_PENDING_EXCEPTION) {
1335 exception = true;
1336 } else {
1337 method_object = wrap(result.get_oop());
1338 }
1339 } else {
1340 JNIAccessMark jni(this, THREAD);
1341 method_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedJavaMethodImpl::clazz(),
1342 JNIJVMCI::HotSpotResolvedJavaMethodImpl_fromMetaspace_method(),
1343 (jlong) handle, holder.as_jobject()));
1344 exception = jni()->ExceptionCheck();
1345 }
1346
1347 if (exception) {
1348 _runtime->release_handle(handle);
1349 return JVMCIObject();
1350 }
1351
1352 assert(asMethod(method_object) == method(), "must be");
1353 if (get_HotSpotResolvedJavaMethodImpl_methodHandle(method_object) != (jlong) handle) {
1354 _runtime->release_handle(handle);
1355 }
1356 assert(!method_object.is_null(), "must be");
1357 return method_object;
1358 }
1359
1360 JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS) {
1361 JVMCIObject type;
1362 if (klass.is_null()) {
1363 return type;
1364 }
1365
1366 guarantee(klass->is_klass(), "must be valid klass");
1367 guarantee(klass->is_loader_alive(), "klass must be alive");
1368
1369 jlong pointer = (jlong) klass();
1370 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1371 jboolean exception = false;
1372 if (is_hotspot()) {
1373 CompilerThreadCanCallJava ccj(THREAD, true);
1374 JavaValue result(T_OBJECT);
1375 JavaCallArguments args;
1376 args.push_long(pointer);
1377 JavaCalls::call_static(&result,
1378 HotSpotJVMCI::HotSpotResolvedObjectTypeImpl::klass(),
1379 vmSymbols::fromMetaspace_name(),
1380 vmSymbols::klass_fromMetaspace_signature(), &args, THREAD);
1381
1382 if (HAS_PENDING_EXCEPTION) {
1383 exception = true;
1384 } else {
1385 type = wrap(result.get_oop());
1386 }
1387 } else {
1388 JNIAccessMark jni(this, THREAD);
1389
1390 HandleMark hm(THREAD);
1391 type = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedObjectTypeImpl::clazz(),
1392 JNIJVMCI::HotSpotResolvedObjectTypeImpl_fromMetaspace_method(),
1393 pointer));
1394 exception = jni()->ExceptionCheck();
1395 }
1396 if (exception) {
1397 return JVMCIObject();
1398 }
1399
1400 assert(type.is_non_null(), "must have result");
1401 return type;
1402 }
1403
1404 JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMCI_TRAPS) {
1405 JVMCIObject cp_object;
1406 jmetadata handle = _runtime->allocate_handle(cp);
1407 jboolean exception = false;
1408 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1409 if (is_hotspot()) {
1410 JavaValue result(T_OBJECT);
1411 JavaCallArguments args;
1412 args.push_long((jlong) handle);
1413 JavaCalls::call_static(&result,
1414 HotSpotJVMCI::HotSpotConstantPool::klass(),
1415 vmSymbols::fromMetaspace_name(),
1416 vmSymbols::constantPool_fromMetaspace_signature(), &args, THREAD);
1417 if (HAS_PENDING_EXCEPTION) {
1418 exception = true;
1419 } else {
1420 cp_object = wrap(result.get_oop());
1421 }
1422 } else {
1423 JNIAccessMark jni(this, THREAD);
1424 cp_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotConstantPool::clazz(),
1425 JNIJVMCI::HotSpotConstantPool_fromMetaspace_method(),
1426 (jlong) handle));
1427 exception = jni()->ExceptionCheck();
1428 }
1429
1430 if (exception) {
1431 _runtime->release_handle(handle);
1432 return JVMCIObject();
1433 }
1434
1435 assert(!cp_object.is_null(), "must be");
1436 // Constant pools aren't cached so this is always a newly created object using the handle
1437 assert(get_HotSpotConstantPool_constantPoolHandle(cp_object) == (jlong) handle, "must use same handle");
1438 return cp_object;
1439 }
1440
1441 JVMCIPrimitiveArray JVMCIEnv::new_booleanArray(int length, JVMCI_TRAPS) {
1442 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1443 if (is_hotspot()) {
1444 typeArrayOop result = oopFactory::new_boolArray(length, CHECK_(JVMCIObject()));
1445 return wrap(result);
1446 } else {
1447 JNIAccessMark jni(this, THREAD);
1448 jbooleanArray result = jni()->NewBooleanArray(length);
1449 return wrap(result);
1450 }
1451 }
1452
1453 JVMCIPrimitiveArray JVMCIEnv::new_byteArray(int length, JVMCI_TRAPS) {
1454 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1455 if (is_hotspot()) {
1456 typeArrayOop result = oopFactory::new_byteArray(length, CHECK_(JVMCIObject()));
1457 return wrap(result);
1458 } else {
1459 JNIAccessMark jni(this, THREAD);
1460 jbyteArray result = jni()->NewByteArray(length);
1461 return wrap(result);
1462 }
1463 }
1464
1465 JVMCIObjectArray JVMCIEnv::new_byte_array_array(int length, JVMCI_TRAPS) {
1466 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1467 if (is_hotspot()) {
1468 objArrayOop result = oopFactory::new_objArray(Universe::byteArrayKlass(), length, CHECK_(JVMCIObject()));
1469 return wrap(result);
1470 } else {
1471 JNIAccessMark jni(this, THREAD);
1472 jobjectArray result = jni()->NewObjectArray(length, JNIJVMCI::byte_array(), nullptr);
1473 return wrap(result);
1474 }
1475 }
1476
1477 JVMCIPrimitiveArray JVMCIEnv::new_intArray(int length, JVMCI_TRAPS) {
1478 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1479 if (is_hotspot()) {
1480 typeArrayOop result = oopFactory::new_intArray(length, CHECK_(JVMCIObject()));
1481 return wrap(result);
1482 } else {
1483 JNIAccessMark jni(this, THREAD);
1484 jintArray result = jni()->NewIntArray(length);
1485 return wrap(result);
1486 }
1487 }
1488
1489 JVMCIPrimitiveArray JVMCIEnv::new_longArray(int length, JVMCI_TRAPS) {
1490 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1491 if (is_hotspot()) {
1492 typeArrayOop result = oopFactory::new_longArray(length, CHECK_(JVMCIObject()));
1493 return wrap(result);
1494 } else {
1495 JNIAccessMark jni(this, THREAD);
1496 jlongArray result = jni()->NewLongArray(length);
1497 return wrap(result);
1498 }
1499 }
1500
1501 JVMCIObject JVMCIEnv::new_VMField(JVMCIObject name, JVMCIObject type, jlong offset, jlong address, JVMCIObject value, JVMCI_TRAPS) {
1502 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1503 if (is_hotspot()) {
1504 HotSpotJVMCI::VMField::klass()->initialize(CHECK_(JVMCIObject()));
1505 oop obj = HotSpotJVMCI::VMField::klass()->allocate_instance(CHECK_(JVMCIObject()));
1506 HotSpotJVMCI::VMField::set_name(this, obj, HotSpotJVMCI::resolve(name));
1507 HotSpotJVMCI::VMField::set_type(this, obj, HotSpotJVMCI::resolve(type));
1508 HotSpotJVMCI::VMField::set_offset(this, obj, offset);
1509 HotSpotJVMCI::VMField::set_address(this, obj, address);
1510 HotSpotJVMCI::VMField::set_value(this, obj, HotSpotJVMCI::resolve(value));
1511 return wrap(obj);
1512 } else {
1513 JNIAccessMark jni(this, THREAD);
1514 jobject result = jni()->NewObject(JNIJVMCI::VMField::clazz(),
1515 JNIJVMCI::VMField::constructor(),
1516 get_jobject(name), get_jobject(type), offset, address, get_jobject(value));
1517 return wrap(result);
1518 }
1519 }
1520
1521 JVMCIObject JVMCIEnv::new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject value, JVMCI_TRAPS) {
1522 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1523 if (is_hotspot()) {
1524 HotSpotJVMCI::VMFlag::klass()->initialize(CHECK_(JVMCIObject()));
1525 oop obj = HotSpotJVMCI::VMFlag::klass()->allocate_instance(CHECK_(JVMCIObject()));
1526 HotSpotJVMCI::VMFlag::set_name(this, obj, HotSpotJVMCI::resolve(name));
1527 HotSpotJVMCI::VMFlag::set_type(this, obj, HotSpotJVMCI::resolve(type));
1528 HotSpotJVMCI::VMFlag::set_value(this, obj, HotSpotJVMCI::resolve(value));
1529 return wrap(obj);
1530 } else {
1531 JNIAccessMark jni(this, THREAD);
1532 jobject result = jni()->NewObject(JNIJVMCI::VMFlag::clazz(),
1533 JNIJVMCI::VMFlag::constructor(),
1534 get_jobject(name), get_jobject(type), get_jobject(value));
1535 return wrap(result);
1536 }
1537 }
1538
1539 JVMCIObject JVMCIEnv::new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, jboolean isAvailable, jboolean c1Supported, jboolean c2Supported, JVMCI_TRAPS) {
1540 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1541 if (is_hotspot()) {
1542 HotSpotJVMCI::VMIntrinsicMethod::klass()->initialize(CHECK_(JVMCIObject()));
1543 oop obj = HotSpotJVMCI::VMIntrinsicMethod::klass()->allocate_instance(CHECK_(JVMCIObject()));
1544 HotSpotJVMCI::VMIntrinsicMethod::set_declaringClass(this, obj, HotSpotJVMCI::resolve(declaringClass));
1545 HotSpotJVMCI::VMIntrinsicMethod::set_name(this, obj, HotSpotJVMCI::resolve(name));
1546 HotSpotJVMCI::VMIntrinsicMethod::set_descriptor(this, obj, HotSpotJVMCI::resolve(descriptor));
1547 HotSpotJVMCI::VMIntrinsicMethod::set_id(this, obj, id);
1548 HotSpotJVMCI::VMIntrinsicMethod::set_isAvailable(this, obj, isAvailable);
1549 HotSpotJVMCI::VMIntrinsicMethod::set_c1Supported(this, obj, c1Supported);
1550 HotSpotJVMCI::VMIntrinsicMethod::set_c2Supported(this, obj, c2Supported);
1551 return wrap(obj);
1552 } else {
1553 JNIAccessMark jni(this, THREAD);
1554 jobject result = jni()->NewObject(JNIJVMCI::VMIntrinsicMethod::clazz(),
1555 JNIJVMCI::VMIntrinsicMethod::constructor(),
1556 get_jobject(declaringClass), get_jobject(name), get_jobject(descriptor), id, isAvailable, c1Supported, c2Supported);
1557 return wrap(result);
1558 }
1559 }
1560
1561 JVMCIObject JVMCIEnv::new_HotSpotStackFrameReference(JVMCI_TRAPS) {
1562 if (is_hotspot()) {
1563 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1564 HotSpotJVMCI::HotSpotStackFrameReference::klass()->initialize(CHECK_(JVMCIObject()));
1565 oop obj = HotSpotJVMCI::HotSpotStackFrameReference::klass()->allocate_instance(CHECK_(JVMCIObject()));
1566 return wrap(obj);
1567 } else {
1568 ShouldNotReachHere();
1569 return JVMCIObject();
1570 }
1571 }
1572 JVMCIObject JVMCIEnv::new_JVMCIError(JVMCI_TRAPS) {
1573 if (is_hotspot()) {
1574 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1575 HotSpotJVMCI::JVMCIError::klass()->initialize(CHECK_(JVMCIObject()));
1576 oop obj = HotSpotJVMCI::JVMCIError::klass()->allocate_instance(CHECK_(JVMCIObject()));
1577 return wrap(obj);
1578 } else {
1579 ShouldNotReachHere();
1580 return JVMCIObject();
1581 }
1582 }
1583
1584 JVMCIObject JVMCIEnv::new_FieldInfo(FieldInfo* fieldinfo, JVMCI_TRAPS) {
1585 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1586 if (is_hotspot()) {
1587 HotSpotJVMCI::FieldInfo::klass()->initialize(CHECK_(JVMCIObject()));
1588 oop obj = HotSpotJVMCI::FieldInfo::klass()->allocate_instance(CHECK_(JVMCIObject()));
1589 Handle obj_h(THREAD, obj);
1590 HotSpotJVMCI::FieldInfo::set_nameIndex(JVMCIENV, obj_h(), (jint)fieldinfo->name_index());
1591 HotSpotJVMCI::FieldInfo::set_signatureIndex(JVMCIENV, obj_h(), (jint)fieldinfo->signature_index());
1592 HotSpotJVMCI::FieldInfo::set_offset(JVMCIENV, obj_h(), (jint)fieldinfo->offset());
1593 HotSpotJVMCI::FieldInfo::set_classfileFlags(JVMCIENV, obj_h(), (jint)fieldinfo->access_flags().as_field_flags());
1594 HotSpotJVMCI::FieldInfo::set_internalFlags(JVMCIENV, obj_h(), (jint)fieldinfo->field_flags().as_uint());
1595 HotSpotJVMCI::FieldInfo::set_initializerIndex(JVMCIENV, obj_h(), (jint)fieldinfo->initializer_index());
1596 return wrap(obj_h());
1597 } else {
1598 JNIAccessMark jni(this, THREAD);
1599 jobject result = jni()->NewObject(JNIJVMCI::FieldInfo::clazz(),
1600 JNIJVMCI::FieldInfo::constructor(),
1601 (jint)fieldinfo->name_index(),
1602 (jint)fieldinfo->signature_index(),
1603 (jint)fieldinfo->offset(),
1604 (jint)fieldinfo->access_flags().as_field_flags(),
1605 (jint)fieldinfo->field_flags().as_uint(),
1606 (jint)fieldinfo->initializer_index());
1607
1608 return wrap(result);
1609 }
1610 }
1611
1612 JVMCIObject JVMCIEnv::get_object_constant(oop objOop, bool compressed, bool dont_register) {
1613 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1614 Handle obj = Handle(THREAD, objOop);
1615 if (obj.is_null()) {
1616 return JVMCIObject();
1617 }
1618 if (is_hotspot()) {
1619 HotSpotJVMCI::DirectHotSpotObjectConstantImpl::klass()->initialize(CHECK_(JVMCIObject()));
1620 oop constant = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::klass()->allocate_instance(CHECK_(JVMCIObject()));
1621 HotSpotJVMCI::DirectHotSpotObjectConstantImpl::set_object(this, constant, obj());
1622 HotSpotJVMCI::HotSpotObjectConstantImpl::set_compressed(this, constant, compressed);
1623 return wrap(constant);
1624 } else {
1625 jlong handle = make_oop_handle(obj);
1626 JNIAccessMark jni(this, THREAD);
1627 jobject result = jni()->NewObject(JNIJVMCI::IndirectHotSpotObjectConstantImpl::clazz(),
1628 JNIJVMCI::IndirectHotSpotObjectConstantImpl::constructor(),
1629 handle, compressed, dont_register);
1630 return wrap(result);
1631 }
1632 }
1633
1634
1635 Handle JVMCIEnv::asConstant(JVMCIObject constant, JVMCI_TRAPS) {
1636 if (constant.is_null()) {
1637 return Handle();
1638 }
1639 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1640 if (is_hotspot()) {
1641 assert(HotSpotJVMCI::DirectHotSpotObjectConstantImpl::is_instance(this, constant), "wrong type");
1642 oop obj = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::object(this, HotSpotJVMCI::resolve(constant));
1643 return Handle(THREAD, obj);
1644 } else if (isa_IndirectHotSpotObjectConstantImpl(constant)) {
1645 jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(constant);
1646 if (object_handle == 0L) {
1647 JVMCI_THROW_MSG_(NullPointerException, "Foreign object reference has been cleared", Handle());
1648 }
1649 oop result = resolve_oop_handle(object_handle);
1650 if (result == nullptr) {
1651 JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly null", Handle());
1652 }
1653 return Handle(THREAD, result);
1654 } else {
1655 JVMCI_THROW_MSG_(IllegalArgumentException, "DirectHotSpotObjectConstantImpl shouldn't reach JVMCI in SVM mode", Handle());
1656 }
1657 }
1658
1659 JVMCIObject JVMCIEnv::wrap(jobject object) {
1660 return JVMCIObject::create(object, is_hotspot());
1661 }
1662
1663 jlong JVMCIEnv::make_oop_handle(const Handle& obj) {
1664 assert(!obj.is_null(), "should only create handle for non-null oops");
1665 return _runtime->make_oop_handle(obj);
1666 }
1667
1668 oop JVMCIEnv::resolve_oop_handle(jlong oopHandle) {
1669 assert(oopHandle != 0, "should be a valid handle");
1670 oop obj = NativeAccess<>::oop_load(reinterpret_cast<oop*>(oopHandle));
1671 if (obj != nullptr) {
1672 guarantee(oopDesc::is_oop_or_null(obj), "invalid oop: " INTPTR_FORMAT, p2i((oopDesc*) obj));
1673 }
1674 return obj;
1675 }
1676
1677 JVMCIObject JVMCIEnv::create_string(const char* str, JVMCI_TRAPS) {
1678 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1679 if (is_hotspot()) {
1680 Handle result = java_lang_String::create_from_str(str, CHECK_(JVMCIObject()));
1681 return HotSpotJVMCI::wrap(result());
1682 } else {
1683 jobject result;
1684 jboolean exception = false;
1685 {
1686 JNIAccessMark jni(this, THREAD);
1687 result = jni()->NewStringUTF(str);
1688 exception = jni()->ExceptionCheck();
1689 }
1690 return wrap(result);
1691 }
1692 }
1693
1694 bool JVMCIEnv::equals(JVMCIObject a, JVMCIObject b) {
1695 if (is_hotspot()) {
1696 return HotSpotJVMCI::resolve(a) == HotSpotJVMCI::resolve(b);
1697 } else {
1698 JNIAccessMark jni(this);
1699 return jni()->IsSameObject(a.as_jobject(), b.as_jobject()) != 0;
1700 }
1701 }
1702
1703 BasicType JVMCIEnv::typeCharToBasicType(jchar ch, JVMCI_TRAPS) {
1704 switch(ch) {
1705 case 'Z': return T_BOOLEAN;
1706 case 'B': return T_BYTE;
1707 case 'S': return T_SHORT;
1708 case 'C': return T_CHAR;
1709 case 'I': return T_INT;
1710 case 'F': return T_FLOAT;
1711 case 'J': return T_LONG;
1712 case 'D': return T_DOUBLE;
1713 case 'A': return T_OBJECT;
1714 case '-': return T_ILLEGAL;
1715 default:
1716 JVMCI_ERROR_(T_ILLEGAL, "unexpected type char: %c", ch);
1717 }
1718 }
1719
1720 BasicType JVMCIEnv::kindToBasicType(JVMCIObject kind, JVMCI_TRAPS) {
1721 if (kind.is_null()) {
1722 JVMCI_THROW_(NullPointerException, T_ILLEGAL);
1723 }
1724 jchar ch = get_JavaKind_typeChar(kind);
1725 BasicType bt = typeCharToBasicType(ch, JVMCI_CHECK_(T_ILLEGAL));
1726 return bt;
1727 }
1728
1729 void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* cb, JVMCI_TRAPS) {
1730 // Ensure that all updates to the InstalledCode fields are consistent.
1731 if (get_InstalledCode_address(installed_code) != 0) {
1732 JVMCI_THROW_MSG(InternalError, "InstalledCode instance already in use");
1733 }
1734 if (!isa_HotSpotInstalledCode(installed_code)) {
1735 JVMCI_THROW_MSG(InternalError, "InstalledCode instance must be a subclass of HotSpotInstalledCode");
1736 }
1737
1738 // Ignore the version which can stay at 0
1739 if (cb->is_nmethod()) {
1740 nmethod* nm = cb->as_nmethod_or_null();
1741 if (nm->is_in_use()) {
1742 set_InstalledCode_entryPoint(installed_code, (jlong) nm->verified_entry_point());
1743 }
1744 } else {
1745 set_InstalledCode_entryPoint(installed_code, (jlong) cb->code_begin());
1746 }
1747 set_InstalledCode_address(installed_code, (jlong) cb);
1748 set_HotSpotInstalledCode_size(installed_code, cb->size());
1749 set_HotSpotInstalledCode_codeStart(installed_code, (jlong) cb->code_begin());
1750 set_HotSpotInstalledCode_codeSize(installed_code, cb->code_size());
1751 }
1752
1753
1754 void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nmethod::InvalidationReason invalidation_reason, JVMCI_TRAPS) {
1755 if (mirror.is_null()) {
1756 JVMCI_THROW(NullPointerException);
1757 }
1758
1759 Thread* current = Thread::current();
1760 if (!mirror.is_hotspot() && !current->is_Java_thread()) {
1761 // Calling back into native might cause the execution to block, so only allow this when calling
1762 // from a JavaThread, which is the normal case anyway.
1763 JVMCI_THROW_MSG(IllegalArgumentException,
1764 "Cannot invalidate HotSpotNmethod object in shared library VM heap from non-JavaThread");
1765 }
1766
1767 JavaThread* thread = JavaThread::cast(current);
1768 JVMCINMethodHandle nmethod_handle(thread);
1769 nmethod* nm = JVMCIENV->get_nmethod(mirror, nmethod_handle);
1770 if (nm == nullptr) {
1771 // Nothing to do
1772 return;
1773 }
1774
1775 if (!deoptimize) {
1776 // Prevent future executions of the nmethod but let current executions complete.
1777 nm->make_not_entrant(invalidation_reason);
1778
1779 // Do not clear the address field here as the Java code may still
1780 // want to later call this method with deoptimize == true. That requires
1781 // the address field to still be pointing at the nmethod.
1782 } else {
1783 // Deoptimize the nmethod immediately.
1784 DeoptimizationScope deopt_scope;
1785 deopt_scope.mark(nm);
1786 nm->make_not_entrant(invalidation_reason);
1787 nm->make_deoptimized();
1788 deopt_scope.deoptimize_marked();
1789
1790 // A HotSpotNmethod instance can only reference a single nmethod
1791 // during its lifetime so simply clear it here.
1792 set_InstalledCode_address(mirror, 0);
1793 }
1794 }
1795
1796 Klass* JVMCIEnv::asKlass(JVMCIObject obj) {
1797 return (Klass*) get_HotSpotResolvedObjectTypeImpl_klassPointer(obj);
1798 }
1799
1800 Method* JVMCIEnv::asMethod(JVMCIObject obj) {
1801 Method** methodHandle = (Method**) get_HotSpotResolvedJavaMethodImpl_methodHandle(obj);
1802 return *methodHandle;
1803 }
1804
1805 ConstantPool* JVMCIEnv::asConstantPool(JVMCIObject obj) {
1806 ConstantPool** constantPoolHandle = (ConstantPool**) get_HotSpotConstantPool_constantPoolHandle(obj);
1807 return *constantPoolHandle;
1808 }
1809
1810 MethodData* JVMCIEnv::asMethodData(JVMCIObject obj) {
1811 return (MethodData*) get_HotSpotMethodData_methodDataPointer(obj);
1812 }
1813
1814 // Lookup an nmethod with a matching base and compile id
1815 nmethod* JVMCIEnv::lookup_nmethod(address code, jlong compile_id_snapshot) {
1816 if (code == nullptr) {
1817 return nullptr;
1818 }
1819
1820 CodeBlob* cb = CodeCache::find_blob(code);
1821 if (cb == (CodeBlob*) code) {
1822 nmethod* nm = cb->as_nmethod_or_null();
1823 if (nm != nullptr && (compile_id_snapshot == 0 || nm->compile_id() == compile_id_snapshot)) {
1824 return nm;
1825 }
1826 }
1827 return nullptr;
1828 }
1829
1830
1831 CodeBlob* JVMCIEnv::get_code_blob(JVMCIObject obj) {
1832 address code = (address) get_InstalledCode_address(obj);
1833 if (code == nullptr) {
1834 return nullptr;
1835 }
1836 if (isa_HotSpotNmethod(obj)) {
1837 jlong compile_id_snapshot = get_HotSpotNmethod_compileIdSnapshot(obj);
1838 nmethod* nm = lookup_nmethod(code, compile_id_snapshot);
1839 if (nm != nullptr && compile_id_snapshot != 0L && nm->is_not_entrant()) {
1840 // Zero the entry point so that the nmethod
1841 // cannot be invoked by the mirror but can
1842 // still be deoptimized.
1843 set_InstalledCode_entryPoint(obj, 0);
1844 // Refetch the nmethod since the previous call will be a safepoint in libjvmci
1845 nm = lookup_nmethod(code, compile_id_snapshot);
1846 }
1847
1848 if (nm == nullptr) {
1849 // The HotSpotNmethod was pointing at some nmethod but the nmethod is no longer valid, so
1850 // clear the InstalledCode fields of this HotSpotNmethod so that it no longer refers to a
1851 // nmethod in the code cache.
1852 set_InstalledCode_address(obj, 0);
1853 set_InstalledCode_entryPoint(obj, 0);
1854 set_HotSpotInstalledCode_codeStart(obj, 0);
1855 }
1856 return nm;
1857 }
1858
1859 CodeBlob* cb = (CodeBlob*) code;
1860 assert(!cb->is_nmethod(), "unexpected nmethod");
1861 return cb;
1862 }
1863
1864 void JVMCINMethodHandle::set_nmethod(nmethod* nm) {
1865 BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
1866 bs_nm->nmethod_entry_barrier(nm);
1867 _thread->set_live_nmethod(nm);
1868 }
1869
1870 nmethod* JVMCIEnv::get_nmethod(JVMCIObject obj, JVMCINMethodHandle& nmethod_handle) {
1871 CodeBlob* cb = get_code_blob(obj);
1872 if (cb != nullptr) {
1873 nmethod* nm = cb->as_nmethod_or_null();
1874 if (nm != nullptr) {
1875 nmethod_handle.set_nmethod(nm);
1876 return nm;
1877 }
1878 }
1879 return nullptr;
1880 }
1881
1882 // Generate implementations for the initialize, new, isa, get and set methods for all the types and
1883 // fields declared in the JVMCI_CLASSES_DO macro.
1884
1885 #define START_CLASS(className, fullClassName) \
1886 void JVMCIEnv::className##_initialize(JVMCI_TRAPS) { \
1887 if (is_hotspot()) { \
1888 HotSpotJVMCI::className::initialize(JVMCI_CHECK); \
1889 } else { \
1890 JNIJVMCI::className::initialize(JVMCI_CHECK); \
1891 } \
1892 } \
1893 JVMCIObjectArray JVMCIEnv::new_##className##_array(int length, JVMCI_TRAPS) { \
1894 if (is_hotspot()) { \
1895 JavaThread* THREAD = JavaThread::current(); /* For exception macros. */ \
1896 objArrayOop array = oopFactory::new_objArray(HotSpotJVMCI::className::klass(), length, CHECK_(JVMCIObject())); \
1897 return (JVMCIObjectArray) wrap(array); \
1898 } else { \
1899 JNIAccessMark jni(this); \
1900 jobjectArray result = jni()->NewObjectArray(length, JNIJVMCI::className::clazz(), nullptr); \
1901 return wrap(result); \
1902 } \
1903 } \
1904 bool JVMCIEnv::isa_##className(JVMCIObject object) { \
1905 if (is_hotspot()) { \
1906 return HotSpotJVMCI::className::is_instance(this, object); \
1907 } else { \
1908 return JNIJVMCI::className::is_instance(this, object); \
1909 } \
1910 }
1911
1912 #define END_CLASS
1913
1914 #define FIELD(className, name, type, accessor, cast) \
1915 type JVMCIEnv::get_##className##_##name(JVMCIObject obj) { \
1916 if (is_hotspot()) { \
1917 return HotSpotJVMCI::className::get_##name(this, obj); \
1918 } else { \
1919 return JNIJVMCI::className::get_##name(this, obj); \
1920 } \
1921 } \
1922 void JVMCIEnv::set_##className##_##name(JVMCIObject obj, type x) { \
1923 if (is_hotspot()) { \
1924 HotSpotJVMCI::className::set_##name(this, obj, x); \
1925 } else { \
1926 JNIJVMCI::className::set_##name(this, obj, x); \
1927 } \
1928 }
1929
1930 #define EMPTY_CAST
1931 #define CHAR_FIELD(className, name) FIELD(className, name, jchar, Char, EMPTY_CAST)
1932 #define INT_FIELD(className, name) FIELD(className, name, jint, Int, EMPTY_CAST)
1933 #define BOOLEAN_FIELD(className, name) FIELD(className, name, jboolean, Boolean, EMPTY_CAST)
1934 #define LONG_FIELD(className, name) FIELD(className, name, jlong, Long, EMPTY_CAST)
1935 #define FLOAT_FIELD(className, name) FIELD(className, name, jfloat, Float, EMPTY_CAST)
1936
1937 #define OBJECT_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIObject, Object, EMPTY_CAST)
1938 #define OBJECTARRAY_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray))
1939 #define PRIMARRAY_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIPrimitiveArray, Object, (JVMCIPrimitiveArray))
1940
1941 #define STATIC_OBJECT_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObject, Object, (JVMCIObject))
1942 #define STATIC_OBJECTARRAY_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray))
1943
1944 #define OOPISH_FIELD(className, name, type, accessor, cast) \
1945 type JVMCIEnv::get_##className##_##name(JVMCIObject obj) { \
1946 if (is_hotspot()) { \
1947 return HotSpotJVMCI::className::get_##name(this, obj); \
1948 } else { \
1949 return JNIJVMCI::className::get_##name(this, obj); \
1950 } \
1951 } \
1952 void JVMCIEnv::set_##className##_##name(JVMCIObject obj, type x) { \
1953 if (is_hotspot()) { \
1954 HotSpotJVMCI::className::set_##name(this, obj, x); \
1955 } else { \
1956 JNIJVMCI::className::set_##name(this, obj, x); \
1957 } \
1958 }
1959
1960 #define STATIC_OOPISH_FIELD(className, name, type, accessor, cast) \
1961 type JVMCIEnv::get_##className##_##name() { \
1962 if (is_hotspot()) { \
1963 return HotSpotJVMCI::className::get_##name(this); \
1964 } else { \
1965 return JNIJVMCI::className::get_##name(this); \
1966 } \
1967 } \
1968 void JVMCIEnv::set_##className##_##name(type x) { \
1969 if (is_hotspot()) { \
1970 HotSpotJVMCI::className::set_##name(this, x); \
1971 } else { \
1972 JNIJVMCI::className::set_##name(this, x); \
1973 } \
1974 }
1975
1976 #define STATIC_PRIMITIVE_FIELD(className, name, type, accessor, cast) \
1977 type JVMCIEnv::get_##className##_##name() { \
1978 if (is_hotspot()) { \
1979 return HotSpotJVMCI::className::get_##name(this); \
1980 } else { \
1981 return JNIJVMCI::className::get_##name(this); \
1982 } \
1983 } \
1984 void JVMCIEnv::set_##className##_##name(type x) { \
1985 if (is_hotspot()) { \
1986 HotSpotJVMCI::className::set_##name(this, x); \
1987 } else { \
1988 JNIJVMCI::className::set_##name(this, x); \
1989 } \
1990 }
1991 #define STATIC_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint, Int, EMPTY_CAST)
1992 #define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean, Boolean, EMPTY_CAST)
1993 #define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName)
1994 #define CONSTRUCTOR(className, signature)
1995
1996 JVMCI_CLASSES_DO(START_CLASS, END_CLASS, CHAR_FIELD, INT_FIELD, BOOLEAN_FIELD, LONG_FIELD, FLOAT_FIELD, OBJECT_FIELD, PRIMARRAY_FIELD, OBJECTARRAY_FIELD, STATIC_OBJECT_FIELD, STATIC_OBJECTARRAY_FIELD, STATIC_INT_FIELD, STATIC_BOOLEAN_FIELD, METHOD, CONSTRUCTOR)
1997
1998 #undef START_CLASS
1999 #undef END_CLASS
2000 #undef METHOD
2001 #undef CONSTRUCTOR
2002 #undef FIELD
2003 #undef CHAR_FIELD
2004 #undef INT_FIELD
2005 #undef BOOLEAN_FIELD
2006 #undef LONG_FIELD
2007 #undef FLOAT_FIELD
2008 #undef OBJECT_FIELD
2009 #undef PRIMARRAY_FIELD
2010 #undef OBJECTARRAY_FIELD
2011 #undef STATIC_OOPISH_FIELD
2012 #undef STATIC_OBJECT_FIELD
2013 #undef STATIC_OBJECTARRAY_FIELD
2014 #undef STATIC_INT_FIELD
2015 #undef STATIC_BOOLEAN_FIELD
2016 #undef EMPTY_CAST