940 |
940 |
941 // return number of elements we at leasted wanted to initialize |
941 // return number of elements we at leasted wanted to initialize |
942 return rfill + overflow; |
942 return rfill + overflow; |
943 } |
943 } |
944 |
944 |
945 // Get context class for a CallSite instance: either extract existing context or use default one. |
945 void MethodHandles::add_dependent_nmethod(oop call_site, nmethod* nm) { |
946 InstanceKlass* MethodHandles::get_call_site_context(oop call_site) { |
946 assert_locked_or_safepoint(CodeCache_lock); |
947 // In order to extract a context the following traversal is performed: |
947 |
948 // CallSite.context => Cleaner.referent => Class._klass => Klass |
948 oop context = java_lang_invoke_CallSite::context(call_site); |
949 assert(java_lang_invoke_CallSite::is_instance(call_site), ""); |
949 nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context); |
950 oop context_oop = java_lang_invoke_CallSite::context_volatile(call_site); |
950 |
951 if (oopDesc::is_null(context_oop)) { |
951 nmethodBucket* new_deps = nmethodBucket::add_dependent_nmethod(deps, nm); |
952 return NULL; // The context hasn't been initialized yet. |
952 if (deps != new_deps) { |
953 } |
953 java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps); |
954 oop context_class_oop = java_lang_ref_Reference::referent(context_oop); |
954 } |
955 if (oopDesc::is_null(context_class_oop)) { |
955 } |
956 // The context reference was cleared by GC, so current dependency context |
956 |
957 // isn't usable anymore. Context should be fetched from CallSite again. |
957 void MethodHandles::remove_dependent_nmethod(oop call_site, nmethod* nm) { |
958 return NULL; |
958 assert_locked_or_safepoint(CodeCache_lock); |
959 } |
959 |
960 return InstanceKlass::cast(java_lang_Class::as_Klass(context_class_oop)); |
960 oop context = java_lang_invoke_CallSite::context(call_site); |
|
961 nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context); |
|
962 |
|
963 if (nmethodBucket::remove_dependent_nmethod(deps, nm)) { |
|
964 nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps); |
|
965 if (deps != new_deps) { |
|
966 java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps); |
|
967 } |
|
968 } |
|
969 } |
|
970 |
|
971 void MethodHandles::flush_dependent_nmethods(Handle call_site, Handle target) { |
|
972 assert_lock_strong(Compile_lock); |
|
973 |
|
974 int marked = 0; |
|
975 CallSiteDepChange changes(call_site(), target()); |
|
976 { |
|
977 MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
|
978 |
|
979 oop context = java_lang_invoke_CallSite::context(call_site()); |
|
980 nmethodBucket* deps = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context); |
|
981 |
|
982 marked = nmethodBucket::mark_dependent_nmethods(deps, changes); |
|
983 if (marked > 0) { |
|
984 nmethodBucket* new_deps = nmethodBucket::clean_dependent_nmethods(deps); |
|
985 if (deps != new_deps) { |
|
986 java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context, new_deps); |
|
987 } |
|
988 } |
|
989 } |
|
990 if (marked > 0) { |
|
991 // At least one nmethod has been marked for deoptimization |
|
992 VM_Deoptimize op; |
|
993 VMThread::execute(&op); |
|
994 } |
961 } |
995 } |
962 |
996 |
963 //------------------------------------------------------------------------------ |
997 //------------------------------------------------------------------------------ |
964 // MemberNameTable |
998 // MemberNameTable |
965 // |
999 // |
1274 Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh)); |
1308 Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh)); |
1275 Handle target (THREAD, JNIHandles::resolve_non_null(target_jh)); |
1309 Handle target (THREAD, JNIHandles::resolve_non_null(target_jh)); |
1276 { |
1310 { |
1277 // Walk all nmethods depending on this call site. |
1311 // Walk all nmethods depending on this call site. |
1278 MutexLocker mu(Compile_lock, thread); |
1312 MutexLocker mu(Compile_lock, thread); |
1279 CodeCache::flush_dependents_on(call_site, target); |
1313 MethodHandles::flush_dependent_nmethods(call_site, target); |
1280 java_lang_invoke_CallSite::set_target(call_site(), target()); |
1314 java_lang_invoke_CallSite::set_target(call_site(), target()); |
1281 } |
1315 } |
1282 } |
1316 } |
1283 JVM_END |
1317 JVM_END |
1284 |
1318 |
1286 Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh)); |
1320 Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh)); |
1287 Handle target (THREAD, JNIHandles::resolve_non_null(target_jh)); |
1321 Handle target (THREAD, JNIHandles::resolve_non_null(target_jh)); |
1288 { |
1322 { |
1289 // Walk all nmethods depending on this call site. |
1323 // Walk all nmethods depending on this call site. |
1290 MutexLocker mu(Compile_lock, thread); |
1324 MutexLocker mu(Compile_lock, thread); |
1291 CodeCache::flush_dependents_on(call_site, target); |
1325 MethodHandles::flush_dependent_nmethods(call_site, target); |
1292 java_lang_invoke_CallSite::set_target_volatile(call_site(), target()); |
1326 java_lang_invoke_CallSite::set_target_volatile(call_site(), target()); |
1293 } |
1327 } |
1294 } |
1328 } |
1295 JVM_END |
1329 JVM_END |
1296 |
1330 |
1297 JVM_ENTRY(void, MHN_invalidateDependentNMethods(JNIEnv* env, jobject igcls, jobject call_site_jh)) { |
1331 JVM_ENTRY(void, MHN_clearCallSiteContext(JNIEnv* env, jobject igcls, jobject context_jh)) { |
1298 Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh)); |
1332 Handle context(THREAD, JNIHandles::resolve_non_null(context_jh)); |
1299 { |
1333 { |
1300 // Walk all nmethods depending on this call site. |
1334 // Walk all nmethods depending on this call site. |
1301 MutexLocker mu1(Compile_lock, thread); |
1335 MutexLocker mu1(Compile_lock, thread); |
1302 |
1336 |
1303 CallSiteDepChange changes(call_site(), Handle()); |
|
1304 |
|
1305 InstanceKlass* ctxk = MethodHandles::get_call_site_context(call_site()); |
|
1306 if (ctxk == NULL) { |
|
1307 return; // No dependencies to invalidate yet. |
|
1308 } |
|
1309 int marked = 0; |
1337 int marked = 0; |
1310 { |
1338 { |
1311 MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
1339 MutexLockerEx mu2(CodeCache_lock, Mutex::_no_safepoint_check_flag); |
1312 marked = ctxk->mark_dependent_nmethods(changes); |
1340 nmethodBucket* b = java_lang_invoke_MethodHandleNatives_CallSiteContext::vmdependencies(context()); |
1313 } |
1341 while(b != NULL) { |
1314 java_lang_invoke_CallSite::set_context_volatile(call_site(), NULL); // Reset call site to initial state |
1342 nmethod* nm = b->get_nmethod(); |
|
1343 if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization()) { |
|
1344 nm->mark_for_deoptimization(); |
|
1345 marked++; |
|
1346 } |
|
1347 nmethodBucket* next = b->next(); |
|
1348 delete b; |
|
1349 b = next; |
|
1350 } |
|
1351 java_lang_invoke_MethodHandleNatives_CallSiteContext::set_vmdependencies(context(), NULL); // reset context |
|
1352 } |
1315 if (marked > 0) { |
1353 if (marked > 0) { |
1316 // At least one nmethod has been marked for deoptimization |
1354 // At least one nmethod has been marked for deoptimization |
1317 VM_Deoptimize op; |
1355 VM_Deoptimize op; |
1318 VMThread::execute(&op); |
1356 VMThread::execute(&op); |
1319 } |
1357 } |
1355 #define STRG LANG"String;" |
1393 #define STRG LANG"String;" |
1356 #define CS JLINV"CallSite;" |
1394 #define CS JLINV"CallSite;" |
1357 #define MT JLINV"MethodType;" |
1395 #define MT JLINV"MethodType;" |
1358 #define MH JLINV"MethodHandle;" |
1396 #define MH JLINV"MethodHandle;" |
1359 #define MEM JLINV"MemberName;" |
1397 #define MEM JLINV"MemberName;" |
|
1398 #define CTX JLINV"MethodHandleNatives$CallSiteContext;" |
1360 |
1399 |
1361 #define CC (char*) /*cast a literal from (const char*)*/ |
1400 #define CC (char*) /*cast a literal from (const char*)*/ |
1362 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) |
1401 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) |
1363 |
1402 |
1364 // These are the native methods on java.lang.invoke.MethodHandleNatives. |
1403 // These are the native methods on java.lang.invoke.MethodHandleNatives. |
1372 // int matchFlags, Class<?> caller, int skip, MemberName[] results); |
1411 // int matchFlags, Class<?> caller, int skip, MemberName[] results); |
1373 {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHN_getMembers)}, |
1412 {CC"getMembers", CC"("CLS""STRG""STRG"I"CLS"I["MEM")I", FN_PTR(MHN_getMembers)}, |
1374 {CC"objectFieldOffset", CC"("MEM")J", FN_PTR(MHN_objectFieldOffset)}, |
1413 {CC"objectFieldOffset", CC"("MEM")J", FN_PTR(MHN_objectFieldOffset)}, |
1375 {CC"setCallSiteTargetNormal", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetNormal)}, |
1414 {CC"setCallSiteTargetNormal", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetNormal)}, |
1376 {CC"setCallSiteTargetVolatile", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetVolatile)}, |
1415 {CC"setCallSiteTargetVolatile", CC"("CS""MH")V", FN_PTR(MHN_setCallSiteTargetVolatile)}, |
1377 {CC"invalidateDependentNMethods", CC"("CS")V", FN_PTR(MHN_invalidateDependentNMethods)}, |
1416 {CC"clearCallSiteContext", CC"("CTX")V", FN_PTR(MHN_clearCallSiteContext)}, |
1378 {CC"staticFieldOffset", CC"("MEM")J", FN_PTR(MHN_staticFieldOffset)}, |
1417 {CC"staticFieldOffset", CC"("MEM")J", FN_PTR(MHN_staticFieldOffset)}, |
1379 {CC"staticFieldBase", CC"("MEM")"OBJ, FN_PTR(MHN_staticFieldBase)}, |
1418 {CC"staticFieldBase", CC"("MEM")"OBJ, FN_PTR(MHN_staticFieldBase)}, |
1380 {CC"getMemberVMInfo", CC"("MEM")"OBJ, FN_PTR(MHN_getMemberVMInfo)} |
1419 {CC"getMemberVMInfo", CC"("MEM")"OBJ, FN_PTR(MHN_getMemberVMInfo)} |
1381 }; |
1420 }; |
1382 |
1421 |