< prev index next >

src/hotspot/share/jvmci/jvmciCompilerToVM.cpp

Print this page




  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);


< prev index next >