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;