src/share/vm/prims/methodHandles.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File 6998541 Cdiff src/share/vm/prims/methodHandles.cpp

src/share/vm/prims/methodHandles.cpp

Print this page

        

*** 1097,1106 **** --- 1097,1114 ---- static oop object_java_mirror() { return Klass::cast(SystemDictionary::Object_klass())->java_mirror(); } + bool MethodHandles::is_float_fixed_reinterpretation_cast(BasicType src, BasicType dst) { + if (src == T_FLOAT) return dst == T_INT; + if (src == T_INT) return dst == T_FLOAT; + if (src == T_DOUBLE) return dst == T_LONG; + if (src == T_LONG) return dst == T_DOUBLE; + return false; + } + bool MethodHandles::same_basic_type_for_arguments(BasicType src, BasicType dst, bool raw, bool for_return) { if (for_return) {
*** 1123,1136 **** return is_subword_type(dst); if (src == T_BYTE && dst == T_SHORT) return true; // remaining case: byte fits in short } // allow float/fixed reinterpretation casts ! if (src == T_FLOAT) return dst == T_INT; ! if (src == T_INT) return dst == T_FLOAT; ! if (src == T_DOUBLE) return dst == T_LONG; ! if (src == T_LONG) return dst == T_DOUBLE; return false; } const char* MethodHandles::check_method_receiver(methodOop m, klassOop passed_recv_type) { --- 1131,1142 ---- return is_subword_type(dst); if (src == T_BYTE && dst == T_SHORT) return true; // remaining case: byte fits in short } // allow float/fixed reinterpretation casts ! if (is_float_fixed_reinterpretation_cast(src, dst)) ! return true; return false; } const char* MethodHandles::check_method_receiver(methodOop m, klassOop passed_recv_type) {
*** 1397,1439 **** BasicType dst_type, klassOop dst_klass, int argnum, bool raw) { const char* err = NULL; ! bool for_return = (argnum < 0); // just in case: if (src_type == T_ARRAY) src_type = T_OBJECT; if (dst_type == T_ARRAY) dst_type = T_OBJECT; // Produce some nice messages if VerifyMethodHandles is turned on: if (!same_basic_type_for_arguments(src_type, dst_type, raw, for_return)) { if (src_type == T_OBJECT) { ! if (raw && dst_type == T_INT && is_always_null_type(src_klass)) ! return NULL; // OK to convert a null pointer to a garbage int ! err = ((argnum >= 0) ? "type mismatch: passing a %s for method argument #%d, which expects primitive %s" : "type mismatch: returning a %s, but caller expects primitive %s"); } else if (dst_type == T_OBJECT) { ! err = ((argnum >= 0) ? "type mismatch: passing a primitive %s for method argument #%d, which expects %s" : "type mismatch: returning a primitive %s, but caller expects %s"); } else { ! err = ((argnum >= 0) ? "type mismatch: passing a %s for method argument #%d, which expects %s" : "type mismatch: returning a %s, but caller expects %s"); } } else if (src_type == T_OBJECT && dst_type == T_OBJECT && class_cast_needed(src_klass, dst_klass)) { if (!class_cast_needed(dst_klass, src_klass)) { if (raw) return NULL; // reverse cast is OK; the MH target is trusted to enforce it ! err = ((argnum >= 0) ? "cast required: passing a %s for method argument #%d, which expects %s" : "cast required: returning a %s, but caller expects %s"); } else { ! err = ((argnum >= 0) ? "reference mismatch: passing a %s for method argument #%d, which expects %s" : "reference mismatch: returning a %s, but caller expects %s"); } } else { // passed the obstacle course --- 1403,1445 ---- BasicType dst_type, klassOop dst_klass, int argnum, bool raw) { const char* err = NULL; ! const bool for_return = (argnum < 0); // just in case: if (src_type == T_ARRAY) src_type = T_OBJECT; if (dst_type == T_ARRAY) dst_type = T_OBJECT; // Produce some nice messages if VerifyMethodHandles is turned on: if (!same_basic_type_for_arguments(src_type, dst_type, raw, for_return)) { if (src_type == T_OBJECT) { ! if (raw && is_java_primitive(dst_type)) ! return NULL; // ref-to-prim discards ref and returns zero ! err = (!for_return ? "type mismatch: passing a %s for method argument #%d, which expects primitive %s" : "type mismatch: returning a %s, but caller expects primitive %s"); } else if (dst_type == T_OBJECT) { ! err = (!for_return ? "type mismatch: passing a primitive %s for method argument #%d, which expects %s" : "type mismatch: returning a primitive %s, but caller expects %s"); } else { ! err = (!for_return ? "type mismatch: passing a %s for method argument #%d, which expects %s" : "type mismatch: returning a %s, but caller expects %s"); } } else if (src_type == T_OBJECT && dst_type == T_OBJECT && class_cast_needed(src_klass, dst_klass)) { if (!class_cast_needed(dst_klass, src_klass)) { if (raw) return NULL; // reverse cast is OK; the MH target is trusted to enforce it ! err = (!for_return ? "cast required: passing a %s for method argument #%d, which expects %s" : "cast required: returning a %s, but caller expects %s"); } else { ! err = (!for_return ? "reference mismatch: passing a %s for method argument #%d, which expects %s" : "reference mismatch: returning a %s, but caller expects %s"); } } else { // passed the obstacle course
*** 1450,1460 **** if (dst_type == T_OBJECT) dst_name = (dst_klass != NULL) ? Klass::cast(dst_klass)->external_name() : "an unresolved class"; size_t msglen = strlen(err) + strlen(src_name) + strlen(dst_name) + (argnum < 10 ? 1 : 11); char* msg = NEW_RESOURCE_ARRAY(char, msglen + 1); ! if (argnum >= 0) { assert(strstr(err, "%d") != NULL, ""); jio_snprintf(msg, msglen, err, src_name, argnum, dst_name); } else { assert(strstr(err, "%d") == NULL, ""); jio_snprintf(msg, msglen, err, src_name, dst_name); --- 1456,1466 ---- if (dst_type == T_OBJECT) dst_name = (dst_klass != NULL) ? Klass::cast(dst_klass)->external_name() : "an unresolved class"; size_t msglen = strlen(err) + strlen(src_name) + strlen(dst_name) + (argnum < 10 ? 1 : 11); char* msg = NEW_RESOURCE_ARRAY(char, msglen + 1); ! if (!for_return) { assert(strstr(err, "%d") != NULL, ""); jio_snprintf(msg, msglen, err, src_name, argnum, dst_name); } else { assert(strstr(err, "%d") == NULL, ""); jio_snprintf(msg, msglen, err, src_name, dst_name);
*** 2178,2187 **** --- 2184,2194 ---- } } void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnum, TRAPS) { + Handle argument = java_lang_invoke_AdapterMethodHandle::argument(mh()); int argslot = java_lang_invoke_AdapterMethodHandle::vmargslot(mh()); jint conversion = java_lang_invoke_AdapterMethodHandle::conversion(mh()); jint conv_op = adapter_conversion_op(conversion); // adjust the adapter code to the internal EntryKind enumeration:
*** 2239,2262 **** ek_opt = _adapter_opt_l2i; vminfo = adapter_prim_to_prim_subword_vminfo(dest); } else if (src == T_DOUBLE && dest == T_FLOAT) { ek_opt = _adapter_opt_d2f; } else { ! assert(false, ""); } break; case 1 *4+ 2: if ((src == T_INT || is_subword_type(src)) && dest == T_LONG) { ek_opt = _adapter_opt_i2l; } else if (src == T_FLOAT && dest == T_DOUBLE) { ek_opt = _adapter_opt_f2d; } else { ! assert(false, ""); } break; default: ! assert(false, ""); break; } } break; --- 2246,2269 ---- ek_opt = _adapter_opt_l2i; vminfo = adapter_prim_to_prim_subword_vminfo(dest); } else if (src == T_DOUBLE && dest == T_FLOAT) { ek_opt = _adapter_opt_d2f; } else { ! goto throw_not_impl; // runs user code, hence could block } break; case 1 *4+ 2: if ((src == T_INT || is_subword_type(src)) && dest == T_LONG) { ek_opt = _adapter_opt_i2l; } else if (src == T_FLOAT && dest == T_DOUBLE) { ek_opt = _adapter_opt_f2d; } else { ! goto throw_not_impl; // runs user code, hence could block } break; default: ! goto throw_not_impl; // runs user code, hence could block break; } } break;
*** 2269,2279 **** break; case 2: ek_opt = _adapter_opt_unboxl; break; default: ! assert(false, ""); break; } } break; --- 2276,2286 ---- break; case 2: ek_opt = _adapter_opt_unboxl; break; default: ! goto throw_not_impl; break; } } break;
*** 2282,2291 **** --- 2289,2301 ---- assert(UseRicochetFrames, "else don't come here"); // vminfo will be the location to insert the return value vminfo = argslot; ek_opt = _adapter_opt_collect_ref; ensure_vmlayout_field(target, CHECK); + // for MethodHandleWalk: + if (java_lang_invoke_AdapterMethodHandle::is_instance(argument())) + ensure_vmlayout_field(argument, CHECK); if (!OptimizeMethodHandles) break; switch (type2size[src]) { case 1: ek_try = EntryKind(_adapter_opt_filter_S0_ref + argslot); if (ek_try < _adapter_opt_collect_LAST &&
*** 2309,2319 **** } // else downgrade to variable slot: ek_opt = _adapter_opt_collect_2_ref; break; default: ! assert(false, ""); break; } } break; --- 2319,2329 ---- } // else downgrade to variable slot: ek_opt = _adapter_opt_collect_2_ref; break; default: ! goto throw_not_impl; break; } } break;
*** 2333,2343 **** case 2: ek_opt = (!rotate ? _adapter_opt_swap_2 : rotate > 0 ? _adapter_opt_rot_2_up : _adapter_opt_rot_2_down); break; default: ! assert(false, ""); break; } } break; --- 2343,2353 ---- case 2: ek_opt = (!rotate ? _adapter_opt_swap_2 : rotate > 0 ? _adapter_opt_rot_2_up : _adapter_opt_rot_2_down); break; default: ! goto throw_not_impl; break; } } break;
*** 2400,2415 **** break; case _adapter_collect_args: { assert(UseRicochetFrames, "else don't come here"); ! int elem_slots = argument_slot_count( ! java_lang_invoke_MethodHandle::type( ! java_lang_invoke_AdapterMethodHandle::argument(mh()) ) ); // vminfo will be the location to insert the return value vminfo = argslot; ensure_vmlayout_field(target, CHECK); // general case: switch (dest) { default : if (!is_subword_type(dest)) goto throw_not_impl; // else fall through: --- 2410,2424 ---- break; case _adapter_collect_args: { assert(UseRicochetFrames, "else don't come here"); ! int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument())); // vminfo will be the location to insert the return value vminfo = argslot; ensure_vmlayout_field(target, CHECK); + ensure_vmlayout_field(argument, CHECK); // general case: switch (dest) { default : if (!is_subword_type(dest)) goto throw_not_impl; // else fall through:
*** 2470,2485 **** } case _adapter_fold_args: { assert(UseRicochetFrames, "else don't come here"); ! int elem_slots = argument_slot_count( ! java_lang_invoke_MethodHandle::type( ! java_lang_invoke_AdapterMethodHandle::argument(mh()) ) ); // vminfo will be the location to insert the return value vminfo = argslot + elem_slots; ensure_vmlayout_field(target, CHECK); switch (dest) { default : if (!is_subword_type(dest)) goto throw_not_impl; // else fall through: case T_INT : ek_opt = _adapter_opt_fold_int; break; --- 2479,2493 ---- } case _adapter_fold_args: { assert(UseRicochetFrames, "else don't come here"); ! int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument())); // vminfo will be the location to insert the return value vminfo = argslot + elem_slots; ensure_vmlayout_field(target, CHECK); + ensure_vmlayout_field(argument, CHECK); switch (dest) { default : if (!is_subword_type(dest)) goto throw_not_impl; // else fall through: case T_INT : ek_opt = _adapter_opt_fold_int; break;
*** 2525,2543 **** if (err == NULL) err = "unknown adapter type"; break; } ! if (err != NULL && (vminfo & CONV_VMINFO_MASK) != vminfo) { // should not happen, since vminfo is used to encode arg/slot indexes < 255 err = "vminfo overflow"; } ! if (err != NULL && !have_entry(ek_opt)) { err = "adapter stub for this kind of method handle is missing"; } if (err != NULL) { throw_InternalError_for_bad_conversion(conversion, err, THREAD); return; } --- 2533,2567 ---- if (err == NULL) err = "unknown adapter type"; break; } ! if (err == NULL && (vminfo & CONV_VMINFO_MASK) != vminfo) { // should not happen, since vminfo is used to encode arg/slot indexes < 255 err = "vminfo overflow"; } ! if (err == NULL && !have_entry(ek_opt)) { err = "adapter stub for this kind of method handle is missing"; } + if (err == NULL && ek_opt == ek_orig) { + switch (ek_opt) { + case _adapter_prim_to_prim: + case _adapter_ref_to_prim: + case _adapter_prim_to_ref: + case _adapter_swap_args: + case _adapter_rot_args: + case _adapter_collect_args: + case _adapter_fold_args: + case _adapter_spread_args: + // should be handled completely by optimized cases; see above + err = "init_AdapterMethodHandle should not issue this"; + break; + } + } + if (err != NULL) { throw_InternalError_for_bad_conversion(conversion, err, THREAD); return; }
src/share/vm/prims/methodHandles.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File