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