Mercurial > hg > truffle
comparison src/share/vm/prims/methodHandles.cpp @ 3371:fabcf26ee72f
6998541: JSR 292 implement missing return-type conversion for OP_RETYPE_RAW
Reviewed-by: jrose, kvn, never
author | twisti |
---|---|
date | Thu, 12 May 2011 14:04:48 -0700 |
parents | 167b70ff3abc |
children | 2848194272f4 a80577f854f9 |
comparison
equal
deleted
inserted
replaced
3370:2f17eb233d13 | 3371:fabcf26ee72f |
---|---|
1097 | 1097 |
1098 static oop object_java_mirror() { | 1098 static oop object_java_mirror() { |
1099 return Klass::cast(SystemDictionary::Object_klass())->java_mirror(); | 1099 return Klass::cast(SystemDictionary::Object_klass())->java_mirror(); |
1100 } | 1100 } |
1101 | 1101 |
1102 bool MethodHandles::is_float_fixed_reinterpretation_cast(BasicType src, BasicType dst) { | |
1103 if (src == T_FLOAT) return dst == T_INT; | |
1104 if (src == T_INT) return dst == T_FLOAT; | |
1105 if (src == T_DOUBLE) return dst == T_LONG; | |
1106 if (src == T_LONG) return dst == T_DOUBLE; | |
1107 return false; | |
1108 } | |
1109 | |
1102 bool MethodHandles::same_basic_type_for_arguments(BasicType src, | 1110 bool MethodHandles::same_basic_type_for_arguments(BasicType src, |
1103 BasicType dst, | 1111 BasicType dst, |
1104 bool raw, | 1112 bool raw, |
1105 bool for_return) { | 1113 bool for_return) { |
1106 if (for_return) { | 1114 if (for_return) { |
1123 return is_subword_type(dst); | 1131 return is_subword_type(dst); |
1124 if (src == T_BYTE && dst == T_SHORT) | 1132 if (src == T_BYTE && dst == T_SHORT) |
1125 return true; // remaining case: byte fits in short | 1133 return true; // remaining case: byte fits in short |
1126 } | 1134 } |
1127 // allow float/fixed reinterpretation casts | 1135 // allow float/fixed reinterpretation casts |
1128 if (src == T_FLOAT) return dst == T_INT; | 1136 if (is_float_fixed_reinterpretation_cast(src, dst)) |
1129 if (src == T_INT) return dst == T_FLOAT; | 1137 return true; |
1130 if (src == T_DOUBLE) return dst == T_LONG; | |
1131 if (src == T_LONG) return dst == T_DOUBLE; | |
1132 return false; | 1138 return false; |
1133 } | 1139 } |
1134 | 1140 |
1135 const char* MethodHandles::check_method_receiver(methodOop m, | 1141 const char* MethodHandles::check_method_receiver(methodOop m, |
1136 klassOop passed_recv_type) { | 1142 klassOop passed_recv_type) { |
1397 BasicType dst_type, | 1403 BasicType dst_type, |
1398 klassOop dst_klass, | 1404 klassOop dst_klass, |
1399 int argnum, | 1405 int argnum, |
1400 bool raw) { | 1406 bool raw) { |
1401 const char* err = NULL; | 1407 const char* err = NULL; |
1402 bool for_return = (argnum < 0); | 1408 const bool for_return = (argnum < 0); |
1403 | 1409 |
1404 // just in case: | 1410 // just in case: |
1405 if (src_type == T_ARRAY) src_type = T_OBJECT; | 1411 if (src_type == T_ARRAY) src_type = T_OBJECT; |
1406 if (dst_type == T_ARRAY) dst_type = T_OBJECT; | 1412 if (dst_type == T_ARRAY) dst_type = T_OBJECT; |
1407 | 1413 |
1408 // Produce some nice messages if VerifyMethodHandles is turned on: | 1414 // Produce some nice messages if VerifyMethodHandles is turned on: |
1409 if (!same_basic_type_for_arguments(src_type, dst_type, raw, for_return)) { | 1415 if (!same_basic_type_for_arguments(src_type, dst_type, raw, for_return)) { |
1410 if (src_type == T_OBJECT) { | 1416 if (src_type == T_OBJECT) { |
1411 if (raw && dst_type == T_INT && is_always_null_type(src_klass)) | 1417 if (raw && is_java_primitive(dst_type)) |
1412 return NULL; // OK to convert a null pointer to a garbage int | 1418 return NULL; // ref-to-prim discards ref and returns zero |
1413 err = ((argnum >= 0) | 1419 err = (!for_return |
1414 ? "type mismatch: passing a %s for method argument #%d, which expects primitive %s" | 1420 ? "type mismatch: passing a %s for method argument #%d, which expects primitive %s" |
1415 : "type mismatch: returning a %s, but caller expects primitive %s"); | 1421 : "type mismatch: returning a %s, but caller expects primitive %s"); |
1416 } else if (dst_type == T_OBJECT) { | 1422 } else if (dst_type == T_OBJECT) { |
1417 err = ((argnum >= 0) | 1423 err = (!for_return |
1418 ? "type mismatch: passing a primitive %s for method argument #%d, which expects %s" | 1424 ? "type mismatch: passing a primitive %s for method argument #%d, which expects %s" |
1419 : "type mismatch: returning a primitive %s, but caller expects %s"); | 1425 : "type mismatch: returning a primitive %s, but caller expects %s"); |
1420 } else { | 1426 } else { |
1421 err = ((argnum >= 0) | 1427 err = (!for_return |
1422 ? "type mismatch: passing a %s for method argument #%d, which expects %s" | 1428 ? "type mismatch: passing a %s for method argument #%d, which expects %s" |
1423 : "type mismatch: returning a %s, but caller expects %s"); | 1429 : "type mismatch: returning a %s, but caller expects %s"); |
1424 } | 1430 } |
1425 } else if (src_type == T_OBJECT && dst_type == T_OBJECT && | 1431 } else if (src_type == T_OBJECT && dst_type == T_OBJECT && |
1426 class_cast_needed(src_klass, dst_klass)) { | 1432 class_cast_needed(src_klass, dst_klass)) { |
1427 if (!class_cast_needed(dst_klass, src_klass)) { | 1433 if (!class_cast_needed(dst_klass, src_klass)) { |
1428 if (raw) | 1434 if (raw) |
1429 return NULL; // reverse cast is OK; the MH target is trusted to enforce it | 1435 return NULL; // reverse cast is OK; the MH target is trusted to enforce it |
1430 err = ((argnum >= 0) | 1436 err = (!for_return |
1431 ? "cast required: passing a %s for method argument #%d, which expects %s" | 1437 ? "cast required: passing a %s for method argument #%d, which expects %s" |
1432 : "cast required: returning a %s, but caller expects %s"); | 1438 : "cast required: returning a %s, but caller expects %s"); |
1433 } else { | 1439 } else { |
1434 err = ((argnum >= 0) | 1440 err = (!for_return |
1435 ? "reference mismatch: passing a %s for method argument #%d, which expects %s" | 1441 ? "reference mismatch: passing a %s for method argument #%d, which expects %s" |
1436 : "reference mismatch: returning a %s, but caller expects %s"); | 1442 : "reference mismatch: returning a %s, but caller expects %s"); |
1437 } | 1443 } |
1438 } else { | 1444 } else { |
1439 // passed the obstacle course | 1445 // passed the obstacle course |
1450 if (dst_type == T_OBJECT) | 1456 if (dst_type == T_OBJECT) |
1451 dst_name = (dst_klass != NULL) ? Klass::cast(dst_klass)->external_name() : "an unresolved class"; | 1457 dst_name = (dst_klass != NULL) ? Klass::cast(dst_klass)->external_name() : "an unresolved class"; |
1452 | 1458 |
1453 size_t msglen = strlen(err) + strlen(src_name) + strlen(dst_name) + (argnum < 10 ? 1 : 11); | 1459 size_t msglen = strlen(err) + strlen(src_name) + strlen(dst_name) + (argnum < 10 ? 1 : 11); |
1454 char* msg = NEW_RESOURCE_ARRAY(char, msglen + 1); | 1460 char* msg = NEW_RESOURCE_ARRAY(char, msglen + 1); |
1455 if (argnum >= 0) { | 1461 if (!for_return) { |
1456 assert(strstr(err, "%d") != NULL, ""); | 1462 assert(strstr(err, "%d") != NULL, ""); |
1457 jio_snprintf(msg, msglen, err, src_name, argnum, dst_name); | 1463 jio_snprintf(msg, msglen, err, src_name, argnum, dst_name); |
1458 } else { | 1464 } else { |
1459 assert(strstr(err, "%d") == NULL, ""); | 1465 assert(strstr(err, "%d") == NULL, ""); |
1460 jio_snprintf(msg, msglen, err, src_name, dst_name); | 1466 jio_snprintf(msg, msglen, err, src_name, dst_name); |
2178 } | 2184 } |
2179 | 2185 |
2180 } | 2186 } |
2181 | 2187 |
2182 void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS) { | 2188 void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS) { |
2183 int argslot = java_lang_invoke_AdapterMethodHandle::vmargslot(mh()); | 2189 Handle argument = java_lang_invoke_AdapterMethodHandle::argument(mh()); |
2184 jint conversion = java_lang_invoke_AdapterMethodHandle::conversion(mh()); | 2190 int argslot = java_lang_invoke_AdapterMethodHandle::vmargslot(mh()); |
2185 jint conv_op = adapter_conversion_op(conversion); | 2191 jint conversion = java_lang_invoke_AdapterMethodHandle::conversion(mh()); |
2192 jint conv_op = adapter_conversion_op(conversion); | |
2186 | 2193 |
2187 // adjust the adapter code to the internal EntryKind enumeration: | 2194 // adjust the adapter code to the internal EntryKind enumeration: |
2188 EntryKind ek_orig = adapter_entry_kind(conv_op); | 2195 EntryKind ek_orig = adapter_entry_kind(conv_op); |
2189 EntryKind ek_opt = ek_orig; // may be optimized | 2196 EntryKind ek_opt = ek_orig; // may be optimized |
2190 EntryKind ek_try; // temp | 2197 EntryKind ek_try; // temp |
2239 ek_opt = _adapter_opt_l2i; | 2246 ek_opt = _adapter_opt_l2i; |
2240 vminfo = adapter_prim_to_prim_subword_vminfo(dest); | 2247 vminfo = adapter_prim_to_prim_subword_vminfo(dest); |
2241 } else if (src == T_DOUBLE && dest == T_FLOAT) { | 2248 } else if (src == T_DOUBLE && dest == T_FLOAT) { |
2242 ek_opt = _adapter_opt_d2f; | 2249 ek_opt = _adapter_opt_d2f; |
2243 } else { | 2250 } else { |
2244 assert(false, ""); | 2251 goto throw_not_impl; // runs user code, hence could block |
2245 } | 2252 } |
2246 break; | 2253 break; |
2247 case 1 *4+ 2: | 2254 case 1 *4+ 2: |
2248 if ((src == T_INT || is_subword_type(src)) && dest == T_LONG) { | 2255 if ((src == T_INT || is_subword_type(src)) && dest == T_LONG) { |
2249 ek_opt = _adapter_opt_i2l; | 2256 ek_opt = _adapter_opt_i2l; |
2250 } else if (src == T_FLOAT && dest == T_DOUBLE) { | 2257 } else if (src == T_FLOAT && dest == T_DOUBLE) { |
2251 ek_opt = _adapter_opt_f2d; | 2258 ek_opt = _adapter_opt_f2d; |
2252 } else { | 2259 } else { |
2253 assert(false, ""); | 2260 goto throw_not_impl; // runs user code, hence could block |
2254 } | 2261 } |
2255 break; | 2262 break; |
2256 default: | 2263 default: |
2257 assert(false, ""); | 2264 goto throw_not_impl; // runs user code, hence could block |
2258 break; | 2265 break; |
2259 } | 2266 } |
2260 } | 2267 } |
2261 break; | 2268 break; |
2262 | 2269 |
2269 break; | 2276 break; |
2270 case 2: | 2277 case 2: |
2271 ek_opt = _adapter_opt_unboxl; | 2278 ek_opt = _adapter_opt_unboxl; |
2272 break; | 2279 break; |
2273 default: | 2280 default: |
2274 assert(false, ""); | 2281 goto throw_not_impl; |
2275 break; | 2282 break; |
2276 } | 2283 } |
2277 } | 2284 } |
2278 break; | 2285 break; |
2279 | 2286 |
2282 assert(UseRicochetFrames, "else don't come here"); | 2289 assert(UseRicochetFrames, "else don't come here"); |
2283 // vminfo will be the location to insert the return value | 2290 // vminfo will be the location to insert the return value |
2284 vminfo = argslot; | 2291 vminfo = argslot; |
2285 ek_opt = _adapter_opt_collect_ref; | 2292 ek_opt = _adapter_opt_collect_ref; |
2286 ensure_vmlayout_field(target, CHECK); | 2293 ensure_vmlayout_field(target, CHECK); |
2294 // for MethodHandleWalk: | |
2295 if (java_lang_invoke_AdapterMethodHandle::is_instance(argument())) | |
2296 ensure_vmlayout_field(argument, CHECK); | |
2287 if (!OptimizeMethodHandles) break; | 2297 if (!OptimizeMethodHandles) break; |
2288 switch (type2size[src]) { | 2298 switch (type2size[src]) { |
2289 case 1: | 2299 case 1: |
2290 ek_try = EntryKind(_adapter_opt_filter_S0_ref + argslot); | 2300 ek_try = EntryKind(_adapter_opt_filter_S0_ref + argslot); |
2291 if (ek_try < _adapter_opt_collect_LAST && | 2301 if (ek_try < _adapter_opt_collect_LAST && |
2309 } | 2319 } |
2310 // else downgrade to variable slot: | 2320 // else downgrade to variable slot: |
2311 ek_opt = _adapter_opt_collect_2_ref; | 2321 ek_opt = _adapter_opt_collect_2_ref; |
2312 break; | 2322 break; |
2313 default: | 2323 default: |
2314 assert(false, ""); | 2324 goto throw_not_impl; |
2315 break; | 2325 break; |
2316 } | 2326 } |
2317 } | 2327 } |
2318 break; | 2328 break; |
2319 | 2329 |
2333 case 2: | 2343 case 2: |
2334 ek_opt = (!rotate ? _adapter_opt_swap_2 : | 2344 ek_opt = (!rotate ? _adapter_opt_swap_2 : |
2335 rotate > 0 ? _adapter_opt_rot_2_up : _adapter_opt_rot_2_down); | 2345 rotate > 0 ? _adapter_opt_rot_2_up : _adapter_opt_rot_2_down); |
2336 break; | 2346 break; |
2337 default: | 2347 default: |
2338 assert(false, ""); | 2348 goto throw_not_impl; |
2339 break; | 2349 break; |
2340 } | 2350 } |
2341 } | 2351 } |
2342 break; | 2352 break; |
2343 | 2353 |
2400 break; | 2410 break; |
2401 | 2411 |
2402 case _adapter_collect_args: | 2412 case _adapter_collect_args: |
2403 { | 2413 { |
2404 assert(UseRicochetFrames, "else don't come here"); | 2414 assert(UseRicochetFrames, "else don't come here"); |
2405 int elem_slots = argument_slot_count( | 2415 int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument())); |
2406 java_lang_invoke_MethodHandle::type( | |
2407 java_lang_invoke_AdapterMethodHandle::argument(mh()) ) ); | |
2408 // vminfo will be the location to insert the return value | 2416 // vminfo will be the location to insert the return value |
2409 vminfo = argslot; | 2417 vminfo = argslot; |
2410 ensure_vmlayout_field(target, CHECK); | 2418 ensure_vmlayout_field(target, CHECK); |
2419 ensure_vmlayout_field(argument, CHECK); | |
2411 | 2420 |
2412 // general case: | 2421 // general case: |
2413 switch (dest) { | 2422 switch (dest) { |
2414 default : if (!is_subword_type(dest)) goto throw_not_impl; | 2423 default : if (!is_subword_type(dest)) goto throw_not_impl; |
2415 // else fall through: | 2424 // else fall through: |
2470 } | 2479 } |
2471 | 2480 |
2472 case _adapter_fold_args: | 2481 case _adapter_fold_args: |
2473 { | 2482 { |
2474 assert(UseRicochetFrames, "else don't come here"); | 2483 assert(UseRicochetFrames, "else don't come here"); |
2475 int elem_slots = argument_slot_count( | 2484 int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument())); |
2476 java_lang_invoke_MethodHandle::type( | |
2477 java_lang_invoke_AdapterMethodHandle::argument(mh()) ) ); | |
2478 // vminfo will be the location to insert the return value | 2485 // vminfo will be the location to insert the return value |
2479 vminfo = argslot + elem_slots; | 2486 vminfo = argslot + elem_slots; |
2480 ensure_vmlayout_field(target, CHECK); | 2487 ensure_vmlayout_field(target, CHECK); |
2488 ensure_vmlayout_field(argument, CHECK); | |
2481 | 2489 |
2482 switch (dest) { | 2490 switch (dest) { |
2483 default : if (!is_subword_type(dest)) goto throw_not_impl; | 2491 default : if (!is_subword_type(dest)) goto throw_not_impl; |
2484 // else fall through: | 2492 // else fall through: |
2485 case T_INT : ek_opt = _adapter_opt_fold_int; break; | 2493 case T_INT : ek_opt = _adapter_opt_fold_int; break; |
2525 if (err == NULL) | 2533 if (err == NULL) |
2526 err = "unknown adapter type"; | 2534 err = "unknown adapter type"; |
2527 break; | 2535 break; |
2528 } | 2536 } |
2529 | 2537 |
2530 if (err != NULL && (vminfo & CONV_VMINFO_MASK) != vminfo) { | 2538 if (err == NULL && (vminfo & CONV_VMINFO_MASK) != vminfo) { |
2531 // should not happen, since vminfo is used to encode arg/slot indexes < 255 | 2539 // should not happen, since vminfo is used to encode arg/slot indexes < 255 |
2532 err = "vminfo overflow"; | 2540 err = "vminfo overflow"; |
2533 } | 2541 } |
2534 | 2542 |
2535 if (err != NULL && !have_entry(ek_opt)) { | 2543 if (err == NULL && !have_entry(ek_opt)) { |
2536 err = "adapter stub for this kind of method handle is missing"; | 2544 err = "adapter stub for this kind of method handle is missing"; |
2545 } | |
2546 | |
2547 if (err == NULL && ek_opt == ek_orig) { | |
2548 switch (ek_opt) { | |
2549 case _adapter_prim_to_prim: | |
2550 case _adapter_ref_to_prim: | |
2551 case _adapter_prim_to_ref: | |
2552 case _adapter_swap_args: | |
2553 case _adapter_rot_args: | |
2554 case _adapter_collect_args: | |
2555 case _adapter_fold_args: | |
2556 case _adapter_spread_args: | |
2557 // should be handled completely by optimized cases; see above | |
2558 err = "init_AdapterMethodHandle should not issue this"; | |
2559 break; | |
2560 } | |
2537 } | 2561 } |
2538 | 2562 |
2539 if (err != NULL) { | 2563 if (err != NULL) { |
2540 throw_InternalError_for_bad_conversion(conversion, err, THREAD); | 2564 throw_InternalError_for_bad_conversion(conversion, err, THREAD); |
2541 return; | 2565 return; |