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_objArray(), "must be");
359 objArrayOop pair_arr = objArrayOop(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) {
682 if (is_hotspot()) {
683 oop result = HotSpotJVMCI::resolve(array)->obj_at(index);
684 return wrap(result);
685 } else {
686 JNIAccessMark jni(this);
687 jobject result = jni()->GetObjectArrayElement(get_jobjectArray(array), index);
688 return wrap(result);
689 }
690 }
691
692 void JVMCIEnv::put_object_at(JVMCIObjectArray array, int index, JVMCIObject value) {
693 if (is_hotspot()) {
694 HotSpotJVMCI::resolve(array)->obj_at_put(index, HotSpotJVMCI::resolve(value));
695 } else {
696 JNIAccessMark jni(this);
697 jni()->SetObjectArrayElement(get_jobjectArray(array), index, get_jobject(value));
698 }
699 }
700
701 jboolean JVMCIEnv::get_bool_at(JVMCIPrimitiveArray array, int index) {
702 if (is_hotspot()) {
703 return HotSpotJVMCI::resolve(array)->bool_at(index);
704 } else {
705 JNIAccessMark jni(this);
706 jboolean result;
707 jni()->GetBooleanArrayRegion(array.as_jbooleanArray(), index, 1, &result);
708 return result;
709 }
710 }
711 void JVMCIEnv::put_bool_at(JVMCIPrimitiveArray array, int index, jboolean value) {
712 if (is_hotspot()) {
713 HotSpotJVMCI::resolve(array)->bool_at_put(index, value);
714 } else {
715 JNIAccessMark jni(this);
716 jni()->SetBooleanArrayRegion(array.as_jbooleanArray(), index, 1, &value);
717 }
718 }
719
720 jbyte JVMCIEnv::get_byte_at(JVMCIPrimitiveArray array, int index) {
721 if (is_hotspot()) {
722 return HotSpotJVMCI::resolve(array)->byte_at(index);
723 } else {
724 JNIAccessMark jni(this);
725 jbyte result;
726 jni()->GetByteArrayRegion(array.as_jbyteArray(), index, 1, &result);
727 return result;
728 }
729 }
730 void JVMCIEnv::put_byte_at(JVMCIPrimitiveArray array, int index, jbyte value) {
731 if (is_hotspot()) {
732 HotSpotJVMCI::resolve(array)->byte_at_put(index, value);
733 } else {
734 JNIAccessMark jni(this);
735 jni()->SetByteArrayRegion(array.as_jbyteArray(), index, 1, &value);
736 }
737 }
738
739 jint JVMCIEnv::get_int_at(JVMCIPrimitiveArray array, int index) {
740 if (is_hotspot()) {
741 return HotSpotJVMCI::resolve(array)->int_at(index);
742 } else {
743 JNIAccessMark jni(this);
744 jint result;
745 jni()->GetIntArrayRegion(array.as_jintArray(), index, 1, &result);
746 return result;
747 }
748 }
749 void JVMCIEnv::put_int_at(JVMCIPrimitiveArray array, int index, jint value) {
750 if (is_hotspot()) {
751 HotSpotJVMCI::resolve(array)->int_at_put(index, value);
752 } else {
753 JNIAccessMark jni(this);
754 jni()->SetIntArrayRegion(array.as_jintArray(), index, 1, &value);
755 }
756 }
757
758 jlong JVMCIEnv::get_long_at(JVMCIPrimitiveArray array, int index) {
759 if (is_hotspot()) {
760 return HotSpotJVMCI::resolve(array)->long_at(index);
761 } else {
762 JNIAccessMark jni(this);
763 jlong result;
764 jni()->GetLongArrayRegion(array.as_jlongArray(), index, 1, &result);
765 return result;
766 }
767 }
768 void JVMCIEnv::put_long_at(JVMCIPrimitiveArray array, int index, jlong value) {
769 if (is_hotspot()) {
770 HotSpotJVMCI::resolve(array)->long_at_put(index, value);
771 } else {
772 JNIAccessMark jni(this);
773 jni()->SetLongArrayRegion(array.as_jlongArray(), index, 1, &value);
774 }
775 }
776
777 void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length) {
778 if (length == 0) {
779 return;
780 }
781 if (is_hotspot()) {
782 memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), length);
783 } else {
784 JNIAccessMark jni(this);
785 jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, length, dest);
786 }
787 }
788 void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
789 if (length == 0) {
790 return;
791 }
792 if (is_hotspot()) {
793 memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, length);
794 } else {
795 JNIAccessMark jni(this);
796 jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, length, src);
797 }
798 }
799
800 void JVMCIEnv::copy_longs_from(jlong* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
801 if (length == 0) {
802 return;
803 }
804 if (is_hotspot()) {
805 memcpy(HotSpotJVMCI::resolve(dest)->long_at_addr(offset), src, length * sizeof(jlong));
806 } else {
807 JNIAccessMark jni(this);
808 jni()->SetLongArrayRegion(dest.as_jlongArray(), offset, length, src);
809 }
810 }
811
812 jboolean JVMCIEnv::is_boxing_object(BasicType type, JVMCIObject object) {
813 if (is_hotspot()) {
814 return java_lang_boxing_object::is_instance(HotSpotJVMCI::resolve(object), type);
815 } else {
816 JNIAccessMark jni(this);
817 return jni()->IsInstanceOf(get_jobject(object), JNIJVMCI::box_class(type));
818 }
819 }
820
821 // Get the primitive value from a Java boxing object. It's hard error to
822 // pass a non-primitive BasicType.
823 jvalue JVMCIEnv::get_boxed_value(BasicType type, JVMCIObject object) {
824 jvalue result;
825 if (is_hotspot()) {
826 if (java_lang_boxing_object::get_value(HotSpotJVMCI::resolve(object), &result) == T_ILLEGAL) {
827 ShouldNotReachHere();
828 }
829 } else {
830 JNIAccessMark jni(this);
831 jfieldID field = JNIJVMCI::box_field(type);
832 switch (type) {
833 case T_BOOLEAN: result.z = jni()->GetBooleanField(get_jobject(object), field); break;
834 case T_BYTE: result.b = jni()->GetByteField(get_jobject(object), field); break;
835 case T_SHORT: result.s = jni()->GetShortField(get_jobject(object), field); break;
836 case T_CHAR: result.c = jni()->GetCharField(get_jobject(object), field); break;
837 case T_INT: result.i = jni()->GetIntField(get_jobject(object), field); break;
838 case T_LONG: result.j = jni()->GetLongField(get_jobject(object), field); break;
839 case T_FLOAT: result.f = jni()->GetFloatField(get_jobject(object), field); break;
840 case T_DOUBLE: result.d = jni()->GetDoubleField(get_jobject(object), field); break;
841 default:
842 ShouldNotReachHere();
843 }
844 }
845 return result;
846 }
847
848 // Return the BasicType of the object if it's a boxing object, otherwise return T_ILLEGAL.
849 BasicType JVMCIEnv::get_box_type(JVMCIObject object) {
850 if (is_hotspot()) {
851 return java_lang_boxing_object::basic_type(HotSpotJVMCI::resolve(object));
852 } else {
853 JNIAccessMark jni(this);
854 jclass clazz = jni()->GetObjectClass(get_jobject(object));
855 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_BOOLEAN))) return T_BOOLEAN;
856 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_BYTE))) return T_BYTE;
857 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_SHORT))) return T_SHORT;
858 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_CHAR))) return T_CHAR;
859 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_INT))) return T_INT;
860 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_LONG))) return T_LONG;
861 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_FLOAT))) return T_FLOAT;
862 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_DOUBLE))) return T_DOUBLE;
863 return T_ILLEGAL;
864 }
865 }
866
867 // Create a boxing object of the appropriate primitive type.
868 JVMCIObject JVMCIEnv::create_box(BasicType type, jvalue* value, JVMCI_TRAPS) {
869 switch (type) {
870 case T_BOOLEAN:
871 case T_BYTE:
872 case T_CHAR:
873 case T_SHORT:
874 case T_INT:
875 case T_LONG:
876 case T_FLOAT:
877 case T_DOUBLE:
878 break;
879 default:
880 JVMCI_THROW_MSG_(IllegalArgumentException, "Only boxes for primitive values can be created", JVMCIObject());
881 }
882 JavaThread* THREAD = JavaThread::current(); // For exception macros.
883 if (is_hotspot()) {
884 oop box = java_lang_boxing_object::create(type, value, CHECK_(JVMCIObject()));
885 return HotSpotJVMCI::wrap(box);
886 } else {
887 JNIAccessMark jni(this, THREAD);
888 jobject box = jni()->NewObjectA(JNIJVMCI::box_class(type), JNIJVMCI::box_constructor(type), value);
889 assert(box != nullptr, "");
890 return wrap(box);
891 }
892 }
893
894 const char* JVMCIEnv::as_utf8_string(JVMCIObject str) {
895 if (is_hotspot()) {
896 return java_lang_String::as_utf8_string(HotSpotJVMCI::resolve(str));
897 } else {
898 JNIAccessMark jni(this);
899 jstring jstr = str.as_jstring();
900 int length = jni()->GetStringLength(jstr);
901 int utf8_length = jni()->GetStringUTFLength(jstr);
902 char* result = NEW_RESOURCE_ARRAY(char, utf8_length + 1);
903 jni()->GetStringUTFRegion(jstr, 0, length, result);
904 return result;
905 }
906 }
907
908 #define DO_THROW(name) \
909 void JVMCIEnv::throw_##name(const char* msg) { \
910 if (is_hotspot()) { \
911 JavaThread* THREAD = JavaThread::current(); \
912 THROW_MSG(HotSpotJVMCI::name::symbol(), msg); \
913 } else { \
914 JNIAccessMark jni(this); \
915 jni()->ThrowNew(JNIJVMCI::name::clazz(), msg); \
916 } \
917 }
918
919 DO_THROW(InternalError)
920 DO_THROW(ArrayIndexOutOfBoundsException)
921 DO_THROW(IllegalStateException)
922 DO_THROW(NullPointerException)
923 DO_THROW(IllegalArgumentException)
924 DO_THROW(InvalidInstalledCodeException)
925 DO_THROW(UnsatisfiedLinkError)
926 DO_THROW(UnsupportedOperationException)
927 DO_THROW(OutOfMemoryError)
928 DO_THROW(NoClassDefFoundError)
929
930 #undef DO_THROW
931
932 void JVMCIEnv::fthrow_error(const char* file, int line, const char* format, ...) {
933 const int max_msg_size = 1024;
934 va_list ap;
935 va_start(ap, format);
936 char msg[max_msg_size];
937 os::vsnprintf(msg, max_msg_size, format, ap);
938 va_end(ap);
939 JavaThread* THREAD = JavaThread::current();
940 if (is_hotspot()) {
941 Handle h_loader;
942 Exceptions::_throw_msg(THREAD, file, line, vmSymbols::jdk_vm_ci_common_JVMCIError(), msg, h_loader );
943 } else {
944 JNIAccessMark jni(this, THREAD);
945 jni()->ThrowNew(JNIJVMCI::JVMCIError::clazz(), msg);
946 }
947 }
948
949 jboolean JVMCIEnv::call_HotSpotJVMCIRuntime_isGCSupported (JVMCIObject runtime, jint gcIdentifier) {
950 JavaThread* THREAD = JavaThread::current(); // For exception macros.
951 if (is_hotspot()) {
952 JavaCallArguments jargs;
953 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
954 jargs.push_int(gcIdentifier);
955 JavaValue result(T_BOOLEAN);
956 JavaCalls::call_special(&result,
957 HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
958 vmSymbols::isGCSupported_name(),
959 vmSymbols::int_bool_signature(), &jargs, CHECK_0);
960 return result.get_jboolean();
961 } else {
962 JNIAccessMark jni(this, THREAD);
963 jboolean result = jni()->CallNonvirtualBooleanMethod(runtime.as_jobject(),
964 JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
965 JNIJVMCI::HotSpotJVMCIRuntime::isGCSupported_method(),
966 gcIdentifier);
967 if (jni()->ExceptionCheck()) {
968 return false;
969 }
970 return result;
971 }
972 }
973
974 jboolean JVMCIEnv::call_HotSpotJVMCIRuntime_isIntrinsicSupported (JVMCIObject runtime, jint intrinsicIdentifier) {
975 JavaThread* THREAD = JavaThread::current(); // For exception macros.
976 if (is_hotspot()) {
977 JavaCallArguments jargs;
978 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
979 jargs.push_int(intrinsicIdentifier);
980 JavaValue result(T_BOOLEAN);
981 JavaCalls::call_special(&result,
982 HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
983 vmSymbols::isIntrinsicSupported_name(),
984 vmSymbols::int_bool_signature(), &jargs, CHECK_0);
985 return result.get_jboolean();
986 } else {
987 JNIAccessMark jni(this, THREAD);
988 jboolean result = jni()->CallNonvirtualBooleanMethod(runtime.as_jobject(),
989 JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
990 JNIJVMCI::HotSpotJVMCIRuntime::isIntrinsicSupported_method(),
991 intrinsicIdentifier);
992 if (jni()->ExceptionCheck()) {
993 return false;
994 }
995 return result;
996 }
997 }
998
999 JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtime, JVMCIObject method, int entry_bci,
1000 jlong compile_state, int id) {
1001 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1002 if (is_hotspot()) {
1003 JavaCallArguments jargs;
1004 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
1005 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(method)));
1006 jargs.push_int(entry_bci);
1007 jargs.push_long(compile_state);
1008 jargs.push_int(id);
1009 JavaValue result(T_OBJECT);
1010 JavaCalls::call_special(&result,
1011 HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
1012 vmSymbols::compileMethod_name(),
1013 vmSymbols::compileMethod_signature(), &jargs, CHECK_(JVMCIObject()));
1014 return wrap(result.get_oop());
1015 } else {
1016 JNIAccessMark jni(this, THREAD);
1017 jobject result = jni()->CallNonvirtualObjectMethod(runtime.as_jobject(),
1018 JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
1019 JNIJVMCI::HotSpotJVMCIRuntime::compileMethod_method(),
1020 method.as_jobject(), entry_bci, compile_state, id);
1021 if (jni()->ExceptionCheck()) {
1022 return JVMCIObject();
1023 }
1024 return wrap(result);
1025 }
1026 }
1027
1028 void JVMCIEnv::call_HotSpotJVMCIRuntime_bootstrapFinished (JVMCIObject runtime, JVMCIEnv* JVMCIENV) {
1029 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1030 if (is_hotspot()) {
1031 JavaCallArguments jargs;
1032 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
1033 JavaValue result(T_VOID);
1034 JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::bootstrapFinished_name(), vmSymbols::void_method_signature(), &jargs, CHECK);
1035 } else {
1036 JNIAccessMark jni(this, THREAD);
1037 jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::bootstrapFinished_method());
1038
1039 }
1040 }
1041
1042 void JVMCIEnv::call_HotSpotJVMCIRuntime_shutdown (JVMCIObject runtime) {
1043 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1044 HandleMark hm(THREAD);
1045 if (is_hotspot()) {
1046 JavaCallArguments jargs;
1047 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
1048 JavaValue result(T_VOID);
1049 JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::shutdown_name(), vmSymbols::void_method_signature(), &jargs, THREAD);
1050 } else {
1051 JNIAccessMark jni(this, THREAD);
1052 jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::shutdown_method());
1053 }
1054 if (has_pending_exception()) {
1055 // This should never happen as HotSpotJVMCIRuntime.shutdown() should
1056 // handle all exceptions.
1057 describe_pending_exception(tty);
1058 }
1059 }
1060
1061 JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) {
1062 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1063 if (is_hotspot()) {
1064 JavaCallArguments jargs;
1065 JavaValue result(T_OBJECT);
1066 JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::runtime_name(), vmSymbols::runtime_signature(), &jargs, CHECK_(JVMCIObject()));
1067 return wrap(result.get_oop());
1068 } else {
1069 JNIAccessMark jni(this, THREAD);
1070 jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::runtime_method());
1071 if (jni()->ExceptionCheck()) {
1072 return JVMCIObject();
1073 }
1074 return wrap(result);
1075 }
1076 }
1077
1078 JVMCIObject JVMCIEnv::call_JVMCI_getRuntime (JVMCIEnv* JVMCIENV) {
1079 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1080 if (is_hotspot()) {
1081 JavaCallArguments jargs;
1082 JavaValue result(T_OBJECT);
1083 JavaCalls::call_static(&result, HotSpotJVMCI::JVMCI::klass(), vmSymbols::getRuntime_name(), vmSymbols::getRuntime_signature(), &jargs, CHECK_(JVMCIObject()));
1084 return wrap(result.get_oop());
1085 } else {
1086 JNIAccessMark jni(this, THREAD);
1087 jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::JVMCI::clazz(), JNIJVMCI::JVMCI::getRuntime_method());
1088 if (jni()->ExceptionCheck()) {
1089 return JVMCIObject();
1090 }
1091 return wrap(result);
1092 }
1093 }
1094
1095 JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime, JVMCIEnv* JVMCIENV) {
1096 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1097 if (is_hotspot()) {
1098 JavaCallArguments jargs;
1099 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
1100 JavaValue result(T_OBJECT);
1101 JavaCalls::call_virtual(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::getCompiler_name(), vmSymbols::getCompiler_signature(), &jargs, CHECK_(JVMCIObject()));
1102 return wrap(result.get_oop());
1103 } else {
1104 JNIAccessMark jni(this, THREAD);
1105 jobject result = jni()->CallObjectMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::getCompiler_method());
1106 if (jni()->ExceptionCheck()) {
1107 return JVMCIObject();
1108 }
1109 return wrap(result);
1110 }
1111 }
1112
1113 void JVMCIEnv::call_HotSpotJVMCIRuntime_postTranslation(JVMCIObject object, JVMCIEnv* JVMCIENV) {
1114 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1115 if (is_hotspot()) {
1116 JavaCallArguments jargs;
1117 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(object)));
1118 JavaValue result(T_VOID);
1119 JavaCalls::call_static(&result,
1120 HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
1121 vmSymbols::postTranslation_name(),
1122 vmSymbols::object_void_signature(), &jargs, CHECK);
1123 } else {
1124 JNIAccessMark jni(this, THREAD);
1125 jni()->CallStaticVoidMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
1126 JNIJVMCI::HotSpotJVMCIRuntime::postTranslation_method(),
1127 object.as_jobject());
1128 }
1129 }
1130
1131 JVMCIObject JVMCIEnv::call_JavaConstant_forPrimitive(jchar type_char, jlong value, JVMCI_TRAPS) {
1132 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1133 if (is_hotspot()) {
1134 JavaCallArguments jargs;
1135 jargs.push_int(type_char);
1136 jargs.push_long(value);
1137 JavaValue result(T_OBJECT);
1138 JavaCalls::call_static(&result,
1139 HotSpotJVMCI::JavaConstant::klass(),
1140 vmSymbols::forPrimitive_name(),
1141 vmSymbols::forPrimitive_signature(), &jargs, CHECK_(JVMCIObject()));
1142 return wrap(result.get_oop());
1143 } else {
1144 JNIAccessMark jni(this, THREAD);
1145 jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(),
1146 JNIJVMCI::JavaConstant::forPrimitive_method(),
1147 type_char, value);
1148 if (jni()->ExceptionCheck()) {
1149 return JVMCIObject();
1150 }
1151 return wrap(result);
1152 }
1153 }
1154
1155 JVMCIObject JVMCIEnv::get_jvmci_primitive_type(BasicType type) {
1156 JVMCIObjectArray primitives = get_HotSpotResolvedPrimitiveType_primitives();
1157 JVMCIObject result = get_object_at(primitives, type);
1158 return result;
1159 }
1160
1161 JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci, JVMCI_TRAPS) {
1162 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1163 Symbol* file_name_sym;
1164 int line_number;
1165 java_lang_StackTraceElement::decode(method, bci, file_name_sym, line_number, CHECK_(JVMCIObject()));
1166
1167 Symbol* method_name_sym = method->name();
1168 InstanceKlass* holder = method->method_holder();
1169 const char* declaring_class_str = holder->external_name();
1170
1171 if (is_hotspot()) {
1172 HotSpotJVMCI::StackTraceElement::klass()->initialize(CHECK_(JVMCIObject()));
1173 oop objOop = HotSpotJVMCI::StackTraceElement::klass()->allocate_instance(CHECK_(JVMCIObject()));
1174 Handle obj = Handle(THREAD, objOop);
1175
1176 oop declaring_class = StringTable::intern((char*) declaring_class_str, CHECK_(JVMCIObject()));
1177 HotSpotJVMCI::StackTraceElement::set_declaringClass(this, obj(), declaring_class);
1178
1179 oop method_name = StringTable::intern(method_name_sym, CHECK_(JVMCIObject()));
1180 HotSpotJVMCI::StackTraceElement::set_methodName(this, obj(), method_name);
1181
1182 if (file_name_sym != nullptr) {
1183 oop file_name = StringTable::intern(file_name_sym, CHECK_(JVMCIObject()));
1184 HotSpotJVMCI::StackTraceElement::set_fileName(this, obj(), file_name);
1185 }
1186 HotSpotJVMCI::StackTraceElement::set_lineNumber(this, obj(), line_number);
1187 return wrap(obj());
1188 } else {
1189 JNIAccessMark jni(this, THREAD);
1190 jobject declaring_class = jni()->NewStringUTF(declaring_class_str);
1191 if (jni()->ExceptionCheck()) {
1192 return JVMCIObject();
1193 }
1194 jobject method_name = jni()->NewStringUTF(method_name_sym->as_C_string());
1195 if (jni()->ExceptionCheck()) {
1196 return JVMCIObject();
1197 }
1198 jobject file_name = nullptr;
1199 if (file_name_sym != nullptr) {
1200 file_name = jni()->NewStringUTF(file_name_sym->as_C_string());
1201 if (jni()->ExceptionCheck()) {
1202 return JVMCIObject();
1203 }
1204 }
1205
1206 jobject result = jni()->NewObject(JNIJVMCI::StackTraceElement::clazz(),
1207 JNIJVMCI::StackTraceElement::constructor(),
1208 declaring_class, method_name, file_name, line_number);
1209 return wrap(result);
1210 }
1211 }
1212
1213 JVMCIObject JVMCIEnv::new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jlong compileId, JVMCI_TRAPS) {
1214 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1215
1216 JVMCIObject methodObject = get_jvmci_method(method, JVMCI_CHECK_(JVMCIObject()));
1217
1218 if (is_hotspot()) {
1219 InstanceKlass* ik = InstanceKlass::cast(HotSpotJVMCI::HotSpotNmethod::klass());
1220 if (ik->should_be_initialized()) {
1221 ik->initialize(CHECK_(JVMCIObject()));
1222 }
1223 oop obj = ik->allocate_instance(CHECK_(JVMCIObject()));
1224 Handle obj_h(THREAD, obj);
1225 Handle nameStr = java_lang_String::create_from_str(name, CHECK_(JVMCIObject()));
1226
1227 // Call constructor
1228 JavaCallArguments jargs;
1229 jargs.push_oop(obj_h);
1230 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(methodObject)));
1231 jargs.push_oop(nameStr);
1232 jargs.push_int(isDefault);
1233 jargs.push_long(compileId);
1234 JavaValue result(T_VOID);
1235 JavaCalls::call_special(&result, ik,
1236 vmSymbols::object_initializer_name(),
1237 vmSymbols::method_string_bool_long_signature(),
1238 &jargs, CHECK_(JVMCIObject()));
1239 return wrap(obj_h());
1240 } else {
1241 JNIAccessMark jni(this, THREAD);
1242 jobject nameStr = name == nullptr ? nullptr : jni()->NewStringUTF(name);
1243 if (jni()->ExceptionCheck()) {
1244 return JVMCIObject();
1245 }
1246
1247 jobject result = jni()->NewObject(JNIJVMCI::HotSpotNmethod::clazz(),
1248 JNIJVMCI::HotSpotNmethod::constructor(),
1249 methodObject.as_jobject(), nameStr, isDefault);
1250 return wrap(result);
1251 }
1252 }
1253
1254 JVMCIObject JVMCIEnv::make_local(JVMCIObject object) {
1255 if (object.is_null()) {
1256 return JVMCIObject();
1257 }
1258 if (is_hotspot()) {
1259 return wrap(JNIHandles::make_local(HotSpotJVMCI::resolve(object)));
1260 } else {
1261 JNIAccessMark jni(this);
1262 return wrap(jni()->NewLocalRef(object.as_jobject()));
1263 }
1264 }
1265
1266 JVMCIObject JVMCIEnv::make_global(JVMCIObject object) {
1267 if (object.is_null()) {
1268 return JVMCIObject();
1269 }
1270 if (is_hotspot()) {
1271 return wrap(JNIHandles::make_global(Handle(Thread::current(), HotSpotJVMCI::resolve(object))));
1272 } else {
1273 JNIAccessMark jni(this);
1274 return wrap(jni()->NewGlobalRef(object.as_jobject()));
1275 }
1276 }
1277
1278 void JVMCIEnv::destroy_local(JVMCIObject object) {
1279 if (is_hotspot()) {
1280 JNIHandles::destroy_local(object.as_jobject());
1281 } else {
1282 JNIAccessMark jni(this);
1283 jni()->DeleteLocalRef(object.as_jobject());
1284 }
1285 }
1286
1287 void JVMCIEnv::destroy_global(JVMCIObject object) {
1288 if (is_hotspot()) {
1289 JNIHandles::destroy_global(object.as_jobject());
1290 } else {
1291 JNIAccessMark jni(this);
1292 jni()->DeleteGlobalRef(object.as_jobject());
1293 }
1294 }
1295
1296 const char* JVMCIEnv::klass_name(JVMCIObject object) {
1297 if (is_hotspot()) {
1298 return HotSpotJVMCI::resolve(object)->klass()->signature_name();
1299 } else {
1300 JVMCIObject name;
1301 {
1302 JNIAccessMark jni(this);
1303 jclass jcl = jni()->GetObjectClass(object.as_jobject());
1304 jobject result = jni()->CallObjectMethod(jcl, JNIJVMCI::Class_getName_method());
1305 name = JVMCIObject::create(result, is_hotspot());
1306 }
1307 return as_utf8_string(name);
1308 }
1309 }
1310
1311 JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS) {
1312 JVMCIObject method_object;
1313 if (method() == nullptr) {
1314 return method_object;
1315 }
1316 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1317 JVMCIKlassHandle holder_klass(THREAD, method->method_holder());
1318 JVMCIObject holder = get_jvmci_type(holder_klass, JVMCI_CHECK_(JVMCIObject()));
1319
1320 CompilerOracle::tag_blackhole_if_possible(method);
1321
1322 jmetadata handle = _runtime->allocate_handle(method);
1323 jboolean exception = false;
1324 if (is_hotspot()) {
1325 JavaValue result(T_OBJECT);
1326 JavaCallArguments args;
1327 args.push_long((jlong) handle);
1328 args.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(holder)));
1329 JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotResolvedJavaMethodImpl::klass(),
1330 vmSymbols::fromMetaspace_name(),
1331 vmSymbols::method_fromMetaspace_signature(), &args, THREAD);
1332 if (HAS_PENDING_EXCEPTION) {
1333 exception = true;
1334 } else {
1335 method_object = wrap(result.get_oop());
1336 }
1337 } else {
1338 JNIAccessMark jni(this, THREAD);
1339 method_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedJavaMethodImpl::clazz(),
1340 JNIJVMCI::HotSpotResolvedJavaMethodImpl_fromMetaspace_method(),
1341 (jlong) handle, holder.as_jobject()));
1342 exception = jni()->ExceptionCheck();
1343 }
1344
1345 if (exception) {
1346 _runtime->release_handle(handle);
1347 return JVMCIObject();
1348 }
1349
1350 assert(asMethod(method_object) == method(), "must be");
1351 if (get_HotSpotResolvedJavaMethodImpl_methodHandle(method_object) != (jlong) handle) {
1352 _runtime->release_handle(handle);
1353 }
1354 assert(!method_object.is_null(), "must be");
1355 return method_object;
1356 }
1357
1358 JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS) {
1359 JVMCIObject type;
1360 if (klass.is_null()) {
1361 return type;
1362 }
1363
1364 guarantee(klass->is_klass(), "must be valid klass");
1365 guarantee(klass->is_loader_alive(), "klass must be alive");
1366
1367 jlong pointer = (jlong) klass();
1368 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1369 jboolean exception = false;
1370 if (is_hotspot()) {
1371 CompilerThreadCanCallJava ccj(THREAD, true);
1372 JavaValue result(T_OBJECT);
1373 JavaCallArguments args;
1374 args.push_long(pointer);
1375 JavaCalls::call_static(&result,
1376 HotSpotJVMCI::HotSpotResolvedObjectTypeImpl::klass(),
1377 vmSymbols::fromMetaspace_name(),
1378 vmSymbols::klass_fromMetaspace_signature(), &args, THREAD);
1379
1380 if (HAS_PENDING_EXCEPTION) {
1381 exception = true;
1382 } else {
1383 type = wrap(result.get_oop());
1384 }
1385 } else {
1386 JNIAccessMark jni(this, THREAD);
1387
1388 HandleMark hm(THREAD);
1389 type = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedObjectTypeImpl::clazz(),
1390 JNIJVMCI::HotSpotResolvedObjectTypeImpl_fromMetaspace_method(),
1391 pointer));
1392 exception = jni()->ExceptionCheck();
1393 }
1394 if (exception) {
1395 return JVMCIObject();
1396 }
1397
1398 assert(type.is_non_null(), "must have result");
1399 return type;
1400 }
1401
1402 JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMCI_TRAPS) {
1403 JVMCIObject cp_object;
1404 jmetadata handle = _runtime->allocate_handle(cp);
1405 jboolean exception = false;
1406 JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
1407 if (is_hotspot()) {
1408 JavaValue result(T_OBJECT);
1409 JavaCallArguments args;
1410 args.push_long((jlong) handle);
1411 JavaCalls::call_static(&result,
1412 HotSpotJVMCI::HotSpotConstantPool::klass(),
1413 vmSymbols::fromMetaspace_name(),
1414 vmSymbols::constantPool_fromMetaspace_signature(), &args, THREAD);
1415 if (HAS_PENDING_EXCEPTION) {
1416 exception = true;
1417 } else {
1418 cp_object = wrap(result.get_oop());
1419 }
1420 } else {
1421 JNIAccessMark jni(this, THREAD);
1422 cp_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotConstantPool::clazz(),
1423 JNIJVMCI::HotSpotConstantPool_fromMetaspace_method(),
1424 (jlong) handle));
1425 exception = jni()->ExceptionCheck();
1426 }
1427
1428 if (exception) {
1429 _runtime->release_handle(handle);
1430 return JVMCIObject();
1431 }
1432
1433 assert(!cp_object.is_null(), "must be");
1434 // Constant pools aren't cached so this is always a newly created object using the handle
1435 assert(get_HotSpotConstantPool_constantPoolHandle(cp_object) == (jlong) handle, "must use same handle");
1436 return cp_object;
1437 }
1438
1439 JVMCIPrimitiveArray JVMCIEnv::new_booleanArray(int length, JVMCI_TRAPS) {
1440 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1441 if (is_hotspot()) {
1442 typeArrayOop result = oopFactory::new_boolArray(length, CHECK_(JVMCIObject()));
1443 return wrap(result);
1444 } else {
1445 JNIAccessMark jni(this, THREAD);
1446 jbooleanArray result = jni()->NewBooleanArray(length);
1447 return wrap(result);
1448 }
1449 }
1450
1451 JVMCIPrimitiveArray JVMCIEnv::new_byteArray(int length, JVMCI_TRAPS) {
1452 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1453 if (is_hotspot()) {
1454 typeArrayOop result = oopFactory::new_byteArray(length, CHECK_(JVMCIObject()));
1455 return wrap(result);
1456 } else {
1457 JNIAccessMark jni(this, THREAD);
1458 jbyteArray result = jni()->NewByteArray(length);
1459 return wrap(result);
1460 }
1461 }
1462
1463 JVMCIObjectArray JVMCIEnv::new_byte_array_array(int length, JVMCI_TRAPS) {
1464 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1465 if (is_hotspot()) {
1466 Klass* byteArrayArrayKlass = TypeArrayKlass::cast(Universe::byteArrayKlass())->array_klass(CHECK_(JVMCIObject()));
1467 objArrayOop result = ObjArrayKlass::cast(byteArrayArrayKlass) ->allocate(length, CHECK_(JVMCIObject()));
1468 return wrap(result);
1469 } else {
1470 JNIAccessMark jni(this, THREAD);
1471 jobjectArray result = jni()->NewObjectArray(length, JNIJVMCI::byte_array(), nullptr);
1472 return wrap(result);
1473 }
1474 }
1475
1476 JVMCIPrimitiveArray JVMCIEnv::new_intArray(int length, JVMCI_TRAPS) {
1477 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1478 if (is_hotspot()) {
1479 typeArrayOop result = oopFactory::new_intArray(length, CHECK_(JVMCIObject()));
1480 return wrap(result);
1481 } else {
1482 JNIAccessMark jni(this, THREAD);
1483 jintArray result = jni()->NewIntArray(length);
1484 return wrap(result);
1485 }
1486 }
1487
1488 JVMCIPrimitiveArray JVMCIEnv::new_longArray(int length, JVMCI_TRAPS) {
1489 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1490 if (is_hotspot()) {
1491 typeArrayOop result = oopFactory::new_longArray(length, CHECK_(JVMCIObject()));
1492 return wrap(result);
1493 } else {
1494 JNIAccessMark jni(this, THREAD);
1495 jlongArray result = jni()->NewLongArray(length);
1496 return wrap(result);
1497 }
1498 }
1499
1500 JVMCIObject JVMCIEnv::new_VMField(JVMCIObject name, JVMCIObject type, jlong offset, jlong address, JVMCIObject value, JVMCI_TRAPS) {
1501 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1502 if (is_hotspot()) {
1503 HotSpotJVMCI::VMField::klass()->initialize(CHECK_(JVMCIObject()));
1504 oop obj = HotSpotJVMCI::VMField::klass()->allocate_instance(CHECK_(JVMCIObject()));
1505 HotSpotJVMCI::VMField::set_name(this, obj, HotSpotJVMCI::resolve(name));
1506 HotSpotJVMCI::VMField::set_type(this, obj, HotSpotJVMCI::resolve(type));
1507 HotSpotJVMCI::VMField::set_offset(this, obj, offset);
1508 HotSpotJVMCI::VMField::set_address(this, obj, address);
1509 HotSpotJVMCI::VMField::set_value(this, obj, HotSpotJVMCI::resolve(value));
1510 return wrap(obj);
1511 } else {
1512 JNIAccessMark jni(this, THREAD);
1513 jobject result = jni()->NewObject(JNIJVMCI::VMField::clazz(),
1514 JNIJVMCI::VMField::constructor(),
1515 get_jobject(name), get_jobject(type), offset, address, get_jobject(value));
1516 return wrap(result);
1517 }
1518 }
1519
1520 JVMCIObject JVMCIEnv::new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject value, JVMCI_TRAPS) {
1521 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1522 if (is_hotspot()) {
1523 HotSpotJVMCI::VMFlag::klass()->initialize(CHECK_(JVMCIObject()));
1524 oop obj = HotSpotJVMCI::VMFlag::klass()->allocate_instance(CHECK_(JVMCIObject()));
1525 HotSpotJVMCI::VMFlag::set_name(this, obj, HotSpotJVMCI::resolve(name));
1526 HotSpotJVMCI::VMFlag::set_type(this, obj, HotSpotJVMCI::resolve(type));
1527 HotSpotJVMCI::VMFlag::set_value(this, obj, HotSpotJVMCI::resolve(value));
1528 return wrap(obj);
1529 } else {
1530 JNIAccessMark jni(this, THREAD);
1531 jobject result = jni()->NewObject(JNIJVMCI::VMFlag::clazz(),
1532 JNIJVMCI::VMFlag::constructor(),
1533 get_jobject(name), get_jobject(type), get_jobject(value));
1534 return wrap(result);
1535 }
1536 }
1537
1538 JVMCIObject JVMCIEnv::new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, jboolean isAvailable, jboolean c1Supported, jboolean c2Supported, JVMCI_TRAPS) {
1539 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1540 if (is_hotspot()) {
1541 HotSpotJVMCI::VMIntrinsicMethod::klass()->initialize(CHECK_(JVMCIObject()));
1542 oop obj = HotSpotJVMCI::VMIntrinsicMethod::klass()->allocate_instance(CHECK_(JVMCIObject()));
1543 HotSpotJVMCI::VMIntrinsicMethod::set_declaringClass(this, obj, HotSpotJVMCI::resolve(declaringClass));
1544 HotSpotJVMCI::VMIntrinsicMethod::set_name(this, obj, HotSpotJVMCI::resolve(name));
1545 HotSpotJVMCI::VMIntrinsicMethod::set_descriptor(this, obj, HotSpotJVMCI::resolve(descriptor));
1546 HotSpotJVMCI::VMIntrinsicMethod::set_id(this, obj, id);
1547 HotSpotJVMCI::VMIntrinsicMethod::set_isAvailable(this, obj, isAvailable);
1548 HotSpotJVMCI::VMIntrinsicMethod::set_c1Supported(this, obj, c1Supported);
1549 HotSpotJVMCI::VMIntrinsicMethod::set_c2Supported(this, obj, c2Supported);
1550 return wrap(obj);
1551 } else {
1552 JNIAccessMark jni(this, THREAD);
1553 jobject result = jni()->NewObject(JNIJVMCI::VMIntrinsicMethod::clazz(),
1554 JNIJVMCI::VMIntrinsicMethod::constructor(),
1555 get_jobject(declaringClass), get_jobject(name), get_jobject(descriptor), id, isAvailable, c1Supported, c2Supported);
1556 return wrap(result);
1557 }
1558 }
1559
1560 JVMCIObject JVMCIEnv::new_HotSpotStackFrameReference(JVMCI_TRAPS) {
1561 if (is_hotspot()) {
1562 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1563 HotSpotJVMCI::HotSpotStackFrameReference::klass()->initialize(CHECK_(JVMCIObject()));
1564 oop obj = HotSpotJVMCI::HotSpotStackFrameReference::klass()->allocate_instance(CHECK_(JVMCIObject()));
1565 return wrap(obj);
1566 } else {
1567 ShouldNotReachHere();
1568 return JVMCIObject();
1569 }
1570 }
1571 JVMCIObject JVMCIEnv::new_JVMCIError(JVMCI_TRAPS) {
1572 if (is_hotspot()) {
1573 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1574 HotSpotJVMCI::JVMCIError::klass()->initialize(CHECK_(JVMCIObject()));
1575 oop obj = HotSpotJVMCI::JVMCIError::klass()->allocate_instance(CHECK_(JVMCIObject()));
1576 return wrap(obj);
1577 } else {
1578 ShouldNotReachHere();
1579 return JVMCIObject();
1580 }
1581 }
1582
1583 JVMCIObject JVMCIEnv::new_FieldInfo(FieldInfo* fieldinfo, JVMCI_TRAPS) {
1584 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1585 if (is_hotspot()) {
1586 HotSpotJVMCI::FieldInfo::klass()->initialize(CHECK_(JVMCIObject()));
1587 oop obj = HotSpotJVMCI::FieldInfo::klass()->allocate_instance(CHECK_(JVMCIObject()));
1588 Handle obj_h(THREAD, obj);
1589 HotSpotJVMCI::FieldInfo::set_nameIndex(JVMCIENV, obj_h(), (jint)fieldinfo->name_index());
1590 HotSpotJVMCI::FieldInfo::set_signatureIndex(JVMCIENV, obj_h(), (jint)fieldinfo->signature_index());
1591 HotSpotJVMCI::FieldInfo::set_offset(JVMCIENV, obj_h(), (jint)fieldinfo->offset());
1592 HotSpotJVMCI::FieldInfo::set_classfileFlags(JVMCIENV, obj_h(), (jint)fieldinfo->access_flags().as_field_flags());
1593 HotSpotJVMCI::FieldInfo::set_internalFlags(JVMCIENV, obj_h(), (jint)fieldinfo->field_flags().as_uint());
1594 HotSpotJVMCI::FieldInfo::set_initializerIndex(JVMCIENV, obj_h(), (jint)fieldinfo->initializer_index());
1595 return wrap(obj_h());
1596 } else {
1597 JNIAccessMark jni(this, THREAD);
1598 jobject result = jni()->NewObject(JNIJVMCI::FieldInfo::clazz(),
1599 JNIJVMCI::FieldInfo::constructor(),
1600 (jint)fieldinfo->name_index(),
1601 (jint)fieldinfo->signature_index(),
1602 (jint)fieldinfo->offset(),
1603 (jint)fieldinfo->access_flags().as_field_flags(),
1604 (jint)fieldinfo->field_flags().as_uint(),
1605 (jint)fieldinfo->initializer_index());
1606
1607 return wrap(result);
1608 }
1609 }
1610
1611 JVMCIObject JVMCIEnv::get_object_constant(oop objOop, bool compressed, bool dont_register) {
1612 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1613 Handle obj = Handle(THREAD, objOop);
1614 if (obj.is_null()) {
1615 return JVMCIObject();
1616 }
1617 if (is_hotspot()) {
1618 HotSpotJVMCI::DirectHotSpotObjectConstantImpl::klass()->initialize(CHECK_(JVMCIObject()));
1619 oop constant = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::klass()->allocate_instance(CHECK_(JVMCIObject()));
1620 HotSpotJVMCI::DirectHotSpotObjectConstantImpl::set_object(this, constant, obj());
1621 HotSpotJVMCI::HotSpotObjectConstantImpl::set_compressed(this, constant, compressed);
1622 return wrap(constant);
1623 } else {
1624 jlong handle = make_oop_handle(obj);
1625 JNIAccessMark jni(this, THREAD);
1626 jobject result = jni()->NewObject(JNIJVMCI::IndirectHotSpotObjectConstantImpl::clazz(),
1627 JNIJVMCI::IndirectHotSpotObjectConstantImpl::constructor(),
1628 handle, compressed, dont_register);
1629 return wrap(result);
1630 }
1631 }
1632
1633
1634 Handle JVMCIEnv::asConstant(JVMCIObject constant, JVMCI_TRAPS) {
1635 if (constant.is_null()) {
1636 return Handle();
1637 }
1638 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1639 if (is_hotspot()) {
1640 assert(HotSpotJVMCI::DirectHotSpotObjectConstantImpl::is_instance(this, constant), "wrong type");
1641 oop obj = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::object(this, HotSpotJVMCI::resolve(constant));
1642 return Handle(THREAD, obj);
1643 } else if (isa_IndirectHotSpotObjectConstantImpl(constant)) {
1644 jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(constant);
1645 if (object_handle == 0L) {
1646 JVMCI_THROW_MSG_(NullPointerException, "Foreign object reference has been cleared", Handle());
1647 }
1648 oop result = resolve_oop_handle(object_handle);
1649 if (result == nullptr) {
1650 JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly null", Handle());
1651 }
1652 return Handle(THREAD, result);
1653 } else {
1654 JVMCI_THROW_MSG_(IllegalArgumentException, "DirectHotSpotObjectConstantImpl shouldn't reach JVMCI in SVM mode", Handle());
1655 }
1656 }
1657
1658 JVMCIObject JVMCIEnv::wrap(jobject object) {
1659 return JVMCIObject::create(object, is_hotspot());
1660 }
1661
1662 jlong JVMCIEnv::make_oop_handle(const Handle& obj) {
1663 assert(!obj.is_null(), "should only create handle for non-null oops");
1664 return _runtime->make_oop_handle(obj);
1665 }
1666
1667 oop JVMCIEnv::resolve_oop_handle(jlong oopHandle) {
1668 assert(oopHandle != 0, "should be a valid handle");
1669 oop obj = NativeAccess<>::oop_load(reinterpret_cast<oop*>(oopHandle));
1670 if (obj != nullptr) {
1671 guarantee(oopDesc::is_oop_or_null(obj), "invalid oop: " INTPTR_FORMAT, p2i((oopDesc*) obj));
1672 }
1673 return obj;
1674 }
1675
1676 JVMCIObject JVMCIEnv::create_string(const char* str, JVMCI_TRAPS) {
1677 JavaThread* THREAD = JavaThread::current(); // For exception macros.
1678 if (is_hotspot()) {
1679 Handle result = java_lang_String::create_from_str(str, CHECK_(JVMCIObject()));
1680 return HotSpotJVMCI::wrap(result());
1681 } else {
1682 jobject result;
1683 jboolean exception = false;
1684 {
1685 JNIAccessMark jni(this, THREAD);
1686 result = jni()->NewStringUTF(str);
1687 exception = jni()->ExceptionCheck();
1688 }
1689 return wrap(result);
1690 }
1691 }
1692
1693 bool JVMCIEnv::equals(JVMCIObject a, JVMCIObject b) {
1694 if (is_hotspot()) {
1695 return HotSpotJVMCI::resolve(a) == HotSpotJVMCI::resolve(b);
1696 } else {
1697 JNIAccessMark jni(this);
1698 return jni()->IsSameObject(a.as_jobject(), b.as_jobject()) != 0;
1699 }
1700 }
1701
1702 BasicType JVMCIEnv::typeCharToBasicType(jchar ch, JVMCI_TRAPS) {
1703 switch(ch) {
1704 case 'Z': return T_BOOLEAN;
1705 case 'B': return T_BYTE;
1706 case 'S': return T_SHORT;
1707 case 'C': return T_CHAR;
1708 case 'I': return T_INT;
1709 case 'F': return T_FLOAT;
1710 case 'J': return T_LONG;
1711 case 'D': return T_DOUBLE;
1712 case 'A': return T_OBJECT;
1713 case '-': return T_ILLEGAL;
1714 default:
1715 JVMCI_ERROR_(T_ILLEGAL, "unexpected type char: %c", ch);
1716 }
1717 }
1718
1719 BasicType JVMCIEnv::kindToBasicType(JVMCIObject kind, JVMCI_TRAPS) {
1720 if (kind.is_null()) {
1721 JVMCI_THROW_(NullPointerException, T_ILLEGAL);
1722 }
1723 jchar ch = get_JavaKind_typeChar(kind);
1724 BasicType bt = typeCharToBasicType(ch, JVMCI_CHECK_(T_ILLEGAL));
1725 return bt;
1726 }
1727
1728 void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* cb, JVMCI_TRAPS) {
1729 // Ensure that all updates to the InstalledCode fields are consistent.
1730 if (get_InstalledCode_address(installed_code) != 0) {
1731 JVMCI_THROW_MSG(InternalError, "InstalledCode instance already in use");
1732 }
1733 if (!isa_HotSpotInstalledCode(installed_code)) {
1734 JVMCI_THROW_MSG(InternalError, "InstalledCode instance must be a subclass of HotSpotInstalledCode");
1735 }
1736
1737 // Ignore the version which can stay at 0
1738 if (cb->is_nmethod()) {
1739 nmethod* nm = cb->as_nmethod_or_null();
1740 if (nm->is_in_use()) {
1741 set_InstalledCode_entryPoint(installed_code, (jlong) nm->verified_entry_point());
1742 }
1743 } else {
1744 set_InstalledCode_entryPoint(installed_code, (jlong) cb->code_begin());
1745 }
1746 set_InstalledCode_address(installed_code, (jlong) cb);
1747 set_HotSpotInstalledCode_size(installed_code, cb->size());
1748 set_HotSpotInstalledCode_codeStart(installed_code, (jlong) cb->code_begin());
1749 set_HotSpotInstalledCode_codeSize(installed_code, cb->code_size());
1750 }
1751
1752
1753 void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nmethod::ChangeReason change_reason, JVMCI_TRAPS) {
1754 if (mirror.is_null()) {
1755 JVMCI_THROW(NullPointerException);
1756 }
1757
1758 Thread* current = Thread::current();
1759 if (!mirror.is_hotspot() && !current->is_Java_thread()) {
1760 // Calling back into native might cause the execution to block, so only allow this when calling
1761 // from a JavaThread, which is the normal case anyway.
1762 JVMCI_THROW_MSG(IllegalArgumentException,
1763 "Cannot invalidate HotSpotNmethod object in shared library VM heap from non-JavaThread");
1764 }
1765
1766 JavaThread* thread = JavaThread::cast(current);
1767 JVMCINMethodHandle nmethod_handle(thread);
1768 nmethod* nm = JVMCIENV->get_nmethod(mirror, nmethod_handle);
1769 if (nm == nullptr) {
1770 // Nothing to do
1771 return;
1772 }
1773
1774 if (!deoptimize) {
1775 // Prevent future executions of the nmethod but let current executions complete.
1776 nm->make_not_entrant(change_reason);
1777
1778 // Do not clear the address field here as the Java code may still
1779 // want to later call this method with deoptimize == true. That requires
1780 // the address field to still be pointing at the nmethod.
1781 } else {
1782 // Deoptimize the nmethod immediately.
1783 DeoptimizationScope deopt_scope;
1784 deopt_scope.mark(nm);
1785 nm->make_not_entrant(change_reason);
1786 nm->make_deoptimized();
1787 deopt_scope.deoptimize_marked();
1788
1789 // A HotSpotNmethod instance can only reference a single nmethod
1790 // during its lifetime so simply clear it here.
1791 set_InstalledCode_address(mirror, 0);
1792 }
1793 }
1794
1795 Klass* JVMCIEnv::asKlass(JVMCIObject obj) {
1796 return (Klass*) get_HotSpotResolvedObjectTypeImpl_klassPointer(obj);
1797 }
1798
1799 Method* JVMCIEnv::asMethod(JVMCIObject obj) {
1800 Method** methodHandle = (Method**) get_HotSpotResolvedJavaMethodImpl_methodHandle(obj);
1801 return *methodHandle;
1802 }
1803
1804 ConstantPool* JVMCIEnv::asConstantPool(JVMCIObject obj) {
1805 ConstantPool** constantPoolHandle = (ConstantPool**) get_HotSpotConstantPool_constantPoolHandle(obj);
1806 return *constantPoolHandle;
1807 }
1808
1809 MethodData* JVMCIEnv::asMethodData(JVMCIObject obj) {
1810 return (MethodData*) get_HotSpotMethodData_methodDataPointer(obj);
1811 }
1812
1813 // Lookup an nmethod with a matching base and compile id
1814 nmethod* JVMCIEnv::lookup_nmethod(address code, jlong compile_id_snapshot) {
1815 if (code == nullptr) {
1816 return nullptr;
1817 }
1818
1819 CodeBlob* cb = CodeCache::find_blob(code);
1820 if (cb == (CodeBlob*) code) {
1821 nmethod* nm = cb->as_nmethod_or_null();
1822 if (nm != nullptr && (compile_id_snapshot == 0 || nm->compile_id() == compile_id_snapshot)) {
1823 return nm;
1824 }
1825 }
1826 return nullptr;
1827 }
1828
1829
1830 CodeBlob* JVMCIEnv::get_code_blob(JVMCIObject obj) {
1831 address code = (address) get_InstalledCode_address(obj);
1832 if (code == nullptr) {
1833 return nullptr;
1834 }
1835 if (isa_HotSpotNmethod(obj)) {
1836 jlong compile_id_snapshot = get_HotSpotNmethod_compileIdSnapshot(obj);
1837 nmethod* nm = lookup_nmethod(code, compile_id_snapshot);
1838 if (nm != nullptr && compile_id_snapshot != 0L && nm->is_not_entrant()) {
1839 // Zero the entry point so that the nmethod
1840 // cannot be invoked by the mirror but can
1841 // still be deoptimized.
1842 set_InstalledCode_entryPoint(obj, 0);
1843 // Refetch the nmethod since the previous call will be a safepoint in libjvmci
1844 nm = lookup_nmethod(code, compile_id_snapshot);
1845 }
1846
1847 if (nm == nullptr) {
1848 // The HotSpotNmethod was pointing at some nmethod but the nmethod is no longer valid, so
1849 // clear the InstalledCode fields of this HotSpotNmethod so that it no longer refers to a
1850 // nmethod in the code cache.
1851 set_InstalledCode_address(obj, 0);
1852 set_InstalledCode_entryPoint(obj, 0);
1853 set_HotSpotInstalledCode_codeStart(obj, 0);
1854 }
1855 return nm;
1856 }
1857
1858 CodeBlob* cb = (CodeBlob*) code;
1859 assert(!cb->is_nmethod(), "unexpected nmethod");
1860 return cb;
1861 }
1862
1863 void JVMCINMethodHandle::set_nmethod(nmethod* nm) {
1864 BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod();
1865 bs_nm->nmethod_entry_barrier(nm);
1866 _thread->set_live_nmethod(nm);
1867 }
1868
1869 nmethod* JVMCIEnv::get_nmethod(JVMCIObject obj, JVMCINMethodHandle& nmethod_handle) {
1870 CodeBlob* cb = get_code_blob(obj);
1871 if (cb != nullptr) {
1872 nmethod* nm = cb->as_nmethod_or_null();
1873 if (nm != nullptr) {
1874 nmethod_handle.set_nmethod(nm);
1875 return nm;
1876 }
1877 }
1878 return nullptr;
1879 }
1880
1881 // Generate implementations for the initialize, new, isa, get and set methods for all the types and
1882 // fields declared in the JVMCI_CLASSES_DO macro.
1883
1884 #define START_CLASS(className, fullClassName) \
1885 void JVMCIEnv::className##_initialize(JVMCI_TRAPS) { \
1886 if (is_hotspot()) { \
1887 HotSpotJVMCI::className::initialize(JVMCI_CHECK); \
1888 } else { \
1889 JNIJVMCI::className::initialize(JVMCI_CHECK); \
1890 } \
1891 } \
1892 JVMCIObjectArray JVMCIEnv::new_##className##_array(int length, JVMCI_TRAPS) { \
1893 if (is_hotspot()) { \
1894 JavaThread* THREAD = JavaThread::current(); /* For exception macros. */ \
1895 objArrayOop array = oopFactory::new_objArray(HotSpotJVMCI::className::klass(), length, CHECK_(JVMCIObject())); \
1896 return (JVMCIObjectArray) wrap(array); \
1897 } else { \
1898 JNIAccessMark jni(this); \
1899 jobjectArray result = jni()->NewObjectArray(length, JNIJVMCI::className::clazz(), nullptr); \
1900 return wrap(result); \
1901 } \
1902 } \
1903 bool JVMCIEnv::isa_##className(JVMCIObject object) { \
1904 if (is_hotspot()) { \
1905 return HotSpotJVMCI::className::is_instance(this, object); \
1906 } else { \
1907 return JNIJVMCI::className::is_instance(this, object); \
1908 } \
1909 }
1910
1911 #define END_CLASS
1912
1913 #define FIELD(className, name, type, accessor, cast) \
1914 type JVMCIEnv::get_##className##_##name(JVMCIObject obj) { \
1915 if (is_hotspot()) { \
1916 return HotSpotJVMCI::className::get_##name(this, obj); \
1917 } else { \
1918 return JNIJVMCI::className::get_##name(this, obj); \
1919 } \
1920 } \
1921 void JVMCIEnv::set_##className##_##name(JVMCIObject obj, type x) { \
1922 if (is_hotspot()) { \
1923 HotSpotJVMCI::className::set_##name(this, obj, x); \
1924 } else { \
1925 JNIJVMCI::className::set_##name(this, obj, x); \
1926 } \
1927 }
1928
1929 #define EMPTY_CAST
1930 #define CHAR_FIELD(className, name) FIELD(className, name, jchar, Char, EMPTY_CAST)
1931 #define INT_FIELD(className, name) FIELD(className, name, jint, Int, EMPTY_CAST)
1932 #define BOOLEAN_FIELD(className, name) FIELD(className, name, jboolean, Boolean, EMPTY_CAST)
1933 #define LONG_FIELD(className, name) FIELD(className, name, jlong, Long, EMPTY_CAST)
1934 #define FLOAT_FIELD(className, name) FIELD(className, name, jfloat, Float, EMPTY_CAST)
1935
1936 #define OBJECT_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIObject, Object, EMPTY_CAST)
1937 #define OBJECTARRAY_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray))
1938 #define PRIMARRAY_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIPrimitiveArray, Object, (JVMCIPrimitiveArray))
1939
1940 #define STATIC_OBJECT_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObject, Object, (JVMCIObject))
1941 #define STATIC_OBJECTARRAY_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray))
1942
1943 #define OOPISH_FIELD(className, name, type, accessor, cast) \
1944 type JVMCIEnv::get_##className##_##name(JVMCIObject obj) { \
1945 if (is_hotspot()) { \
1946 return HotSpotJVMCI::className::get_##name(this, obj); \
1947 } else { \
1948 return JNIJVMCI::className::get_##name(this, obj); \
1949 } \
1950 } \
1951 void JVMCIEnv::set_##className##_##name(JVMCIObject obj, type x) { \
1952 if (is_hotspot()) { \
1953 HotSpotJVMCI::className::set_##name(this, obj, x); \
1954 } else { \
1955 JNIJVMCI::className::set_##name(this, obj, x); \
1956 } \
1957 }
1958
1959 #define STATIC_OOPISH_FIELD(className, name, type, accessor, cast) \
1960 type JVMCIEnv::get_##className##_##name() { \
1961 if (is_hotspot()) { \
1962 return HotSpotJVMCI::className::get_##name(this); \
1963 } else { \
1964 return JNIJVMCI::className::get_##name(this); \
1965 } \
1966 } \
1967 void JVMCIEnv::set_##className##_##name(type x) { \
1968 if (is_hotspot()) { \
1969 HotSpotJVMCI::className::set_##name(this, x); \
1970 } else { \
1971 JNIJVMCI::className::set_##name(this, x); \
1972 } \
1973 }
1974
1975 #define STATIC_PRIMITIVE_FIELD(className, name, type, accessor, cast) \
1976 type JVMCIEnv::get_##className##_##name() { \
1977 if (is_hotspot()) { \
1978 return HotSpotJVMCI::className::get_##name(this); \
1979 } else { \
1980 return JNIJVMCI::className::get_##name(this); \
1981 } \
1982 } \
1983 void JVMCIEnv::set_##className##_##name(type x) { \
1984 if (is_hotspot()) { \
1985 HotSpotJVMCI::className::set_##name(this, x); \
1986 } else { \
1987 JNIJVMCI::className::set_##name(this, x); \
1988 } \
1989 }
1990 #define STATIC_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint, Int, EMPTY_CAST)
1991 #define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean, Boolean, EMPTY_CAST)
1992 #define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName)
1993 #define CONSTRUCTOR(className, signature)
1994
1995 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)
1996
1997 #undef START_CLASS
1998 #undef END_CLASS
1999 #undef METHOD
2000 #undef CONSTRUCTOR
2001 #undef FIELD
2002 #undef CHAR_FIELD
2003 #undef INT_FIELD
2004 #undef BOOLEAN_FIELD
2005 #undef LONG_FIELD
2006 #undef FLOAT_FIELD
2007 #undef OBJECT_FIELD
2008 #undef PRIMARRAY_FIELD
2009 #undef OBJECTARRAY_FIELD
2010 #undef STATIC_OOPISH_FIELD
2011 #undef STATIC_OBJECT_FIELD
2012 #undef STATIC_OBJECTARRAY_FIELD
2013 #undef STATIC_INT_FIELD
2014 #undef STATIC_BOOLEAN_FIELD
2015 #undef EMPTY_CAST