1 /*
2 * Copyright (c) 1999, 2019, 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 "precompiled.hpp"
26 #include "classfile/stringTable.hpp"
27 #include "classfile/symbolTable.hpp"
28 #include "code/codeCache.hpp"
29 #include "memory/oopFactory.hpp"
30 #include "memory/resourceArea.hpp"
31 #include "memory/universe.hpp"
32 #include "oops/objArrayKlass.hpp"
33 #include "oops/typeArrayOop.inline.hpp"
34 #include "runtime/deoptimization.hpp"
35 #include "runtime/jniHandles.inline.hpp"
36 #include "runtime/javaCalls.hpp"
37 #include "jvmci/jniAccessMark.inline.hpp"
38 #include "jvmci/jvmciRuntime.hpp"
39
JVMCICompileState(CompileTask * task)40 JVMCICompileState::JVMCICompileState(CompileTask* task):
41 _task(task),
42 _retryable(true),
43 _failure_reason(NULL),
44 _failure_reason_on_C_heap(false) {
45 // Get Jvmti capabilities under lock to get consistent values.
46 MutexLocker mu(JvmtiThreadState_lock);
47 _jvmti_redefinition_count = JvmtiExport::redefinition_count();
48 _jvmti_can_hotswap_or_post_breakpoint = JvmtiExport::can_hotswap_or_post_breakpoint() ? 1 : 0;
49 _jvmti_can_access_local_variables = JvmtiExport::can_access_local_variables() ? 1 : 0;
50 _jvmti_can_post_on_exceptions = JvmtiExport::can_post_on_exceptions() ? 1 : 0;
51 _jvmti_can_pop_frame = JvmtiExport::can_pop_frame() ? 1 : 0;
52 }
53
jvmti_state_changed() const54 bool JVMCICompileState::jvmti_state_changed() const {
55 // Some classes were redefined
56 if (jvmti_redefinition_count() != JvmtiExport::redefinition_count()) {
57 return true;
58 }
59 if (!jvmti_can_access_local_variables() &&
60 JvmtiExport::can_access_local_variables()) {
61 return true;
62 }
63 if (!jvmti_can_hotswap_or_post_breakpoint() &&
64 JvmtiExport::can_hotswap_or_post_breakpoint()) {
65 return true;
66 }
67 if (!jvmti_can_post_on_exceptions() &&
68 JvmtiExport::can_post_on_exceptions()) {
69 return true;
70 }
71 if (!jvmti_can_pop_frame() &&
72 JvmtiExport::can_pop_frame()) {
73 return true;
74 }
75 return false;
76 }
77
78 JavaVM* JVMCIEnv::_shared_library_javavm = NULL;
79 void* JVMCIEnv::_shared_library_handle = NULL;
80 char* JVMCIEnv::_shared_library_path = NULL;
81
copy_saved_properties()82 void JVMCIEnv::copy_saved_properties() {
83 assert(!is_hotspot(), "can only copy saved properties from HotSpot to native image");
84
85 JavaThread* THREAD = JavaThread::current();
86
87 Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_vm_ci_services_Services(), Handle(), Handle(), true, THREAD);
88 if (HAS_PENDING_EXCEPTION) {
89 JVMCIRuntime::exit_on_pending_exception(NULL, "Error initializing jdk.vm.ci.services.Services");
90 }
91 InstanceKlass* ik = InstanceKlass::cast(k);
92 if (ik->should_be_initialized()) {
93 ik->initialize(THREAD);
94 if (HAS_PENDING_EXCEPTION) {
95 JVMCIRuntime::exit_on_pending_exception(NULL, "Error initializing jdk.vm.ci.services.Services");
96 }
97 }
98
99 // Get the serialized saved properties from HotSpot
100 TempNewSymbol serializeSavedProperties = SymbolTable::new_symbol("serializeSavedProperties");
101 JavaValue result(T_OBJECT);
102 JavaCallArguments args;
103 JavaCalls::call_static(&result, ik, serializeSavedProperties, vmSymbols::serializePropertiesToByteArray_signature(), &args, THREAD);
104 if (HAS_PENDING_EXCEPTION) {
105 JVMCIRuntime::exit_on_pending_exception(NULL, "Error calling jdk.vm.ci.services.Services.serializeSavedProperties");
106 }
107 oop res = (oop) result.get_jobject();
108 assert(res->is_typeArray(), "must be");
109 assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "must be");
110 typeArrayOop ba = typeArrayOop(res);
111 int serialized_properties_len = ba->length();
112
113 // Copy serialized saved properties from HotSpot object into native buffer
114 jbyte* serialized_properties = NEW_RESOURCE_ARRAY(jbyte, serialized_properties_len);
115 memcpy(serialized_properties, ba->byte_at_addr(0), serialized_properties_len);
116
117 // Copy native buffer into shared library object
118 JVMCIPrimitiveArray buf = new_byteArray(serialized_properties_len, this);
119 if (has_pending_exception()) {
120 describe_pending_exception(true);
121 fatal("Error in copy_saved_properties");
122 }
123 copy_bytes_from(serialized_properties, buf, 0, serialized_properties_len);
124 if (has_pending_exception()) {
125 describe_pending_exception(true);
126 fatal("Error in copy_saved_properties");
127 }
128
129 // Initialize saved properties in shared library
130 jclass servicesClass = JNIJVMCI::Services::clazz();
131 jmethodID initializeSavedProperties = JNIJVMCI::Services::initializeSavedProperties_method();
132 JNIAccessMark jni(this);
133 jni()->CallStaticVoidMethod(servicesClass, initializeSavedProperties, buf.as_jobject());
134 if (jni()->ExceptionCheck()) {
135 jni()->ExceptionDescribe();
136 fatal("Error calling jdk.vm.ci.services.Services.initializeSavedProperties");
137 }
138 }
139
init_shared_library(JavaThread * thread)140 JNIEnv* JVMCIEnv::init_shared_library(JavaThread* thread) {
141 if (_shared_library_javavm == NULL) {
142 MutexLocker locker(JVMCI_lock);
143 if (_shared_library_javavm == NULL) {
144 char path[JVM_MAXPATHLEN];
145 char ebuf[1024];
146 if (JVMCILibPath != NULL) {
147 if (!os::dll_locate_lib(path, sizeof(path), JVMCILibPath, JVMCI_SHARED_LIBRARY_NAME)) {
148 vm_exit_during_initialization("Unable to create JVMCI shared library path from -XX:JVMCILibPath value", JVMCILibPath);
149 }
150 } else {
151 if (!os::dll_locate_lib(path, sizeof(path), Arguments::get_dll_dir(), JVMCI_SHARED_LIBRARY_NAME)) {
152 vm_exit_during_initialization("Unable to create path to JVMCI shared library");
153 }
154 }
155
156 void* handle = os::dll_load(path, ebuf, sizeof ebuf);
157 if (handle == NULL) {
158 vm_exit_during_initialization("Unable to load JVMCI shared library", ebuf);
159 }
160 _shared_library_handle = handle;
161 _shared_library_path = strdup(path);
162 jint (*JNI_CreateJavaVM)(JavaVM **pvm, void **penv, void *args);
163 typedef jint (*JNI_CreateJavaVM_t)(JavaVM **pvm, void **penv, void *args);
164
165 JNI_CreateJavaVM = CAST_TO_FN_PTR(JNI_CreateJavaVM_t, os::dll_lookup(handle, "JNI_CreateJavaVM"));
166 JNIEnv* env;
167 if (JNI_CreateJavaVM == NULL) {
168 vm_exit_during_initialization("Unable to find JNI_CreateJavaVM", path);
169 }
170
171 ResourceMark rm;
172 JavaVMInitArgs vm_args;
173 vm_args.version = JNI_VERSION_1_2;
174 vm_args.ignoreUnrecognized = JNI_TRUE;
175 vm_args.options = NULL;
176 vm_args.nOptions = 0;
177
178 JavaVM* the_javavm = NULL;
179 int result = (*JNI_CreateJavaVM)(&the_javavm, (void**) &env, &vm_args);
180 if (result == JNI_OK) {
181 guarantee(env != NULL, "missing env");
182 _shared_library_javavm = the_javavm;
183 return env;
184 } else {
185 vm_exit_during_initialization(err_msg("JNI_CreateJavaVM failed with return value %d", result), path);
186 }
187 }
188 }
189 return NULL;
190 }
191
init_env_mode_runtime(JavaThread * thread,JNIEnv * parent_env)192 void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) {
193 assert(thread != NULL, "npe");
194 // By default there is only one runtime which is the compiler runtime.
195 _runtime = JVMCI::compiler_runtime();
196 _env = NULL;
197 _pop_frame_on_close = false;
198 _detach_on_close = false;
199 if (!UseJVMCINativeLibrary) {
200 // In HotSpot mode, JNI isn't used at all.
201 _is_hotspot = true;
202 return;
203 }
204
205 if (parent_env != NULL) {
206 // If the parent JNI environment is non-null then figure out whether it
207 // is a HotSpot or shared library JNIEnv and set the state appropriately.
208 _is_hotspot = thread->jni_environment() == parent_env;
209 if (_is_hotspot) {
210 // Select the Java runtime
211 _runtime = JVMCI::java_runtime();
212 return;
213 }
214 _env = parent_env;
215 return;
216 }
217
218 // Running in JVMCI shared library mode so ensure the shared library
219 // is loaded and initialized and get a shared library JNIEnv
220 _is_hotspot = false;
221 _env = init_shared_library(thread);
222
223 if (_env != NULL) {
224 // Creating the JVMCI shared library VM also attaches the current thread
225 _detach_on_close = true;
226 } else {
227 _shared_library_javavm->GetEnv((void**)&parent_env, JNI_VERSION_1_2);
228 if (parent_env != NULL) {
229 // Even though there's a parent JNI env, there's no guarantee
230 // it was opened by a JVMCIEnv scope and thus may not have
231 // pushed a local JNI frame. As such, we use a new JNI local
232 // frame in this scope to ensure local JNI refs are collected
233 // in a timely manner after leaving this scope.
234 _env = parent_env;
235 } else {
236 ResourceMark rm; // Thread name is resource allocated
237 JavaVMAttachArgs attach_args;
238 attach_args.version = JNI_VERSION_1_2;
239 attach_args.name = thread->name();
240 attach_args.group = NULL;
241 if (_shared_library_javavm->AttachCurrentThread((void**)&_env, &attach_args) != JNI_OK) {
242 fatal("Error attaching current thread (%s) to JVMCI shared library JNI interface", attach_args.name);
243 }
244 _detach_on_close = true;
245 }
246 }
247
248 assert(_env != NULL, "missing env");
249 assert(_throw_to_caller == false, "must be");
250
251 JNIAccessMark jni(this);
252 jint result = _env->PushLocalFrame(32);
253 if (result != JNI_OK) {
254 char message[256];
255 jio_snprintf(message, 256, "Uncaught exception pushing local frame for JVMCIEnv scope entered at %s:%d", _file, _line);
256 JVMCIRuntime::exit_on_pending_exception(this, message);
257 }
258 _pop_frame_on_close = true;
259 }
260
JVMCIEnv(JavaThread * thread,JVMCICompileState * compile_state,const char * file,int line)261 JVMCIEnv::JVMCIEnv(JavaThread* thread, JVMCICompileState* compile_state, const char* file, int line):
262 _throw_to_caller(false), _file(file), _line(line), _compile_state(compile_state) {
263 init_env_mode_runtime(thread, NULL);
264 }
265
JVMCIEnv(JavaThread * thread,const char * file,int line)266 JVMCIEnv::JVMCIEnv(JavaThread* thread, const char* file, int line):
267 _throw_to_caller(false), _file(file), _line(line), _compile_state(NULL) {
268 init_env_mode_runtime(thread, NULL);
269 }
270
JVMCIEnv(JavaThread * thread,JNIEnv * parent_env,const char * file,int line)271 JVMCIEnv::JVMCIEnv(JavaThread* thread, JNIEnv* parent_env, const char* file, int line):
272 _throw_to_caller(true), _file(file), _line(line), _compile_state(NULL) {
273 init_env_mode_runtime(thread, parent_env);
274 assert(_env == NULL || parent_env == _env, "mismatched JNIEnvironment");
275 }
276
init(JavaThread * thread,bool is_hotspot,const char * file,int line)277 void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, const char* file, int line) {
278 _compile_state = NULL;
279 _throw_to_caller = false;
280 _file = file;
281 _line = line;
282 if (is_hotspot) {
283 _env = NULL;
284 _pop_frame_on_close = false;
285 _detach_on_close = false;
286 _is_hotspot = true;
287 _runtime = JVMCI::java_runtime();
288 } else {
289 init_env_mode_runtime(thread, NULL);
290 }
291 }
292
293 // Prints a pending exception (if any) and its stack trace.
describe_pending_exception(bool clear)294 void JVMCIEnv::describe_pending_exception(bool clear) {
295 if (!is_hotspot()) {
296 JNIAccessMark jni(this);
297 if (jni()->ExceptionCheck()) {
298 jthrowable ex = !clear ? jni()->ExceptionOccurred() : NULL;
299 jni()->ExceptionDescribe();
300 if (ex != NULL) {
301 jni()->Throw(ex);
302 }
303 }
304 } else {
305 Thread* THREAD = Thread::current();
306 if (HAS_PENDING_EXCEPTION) {
307 JVMCIRuntime::describe_pending_hotspot_exception((JavaThread*) THREAD, clear);
308 }
309 }
310 }
311
translate_hotspot_exception_to_jni_exception(JavaThread * THREAD,const Handle & throwable)312 void JVMCIEnv::translate_hotspot_exception_to_jni_exception(JavaThread* THREAD, const Handle& throwable) {
313 assert(!is_hotspot(), "must_be");
314 // Resolve HotSpotJVMCIRuntime class explicitly as HotSpotJVMCI::compute_offsets
315 // may not have been called.
316 Klass* runtimeKlass = SystemDictionary::resolve_or_fail(vmSymbols::jdk_vm_ci_hotspot_HotSpotJVMCIRuntime(), true, CHECK);
317 JavaCallArguments jargs;
318 jargs.push_oop(throwable);
319 JavaValue result(T_OBJECT);
320 JavaCalls::call_static(&result,
321 runtimeKlass,
322 vmSymbols::encodeThrowable_name(),
323 vmSymbols::encodeThrowable_signature(), &jargs, THREAD);
324 if (HAS_PENDING_EXCEPTION) {
325 JVMCIRuntime::exit_on_pending_exception(this, "HotSpotJVMCIRuntime.encodeThrowable should not throw an exception");
326 }
327
328 oop encoded_throwable_string = (oop) result.get_jobject();
329
330 ResourceMark rm;
331 const char* encoded_throwable_chars = java_lang_String::as_utf8_string(encoded_throwable_string);
332
333 JNIAccessMark jni(this);
334 jobject jni_encoded_throwable_string = jni()->NewStringUTF(encoded_throwable_chars);
335 jthrowable jni_throwable = (jthrowable) jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
336 JNIJVMCI::HotSpotJVMCIRuntime::decodeThrowable_method(),
337 jni_encoded_throwable_string);
338 jni()->Throw(jni_throwable);
339 }
340
~JVMCIEnv()341 JVMCIEnv::~JVMCIEnv() {
342 if (_throw_to_caller) {
343 if (is_hotspot()) {
344 // Nothing to do
345 } else {
346 if (Thread::current()->is_Java_thread()) {
347 JavaThread* THREAD = JavaThread::current();
348 if (HAS_PENDING_EXCEPTION) {
349 Handle throwable = Handle(THREAD, PENDING_EXCEPTION);
350 CLEAR_PENDING_EXCEPTION;
351 translate_hotspot_exception_to_jni_exception(THREAD, throwable);
352 }
353 }
354 }
355 } else {
356 if (_pop_frame_on_close) {
357 // Pop the JNI local frame that was pushed when entering this JVMCIEnv scope.
358 JNIAccessMark jni(this);
359 jni()->PopLocalFrame(NULL);
360 }
361
362 if (has_pending_exception()) {
363 char message[256];
364 jio_snprintf(message, 256, "Uncaught exception exiting JVMCIEnv scope entered at %s:%d", _file, _line);
365 JVMCIRuntime::exit_on_pending_exception(this, message);
366 }
367
368 if (_detach_on_close) {
369 get_shared_library_javavm()->DetachCurrentThread();
370 }
371 }
372 }
373
has_pending_exception()374 jboolean JVMCIEnv::has_pending_exception() {
375 if (is_hotspot()) {
376 Thread* THREAD = Thread::current();
377 return HAS_PENDING_EXCEPTION;
378 } else {
379 JNIAccessMark jni(this);
380 return jni()->ExceptionCheck();
381 }
382 }
383
clear_pending_exception()384 void JVMCIEnv::clear_pending_exception() {
385 if (is_hotspot()) {
386 Thread* THREAD = Thread::current();
387 CLEAR_PENDING_EXCEPTION;
388 } else {
389 JNIAccessMark jni(this);
390 jni()->ExceptionClear();
391 }
392 }
393
get_length(JVMCIArray array)394 int JVMCIEnv::get_length(JVMCIArray array) {
395 if (is_hotspot()) {
396 return HotSpotJVMCI::resolve(array)->length();
397 } else {
398 JNIAccessMark jni(this);
399 return jni()->GetArrayLength(get_jarray(array));
400 }
401 }
402
get_object_at(JVMCIObjectArray array,int index)403 JVMCIObject JVMCIEnv::get_object_at(JVMCIObjectArray array, int index) {
404 if (is_hotspot()) {
405 oop result = HotSpotJVMCI::resolve(array)->obj_at(index);
406 return wrap(result);
407 } else {
408 JNIAccessMark jni(this);
409 jobject result = jni()->GetObjectArrayElement(get_jobjectArray(array), index);
410 return wrap(result);
411 }
412 }
413
put_object_at(JVMCIObjectArray array,int index,JVMCIObject value)414 void JVMCIEnv::put_object_at(JVMCIObjectArray array, int index, JVMCIObject value) {
415 if (is_hotspot()) {
416 HotSpotJVMCI::resolve(array)->obj_at_put(index, HotSpotJVMCI::resolve(value));
417 } else {
418 JNIAccessMark jni(this);
419 jni()->SetObjectArrayElement(get_jobjectArray(array), index, get_jobject(value));
420 }
421 }
422
get_bool_at(JVMCIPrimitiveArray array,int index)423 jboolean JVMCIEnv::get_bool_at(JVMCIPrimitiveArray array, int index) {
424 if (is_hotspot()) {
425 return HotSpotJVMCI::resolve(array)->bool_at(index);
426 } else {
427 JNIAccessMark jni(this);
428 jboolean result;
429 jni()->GetBooleanArrayRegion(array.as_jbooleanArray(), index, 1, &result);
430 return result;
431 }
432 }
put_bool_at(JVMCIPrimitiveArray array,int index,jboolean value)433 void JVMCIEnv::put_bool_at(JVMCIPrimitiveArray array, int index, jboolean value) {
434 if (is_hotspot()) {
435 HotSpotJVMCI::resolve(array)->bool_at_put(index, value);
436 } else {
437 JNIAccessMark jni(this);
438 jni()->SetBooleanArrayRegion(array.as_jbooleanArray(), index, 1, &value);
439 }
440 }
441
get_byte_at(JVMCIPrimitiveArray array,int index)442 jbyte JVMCIEnv::get_byte_at(JVMCIPrimitiveArray array, int index) {
443 if (is_hotspot()) {
444 return HotSpotJVMCI::resolve(array)->byte_at(index);
445 } else {
446 JNIAccessMark jni(this);
447 jbyte result;
448 jni()->GetByteArrayRegion(array.as_jbyteArray(), index, 1, &result);
449 return result;
450 }
451 }
put_byte_at(JVMCIPrimitiveArray array,int index,jbyte value)452 void JVMCIEnv::put_byte_at(JVMCIPrimitiveArray array, int index, jbyte value) {
453 if (is_hotspot()) {
454 HotSpotJVMCI::resolve(array)->byte_at_put(index, value);
455 } else {
456 JNIAccessMark jni(this);
457 jni()->SetByteArrayRegion(array.as_jbyteArray(), index, 1, &value);
458 }
459 }
460
get_int_at(JVMCIPrimitiveArray array,int index)461 jint JVMCIEnv::get_int_at(JVMCIPrimitiveArray array, int index) {
462 if (is_hotspot()) {
463 return HotSpotJVMCI::resolve(array)->int_at(index);
464 } else {
465 JNIAccessMark jni(this);
466 jint result;
467 jni()->GetIntArrayRegion(array.as_jintArray(), index, 1, &result);
468 return result;
469 }
470 }
put_int_at(JVMCIPrimitiveArray array,int index,jint value)471 void JVMCIEnv::put_int_at(JVMCIPrimitiveArray array, int index, jint value) {
472 if (is_hotspot()) {
473 HotSpotJVMCI::resolve(array)->int_at_put(index, value);
474 } else {
475 JNIAccessMark jni(this);
476 jni()->SetIntArrayRegion(array.as_jintArray(), index, 1, &value);
477 }
478 }
479
get_long_at(JVMCIPrimitiveArray array,int index)480 long JVMCIEnv::get_long_at(JVMCIPrimitiveArray array, int index) {
481 if (is_hotspot()) {
482 return HotSpotJVMCI::resolve(array)->long_at(index);
483 } else {
484 JNIAccessMark jni(this);
485 jlong result;
486 jni()->GetLongArrayRegion(array.as_jlongArray(), index, 1, &result);
487 return result;
488 }
489 }
put_long_at(JVMCIPrimitiveArray array,int index,jlong value)490 void JVMCIEnv::put_long_at(JVMCIPrimitiveArray array, int index, jlong value) {
491 if (is_hotspot()) {
492 HotSpotJVMCI::resolve(array)->long_at_put(index, value);
493 } else {
494 JNIAccessMark jni(this);
495 jni()->SetLongArrayRegion(array.as_jlongArray(), index, 1, &value);
496 }
497 }
498
copy_bytes_to(JVMCIPrimitiveArray src,jbyte * dest,int offset,jsize length)499 void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length) {
500 if (length == 0) {
501 return;
502 }
503 if (is_hotspot()) {
504 memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), length);
505 } else {
506 JNIAccessMark jni(this);
507 jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, length, dest);
508 }
509 }
copy_bytes_from(jbyte * src,JVMCIPrimitiveArray dest,int offset,jsize length)510 void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
511 if (length == 0) {
512 return;
513 }
514 if (is_hotspot()) {
515 memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, length);
516 } else {
517 JNIAccessMark jni(this);
518 jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, length, src);
519 }
520 }
521
copy_longs_from(jlong * src,JVMCIPrimitiveArray dest,int offset,jsize length)522 void JVMCIEnv::copy_longs_from(jlong* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
523 if (length == 0) {
524 return;
525 }
526 if (is_hotspot()) {
527 memcpy(HotSpotJVMCI::resolve(dest)->long_at_addr(offset), src, length * sizeof(jlong));
528 } else {
529 JNIAccessMark jni(this);
530 jni()->SetLongArrayRegion(dest.as_jlongArray(), offset, length, src);
531 }
532 }
533
is_boxing_object(BasicType type,JVMCIObject object)534 jboolean JVMCIEnv::is_boxing_object(BasicType type, JVMCIObject object) {
535 if (is_hotspot()) {
536 return java_lang_boxing_object::is_instance(HotSpotJVMCI::resolve(object), type);
537 } else {
538 JNIAccessMark jni(this);
539 return jni()->IsInstanceOf(get_jobject(object), JNIJVMCI::box_class(type));
540 }
541 }
542
543 // Get the primitive value from a Java boxing object. It's hard error to
544 // pass a non-primitive BasicType.
get_boxed_value(BasicType type,JVMCIObject object)545 jvalue JVMCIEnv::get_boxed_value(BasicType type, JVMCIObject object) {
546 jvalue result;
547 if (is_hotspot()) {
548 if (java_lang_boxing_object::get_value(HotSpotJVMCI::resolve(object), &result) == T_ILLEGAL) {
549 ShouldNotReachHere();
550 }
551 } else {
552 JNIAccessMark jni(this);
553 jfieldID field = JNIJVMCI::box_field(type);
554 switch (type) {
555 case T_BOOLEAN: result.z = jni()->GetBooleanField(get_jobject(object), field); break;
556 case T_BYTE: result.b = jni()->GetByteField(get_jobject(object), field); break;
557 case T_SHORT: result.s = jni()->GetShortField(get_jobject(object), field); break;
558 case T_CHAR: result.c = jni()->GetCharField(get_jobject(object), field); break;
559 case T_INT: result.i = jni()->GetIntField(get_jobject(object), field); break;
560 case T_LONG: result.j = jni()->GetLongField(get_jobject(object), field); break;
561 case T_FLOAT: result.f = jni()->GetFloatField(get_jobject(object), field); break;
562 case T_DOUBLE: result.d = jni()->GetDoubleField(get_jobject(object), field); break;
563 default:
564 ShouldNotReachHere();
565 }
566 }
567 return result;
568 }
569
570 // Return the BasicType of the object if it's a boxing object, otherwise return T_ILLEGAL.
get_box_type(JVMCIObject object)571 BasicType JVMCIEnv::get_box_type(JVMCIObject object) {
572 if (is_hotspot()) {
573 return java_lang_boxing_object::basic_type(HotSpotJVMCI::resolve(object));
574 } else {
575 JNIAccessMark jni(this);
576 jclass clazz = jni()->GetObjectClass(get_jobject(object));
577 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_BOOLEAN))) return T_BOOLEAN;
578 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_BYTE))) return T_BYTE;
579 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_SHORT))) return T_SHORT;
580 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_CHAR))) return T_CHAR;
581 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_INT))) return T_INT;
582 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_LONG))) return T_LONG;
583 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_FLOAT))) return T_FLOAT;
584 if (jni()->IsSameObject(clazz, JNIJVMCI::box_class(T_DOUBLE))) return T_DOUBLE;
585 return T_ILLEGAL;
586 }
587 }
588
589 // Create a boxing object of the appropriate primitive type.
create_box(BasicType type,jvalue * value,JVMCI_TRAPS)590 JVMCIObject JVMCIEnv::create_box(BasicType type, jvalue* value, JVMCI_TRAPS) {
591 switch (type) {
592 case T_BOOLEAN:
593 case T_BYTE:
594 case T_CHAR:
595 case T_SHORT:
596 case T_INT:
597 case T_LONG:
598 case T_FLOAT:
599 case T_DOUBLE:
600 break;
601 default:
602 JVMCI_THROW_MSG_(IllegalArgumentException, "Only boxes for primitive values can be created", JVMCIObject());
603 }
604 if (is_hotspot()) {
605 JavaThread* THREAD = JavaThread::current();
606 oop box = java_lang_boxing_object::create(type, value, CHECK_(JVMCIObject()));
607 return HotSpotJVMCI::wrap(box);
608 } else {
609 JNIAccessMark jni(this);
610 jobject box = jni()->NewObjectA(JNIJVMCI::box_class(type), JNIJVMCI::box_constructor(type), value);
611 assert(box != NULL, "");
612 return wrap(box);
613 }
614 }
615
as_utf8_string(JVMCIObject str)616 const char* JVMCIEnv::as_utf8_string(JVMCIObject str) {
617 if (is_hotspot()) {
618 return java_lang_String::as_utf8_string(HotSpotJVMCI::resolve(str));
619 } else {
620 JNIAccessMark jni(this);
621 int length = jni()->GetStringLength(str.as_jstring());
622 char* result = NEW_RESOURCE_ARRAY(char, length + 1);
623 jni()->GetStringUTFRegion(str.as_jstring(), 0, length, result);
624 return result;
625 }
626 }
627
as_utf8_string(JVMCIObject str,char * buf,int buflen)628 char* JVMCIEnv::as_utf8_string(JVMCIObject str, char* buf, int buflen) {
629 if (is_hotspot()) {
630 return java_lang_String::as_utf8_string(HotSpotJVMCI::resolve(str), buf, buflen);
631 } else {
632 JNIAccessMark jni(this);
633 int length = jni()->GetStringLength(str.as_jstring());
634 if (length >= buflen) {
635 length = buflen;
636 }
637 jni()->GetStringUTFRegion(str.as_jstring(), 0, length, buf);
638 return buf;
639 }
640 }
641
642 #define DO_THROW(name) \
643 void JVMCIEnv::throw_##name(const char* msg) { \
644 if (is_hotspot()) { \
645 JavaThread* THREAD = JavaThread::current(); \
646 THROW_MSG(HotSpotJVMCI::name::symbol(), msg); \
647 } else { \
648 JNIAccessMark jni(this); \
649 jni()->ThrowNew(JNIJVMCI::name::clazz(), msg); \
650 } \
651 }
652
653 DO_THROW(InternalError)
DO_THROW(ArrayIndexOutOfBoundsException)654 DO_THROW(ArrayIndexOutOfBoundsException)
655 DO_THROW(IllegalStateException)
656 DO_THROW(NullPointerException)
657 DO_THROW(IllegalArgumentException)
658 DO_THROW(InvalidInstalledCodeException)
659 DO_THROW(UnsatisfiedLinkError)
660 DO_THROW(UnsupportedOperationException)
661 DO_THROW(ClassNotFoundException)
662
663 #undef DO_THROW
664
665 void JVMCIEnv::fthrow_error(const char* file, int line, const char* format, ...) {
666 const int max_msg_size = 1024;
667 va_list ap;
668 va_start(ap, format);
669 char msg[max_msg_size];
670 vsnprintf(msg, max_msg_size, format, ap);
671 msg[max_msg_size-1] = '\0';
672 va_end(ap);
673 if (is_hotspot()) {
674 JavaThread* THREAD = JavaThread::current();
675 Handle h_loader = Handle();
676 Handle h_protection_domain = Handle();
677 Exceptions::_throw_msg(THREAD, file, line, vmSymbols::jdk_vm_ci_common_JVMCIError(), msg, h_loader, h_protection_domain);
678 } else {
679 JNIAccessMark jni(this);
680 jni()->ThrowNew(JNIJVMCI::JVMCIError::clazz(), msg);
681 }
682 }
683
call_HotSpotJVMCIRuntime_compileMethod(JVMCIObject runtime,JVMCIObject method,int entry_bci,jlong compile_state,int id)684 JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtime, JVMCIObject method, int entry_bci,
685 jlong compile_state, int id) {
686 if (is_hotspot()) {
687 Thread* THREAD = Thread::current();
688 JavaCallArguments jargs;
689 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
690 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(method)));
691 jargs.push_int(entry_bci);
692 jargs.push_long(compile_state);
693 jargs.push_int(id);
694 JavaValue result(T_OBJECT);
695 JavaCalls::call_special(&result,
696 HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
697 vmSymbols::compileMethod_name(),
698 vmSymbols::compileMethod_signature(), &jargs, CHECK_(JVMCIObject()));
699 return wrap((oop) result.get_jobject());
700 } else {
701 JNIAccessMark jni(this);
702 jobject result = jni()->CallNonvirtualObjectMethod(runtime.as_jobject(),
703 JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
704 JNIJVMCI::HotSpotJVMCIRuntime::compileMethod_method(),
705 method.as_jobject(), entry_bci, compile_state, id);
706 if (jni()->ExceptionCheck()) {
707 return JVMCIObject();
708 }
709 return wrap(result);
710 }
711 }
712
call_HotSpotJVMCIRuntime_bootstrapFinished(JVMCIObject runtime,JVMCIEnv * JVMCIENV)713 void JVMCIEnv::call_HotSpotJVMCIRuntime_bootstrapFinished (JVMCIObject runtime, JVMCIEnv* JVMCIENV) {
714 if (is_hotspot()) {
715 Thread* THREAD = Thread::current();
716 JavaCallArguments jargs;
717 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
718 JavaValue result(T_VOID);
719 JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::bootstrapFinished_name(), vmSymbols::void_method_signature(), &jargs, CHECK);
720 } else {
721 JNIAccessMark jni(this);
722 jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::bootstrapFinished_method());
723
724 }
725 }
726
call_HotSpotJVMCIRuntime_shutdown(JVMCIObject runtime)727 void JVMCIEnv::call_HotSpotJVMCIRuntime_shutdown (JVMCIObject runtime) {
728 HandleMark hm;
729 JavaThread* THREAD = JavaThread::current();
730 if (is_hotspot()) {
731 JavaCallArguments jargs;
732 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
733 JavaValue result(T_VOID);
734 JavaCalls::call_special(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::shutdown_name(), vmSymbols::void_method_signature(), &jargs, THREAD);
735 } else {
736 JNIAccessMark jni(this);
737 jni()->CallNonvirtualVoidMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::shutdown_method());
738 }
739 if (has_pending_exception()) {
740 // This should never happen as HotSpotJVMCIRuntime.shutdown() should
741 // handle all exceptions.
742 describe_pending_exception(true);
743 }
744 }
745
call_HotSpotJVMCIRuntime_runtime(JVMCIEnv * JVMCIENV)746 JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_runtime (JVMCIEnv* JVMCIENV) {
747 JavaThread* THREAD = JavaThread::current();
748 if (is_hotspot()) {
749 JavaCallArguments jargs;
750 JavaValue result(T_OBJECT);
751 JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::runtime_name(), vmSymbols::runtime_signature(), &jargs, CHECK_(JVMCIObject()));
752 return wrap((oop) result.get_jobject());
753 } else {
754 JNIAccessMark jni(this);
755 jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), JNIJVMCI::HotSpotJVMCIRuntime::runtime_method());
756 if (jni()->ExceptionCheck()) {
757 return JVMCIObject();
758 }
759 return wrap(result);
760 }
761 }
762
call_JVMCI_getRuntime(JVMCIEnv * JVMCIENV)763 JVMCIObject JVMCIEnv::call_JVMCI_getRuntime (JVMCIEnv* JVMCIENV) {
764 JavaThread* THREAD = JavaThread::current();
765 if (is_hotspot()) {
766 JavaCallArguments jargs;
767 JavaValue result(T_OBJECT);
768 JavaCalls::call_static(&result, HotSpotJVMCI::JVMCI::klass(), vmSymbols::getRuntime_name(), vmSymbols::getRuntime_signature(), &jargs, CHECK_(JVMCIObject()));
769 return wrap((oop) result.get_jobject());
770 } else {
771 JNIAccessMark jni(this);
772 jobject result = jni()->CallStaticObjectMethod(JNIJVMCI::JVMCI::clazz(), JNIJVMCI::JVMCI::getRuntime_method());
773 if (jni()->ExceptionCheck()) {
774 return JVMCIObject();
775 }
776 return wrap(result);
777 }
778 }
779
call_HotSpotJVMCIRuntime_getCompiler(JVMCIObject runtime,JVMCIEnv * JVMCIENV)780 JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_getCompiler (JVMCIObject runtime, JVMCIEnv* JVMCIENV) {
781 JavaThread* THREAD = JavaThread::current();
782 if (is_hotspot()) {
783 JavaCallArguments jargs;
784 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
785 JavaValue result(T_OBJECT);
786 JavaCalls::call_virtual(&result, HotSpotJVMCI::HotSpotJVMCIRuntime::klass(), vmSymbols::getCompiler_name(), vmSymbols::getCompiler_signature(), &jargs, CHECK_(JVMCIObject()));
787 return wrap((oop) result.get_jobject());
788 } else {
789 JNIAccessMark jni(this);
790 jobject result = jni()->CallObjectMethod(runtime.as_jobject(), JNIJVMCI::HotSpotJVMCIRuntime::getCompiler_method());
791 if (jni()->ExceptionCheck()) {
792 return JVMCIObject();
793 }
794 return wrap(result);
795 }
796 }
797
798
call_HotSpotJVMCIRuntime_callToString(JVMCIObject object,JVMCIEnv * JVMCIENV)799 JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_callToString(JVMCIObject object, JVMCIEnv* JVMCIENV) {
800 JavaThread* THREAD = JavaThread::current();
801 if (is_hotspot()) {
802 JavaCallArguments jargs;
803 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(object)));
804 JavaValue result(T_OBJECT);
805 JavaCalls::call_static(&result,
806 HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
807 vmSymbols::callToString_name(),
808 vmSymbols::callToString_signature(), &jargs, CHECK_(JVMCIObject()));
809 return wrap((oop) result.get_jobject());
810 } else {
811 JNIAccessMark jni(this);
812 jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
813 JNIJVMCI::HotSpotJVMCIRuntime::callToString_method(),
814 object.as_jobject());
815 if (jni()->ExceptionCheck()) {
816 return JVMCIObject();
817 }
818 return wrap(result);
819 }
820 }
821
822
call_PrimitiveConstant_forTypeChar(jchar kind,jlong value,JVMCI_TRAPS)823 JVMCIObject JVMCIEnv::call_PrimitiveConstant_forTypeChar(jchar kind, jlong value, JVMCI_TRAPS) {
824 JavaThread* THREAD = JavaThread::current();
825 if (is_hotspot()) {
826 JavaCallArguments jargs;
827 jargs.push_int(kind);
828 jargs.push_long(value);
829 JavaValue result(T_OBJECT);
830 JavaCalls::call_static(&result,
831 HotSpotJVMCI::PrimitiveConstant::klass(),
832 vmSymbols::forTypeChar_name(),
833 vmSymbols::forTypeChar_signature(), &jargs, CHECK_(JVMCIObject()));
834 return wrap((oop) result.get_jobject());
835 } else {
836 JNIAccessMark jni(this);
837 jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::PrimitiveConstant::clazz(),
838 JNIJVMCI::PrimitiveConstant::forTypeChar_method(),
839 kind, value);
840 if (jni()->ExceptionCheck()) {
841 return JVMCIObject();
842 }
843 return wrap(result);
844 }
845 }
846
call_JavaConstant_forFloat(float value,JVMCI_TRAPS)847 JVMCIObject JVMCIEnv::call_JavaConstant_forFloat(float value, JVMCI_TRAPS) {
848 JavaThread* THREAD = JavaThread::current();
849 if (is_hotspot()) {
850 JavaCallArguments jargs;
851 jargs.push_float(value);
852 JavaValue result(T_OBJECT);
853 JavaCalls::call_static(&result,
854 HotSpotJVMCI::JavaConstant::klass(),
855 vmSymbols::forFloat_name(),
856 vmSymbols::forFloat_signature(), &jargs, CHECK_(JVMCIObject()));
857 return wrap((oop) result.get_jobject());
858 } else {
859 JNIAccessMark jni(this);
860 jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(),
861 JNIJVMCI::JavaConstant::forFloat_method(),
862 value);
863 if (jni()->ExceptionCheck()) {
864 return JVMCIObject();
865 }
866 return wrap(result);
867 }
868 }
869
call_JavaConstant_forDouble(double value,JVMCI_TRAPS)870 JVMCIObject JVMCIEnv::call_JavaConstant_forDouble(double value, JVMCI_TRAPS) {
871 JavaThread* THREAD = JavaThread::current();
872 if (is_hotspot()) {
873 JavaCallArguments jargs;
874 jargs.push_double(value);
875 JavaValue result(T_OBJECT);
876 JavaCalls::call_static(&result,
877 HotSpotJVMCI::JavaConstant::klass(),
878 vmSymbols::forDouble_name(),
879 vmSymbols::forDouble_signature(), &jargs, CHECK_(JVMCIObject()));
880 return wrap((oop) result.get_jobject());
881 } else {
882 JNIAccessMark jni(this);
883 jobject result = (jstring) jni()->CallStaticObjectMethod(JNIJVMCI::JavaConstant::clazz(),
884 JNIJVMCI::JavaConstant::forDouble_method(),
885 value);
886 if (jni()->ExceptionCheck()) {
887 return JVMCIObject();
888 }
889 return wrap(result);
890 }
891 }
892
get_jvmci_primitive_type(BasicType type)893 JVMCIObject JVMCIEnv::get_jvmci_primitive_type(BasicType type) {
894 JVMCIObjectArray primitives = get_HotSpotResolvedPrimitiveType_primitives();
895 JVMCIObject result = get_object_at(primitives, type);
896 return result;
897 }
898
new_StackTraceElement(const methodHandle & method,int bci,JVMCI_TRAPS)899 JVMCIObject JVMCIEnv::new_StackTraceElement(const methodHandle& method, int bci, JVMCI_TRAPS) {
900 JavaThread* THREAD = JavaThread::current();
901 Symbol* file_name_sym;
902 int line_number;
903 java_lang_StackTraceElement::decode(method, bci, file_name_sym, line_number, CHECK_(JVMCIObject()));
904
905 Symbol* method_name_sym = method->name();
906 InstanceKlass* holder = method->method_holder();
907 const char* declaring_class_str = holder->external_name();
908
909 if (is_hotspot()) {
910 HotSpotJVMCI::StackTraceElement::klass()->initialize(CHECK_(JVMCIObject()));
911 oop objOop = HotSpotJVMCI::StackTraceElement::klass()->allocate_instance(CHECK_(JVMCIObject()));
912 Handle obj = Handle(THREAD, objOop);
913
914 oop declaring_class = StringTable::intern((char*) declaring_class_str, CHECK_(JVMCIObject()));
915 HotSpotJVMCI::StackTraceElement::set_declaringClass(this, obj(), declaring_class);
916
917 oop method_name = StringTable::intern(method_name_sym, CHECK_(JVMCIObject()));
918 HotSpotJVMCI::StackTraceElement::set_methodName(this, obj(), method_name);
919
920 if (file_name_sym != NULL) {
921 oop file_name = StringTable::intern(file_name_sym, CHECK_(JVMCIObject()));
922 HotSpotJVMCI::StackTraceElement::set_fileName(this, obj(), file_name);
923 }
924 HotSpotJVMCI::StackTraceElement::set_lineNumber(this, obj(), line_number);
925 return wrap(obj());
926 } else {
927 JNIAccessMark jni(this);
928 jobject declaring_class = jni()->NewStringUTF(declaring_class_str);
929 if (jni()->ExceptionCheck()) {
930 return JVMCIObject();
931 }
932 jobject method_name = jni()->NewStringUTF(method_name_sym->as_C_string());
933 if (jni()->ExceptionCheck()) {
934 return JVMCIObject();
935 }
936 jobject file_name = NULL;
937 if (file_name_sym != NULL) {
938 file_name = jni()->NewStringUTF(file_name_sym->as_C_string());
939 if (jni()->ExceptionCheck()) {
940 return JVMCIObject();
941 }
942 }
943
944 jobject result = jni()->NewObject(JNIJVMCI::StackTraceElement::clazz(),
945 JNIJVMCI::StackTraceElement::constructor(),
946 declaring_class, method_name, file_name, line_number);
947 return wrap(result);
948 }
949 }
950
new_HotSpotNmethod(const methodHandle & method,const char * name,jboolean isDefault,jlong compileId,JVMCI_TRAPS)951 JVMCIObject JVMCIEnv::new_HotSpotNmethod(const methodHandle& method, const char* name, jboolean isDefault, jlong compileId, JVMCI_TRAPS) {
952 JavaThread* THREAD = JavaThread::current();
953
954 JVMCIObject methodObject = get_jvmci_method(method, JVMCI_CHECK_(JVMCIObject()));
955
956 if (is_hotspot()) {
957 InstanceKlass* ik = InstanceKlass::cast(HotSpotJVMCI::HotSpotNmethod::klass());
958 if (ik->should_be_initialized()) {
959 ik->initialize(CHECK_(JVMCIObject()));
960 }
961 oop obj = ik->allocate_instance(CHECK_(JVMCIObject()));
962 Handle obj_h(THREAD, obj);
963 Handle nameStr = java_lang_String::create_from_str(name, CHECK_(JVMCIObject()));
964
965 // Call constructor
966 JavaCallArguments jargs;
967 jargs.push_oop(obj_h);
968 jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(methodObject)));
969 jargs.push_oop(nameStr);
970 jargs.push_int(isDefault);
971 jargs.push_long(compileId);
972 JavaValue result(T_VOID);
973 JavaCalls::call_special(&result, ik,
974 vmSymbols::object_initializer_name(),
975 vmSymbols::method_string_bool_long_signature(),
976 &jargs, CHECK_(JVMCIObject()));
977 return wrap(obj_h());
978 } else {
979 JNIAccessMark jni(this);
980 jobject nameStr = name == NULL ? NULL : jni()->NewStringUTF(name);
981 if (jni()->ExceptionCheck()) {
982 return JVMCIObject();
983 }
984
985 jobject result = jni()->NewObject(JNIJVMCI::HotSpotNmethod::clazz(),
986 JNIJVMCI::HotSpotNmethod::constructor(),
987 methodObject.as_jobject(), nameStr, isDefault);
988 return wrap(result);
989 }
990 }
991
make_local(JVMCIObject object)992 JVMCIObject JVMCIEnv::make_local(JVMCIObject object) {
993 if (object.is_null()) {
994 return JVMCIObject();
995 }
996 if (is_hotspot()) {
997 return wrap(JNIHandles::make_local(HotSpotJVMCI::resolve(object)));
998 } else {
999 JNIAccessMark jni(this);
1000 return wrap(jni()->NewLocalRef(object.as_jobject()));
1001 }
1002 }
1003
make_global(JVMCIObject object)1004 JVMCIObject JVMCIEnv::make_global(JVMCIObject object) {
1005 if (object.is_null()) {
1006 return JVMCIObject();
1007 }
1008 if (is_hotspot()) {
1009 return wrap(JNIHandles::make_global(Handle(Thread::current(), HotSpotJVMCI::resolve(object))));
1010 } else {
1011 JNIAccessMark jni(this);
1012 return wrap(jni()->NewGlobalRef(object.as_jobject()));
1013 }
1014 }
1015
make_weak(JVMCIObject object)1016 JVMCIObject JVMCIEnv::make_weak(JVMCIObject object) {
1017 if (object.is_null()) {
1018 return JVMCIObject();
1019 }
1020 if (is_hotspot()) {
1021 return wrap(JNIHandles::make_weak_global(Handle(Thread::current(), HotSpotJVMCI::resolve(object))));
1022 } else {
1023 JNIAccessMark jni(this);
1024 return wrap(jni()->NewWeakGlobalRef(object.as_jobject()));
1025 }
1026 }
1027
destroy_local(JVMCIObject object)1028 void JVMCIEnv::destroy_local(JVMCIObject object) {
1029 if (is_hotspot()) {
1030 JNIHandles::destroy_local(object.as_jobject());
1031 } else {
1032 JNIAccessMark jni(this);
1033 jni()->DeleteLocalRef(object.as_jobject());
1034 }
1035 }
1036
destroy_global(JVMCIObject object)1037 void JVMCIEnv::destroy_global(JVMCIObject object) {
1038 if (is_hotspot()) {
1039 JNIHandles::destroy_global(object.as_jobject());
1040 } else {
1041 JNIAccessMark jni(this);
1042 jni()->DeleteGlobalRef(object.as_jobject());
1043 }
1044 }
1045
destroy_weak(JVMCIObject object)1046 void JVMCIEnv::destroy_weak(JVMCIObject object) {
1047 if (is_hotspot()) {
1048 JNIHandles::destroy_weak_global(object.as_jweak());
1049 } else {
1050 JNIAccessMark jni(this);
1051 jni()->DeleteWeakGlobalRef(object.as_jweak());
1052 }
1053 }
1054
klass_name(JVMCIObject object)1055 const char* JVMCIEnv::klass_name(JVMCIObject object) {
1056 if (is_hotspot()) {
1057 return HotSpotJVMCI::resolve(object)->klass()->signature_name();
1058 } else {
1059 JVMCIObject name;
1060 {
1061 JNIAccessMark jni(this);
1062 jclass jcl = jni()->GetObjectClass(object.as_jobject());
1063 jobject result = jni()->CallObjectMethod(jcl, JNIJVMCI::Class_getName_method());
1064 name = JVMCIObject::create(result, is_hotspot());
1065 }
1066 return as_utf8_string(name);
1067 }
1068 }
1069
get_jvmci_method(const methodHandle & method,JVMCI_TRAPS)1070 JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS) {
1071 JVMCIObject method_object;
1072 if (method() == NULL) {
1073 return method_object;
1074 }
1075
1076 Thread* THREAD = Thread::current();
1077 jmetadata handle = JVMCI::allocate_handle(method);
1078 jboolean exception = false;
1079 if (is_hotspot()) {
1080 JavaValue result(T_OBJECT);
1081 JavaCallArguments args;
1082 args.push_long((jlong) handle);
1083 JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotResolvedJavaMethodImpl::klass(),
1084 vmSymbols::fromMetaspace_name(),
1085 vmSymbols::method_fromMetaspace_signature(), &args, THREAD);
1086 if (HAS_PENDING_EXCEPTION) {
1087 exception = true;
1088 } else {
1089 method_object = wrap((oop)result.get_jobject());
1090 }
1091 } else {
1092 JNIAccessMark jni(this);
1093 method_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedJavaMethodImpl::clazz(),
1094 JNIJVMCI::HotSpotResolvedJavaMethodImpl_fromMetaspace_method(),
1095 (jlong) handle));
1096 exception = jni()->ExceptionCheck();
1097 }
1098
1099 if (exception) {
1100 JVMCI::release_handle(handle);
1101 return JVMCIObject();
1102 }
1103
1104 assert(asMethod(method_object) == method(), "must be");
1105 if (get_HotSpotResolvedJavaMethodImpl_metadataHandle(method_object) != (jlong) handle) {
1106 JVMCI::release_handle(handle);
1107 }
1108 assert(!method_object.is_null(), "must be");
1109 return method_object;
1110 }
1111
get_jvmci_type(const JVMCIKlassHandle & klass,JVMCI_TRAPS)1112 JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS) {
1113 JVMCIObject type;
1114 if (klass.is_null()) {
1115 return type;
1116 }
1117
1118 jlong pointer = (jlong) klass();
1119 JavaThread* THREAD = JavaThread::current();
1120 JVMCIObject signature = create_string(klass->signature_name(), JVMCI_CHECK_(JVMCIObject()));
1121 jboolean exception = false;
1122 if (is_hotspot()) {
1123 JavaValue result(T_OBJECT);
1124 JavaCallArguments args;
1125 args.push_long(pointer);
1126 args.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(signature)));
1127 JavaCalls::call_static(&result,
1128 HotSpotJVMCI::HotSpotResolvedObjectTypeImpl::klass(),
1129 vmSymbols::fromMetaspace_name(),
1130 vmSymbols::klass_fromMetaspace_signature(), &args, THREAD);
1131
1132 if (HAS_PENDING_EXCEPTION) {
1133 exception = true;
1134 } else {
1135 type = wrap((oop)result.get_jobject());
1136 }
1137 } else {
1138 JNIAccessMark jni(this);
1139
1140 HandleMark hm(THREAD);
1141 type = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedObjectTypeImpl::clazz(),
1142 JNIJVMCI::HotSpotResolvedObjectTypeImpl_fromMetaspace_method(),
1143 pointer, signature.as_jstring()));
1144 exception = jni()->ExceptionCheck();
1145 }
1146 if (exception) {
1147 return JVMCIObject();
1148 }
1149
1150 assert(type.is_non_null(), "must have result");
1151 return type;
1152 }
1153
get_jvmci_constant_pool(const constantPoolHandle & cp,JVMCI_TRAPS)1154 JVMCIObject JVMCIEnv::get_jvmci_constant_pool(const constantPoolHandle& cp, JVMCI_TRAPS) {
1155 JVMCIObject cp_object;
1156 jmetadata handle = JVMCI::allocate_handle(cp);
1157 jboolean exception = false;
1158 if (is_hotspot()) {
1159 JavaThread* THREAD = JavaThread::current();
1160 JavaValue result(T_OBJECT);
1161 JavaCallArguments args;
1162 args.push_long((jlong) handle);
1163 JavaCalls::call_static(&result,
1164 HotSpotJVMCI::HotSpotConstantPool::klass(),
1165 vmSymbols::fromMetaspace_name(),
1166 vmSymbols::constantPool_fromMetaspace_signature(), &args, THREAD);
1167 if (HAS_PENDING_EXCEPTION) {
1168 exception = true;
1169 } else {
1170 cp_object = wrap((oop)result.get_jobject());
1171 }
1172 } else {
1173 JNIAccessMark jni(this);
1174 cp_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotConstantPool::clazz(),
1175 JNIJVMCI::HotSpotConstantPool_fromMetaspace_method(),
1176 (jlong) handle));
1177 exception = jni()->ExceptionCheck();
1178 }
1179
1180 if (exception) {
1181 JVMCI::release_handle(handle);
1182 return JVMCIObject();
1183 }
1184
1185 assert(!cp_object.is_null(), "must be");
1186 // Constant pools aren't cached so this is always a newly created object using the handle
1187 assert(get_HotSpotConstantPool_metadataHandle(cp_object) == (jlong) handle, "must use same handle");
1188 return cp_object;
1189 }
1190
new_booleanArray(int length,JVMCI_TRAPS)1191 JVMCIPrimitiveArray JVMCIEnv::new_booleanArray(int length, JVMCI_TRAPS) {
1192 if (is_hotspot()) {
1193 JavaThread* THREAD = JavaThread::current();
1194 typeArrayOop result = oopFactory::new_boolArray(length, CHECK_(JVMCIObject()));
1195 return wrap(result);
1196 } else {
1197 JNIAccessMark jni(this);
1198 jbooleanArray result = jni()->NewBooleanArray(length);
1199 return wrap(result);
1200 }
1201 }
1202
new_byteArray(int length,JVMCI_TRAPS)1203 JVMCIPrimitiveArray JVMCIEnv::new_byteArray(int length, JVMCI_TRAPS) {
1204 if (is_hotspot()) {
1205 JavaThread* THREAD = JavaThread::current();
1206 typeArrayOop result = oopFactory::new_byteArray(length, CHECK_(JVMCIObject()));
1207 return wrap(result);
1208 } else {
1209 JNIAccessMark jni(this);
1210 jbyteArray result = jni()->NewByteArray(length);
1211 return wrap(result);
1212 }
1213 }
1214
new_byte_array_array(int length,JVMCI_TRAPS)1215 JVMCIObjectArray JVMCIEnv::new_byte_array_array(int length, JVMCI_TRAPS) {
1216 if (is_hotspot()) {
1217 JavaThread* THREAD = JavaThread::current();
1218 Klass* byteArrayArrayKlass = TypeArrayKlass::cast(Universe::byteArrayKlassObj ())->array_klass(CHECK_(JVMCIObject()));
1219 objArrayOop result = ObjArrayKlass::cast(byteArrayArrayKlass) ->allocate(length, CHECK_(JVMCIObject()));
1220 return wrap(result);
1221 } else {
1222 JNIAccessMark jni(this);
1223 jobjectArray result = jni()->NewObjectArray(length, JNIJVMCI::byte_array(), NULL);
1224 return wrap(result);
1225 }
1226 }
1227
new_intArray(int length,JVMCI_TRAPS)1228 JVMCIPrimitiveArray JVMCIEnv::new_intArray(int length, JVMCI_TRAPS) {
1229 if (is_hotspot()) {
1230 JavaThread* THREAD = JavaThread::current();
1231 typeArrayOop result = oopFactory::new_intArray(length, CHECK_(JVMCIObject()));
1232 return wrap(result);
1233 } else {
1234 JNIAccessMark jni(this);
1235 jintArray result = jni()->NewIntArray(length);
1236 return wrap(result);
1237 }
1238 }
1239
new_longArray(int length,JVMCI_TRAPS)1240 JVMCIPrimitiveArray JVMCIEnv::new_longArray(int length, JVMCI_TRAPS) {
1241 if (is_hotspot()) {
1242 JavaThread* THREAD = JavaThread::current();
1243 typeArrayOop result = oopFactory::new_longArray(length, CHECK_(JVMCIObject()));
1244 return wrap(result);
1245 } else {
1246 JNIAccessMark jni(this);
1247 jlongArray result = jni()->NewLongArray(length);
1248 return wrap(result);
1249 }
1250 }
1251
new_VMField(JVMCIObject name,JVMCIObject type,jlong offset,jlong address,JVMCIObject value,JVMCI_TRAPS)1252 JVMCIObject JVMCIEnv::new_VMField(JVMCIObject name, JVMCIObject type, jlong offset, jlong address, JVMCIObject value, JVMCI_TRAPS) {
1253 if (is_hotspot()) {
1254 JavaThread* THREAD = JavaThread::current();
1255 HotSpotJVMCI::VMField::klass()->initialize(CHECK_(JVMCIObject()));
1256 oop obj = HotSpotJVMCI::VMField::klass()->allocate_instance(CHECK_(JVMCIObject()));
1257 HotSpotJVMCI::VMField::set_name(this, obj, HotSpotJVMCI::resolve(name));
1258 HotSpotJVMCI::VMField::set_type(this, obj, HotSpotJVMCI::resolve(type));
1259 HotSpotJVMCI::VMField::set_offset(this, obj, offset);
1260 HotSpotJVMCI::VMField::set_address(this, obj, address);
1261 HotSpotJVMCI::VMField::set_value(this, obj, HotSpotJVMCI::resolve(value));
1262 return wrap(obj);
1263 } else {
1264 JNIAccessMark jni(this);
1265 jobject result = jni()->NewObject(JNIJVMCI::VMField::clazz(),
1266 JNIJVMCI::VMField::constructor(),
1267 get_jobject(name), get_jobject(type), offset, address, get_jobject(value));
1268 return wrap(result);
1269 }
1270 }
1271
new_VMFlag(JVMCIObject name,JVMCIObject type,JVMCIObject value,JVMCI_TRAPS)1272 JVMCIObject JVMCIEnv::new_VMFlag(JVMCIObject name, JVMCIObject type, JVMCIObject value, JVMCI_TRAPS) {
1273 if (is_hotspot()) {
1274 JavaThread* THREAD = JavaThread::current();
1275 HotSpotJVMCI::VMFlag::klass()->initialize(CHECK_(JVMCIObject()));
1276 oop obj = HotSpotJVMCI::VMFlag::klass()->allocate_instance(CHECK_(JVMCIObject()));
1277 HotSpotJVMCI::VMFlag::set_name(this, obj, HotSpotJVMCI::resolve(name));
1278 HotSpotJVMCI::VMFlag::set_type(this, obj, HotSpotJVMCI::resolve(type));
1279 HotSpotJVMCI::VMFlag::set_value(this, obj, HotSpotJVMCI::resolve(value));
1280 return wrap(obj);
1281 } else {
1282 JNIAccessMark jni(this);
1283 jobject result = jni()->NewObject(JNIJVMCI::VMFlag::clazz(),
1284 JNIJVMCI::VMFlag::constructor(),
1285 get_jobject(name), get_jobject(type), get_jobject(value));
1286 return wrap(result);
1287 }
1288 }
1289
new_VMIntrinsicMethod(JVMCIObject declaringClass,JVMCIObject name,JVMCIObject descriptor,int id,JVMCI_TRAPS)1290 JVMCIObject JVMCIEnv::new_VMIntrinsicMethod(JVMCIObject declaringClass, JVMCIObject name, JVMCIObject descriptor, int id, JVMCI_TRAPS) {
1291 if (is_hotspot()) {
1292 JavaThread* THREAD = JavaThread::current();
1293 HotSpotJVMCI::VMIntrinsicMethod::klass()->initialize(CHECK_(JVMCIObject()));
1294 oop obj = HotSpotJVMCI::VMIntrinsicMethod::klass()->allocate_instance(CHECK_(JVMCIObject()));
1295 HotSpotJVMCI::VMIntrinsicMethod::set_declaringClass(this, obj, HotSpotJVMCI::resolve(declaringClass));
1296 HotSpotJVMCI::VMIntrinsicMethod::set_name(this, obj, HotSpotJVMCI::resolve(name));
1297 HotSpotJVMCI::VMIntrinsicMethod::set_descriptor(this, obj, HotSpotJVMCI::resolve(descriptor));
1298 HotSpotJVMCI::VMIntrinsicMethod::set_id(this, obj, id);
1299 return wrap(obj);
1300 } else {
1301 JNIAccessMark jni(this);
1302 jobject result = jni()->NewObject(JNIJVMCI::VMIntrinsicMethod::clazz(),
1303 JNIJVMCI::VMIntrinsicMethod::constructor(),
1304 get_jobject(declaringClass), get_jobject(name), get_jobject(descriptor), id);
1305 return wrap(result);
1306 }
1307 }
1308
new_HotSpotStackFrameReference(JVMCI_TRAPS)1309 JVMCIObject JVMCIEnv::new_HotSpotStackFrameReference(JVMCI_TRAPS) {
1310 if (is_hotspot()) {
1311 JavaThread* THREAD = JavaThread::current();
1312 HotSpotJVMCI::HotSpotStackFrameReference::klass()->initialize(CHECK_(JVMCIObject()));
1313 oop obj = HotSpotJVMCI::HotSpotStackFrameReference::klass()->allocate_instance(CHECK_(JVMCIObject()));
1314 return wrap(obj);
1315 } else {
1316 ShouldNotReachHere();
1317 return JVMCIObject();
1318 }
1319 }
new_JVMCIError(JVMCI_TRAPS)1320 JVMCIObject JVMCIEnv::new_JVMCIError(JVMCI_TRAPS) {
1321 if (is_hotspot()) {
1322 JavaThread* THREAD = JavaThread::current();
1323 HotSpotJVMCI::JVMCIError::klass()->initialize(CHECK_(JVMCIObject()));
1324 oop obj = HotSpotJVMCI::JVMCIError::klass()->allocate_instance(CHECK_(JVMCIObject()));
1325 return wrap(obj);
1326 } else {
1327 ShouldNotReachHere();
1328 return JVMCIObject();
1329 }
1330 }
1331
1332
get_object_constant(oop objOop,bool compressed,bool dont_register)1333 JVMCIObject JVMCIEnv::get_object_constant(oop objOop, bool compressed, bool dont_register) {
1334 JavaThread* THREAD = JavaThread::current();
1335 Handle obj = Handle(THREAD, objOop);
1336 if (obj.is_null()) {
1337 return JVMCIObject();
1338 }
1339 if (is_hotspot()) {
1340 HotSpotJVMCI::DirectHotSpotObjectConstantImpl::klass()->initialize(CHECK_(JVMCIObject()));
1341 oop constant = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::klass()->allocate_instance(CHECK_(JVMCIObject()));
1342 HotSpotJVMCI::DirectHotSpotObjectConstantImpl::set_object(this, constant, obj());
1343 HotSpotJVMCI::HotSpotObjectConstantImpl::set_compressed(this, constant, compressed);
1344 return wrap(constant);
1345 } else {
1346 jlong handle = make_handle(obj);
1347 JNIAccessMark jni(this);
1348 jobject result = jni()->NewObject(JNIJVMCI::IndirectHotSpotObjectConstantImpl::clazz(),
1349 JNIJVMCI::IndirectHotSpotObjectConstantImpl::constructor(),
1350 handle, compressed, dont_register);
1351 return wrap(result);
1352 }
1353 }
1354
1355
asConstant(JVMCIObject constant,JVMCI_TRAPS)1356 Handle JVMCIEnv::asConstant(JVMCIObject constant, JVMCI_TRAPS) {
1357 if (constant.is_null()) {
1358 return Handle();
1359 }
1360 JavaThread* THREAD = JavaThread::current();
1361 if (is_hotspot()) {
1362 assert(HotSpotJVMCI::DirectHotSpotObjectConstantImpl::is_instance(this, constant), "wrong type");
1363 oop obj = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::object(this, HotSpotJVMCI::resolve(constant));
1364 return Handle(THREAD, obj);
1365 } else if (isa_IndirectHotSpotObjectConstantImpl(constant)) {
1366 jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(constant);
1367 if (object_handle == 0L) {
1368 JVMCI_THROW_MSG_(NullPointerException, "Foreign object reference has been cleared", Handle());
1369 }
1370 oop result = resolve_handle(object_handle);
1371 if (result == NULL) {
1372 JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly NULL", Handle());
1373 }
1374 return Handle(THREAD, result);
1375 } else {
1376 JVMCI_THROW_MSG_(IllegalArgumentException, "DirectHotSpotObjectConstantImpl shouldn't reach JVMCI in SVM mode", Handle());
1377 }
1378 }
1379
wrap(jobject object)1380 JVMCIObject JVMCIEnv::wrap(jobject object) {
1381 return JVMCIObject::create(object, is_hotspot());
1382 }
1383
make_handle(const Handle & obj)1384 jlong JVMCIEnv::make_handle(const Handle& obj) {
1385 assert(!obj.is_null(), "should only create handle for non-NULL oops");
1386 jobject handle = JVMCI::make_global(obj);
1387 return (jlong) handle;
1388 }
1389
resolve_handle(jlong objectHandle)1390 oop JVMCIEnv::resolve_handle(jlong objectHandle) {
1391 assert(objectHandle != 0, "should be a valid handle");
1392 oop obj = *((oopDesc**)objectHandle);
1393 if (obj != NULL) {
1394 oopDesc::verify(obj);
1395 }
1396 return obj;
1397 }
1398
create_string(const char * str,JVMCI_TRAPS)1399 JVMCIObject JVMCIEnv::create_string(const char* str, JVMCI_TRAPS) {
1400 if (is_hotspot()) {
1401 JavaThread* THREAD = JavaThread::current();
1402 Handle result = java_lang_String::create_from_str(str, CHECK_(JVMCIObject()));
1403 return HotSpotJVMCI::wrap(result());
1404 } else {
1405 jobject result;
1406 jboolean exception = false;
1407 {
1408 JNIAccessMark jni(this);
1409 result = jni()->NewStringUTF(str);
1410 exception = jni()->ExceptionCheck();
1411 }
1412 return wrap(result);
1413 }
1414 }
1415
equals(JVMCIObject a,JVMCIObject b)1416 bool JVMCIEnv::equals(JVMCIObject a, JVMCIObject b) {
1417 if (is_hotspot()) {
1418 return HotSpotJVMCI::resolve(a) == HotSpotJVMCI::resolve(b);
1419 } else {
1420 JNIAccessMark jni(this);
1421 return jni()->IsSameObject(a.as_jobject(), b.as_jobject()) != 0;
1422 }
1423 }
1424
kindToBasicType(JVMCIObject kind,JVMCI_TRAPS)1425 BasicType JVMCIEnv::kindToBasicType(JVMCIObject kind, JVMCI_TRAPS) {
1426 if (kind.is_null()) {
1427 JVMCI_THROW_(NullPointerException, T_ILLEGAL);
1428 }
1429 jchar ch = get_JavaKind_typeChar(kind);
1430 switch(ch) {
1431 case 'Z': return T_BOOLEAN;
1432 case 'B': return T_BYTE;
1433 case 'S': return T_SHORT;
1434 case 'C': return T_CHAR;
1435 case 'I': return T_INT;
1436 case 'F': return T_FLOAT;
1437 case 'J': return T_LONG;
1438 case 'D': return T_DOUBLE;
1439 case 'A': return T_OBJECT;
1440 case '-': return T_ILLEGAL;
1441 default:
1442 JVMCI_ERROR_(T_ILLEGAL, "unexpected Kind: %c", ch);
1443 }
1444 }
1445
initialize_installed_code(JVMCIObject installed_code,CodeBlob * cb,JVMCI_TRAPS)1446 void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* cb, JVMCI_TRAPS) {
1447 // Ensure that all updates to the InstalledCode fields are consistent.
1448 if (get_InstalledCode_address(installed_code) != 0) {
1449 JVMCI_THROW_MSG(InternalError, "InstalledCode instance already in use");
1450 }
1451 if (!isa_HotSpotInstalledCode(installed_code)) {
1452 JVMCI_THROW_MSG(InternalError, "InstalledCode instance must be a subclass of HotSpotInstalledCode");
1453 }
1454
1455 // Ignore the version which can stay at 0
1456 if (cb->is_nmethod()) {
1457 nmethod* nm = cb->as_nmethod_or_null();
1458 if (!nm->is_alive()) {
1459 JVMCI_THROW_MSG(InternalError, "nmethod has been reclaimed");
1460 }
1461 if (nm->is_in_use()) {
1462 set_InstalledCode_entryPoint(installed_code, (jlong) nm->verified_entry_point());
1463 }
1464 } else {
1465 set_InstalledCode_entryPoint(installed_code, (jlong) cb->code_begin());
1466 }
1467 set_InstalledCode_address(installed_code, (jlong) cb);
1468 set_HotSpotInstalledCode_size(installed_code, cb->size());
1469 set_HotSpotInstalledCode_codeStart(installed_code, (jlong) cb->code_begin());
1470 set_HotSpotInstalledCode_codeSize(installed_code, cb->code_size());
1471 }
1472
1473
invalidate_nmethod_mirror(JVMCIObject mirror,JVMCI_TRAPS)1474 void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, JVMCI_TRAPS) {
1475 if (mirror.is_null()) {
1476 JVMCI_THROW(NullPointerException);
1477 }
1478
1479 nmethodLocker locker;
1480 nmethod* nm = JVMCIENV->get_nmethod(mirror, locker);
1481 if (nm == NULL) {
1482 // Nothing to do
1483 return;
1484 }
1485
1486 Thread* THREAD = Thread::current();
1487 if (!mirror.is_hotspot() && !THREAD->is_Java_thread()) {
1488 // Calling back into native might cause the execution to block, so only allow this when calling
1489 // from a JavaThread, which is the normal case anyway.
1490 JVMCI_THROW_MSG(IllegalArgumentException,
1491 "Cannot invalidate HotSpotNmethod object in shared library VM heap from non-JavaThread");
1492 }
1493
1494 nmethodLocker nml(nm);
1495 if (nm->is_alive()) {
1496 // Invalidating the HotSpotNmethod means we want the nmethod to be deoptimized.
1497 Deoptimization::deoptimize_all_marked(nm);
1498 }
1499
1500 // A HotSpotNmethod instance can only reference a single nmethod
1501 // during its lifetime so simply clear it here.
1502 set_InstalledCode_address(mirror, 0);
1503 }
1504
asKlass(JVMCIObject obj)1505 Klass* JVMCIEnv::asKlass(JVMCIObject obj) {
1506 return (Klass*) get_HotSpotResolvedObjectTypeImpl_metadataPointer(obj);
1507 }
1508
asMethod(JVMCIObject obj)1509 Method* JVMCIEnv::asMethod(JVMCIObject obj) {
1510 Method** metadataHandle = (Method**) get_HotSpotResolvedJavaMethodImpl_metadataHandle(obj);
1511 return *metadataHandle;
1512 }
1513
asConstantPool(JVMCIObject obj)1514 ConstantPool* JVMCIEnv::asConstantPool(JVMCIObject obj) {
1515 ConstantPool** metadataHandle = (ConstantPool**) get_HotSpotConstantPool_metadataHandle(obj);
1516 return *metadataHandle;
1517 }
1518
get_code_blob(JVMCIObject obj,nmethodLocker & locker)1519 CodeBlob* JVMCIEnv::get_code_blob(JVMCIObject obj, nmethodLocker& locker) {
1520 address code = (address) get_InstalledCode_address(obj);
1521 if (code == NULL) {
1522 return NULL;
1523 }
1524 if (isa_HotSpotNmethod(obj)) {
1525 nmethod* nm = NULL;
1526 {
1527 // Lookup the CodeBlob while holding the CodeCache_lock to ensure the nmethod can't be freed
1528 // by nmethod::flush while we're interrogating it.
1529 MutexLocker cm_lock(CodeCache_lock, Mutex::_no_safepoint_check_flag);
1530 CodeBlob* cb = CodeCache::find_blob_unsafe(code);
1531 if (cb == (CodeBlob*) code) {
1532 nmethod* the_nm = cb->as_nmethod_or_null();
1533 if (the_nm != NULL && the_nm->is_alive()) {
1534 // Lock the nmethod to stop any further transitions by the sweeper. It's still possible
1535 // for this code to execute in the middle of the sweeping of the nmethod but that will be
1536 // handled below.
1537 locker.set_code(nm, true);
1538 nm = the_nm;
1539 }
1540 }
1541 }
1542
1543 if (nm != NULL) {
1544 // We found the nmethod but it could be in the process of being freed. Check the state of the
1545 // nmethod while holding the CompiledMethod_lock. This ensures that any transitions by other
1546 // threads have seen the is_locked_by_vm() update above.
1547 MutexLocker cm_lock(CompiledMethod_lock, Mutex::_no_safepoint_check_flag);
1548 if (!nm->is_alive()) {
1549 // It was alive when we looked it up but it's no longer alive so release it.
1550 locker.set_code(NULL);
1551 nm = NULL;
1552 }
1553 }
1554
1555 jlong compile_id_snapshot = get_HotSpotNmethod_compileIdSnapshot(obj);
1556 if (compile_id_snapshot != 0L) {
1557 // Found a live nmethod with the same address, make sure it's the same nmethod
1558 if (nm == (nmethod*) code && nm->compile_id() == compile_id_snapshot && nm->is_alive()) {
1559 if (nm->is_not_entrant()) {
1560 // Zero the entry point so that the nmethod
1561 // cannot be invoked by the mirror but can
1562 // still be deoptimized.
1563 set_InstalledCode_entryPoint(obj, 0);
1564 }
1565 return nm;
1566 }
1567 // The HotSpotNmethod no longer refers to a valid nmethod so clear the state
1568 locker.set_code(NULL);
1569 nm = NULL;
1570 }
1571
1572 if (nm == NULL) {
1573 // The HotSpotNmethod was pointing at some nmethod but the nmethod is no longer valid, so
1574 // clear the InstalledCode fields of this HotSpotNmethod so that it no longer refers to a
1575 // nmethod in the code cache.
1576 set_InstalledCode_address(obj, 0);
1577 set_InstalledCode_entryPoint(obj, 0);
1578 }
1579 return nm;
1580 }
1581
1582 CodeBlob* cb = (CodeBlob*) code;
1583 assert(!cb->is_nmethod(), "unexpected nmethod");
1584 return cb;
1585 }
1586
get_nmethod(JVMCIObject obj,nmethodLocker & locker)1587 nmethod* JVMCIEnv::get_nmethod(JVMCIObject obj, nmethodLocker& locker) {
1588 CodeBlob* cb = get_code_blob(obj, locker);
1589 if (cb != NULL) {
1590 return cb->as_nmethod_or_null();
1591 }
1592 return NULL;
1593 }
1594
1595 // Generate implementations for the initialize, new, isa, get and set methods for all the types and
1596 // fields declared in the JVMCI_CLASSES_DO macro.
1597
1598 #define START_CLASS(className, fullClassName) \
1599 void JVMCIEnv::className##_initialize(JVMCI_TRAPS) { \
1600 if (is_hotspot()) { \
1601 HotSpotJVMCI::className::initialize(JVMCI_CHECK); \
1602 } else { \
1603 JNIJVMCI::className::initialize(JVMCI_CHECK); \
1604 } \
1605 } \
1606 JVMCIObjectArray JVMCIEnv::new_##className##_array(int length, JVMCI_TRAPS) { \
1607 if (is_hotspot()) { \
1608 Thread* THREAD = Thread::current(); \
1609 objArrayOop array = oopFactory::new_objArray(HotSpotJVMCI::className::klass(), length, CHECK_(JVMCIObject())); \
1610 return (JVMCIObjectArray) wrap(array); \
1611 } else { \
1612 JNIAccessMark jni(this); \
1613 jobjectArray result = jni()->NewObjectArray(length, JNIJVMCI::className::clazz(), NULL); \
1614 return wrap(result); \
1615 } \
1616 } \
1617 bool JVMCIEnv::isa_##className(JVMCIObject object) { \
1618 if (is_hotspot()) { \
1619 return HotSpotJVMCI::className::is_instance(this, object); \
1620 } else { \
1621 return JNIJVMCI::className::is_instance(this, object); \
1622 } \
1623 }
1624
1625 #define END_CLASS
1626
1627 #define FIELD(className, name, type, accessor, cast) \
1628 type JVMCIEnv::get_##className##_##name(JVMCIObject obj) { \
1629 if (is_hotspot()) { \
1630 return HotSpotJVMCI::className::get_##name(this, obj); \
1631 } else { \
1632 return JNIJVMCI::className::get_##name(this, obj); \
1633 } \
1634 } \
1635 void JVMCIEnv::set_##className##_##name(JVMCIObject obj, type x) { \
1636 if (is_hotspot()) { \
1637 HotSpotJVMCI::className::set_##name(this, obj, x); \
1638 } else { \
1639 JNIJVMCI::className::set_##name(this, obj, x); \
1640 } \
1641 }
1642
1643 #define EMPTY_CAST
1644 #define CHAR_FIELD(className, name) FIELD(className, name, jchar, Char, EMPTY_CAST)
1645 #define INT_FIELD(className, name) FIELD(className, name, jint, Int, EMPTY_CAST)
1646 #define BOOLEAN_FIELD(className, name) FIELD(className, name, jboolean, Boolean, EMPTY_CAST)
1647 #define LONG_FIELD(className, name) FIELD(className, name, jlong, Long, EMPTY_CAST)
1648 #define FLOAT_FIELD(className, name) FIELD(className, name, jfloat, Float, EMPTY_CAST)
1649
1650 #define OBJECT_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIObject, Object, EMPTY_CAST)
1651 #define OBJECTARRAY_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray))
1652 #define PRIMARRAY_FIELD(className, name, signature) OOPISH_FIELD(className, name, JVMCIPrimitiveArray, Object, (JVMCIPrimitiveArray))
1653
1654 #define STATIC_OBJECT_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObject, Object, (JVMCIObject))
1655 #define STATIC_OBJECTARRAY_FIELD(className, name, signature) STATIC_OOPISH_FIELD(className, name, JVMCIObjectArray, Object, (JVMCIObjectArray))
1656
1657 #define OOPISH_FIELD(className, name, type, accessor, cast) \
1658 type JVMCIEnv::get_##className##_##name(JVMCIObject obj) { \
1659 if (is_hotspot()) { \
1660 return HotSpotJVMCI::className::get_##name(this, obj); \
1661 } else { \
1662 return JNIJVMCI::className::get_##name(this, obj); \
1663 } \
1664 } \
1665 void JVMCIEnv::set_##className##_##name(JVMCIObject obj, type x) { \
1666 if (is_hotspot()) { \
1667 HotSpotJVMCI::className::set_##name(this, obj, x); \
1668 } else { \
1669 JNIJVMCI::className::set_##name(this, obj, x); \
1670 } \
1671 }
1672
1673 #define STATIC_OOPISH_FIELD(className, name, type, accessor, cast) \
1674 type JVMCIEnv::get_##className##_##name() { \
1675 if (is_hotspot()) { \
1676 return HotSpotJVMCI::className::get_##name(this); \
1677 } else { \
1678 return JNIJVMCI::className::get_##name(this); \
1679 } \
1680 } \
1681 void JVMCIEnv::set_##className##_##name(type x) { \
1682 if (is_hotspot()) { \
1683 HotSpotJVMCI::className::set_##name(this, x); \
1684 } else { \
1685 JNIJVMCI::className::set_##name(this, x); \
1686 } \
1687 }
1688
1689 #define STATIC_PRIMITIVE_FIELD(className, name, type, accessor, cast) \
1690 type JVMCIEnv::get_##className##_##name() { \
1691 if (is_hotspot()) { \
1692 return HotSpotJVMCI::className::get_##name(this); \
1693 } else { \
1694 return JNIJVMCI::className::get_##name(this); \
1695 } \
1696 } \
1697 void JVMCIEnv::set_##className##_##name(type x) { \
1698 if (is_hotspot()) { \
1699 HotSpotJVMCI::className::set_##name(this, x); \
1700 } else { \
1701 JNIJVMCI::className::set_##name(this, x); \
1702 } \
1703 }
1704 #define STATIC_INT_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jint, Int, EMPTY_CAST)
1705 #define STATIC_BOOLEAN_FIELD(className, name) STATIC_PRIMITIVE_FIELD(className, name, jboolean, Boolean, EMPTY_CAST)
1706 #define METHOD(jniCallType, jniGetMethod, hsCallType, returnType, className, methodName, signatureSymbolName, args)
1707 #define CONSTRUCTOR(className, signature)
1708
1709 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)
1710
1711 #undef START_CLASS
1712 #undef END_CLASS
1713 #undef METHOD
1714 #undef CONSTRUCTOR
1715 #undef FIELD
1716 #undef CHAR_FIELD
1717 #undef INT_FIELD
1718 #undef BOOLEAN_FIELD
1719 #undef LONG_FIELD
1720 #undef FLOAT_FIELD
1721 #undef OBJECT_FIELD
1722 #undef PRIMARRAY_FIELD
1723 #undef OBJECTARRAY_FIELD
1724 #undef STATIC_OOPISH_FIELD
1725 #undef STATIC_OBJECT_FIELD
1726 #undef STATIC_OBJECTARRAY_FIELD
1727 #undef STATIC_INT_FIELD
1728 #undef STATIC_BOOLEAN_FIELD
1729 #undef EMPTY_CAST
1730