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