80 thread->set_active_handles(compile_handles); 81 } 82 } 83 84 void JNIHandleMark::pop_jni_handle_block(JavaThread* thread) { 85 if (thread != NULL) { 86 // Release our JNI handle block 87 JNIHandleBlock* compile_handles = thread->active_handles(); 88 JNIHandleBlock* java_handles = compile_handles->pop_frame_link(); 89 thread->set_active_handles(java_handles); 90 compile_handles->set_pop_frame_link(NULL); 91 JNIHandleBlock::release_block(compile_handles, thread); // may block 92 } 93 } 94 95 class JVMCITraceMark : public StackObj { 96 const char* _msg; 97 public: 98 JVMCITraceMark(const char* msg) { 99 _msg = msg; 100 if (JVMCITraceLevel >= 1) { 101 tty->print_cr(PTR_FORMAT " JVMCITrace-1: Enter %s", p2i(JavaThread::current()), _msg); 102 } 103 } 104 ~JVMCITraceMark() { 105 if (JVMCITraceLevel >= 1) { 106 tty->print_cr(PTR_FORMAT " JVMCITrace-1: Exit %s", p2i(JavaThread::current()), _msg); 107 } 108 } 109 }; 110 111 112 Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) { 113 assert(_index < _args->length(), "out of bounds"); 114 oop arg=((objArrayOop) (_args))->obj_at(_index++); 115 assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch"); 116 return Handle(Thread::current(), arg); 117 } 118 119 // Bring the JVMCI compiler thread into the VM state. 120 #define JVMCI_VM_ENTRY_MARK \ 121 ThreadInVMfromNative __tiv(thread); \ 122 ResetNoHandleMark rnhm; \ 123 HandleMarkCleaner __hm(thread); \ 124 Thread* THREAD = thread; \ 125 debug_only(VMNativeEntryWrapper __vew;) 126 127 // Native method block that transitions current thread to '_thread_in_vm'. 128 #define C2V_BLOCK(result_type, name, signature) \ 129 TRACE_CALL(result_type, jvmci_ ## name signature) \ 130 JVMCI_VM_ENTRY_MARK; \ 131 ResourceMark rm; \ 132 JNI_JVMCIENV(thread, env); 133 134 static Thread* get_current_thread() { 135 return Thread::current_or_null_safe(); 136 } 137 138 // Entry to native method implementation that transitions 139 // current thread to '_thread_in_vm'. 140 #define C2V_VMENTRY(result_type, name, signature) \ 141 JNIEXPORT result_type JNICALL c2v_ ## name signature { \ 142 Thread* base_thread = get_current_thread(); \ 143 if (base_thread == NULL) { \ 144 env->ThrowNew(JNIJVMCI::InternalError::clazz(), \ 145 err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \ 146 return; \ 147 } \ 148 assert(base_thread->is_Java_thread(), "just checking");\ 149 JavaThread* thread = (JavaThread*) base_thread; \ 150 JVMCITraceMark jtm("CompilerToVM::" #name); \ 151 C2V_BLOCK(result_type, name, signature) 152 153 #define C2V_VMENTRY_(result_type, name, signature, result) \ 154 JNIEXPORT result_type JNICALL c2v_ ## name signature { \ 155 Thread* base_thread = get_current_thread(); \ 156 if (base_thread == NULL) { \ 157 env->ThrowNew(JNIJVMCI::InternalError::clazz(), \ 158 err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \ 159 return result; \ 160 } \ 161 assert(base_thread->is_Java_thread(), "just checking");\ 162 JavaThread* thread = (JavaThread*) base_thread; \ 163 JVMCITraceMark jtm("CompilerToVM::" #name); \ 164 C2V_BLOCK(result_type, name, signature) 165 166 #define C2V_VMENTRY_NULL(result_type, name, signature) C2V_VMENTRY_(result_type, name, signature, NULL) 167 #define C2V_VMENTRY_0(result_type, name, signature) C2V_VMENTRY_(result_type, name, signature, 0) 168 169 // Entry to native method implementation that does not transition 170 // current thread to '_thread_in_vm'. 171 #define C2V_VMENTRY_PREFIX(result_type, name, signature) \ 172 JNIEXPORT result_type JNICALL c2v_ ## name signature { \ 173 Thread* base_thread = get_current_thread(); 174 175 #define C2V_END } 176 177 #define JNI_THROW(caller, name, msg) do { \ 178 jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg); \ 179 if (__throw_res != JNI_OK) { \ 180 tty->print_cr("Throwing " #name " in " caller " returned %d", __throw_res); \ 181 } \ 182 return; \ 183 } while (0); 184 185 #define JNI_THROW_(caller, name, msg, result) do { \ 186 jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg); \ 187 if (__throw_res != JNI_OK) { \ 188 tty->print_cr("Throwing " #name " in " caller " returned %d", __throw_res); \ 189 } \ 190 return result; \ 191 } while (0) 192 193 jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS); 1557 // all locals are materialized by now 1558 JVMCIENV->set_HotSpotStackFrameReference_localIsVirtual(hs_frame, NULL); 1559 // update the locals array 1560 JVMCIObjectArray array = JVMCIENV->get_HotSpotStackFrameReference_locals(hs_frame); 1561 StackValueCollection* locals = virtualFrames->at(last_frame_number)->locals(); 1562 for (int i = 0; i < locals->size(); i++) { 1563 StackValue* var = locals->at(i); 1564 if (var->type() == T_OBJECT) { 1565 JVMCIENV->put_object_at(array, i, HotSpotJVMCI::wrap(locals->at(i)->get_obj()())); 1566 } 1567 } 1568 HotSpotJVMCI::HotSpotStackFrameReference::set_objectsMaterialized(JVMCIENV, hs_frame, JNI_TRUE); 1569 C2V_END 1570 1571 // Creates a scope where the current thread is attached and detached 1572 // from HotSpot if it wasn't already attached when entering the scope. 1573 extern "C" void jio_printf(const char *fmt, ...); 1574 class AttachDetach : public StackObj { 1575 public: 1576 bool _attached; 1577 AttachDetach(JNIEnv* env, Thread* current_thread) { 1578 if (current_thread == NULL) { 1579 extern struct JavaVM_ main_vm; 1580 JNIEnv* hotspotEnv; 1581 jint res = main_vm.AttachCurrentThread((void**)&hotspotEnv, NULL); 1582 _attached = res == JNI_OK; 1583 static volatile int report_attach_error = 0; 1584 if (res != JNI_OK && report_attach_error == 0 && Atomic::cmpxchg(1, &report_attach_error, 0) == 0) { 1585 // Only report an attach error once 1586 jio_printf("Warning: attaching current thread to VM failed with %d (future attach errors are suppressed)\n", res); 1587 } 1588 } else { 1589 _attached = false; 1590 } 1591 } 1592 ~AttachDetach() { 1593 if (_attached && get_current_thread() != NULL) { 1594 extern struct JavaVM_ main_vm; 1595 jint res = main_vm.DetachCurrentThread(); 1596 static volatile int report_detach_error = 0; 1597 if (res != JNI_OK && report_detach_error == 0 && Atomic::cmpxchg(1, &report_detach_error, 0) == 0) { 1598 // Only report an attach error once 1599 jio_printf("Warning: detaching current thread from VM failed with %d (future attach errors are suppressed)\n", res); 1600 } 1601 } 1602 } 1603 }; 1604 1605 C2V_VMENTRY_PREFIX(jint, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length, bool flush, bool can_throw)) 1606 AttachDetach ad(env, base_thread); 1607 bool use_tty = true; 1608 if (base_thread == NULL) { 1609 if (!ad._attached) { 1610 // Can only use tty if the current thread is attached 1611 return 0; 1612 } 1613 base_thread = get_current_thread(); 1614 } 1615 JVMCITraceMark jtm("writeDebugOutput"); 1616 assert(base_thread->is_Java_thread(), "just checking"); 1617 JavaThread* thread = (JavaThread*) base_thread; 1618 C2V_BLOCK(void, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length)) 1619 if (bytes == NULL) { 1620 if (can_throw) { 1621 JVMCI_THROW_0(NullPointerException); 1622 } 1623 return -1; 1624 } 1625 JVMCIPrimitiveArray array = JVMCIENV->wrap(bytes); 1626 1627 // Check if offset and length are non negative. 1628 if (offset < 0 || length < 0) { 1629 if (can_throw) { 1630 JVMCI_THROW_0(ArrayIndexOutOfBoundsException); 1631 } 1632 return -2; 1633 } 1634 // Check if the range is valid. 1635 int array_length = JVMCIENV->get_length(array); 1636 if ((((unsigned int) length + (unsigned int) offset) > (unsigned int) array_length)) { 1637 if (can_throw) { 2193 if (x == NULL) { 2194 JVMCI_THROW_0(NullPointerException); 2195 } 2196 Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0); 2197 return xobj->long_field(displacement); 2198 } 2199 2200 C2V_VMENTRY_NULL(jobject, getObject, (JNIEnv* env, jobject, jobject x, long displacement)) 2201 if (x == NULL) { 2202 JVMCI_THROW_0(NullPointerException); 2203 } 2204 Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0); 2205 oop res = xobj->obj_field(displacement); 2206 JVMCIObject result = JVMCIENV->get_object_constant(res); 2207 return JVMCIENV->get_jobject(result); 2208 } 2209 2210 C2V_VMENTRY(void, deleteGlobalHandle, (JNIEnv* env, jobject, jlong h)) 2211 jobject handle = (jobject)(address)h; 2212 if (handle != NULL) { 2213 JVMCI::destroy_global(handle); 2214 } 2215 } 2216 2217 static void requireJVMCINativeLibrary(JVMCI_TRAPS) { 2218 if (!UseJVMCINativeLibrary) { 2219 JVMCI_THROW_MSG(UnsupportedOperationException, "JVMCI shared library is not enabled (requires -XX:+UseJVMCINativeLibrary)"); 2220 } 2221 } 2222 2223 static JavaVM* requireNativeLibraryJavaVM(const char* caller, JVMCI_TRAPS) { 2224 JavaVM* javaVM = JVMCIEnv::get_shared_library_javavm(); 2225 if (javaVM == NULL) { 2226 JVMCI_THROW_MSG_NULL(IllegalStateException, err_msg("Require JVMCI shared library to be initialized in %s", caller)); 2227 } 2228 return javaVM; 2229 } 2230 2231 C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclass mirror)) 2232 requireJVMCINativeLibrary(JVMCI_CHECK_NULL); 2233 requireInHotSpot("registerNativeMethods", JVMCI_CHECK_NULL); 2234 void* shared_library = JVMCIEnv::get_shared_library_handle(); 2235 if (shared_library == NULL) { 2236 // Ensure the JVMCI shared library runtime is initialized. 2237 JVMCIEnv __peer_jvmci_env__(thread, false, __FILE__, __LINE__); 2238 JVMCIEnv* peerEnv = &__peer_jvmci_env__; 2239 HandleMark hm; 2240 JVMCIRuntime* runtime = JVMCI::compiler_runtime(); 2241 JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(peerEnv); 2242 if (peerEnv->has_pending_exception()) { 2243 peerEnv->describe_pending_exception(true); 2244 } 2245 shared_library = JVMCIEnv::get_shared_library_handle(); 2246 if (shared_library == NULL) { 2247 JVMCI_THROW_MSG_0(InternalError, "Error initializing JVMCI runtime"); 2248 } 2249 } 2250 2251 if (mirror == NULL) { 2252 JVMCI_THROW_0(NullPointerException); 2253 } 2254 Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve(mirror)); 2255 if (klass == NULL || !klass->is_instance_klass()) { 2256 JVMCI_THROW_MSG_0(IllegalArgumentException, "clazz is for primitive type"); 2257 } 2258 2259 InstanceKlass* iklass = InstanceKlass::cast(klass); 2260 for (int i = 0; i < iklass->methods()->length(); i++) { 2261 Method* method = iklass->methods()->at(i); 2262 if (method->is_native()) { 2263 2264 // Compute argument size 2265 int args_size = 1 // JNIEnv 2266 + (method->is_static() ? 1 : 0) // class for static methods 2267 + method->size_of_parameters(); // actual parameters 2268 2269 // 1) Try JNI short style 2270 stringStream st; 2271 char* pure_name = NativeLookup::pure_jni_name(method); 2272 os::print_jni_name_prefix_on(&st, args_size); 2273 st.print_raw(pure_name); 2274 os::print_jni_name_suffix_on(&st, args_size); 2275 char* jni_name = st.as_string(); 2276 2277 address entry = (address) os::dll_lookup(shared_library, jni_name); 2278 if (entry == NULL) { 2279 // 2) Try JNI long style 2280 st.reset(); 2281 char* long_name = NativeLookup::long_jni_name(method); 2282 os::print_jni_name_prefix_on(&st, args_size); 2283 st.print_raw(pure_name); 2284 st.print_raw(long_name); 2285 os::print_jni_name_suffix_on(&st, args_size); 2286 char* jni_long_name = st.as_string(); 2287 entry = (address) os::dll_lookup(shared_library, jni_long_name); 2288 if (entry == NULL) { 2289 JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("%s [neither %s nor %s exist in %s]", 2290 method->name_and_sig_as_C_string(), 2291 jni_name, jni_long_name, JVMCIEnv::get_shared_library_path())); 2292 } 2293 } 2294 2295 if (method->has_native_function() && entry != method->native_function()) { 2296 JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("%s [cannot re-link from " PTR_FORMAT " to " PTR_FORMAT "]", 2297 method->name_and_sig_as_C_string(), p2i(method->native_function()), p2i(entry))); 2298 } 2299 method->set_native_function(entry, Method::native_bind_event_is_interesting); 2300 if (PrintJNIResolving) { 2301 tty->print_cr("[Dynamic-linking native method %s.%s ... JNI]", 2302 method->method_holder()->external_name(), 2303 method->name()->as_C_string()); 2304 } 2305 } 2306 } 2307 2308 JavaVM* javaVM = JVMCIEnv::get_shared_library_javavm(); 2309 JVMCIPrimitiveArray result = JVMCIENV->new_longArray(4, JVMCI_CHECK_NULL); 2310 JVMCIENV->put_long_at(result, 0, (jlong) (address) javaVM); 2311 JVMCIENV->put_long_at(result, 1, (jlong) (address) javaVM->functions->reserved0); 2312 JVMCIENV->put_long_at(result, 2, (jlong) (address) javaVM->functions->reserved1); 2313 JVMCIENV->put_long_at(result, 3, (jlong) (address) javaVM->functions->reserved2); 2314 return (jlongArray) JVMCIENV->get_jobject(result); 2315 } 2316 2317 C2V_VMENTRY_PREFIX(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject c2vm)) 2318 if (base_thread == NULL) { 2319 // Called from unattached JVMCI shared library thread 2320 return false; 2321 } 2322 JVMCITraceMark jtm("isCurrentThreadAttached"); 2323 assert(base_thread->is_Java_thread(), "just checking"); 2324 JavaThread* thread = (JavaThread*) base_thread; 2325 if (thread->jni_environment() == env) { 2326 C2V_BLOCK(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject)) 2327 requireJVMCINativeLibrary(JVMCI_CHECK_0); 2328 JavaVM* javaVM = requireNativeLibraryJavaVM("isCurrentThreadAttached", JVMCI_CHECK_0); 2329 JNIEnv* peerEnv; 2330 return javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) == JNI_OK; 2331 } 2332 return true; 2333 C2V_END 2334 2335 C2V_VMENTRY_PREFIX(jlong, getCurrentJavaThread, (JNIEnv* env, jobject c2vm)) 2336 if (base_thread == NULL) { 2337 // Called from unattached JVMCI shared library thread 2338 return 0L; 2339 } 2340 JVMCITraceMark jtm("getCurrentJavaThread"); 2341 assert(base_thread->is_Java_thread(), "just checking"); 2342 return (jlong) p2i(base_thread); 2343 C2V_END 2344 2345 C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jboolean as_daemon)) 2346 if (base_thread == NULL) { 2347 // Called from unattached JVMCI shared library thread 2348 extern struct JavaVM_ main_vm; 2349 JNIEnv* hotspotEnv; 2350 jint res = as_daemon ? main_vm.AttachCurrentThreadAsDaemon((void**)&hotspotEnv, NULL) : 2351 main_vm.AttachCurrentThread((void**)&hotspotEnv, NULL); 2352 if (res != JNI_OK) { 2353 JNI_THROW_("attachCurrentThread", InternalError, err_msg("Trying to attach thread returned %d", res), false); 2354 } 2355 return true; 2356 } 2357 JVMCITraceMark jtm("attachCurrentThread"); 2358 assert(base_thread->is_Java_thread(), "just checking");\ 2359 JavaThread* thread = (JavaThread*) base_thread; 2360 if (thread->jni_environment() == env) { 2361 // Called from HotSpot 2362 C2V_BLOCK(jboolean, attachCurrentThread, (JNIEnv* env, jobject, jboolean)) 2363 requireJVMCINativeLibrary(JVMCI_CHECK_0); 2364 JavaVM* javaVM = requireNativeLibraryJavaVM("attachCurrentThread", JVMCI_CHECK_0); 2365 JavaVMAttachArgs attach_args; 2366 attach_args.version = JNI_VERSION_1_2; 2367 attach_args.name = thread->name(); 2368 attach_args.group = NULL; 2369 JNIEnv* peerEnv; 2370 if (javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) == JNI_OK) { 2371 return false; 2372 } 2373 jint res = as_daemon ? javaVM->AttachCurrentThreadAsDaemon((void**)&peerEnv, &attach_args) : 2374 javaVM->AttachCurrentThread((void**)&peerEnv, &attach_args); 2375 if (res == JNI_OK) { 2376 guarantee(peerEnv != NULL, "must be"); 2377 return true; 2378 } 2379 JVMCI_THROW_MSG_0(InternalError, err_msg("Error %d while attaching %s", res, attach_args.name)); 2380 } 2381 // Called from JVMCI shared library 2382 return false; 2383 C2V_END 2384 2385 C2V_VMENTRY_PREFIX(void, detachCurrentThread, (JNIEnv* env, jobject c2vm)) 2386 if (base_thread == NULL) { 2387 // Called from unattached JVMCI shared library thread 2388 JNI_THROW("detachCurrentThread", IllegalStateException, err_msg("Cannot detach non-attached thread")); 2389 } 2390 JVMCITraceMark jtm("detachCurrentThread"); 2391 assert(base_thread->is_Java_thread(), "just checking");\ 2392 JavaThread* thread = (JavaThread*) base_thread; 2393 if (thread->jni_environment() == env) { 2394 // Called from HotSpot 2395 C2V_BLOCK(void, detachCurrentThread, (JNIEnv* env, jobject)) 2396 requireJVMCINativeLibrary(JVMCI_CHECK); 2397 requireInHotSpot("detachCurrentThread", JVMCI_CHECK); 2398 JavaVM* javaVM = requireNativeLibraryJavaVM("detachCurrentThread", JVMCI_CHECK); 2399 JNIEnv* peerEnv; 2400 if (javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) != JNI_OK) { 2401 JVMCI_THROW_MSG(IllegalStateException, err_msg("Cannot detach non-attached thread: %s", thread->name())); 2402 } 2403 jint res = javaVM->DetachCurrentThread(); 2404 if (res != JNI_OK) { 2405 JVMCI_THROW_MSG(InternalError, err_msg("Error %d while attaching %s", res, thread->name())); 2406 } 2407 } else { 2408 // Called from attached JVMCI shared library thread 2409 extern struct JavaVM_ main_vm; 2410 jint res = main_vm.DetachCurrentThread(); 2411 if (res != JNI_OK) { 2412 JNI_THROW("detachCurrentThread", InternalError, err_msg("Cannot detach non-attached thread")); 2413 } 2414 } 2415 C2V_END 2416 2417 C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle)) 2418 requireJVMCINativeLibrary(JVMCI_CHECK_0); 2419 if (obj_handle == NULL) { 2420 return 0L; 2421 } 2422 JVMCIEnv __peer_jvmci_env__(thread, !JVMCIENV->is_hotspot(), __FILE__, __LINE__); 2423 JVMCIEnv* peerEnv = &__peer_jvmci_env__; 2424 JVMCIEnv* thisEnv = JVMCIENV; 2425 2426 JVMCIObject obj = thisEnv->wrap(obj_handle); 2427 JVMCIObject result; 2428 if (thisEnv->isa_HotSpotResolvedJavaMethodImpl(obj)) { 2429 Method* method = thisEnv->asMethod(obj); 2430 result = peerEnv->get_jvmci_method(method, JVMCI_CHECK_0); 2431 } else if (thisEnv->isa_HotSpotResolvedObjectTypeImpl(obj)) { 2432 Klass* klass = thisEnv->asKlass(obj); | 80 thread->set_active_handles(compile_handles); 81 } 82 } 83 84 void JNIHandleMark::pop_jni_handle_block(JavaThread* thread) { 85 if (thread != NULL) { 86 // Release our JNI handle block 87 JNIHandleBlock* compile_handles = thread->active_handles(); 88 JNIHandleBlock* java_handles = compile_handles->pop_frame_link(); 89 thread->set_active_handles(java_handles); 90 compile_handles->set_pop_frame_link(NULL); 91 JNIHandleBlock::release_block(compile_handles, thread); // may block 92 } 93 } 94 95 class JVMCITraceMark : public StackObj { 96 const char* _msg; 97 public: 98 JVMCITraceMark(const char* msg) { 99 _msg = msg; 100 TRACE_jvmci_2("Enter %s", _msg); 101 } 102 ~JVMCITraceMark() { 103 TRACE_jvmci_2(" Exit %s", _msg); 104 } 105 }; 106 107 108 Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) { 109 assert(_index < _args->length(), "out of bounds"); 110 oop arg=((objArrayOop) (_args))->obj_at(_index++); 111 assert(expectedType == T_OBJECT || java_lang_boxing_object::is_instance(arg, expectedType), "arg type mismatch"); 112 return Handle(Thread::current(), arg); 113 } 114 115 // Bring the JVMCI compiler thread into the VM state. 116 #define JVMCI_VM_ENTRY_MARK \ 117 ThreadInVMfromNative __tiv(thread); \ 118 ResetNoHandleMark rnhm; \ 119 HandleMarkCleaner __hm(thread); \ 120 Thread* THREAD = thread; \ 121 debug_only(VMNativeEntryWrapper __vew;) 122 123 // Native method block that transitions current thread to '_thread_in_vm'. 124 #define C2V_BLOCK(result_type, name, signature) \ 125 TRACE_CALL(result_type, jvmci_ ## name signature) \ 126 JVMCI_VM_ENTRY_MARK; \ 127 ResourceMark rm; \ 128 JNI_JVMCIENV(thread, env); 129 130 static JavaThread* get_current_thread(bool allow_null=true) { 131 Thread* thread = Thread::current_or_null_safe(); 132 if (thread == NULL) { 133 assert(allow_null, "npe"); 134 return NULL; 135 } 136 assert(thread->is_Java_thread(), "must be"); 137 return (JavaThread*) thread; 138 } 139 140 // Entry to native method implementation that transitions 141 // current thread to '_thread_in_vm'. 142 #define C2V_VMENTRY(result_type, name, signature) \ 143 JNIEXPORT result_type JNICALL c2v_ ## name signature { \ 144 JavaThread* thread = get_current_thread(); \ 145 if (thread == NULL) { \ 146 env->ThrowNew(JNIJVMCI::InternalError::clazz(), \ 147 err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \ 148 return; \ 149 } \ 150 JVMCITraceMark jtm("CompilerToVM::" #name); \ 151 C2V_BLOCK(result_type, name, signature) 152 153 #define C2V_VMENTRY_(result_type, name, signature, result) \ 154 JNIEXPORT result_type JNICALL c2v_ ## name signature { \ 155 JavaThread* thread = get_current_thread(); \ 156 if (thread == NULL) { \ 157 env->ThrowNew(JNIJVMCI::InternalError::clazz(), \ 158 err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \ 159 return result; \ 160 } \ 161 JVMCITraceMark jtm("CompilerToVM::" #name); \ 162 C2V_BLOCK(result_type, name, signature) 163 164 #define C2V_VMENTRY_NULL(result_type, name, signature) C2V_VMENTRY_(result_type, name, signature, NULL) 165 #define C2V_VMENTRY_0(result_type, name, signature) C2V_VMENTRY_(result_type, name, signature, 0) 166 167 // Entry to native method implementation that does not transition 168 // current thread to '_thread_in_vm'. 169 #define C2V_VMENTRY_PREFIX(result_type, name, signature) \ 170 JNIEXPORT result_type JNICALL c2v_ ## name signature { \ 171 JavaThread* thread = get_current_thread(); 172 173 #define C2V_END } 174 175 #define JNI_THROW(caller, name, msg) do { \ 176 jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg); \ 177 if (__throw_res != JNI_OK) { \ 178 tty->print_cr("Throwing " #name " in " caller " returned %d", __throw_res); \ 179 } \ 180 return; \ 181 } while (0); 182 183 #define JNI_THROW_(caller, name, msg, result) do { \ 184 jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg); \ 185 if (__throw_res != JNI_OK) { \ 186 tty->print_cr("Throwing " #name " in " caller " returned %d", __throw_res); \ 187 } \ 188 return result; \ 189 } while (0) 190 191 jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS); 1555 // all locals are materialized by now 1556 JVMCIENV->set_HotSpotStackFrameReference_localIsVirtual(hs_frame, NULL); 1557 // update the locals array 1558 JVMCIObjectArray array = JVMCIENV->get_HotSpotStackFrameReference_locals(hs_frame); 1559 StackValueCollection* locals = virtualFrames->at(last_frame_number)->locals(); 1560 for (int i = 0; i < locals->size(); i++) { 1561 StackValue* var = locals->at(i); 1562 if (var->type() == T_OBJECT) { 1563 JVMCIENV->put_object_at(array, i, HotSpotJVMCI::wrap(locals->at(i)->get_obj()())); 1564 } 1565 } 1566 HotSpotJVMCI::HotSpotStackFrameReference::set_objectsMaterialized(JVMCIENV, hs_frame, JNI_TRUE); 1567 C2V_END 1568 1569 // Creates a scope where the current thread is attached and detached 1570 // from HotSpot if it wasn't already attached when entering the scope. 1571 extern "C" void jio_printf(const char *fmt, ...); 1572 class AttachDetach : public StackObj { 1573 public: 1574 bool _attached; 1575 AttachDetach(JNIEnv* env, JavaThread* current_thread) { 1576 if (current_thread == NULL) { 1577 extern struct JavaVM_ main_vm; 1578 JNIEnv* hotspotEnv; 1579 jint res = main_vm.AttachCurrentThread((void**)&hotspotEnv, NULL); 1580 _attached = res == JNI_OK; 1581 static volatile int report_attach_error = 0; 1582 if (res != JNI_OK && report_attach_error == 0 && Atomic::cmpxchg(1, &report_attach_error, 0) == 0) { 1583 // Only report an attach error once 1584 jio_printf("Warning: attaching current thread to VM failed with %d (future attach errors are suppressed)\n", res); 1585 } 1586 } else { 1587 _attached = false; 1588 } 1589 } 1590 ~AttachDetach() { 1591 if (_attached && get_current_thread() != NULL) { 1592 extern struct JavaVM_ main_vm; 1593 jint res = main_vm.DetachCurrentThread(); 1594 static volatile int report_detach_error = 0; 1595 if (res != JNI_OK && report_detach_error == 0 && Atomic::cmpxchg(1, &report_detach_error, 0) == 0) { 1596 // Only report an attach error once 1597 jio_printf("Warning: detaching current thread from VM failed with %d (future attach errors are suppressed)\n", res); 1598 } 1599 } 1600 } 1601 }; 1602 1603 C2V_VMENTRY_PREFIX(jint, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length, bool flush, bool can_throw)) 1604 AttachDetach ad(env, thread); 1605 bool use_tty = true; 1606 if (thread == NULL) { 1607 if (!ad._attached) { 1608 // Can only use tty if the current thread is attached 1609 TRACE_jvmci_1("Cannot write to tty on unattached thread"); 1610 return 0; 1611 } 1612 thread = get_current_thread(); 1613 } 1614 JVMCITraceMark jtm("writeDebugOutput"); 1615 C2V_BLOCK(void, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length)) 1616 if (bytes == NULL) { 1617 if (can_throw) { 1618 JVMCI_THROW_0(NullPointerException); 1619 } 1620 return -1; 1621 } 1622 JVMCIPrimitiveArray array = JVMCIENV->wrap(bytes); 1623 1624 // Check if offset and length are non negative. 1625 if (offset < 0 || length < 0) { 1626 if (can_throw) { 1627 JVMCI_THROW_0(ArrayIndexOutOfBoundsException); 1628 } 1629 return -2; 1630 } 1631 // Check if the range is valid. 1632 int array_length = JVMCIENV->get_length(array); 1633 if ((((unsigned int) length + (unsigned int) offset) > (unsigned int) array_length)) { 1634 if (can_throw) { 2190 if (x == NULL) { 2191 JVMCI_THROW_0(NullPointerException); 2192 } 2193 Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0); 2194 return xobj->long_field(displacement); 2195 } 2196 2197 C2V_VMENTRY_NULL(jobject, getObject, (JNIEnv* env, jobject, jobject x, long displacement)) 2198 if (x == NULL) { 2199 JVMCI_THROW_0(NullPointerException); 2200 } 2201 Handle xobj = JVMCIENV->asConstant(JVMCIENV->wrap(x), JVMCI_CHECK_0); 2202 oop res = xobj->obj_field(displacement); 2203 JVMCIObject result = JVMCIENV->get_object_constant(res); 2204 return JVMCIENV->get_jobject(result); 2205 } 2206 2207 C2V_VMENTRY(void, deleteGlobalHandle, (JNIEnv* env, jobject, jlong h)) 2208 jobject handle = (jobject)(address)h; 2209 if (handle != NULL) { 2210 JVMCIENV->runtime()->destroy_global(handle); 2211 } 2212 } 2213 2214 static void requireJVMCINativeLibrary(JVMCI_TRAPS) { 2215 if (!UseJVMCINativeLibrary) { 2216 JVMCI_THROW_MSG(UnsupportedOperationException, "JVMCI shared library is not enabled (requires -XX:+UseJVMCINativeLibrary)"); 2217 } 2218 } 2219 2220 C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclass mirror)) 2221 requireJVMCINativeLibrary(JVMCI_CHECK_NULL); 2222 requireInHotSpot("registerNativeMethods", JVMCI_CHECK_NULL); 2223 char* sl_path; 2224 void* sl_handle; 2225 JVMCIRuntime* runtime = JVMCI::compiler_runtime(); 2226 { 2227 // Ensure the JVMCI shared library runtime is initialized. 2228 JVMCIEnv __peer_jvmci_env__(thread, false, __FILE__, __LINE__); 2229 JVMCIEnv* peerEnv = &__peer_jvmci_env__; 2230 HandleMark hm; 2231 JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(peerEnv); 2232 if (peerEnv->has_pending_exception()) { 2233 peerEnv->describe_pending_exception(true); 2234 } 2235 sl_handle = JVMCI::get_shared_library(sl_path, false); 2236 if (sl_handle == NULL) { 2237 JVMCI_THROW_MSG_0(InternalError, err_msg("Error initializing JVMCI runtime %d", runtime->id())); 2238 } 2239 } 2240 2241 if (mirror == NULL) { 2242 JVMCI_THROW_0(NullPointerException); 2243 } 2244 Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve(mirror)); 2245 if (klass == NULL || !klass->is_instance_klass()) { 2246 JVMCI_THROW_MSG_0(IllegalArgumentException, "clazz is for primitive type"); 2247 } 2248 2249 InstanceKlass* iklass = InstanceKlass::cast(klass); 2250 for (int i = 0; i < iklass->methods()->length(); i++) { 2251 Method* method = iklass->methods()->at(i); 2252 if (method->is_native()) { 2253 2254 // Compute argument size 2255 int args_size = 1 // JNIEnv 2256 + (method->is_static() ? 1 : 0) // class for static methods 2257 + method->size_of_parameters(); // actual parameters 2258 2259 // 1) Try JNI short style 2260 stringStream st; 2261 char* pure_name = NativeLookup::pure_jni_name(method); 2262 os::print_jni_name_prefix_on(&st, args_size); 2263 st.print_raw(pure_name); 2264 os::print_jni_name_suffix_on(&st, args_size); 2265 char* jni_name = st.as_string(); 2266 2267 address entry = (address) os::dll_lookup(sl_handle, jni_name); 2268 if (entry == NULL) { 2269 // 2) Try JNI long style 2270 st.reset(); 2271 char* long_name = NativeLookup::long_jni_name(method); 2272 os::print_jni_name_prefix_on(&st, args_size); 2273 st.print_raw(pure_name); 2274 st.print_raw(long_name); 2275 os::print_jni_name_suffix_on(&st, args_size); 2276 char* jni_long_name = st.as_string(); 2277 entry = (address) os::dll_lookup(sl_handle, jni_long_name); 2278 if (entry == NULL) { 2279 JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("%s [neither %s nor %s exist in %s]", 2280 method->name_and_sig_as_C_string(), 2281 jni_name, jni_long_name, sl_path)); 2282 } 2283 } 2284 2285 if (method->has_native_function() && entry != method->native_function()) { 2286 JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("%s [cannot re-link from " PTR_FORMAT " to " PTR_FORMAT "]", 2287 method->name_and_sig_as_C_string(), p2i(method->native_function()), p2i(entry))); 2288 } 2289 method->set_native_function(entry, Method::native_bind_event_is_interesting); 2290 if (PrintJNIResolving) { 2291 tty->print_cr("[Dynamic-linking native method %s.%s ... JNI] @ " PTR_FORMAT, 2292 method->method_holder()->external_name(), 2293 method->name()->as_C_string(), p2i((void*) entry)); 2294 } 2295 } 2296 } 2297 2298 typeArrayOop info_oop = oopFactory::new_longArray(4, CHECK_0); 2299 jlongArray info = (jlongArray) JNIHandles::make_local(info_oop); 2300 runtime->init_JavaVM_info(info, JVMCI_CHECK_0); 2301 return info; 2302 } 2303 2304 C2V_VMENTRY_PREFIX(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject c2vm)) 2305 if (thread == NULL) { 2306 // Called from unattached JVMCI shared library thread 2307 return false; 2308 } 2309 JVMCITraceMark jtm("isCurrentThreadAttached"); 2310 if (thread->jni_environment() == env) { 2311 C2V_BLOCK(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject)) 2312 requireJVMCINativeLibrary(JVMCI_CHECK_0); 2313 JVMCIRuntime* runtime = JVMCI::compiler_runtime(); 2314 if (runtime == NULL || !runtime->has_shared_library_javavm()) { 2315 JVMCI_THROW_MSG_0(IllegalStateException, "Require JVMCI shared library JavaVM to be initialized in isCurrentThreadAttached"); 2316 } 2317 JNIEnv* peerEnv; 2318 return runtime->GetEnv(thread, (void**) &peerEnv, JNI_VERSION_1_2) == JNI_OK; 2319 } 2320 return true; 2321 C2V_END 2322 2323 C2V_VMENTRY_PREFIX(jlong, getCurrentJavaThread, (JNIEnv* env, jobject c2vm)) 2324 if (thread == NULL) { 2325 // Called from unattached JVMCI shared library thread 2326 return 0L; 2327 } 2328 JVMCITraceMark jtm("getCurrentJavaThread"); 2329 return (jlong) p2i(thread); 2330 C2V_END 2331 2332 C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jboolean as_daemon)) 2333 if (thread == NULL) { 2334 // Called from unattached JVMCI shared library thread 2335 extern struct JavaVM_ main_vm; 2336 JNIEnv* hotspotEnv; 2337 jint res = as_daemon ? main_vm.AttachCurrentThreadAsDaemon((void**) &hotspotEnv, NULL) : 2338 main_vm.AttachCurrentThread((void**) &hotspotEnv, NULL); 2339 if (res != JNI_OK) { 2340 JNI_THROW_("attachCurrentThread", InternalError, err_msg("Trying to attach thread returned %d", res), false); 2341 } 2342 return true; 2343 } 2344 JVMCITraceMark jtm("attachCurrentThread"); 2345 if (thread->jni_environment() == env) { 2346 // Called from HotSpot 2347 C2V_BLOCK(jboolean, attachCurrentThread, (JNIEnv* env, jobject, jboolean)) 2348 requireJVMCINativeLibrary(JVMCI_CHECK_0); 2349 JVMCIRuntime* runtime = JVMCI::compiler_runtime(); 2350 if (runtime == NULL || !runtime->has_shared_library_javavm()) { 2351 JVMCI_THROW_MSG_0(IllegalStateException, "Require JVMCI shared library JavaVM to be initialized in attachCurrentThread"); 2352 } 2353 2354 JavaVMAttachArgs attach_args; 2355 attach_args.version = JNI_VERSION_1_2; 2356 attach_args.name = thread->name(); 2357 attach_args.group = NULL; 2358 JNIEnv* peerJNIEnv; 2359 if (runtime->GetEnv(thread, (void**) &peerJNIEnv, JNI_VERSION_1_2) == JNI_OK) { 2360 return false; 2361 } 2362 jint res = as_daemon ? runtime->AttachCurrentThreadAsDaemon(thread, (void**) &peerJNIEnv, &attach_args) : 2363 runtime->AttachCurrentThread(thread, (void**) &peerJNIEnv, &attach_args); 2364 2365 if (res == JNI_OK) { 2366 guarantee(peerJNIEnv != NULL, "must be"); 2367 TRACE_jvmci_1("attached to JavaVM for JVMCI runtime %d", runtime->id()); 2368 return true; 2369 } 2370 JVMCI_THROW_MSG_0(InternalError, err_msg("Error %d while attaching %s", res, attach_args.name)); 2371 } 2372 // Called from JVMCI shared library 2373 return false; 2374 C2V_END 2375 2376 C2V_VMENTRY_PREFIX(void, detachCurrentThread, (JNIEnv* env, jobject c2vm)) 2377 if (thread == NULL) { 2378 // Called from unattached JVMCI shared library thread 2379 JNI_THROW("detachCurrentThread", IllegalStateException, "Cannot detach non-attached thread"); 2380 } 2381 JVMCITraceMark jtm("detachCurrentThread"); 2382 if (thread->jni_environment() == env) { 2383 // Called from HotSpot 2384 C2V_BLOCK(void, detachCurrentThread, (JNIEnv* env, jobject)) 2385 requireJVMCINativeLibrary(JVMCI_CHECK); 2386 requireInHotSpot("detachCurrentThread", JVMCI_CHECK); 2387 JVMCIRuntime* runtime = JVMCI::compiler_runtime(); 2388 if (runtime == NULL || !runtime->has_shared_library_javavm()) { 2389 JVMCI_THROW_MSG(IllegalStateException, "Require JVMCI shared library JavaVM to be initialized in detachCurrentThread"); 2390 } 2391 JNIEnv* peerJNIEnv; 2392 if (runtime->GetEnv(thread, (void**) &peerJNIEnv, JNI_VERSION_1_2) != JNI_OK) { 2393 JVMCI_THROW_MSG(IllegalStateException, err_msg("Cannot detach non-attached thread: %s", thread->name())); 2394 } 2395 jint res = runtime->DetachCurrentThread(thread); 2396 if (res != JNI_OK) { 2397 JVMCI_THROW_MSG(InternalError, err_msg("Error %d while attaching %s", res, thread->name())); 2398 } 2399 } else { 2400 // Called from attached JVMCI shared library thread 2401 extern struct JavaVM_ main_vm; 2402 jint res = main_vm.DetachCurrentThread(); 2403 if (res != JNI_OK) { 2404 JNI_THROW("detachCurrentThread", InternalError, "Cannot detach non-attached thread"); 2405 } 2406 } 2407 C2V_END 2408 2409 C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle)) 2410 requireJVMCINativeLibrary(JVMCI_CHECK_0); 2411 if (obj_handle == NULL) { 2412 return 0L; 2413 } 2414 JVMCIEnv __peer_jvmci_env__(thread, !JVMCIENV->is_hotspot(), __FILE__, __LINE__); 2415 JVMCIEnv* peerEnv = &__peer_jvmci_env__; 2416 JVMCIEnv* thisEnv = JVMCIENV; 2417 2418 JVMCIObject obj = thisEnv->wrap(obj_handle); 2419 JVMCIObject result; 2420 if (thisEnv->isa_HotSpotResolvedJavaMethodImpl(obj)) { 2421 Method* method = thisEnv->asMethod(obj); 2422 result = peerEnv->get_jvmci_method(method, JVMCI_CHECK_0); 2423 } else if (thisEnv->isa_HotSpotResolvedObjectTypeImpl(obj)) { 2424 Klass* klass = thisEnv->asKlass(obj); |