提交 730a6a98 编写于 作者: N never

7047961: JSR 292 MethodHandleWalk swap args doesn't handle T_LONG and T_DOUBLE properly

Reviewed-by: kvn, jrose
上级 7c843ca5
...@@ -141,6 +141,12 @@ BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int ...@@ -141,6 +141,12 @@ BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int
void MethodHandleChain::lose(const char* msg, TRAPS) { void MethodHandleChain::lose(const char* msg, TRAPS) {
_lose_message = msg; _lose_message = msg;
#ifdef ASSERT
if (Verbose) {
tty->print_cr(INTPTR_FORMAT " lose: %s", _method_handle(), msg);
print();
}
#endif
if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) { if (!THREAD->is_Java_thread() || ((JavaThread*)THREAD)->thread_state() != _thread_in_vm) {
// throw a preallocated exception // throw a preallocated exception
THROW_OOP(Universe::virtual_machine_error_instance()); THROW_OOP(Universe::virtual_machine_error_instance());
...@@ -149,6 +155,145 @@ void MethodHandleChain::lose(const char* msg, TRAPS) { ...@@ -149,6 +155,145 @@ void MethodHandleChain::lose(const char* msg, TRAPS) {
} }
#ifdef ASSERT
static const char* adapter_ops[] = {
"retype_only" ,
"retype_raw" ,
"check_cast" ,
"prim_to_prim" ,
"ref_to_prim" ,
"prim_to_ref" ,
"swap_args" ,
"rot_args" ,
"dup_args" ,
"drop_args" ,
"collect_args" ,
"spread_args" ,
"fold_args"
};
static const char* adapter_op_to_string(int op) {
if (op >= 0 && op < (int)ARRAY_SIZE(adapter_ops))
return adapter_ops[op];
return "unknown_op";
}
void MethodHandleChain::print(Handle mh) {
EXCEPTION_MARK;
MethodHandleChain mhc(mh, THREAD);
if (HAS_PENDING_EXCEPTION) {
oop ex = THREAD->pending_exception();
CLEAR_PENDING_EXCEPTION;
ex->print();
return;
}
mhc.print();
}
void MethodHandleChain::print() {
EXCEPTION_MARK;
print_impl(THREAD);
if (HAS_PENDING_EXCEPTION) {
oop ex = THREAD->pending_exception();
CLEAR_PENDING_EXCEPTION;
ex->print();
}
}
void MethodHandleChain::print_impl(TRAPS) {
ResourceMark rm;
MethodHandleChain chain(_root, CHECK);
for (;;) {
tty->print(INTPTR_FORMAT ": ", chain.method_handle()());
if (chain.is_bound()) {
tty->print("bound: arg_type %s arg_slot %d",
type2name(chain.bound_arg_type()),
chain.bound_arg_slot());
oop o = chain.bound_arg_oop();
if (o != NULL) {
if (o->is_instance()) {
tty->print(" instance %s", o->klass()->klass_part()->internal_name());
} else {
o->print();
}
}
} else if (chain.is_adapter()) {
tty->print("adapter: arg_slot %d conversion op %s",
chain.adapter_arg_slot(),
adapter_op_to_string(chain.adapter_conversion_op()));
switch (chain.adapter_conversion_op()) {
case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY:
case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW:
case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST:
case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM:
case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM:
case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF:
break;
case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS:
case java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS: {
int dest_arg_slot = chain.adapter_conversion_vminfo();
tty->print(" dest_arg_slot %d type %s", dest_arg_slot, type2name(chain.adapter_conversion_src_type()));
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS:
case java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS: {
int dup_slots = chain.adapter_conversion_stack_pushes();
tty->print(" pushes %d", dup_slots);
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS:
case java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS: {
int coll_slots = chain.MethodHandle_vmslots();
tty->print(" coll_slots %d", coll_slots);
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS: {
// Check the required length.
int spread_slots = 1 + chain.adapter_conversion_stack_pushes();
tty->print(" spread_slots %d", spread_slots);
break;
}
default:
tty->print_cr("bad adapter conversion");
break;
}
} else {
// DMH
tty->print("direct: ");
chain.last_method_oop()->print_short_name(tty);
}
tty->print(" (");
objArrayOop ptypes = java_lang_invoke_MethodType::ptypes(chain.method_type_oop());
for (int i = ptypes->length() - 1; i >= 0; i--) {
BasicType t = java_lang_Class::as_BasicType(ptypes->obj_at(i));
if (t == T_ARRAY) t = T_OBJECT;
tty->print("%c", type2char(t));
if (t == T_LONG || t == T_DOUBLE) tty->print("_");
}
tty->print(")");
BasicType rtype = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(chain.method_type_oop()));
if (rtype == T_ARRAY) rtype = T_OBJECT;
tty->print("%c", type2char(rtype));
tty->cr();
if (!chain.is_last()) {
chain.next(CHECK);
} else {
break;
}
}
}
#endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// MethodHandleWalker // MethodHandleWalker
...@@ -205,10 +350,16 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -205,10 +350,16 @@ MethodHandleWalker::walk(TRAPS) {
if (chain().is_adapter()) { if (chain().is_adapter()) {
int conv_op = chain().adapter_conversion_op(); int conv_op = chain().adapter_conversion_op();
int arg_slot = chain().adapter_arg_slot(); int arg_slot = chain().adapter_arg_slot();
SlotState* arg_state = slot_state(arg_slot);
if (arg_state == NULL // Check that the arg_slot is valid. In most cases it must be
&& conv_op > java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW) { // within range of the current arguments but there are some
lose("bad argument index", CHECK_(empty)); // exceptions. Those are sanity checked in their implemention
// below.
if ((arg_slot < 0 || arg_slot >= _outgoing.length()) &&
conv_op > java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW &&
conv_op != java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS &&
conv_op != java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS) {
lose(err_msg("bad argument index %d", arg_slot), CHECK_(empty));
} }
bool retain_original_args = false; // used by fold/collect logic bool retain_original_args = false; // used by fold/collect logic
...@@ -237,8 +388,7 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -237,8 +388,7 @@ MethodHandleWalker::walk(TRAPS) {
// Argument types. // Argument types.
for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) { for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) {
SlotState* arg_state = slot_state(slot); if (arg_type(slot) == T_VOID) continue;
if (arg_state->_type == T_VOID) continue;
klassOop src_klass = NULL; klassOop src_klass = NULL;
klassOop dst_klass = NULL; klassOop dst_klass = NULL;
...@@ -262,8 +412,8 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -262,8 +412,8 @@ MethodHandleWalker::walk(TRAPS) {
klassOop dest_klass = NULL; klassOop dest_klass = NULL;
BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass); BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass);
assert(dest == T_OBJECT, ""); assert(dest == T_OBJECT, "");
assert(dest == arg_state->_type, ""); ArgToken arg = _outgoing.at(arg_slot);
ArgToken arg = arg_state->_arg; assert(dest == arg.basic_type(), "");
ArgToken new_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg, CHECK_(empty)); ArgToken new_arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg, CHECK_(empty));
assert(!arg.has_index() || arg.index() == new_arg.index(), "should be the same index"); assert(!arg.has_index() || arg.index() == new_arg.index(), "should be the same index");
debug_only(dest_klass = (klassOop)badOop); debug_only(dest_klass = (klassOop)badOop);
...@@ -274,8 +424,8 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -274,8 +424,8 @@ MethodHandleWalker::walk(TRAPS) {
// i2l, etc., on the Nth outgoing argument in place // i2l, etc., on the Nth outgoing argument in place
BasicType src = chain().adapter_conversion_src_type(), BasicType src = chain().adapter_conversion_src_type(),
dest = chain().adapter_conversion_dest_type(); dest = chain().adapter_conversion_dest_type();
ArgToken arg = _outgoing.at(arg_slot);
Bytecodes::Code bc = conversion_code(src, dest); Bytecodes::Code bc = conversion_code(src, dest);
ArgToken arg = arg_state->_arg;
if (bc == Bytecodes::_nop) { if (bc == Bytecodes::_nop) {
break; break;
} else if (bc != Bytecodes::_illegal) { } else if (bc != Bytecodes::_illegal) {
...@@ -289,7 +439,7 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -289,7 +439,7 @@ MethodHandleWalker::walk(TRAPS) {
} }
} }
if (bc == Bytecodes::_illegal) { if (bc == Bytecodes::_illegal) {
lose("bad primitive conversion", CHECK_(empty)); lose(err_msg("bad primitive conversion for %s -> %s", type2name(src), type2name(dest)), CHECK_(empty));
} }
change_argument(src, arg_slot, dest, arg); change_argument(src, arg_slot, dest, arg);
break; break;
...@@ -298,7 +448,7 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -298,7 +448,7 @@ MethodHandleWalker::walk(TRAPS) {
case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM: { case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM: {
// checkcast to wrapper type & call intValue, etc. // checkcast to wrapper type & call intValue, etc.
BasicType dest = chain().adapter_conversion_dest_type(); BasicType dest = chain().adapter_conversion_dest_type();
ArgToken arg = arg_state->_arg; ArgToken arg = _outgoing.at(arg_slot);
arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest), arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest),
Bytecodes::_checkcast, arg, CHECK_(empty)); Bytecodes::_checkcast, arg, CHECK_(empty));
vmIntrinsics::ID unboxer = vmIntrinsics::for_unboxing(dest); vmIntrinsics::ID unboxer = vmIntrinsics::for_unboxing(dest);
...@@ -316,11 +466,11 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -316,11 +466,11 @@ MethodHandleWalker::walk(TRAPS) {
case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF: { case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF: {
// call wrapper type.valueOf // call wrapper type.valueOf
BasicType src = chain().adapter_conversion_src_type(); BasicType src = chain().adapter_conversion_src_type();
ArgToken arg = arg_state->_arg;
vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src); vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src);
if (boxer == vmIntrinsics::_none) { if (boxer == vmIntrinsics::_none) {
lose("no boxing method", CHECK_(empty)); lose("no boxing method", CHECK_(empty));
} }
ArgToken arg = _outgoing.at(arg_slot);
ArgToken arglist[2]; ArgToken arglist[2];
arglist[0] = arg; // outgoing value arglist[0] = arg; // outgoing value
arglist[1] = ArgToken(); // sentinel arglist[1] = ArgToken(); // sentinel
...@@ -331,40 +481,45 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -331,40 +481,45 @@ MethodHandleWalker::walk(TRAPS) {
case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: { case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: {
int dest_arg_slot = chain().adapter_conversion_vminfo(); int dest_arg_slot = chain().adapter_conversion_vminfo();
if (!slot_has_argument(dest_arg_slot)) { if (!has_argument(dest_arg_slot)) {
lose("bad swap index", CHECK_(empty)); lose("bad swap index", CHECK_(empty));
} }
// a simple swap between two arguments // a simple swap between two arguments
SlotState* dest_arg_state = slot_state(dest_arg_slot); if (arg_slot > dest_arg_slot) {
SlotState temp = (*dest_arg_state); int tmp = arg_slot;
(*dest_arg_state) = (*arg_state); arg_slot = dest_arg_slot;
(*arg_state) = temp; dest_arg_slot = tmp;
}
ArgToken a1 = _outgoing.at(arg_slot);
ArgToken a2 = _outgoing.at(dest_arg_slot);
change_argument(a2.basic_type(), dest_arg_slot, a1);
change_argument(a1.basic_type(), arg_slot, a2);
break; break;
} }
case java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS: { case java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS: {
int dest_arg_slot = chain().adapter_conversion_vminfo(); int dest_arg_slot = chain().adapter_conversion_vminfo();
if (!slot_has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) { if (!has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) {
lose("bad rotate index", CHECK_(empty)); lose("bad rotate index", CHECK_(empty));
} }
SlotState* dest_arg_state = slot_state(dest_arg_slot);
// Rotate the source argument (plus following N slots) into the // Rotate the source argument (plus following N slots) into the
// position occupied by the dest argument (plus following N slots). // position occupied by the dest argument (plus following N slots).
int rotate_count = type2size[dest_arg_state->_type]; int rotate_count = type2size[chain().adapter_conversion_src_type()];
// (no other rotate counts are currently supported) // (no other rotate counts are currently supported)
if (arg_slot < dest_arg_slot) { if (arg_slot < dest_arg_slot) {
for (int i = 0; i < rotate_count; i++) { for (int i = 0; i < rotate_count; i++) {
SlotState temp = _outgoing.at(arg_slot); ArgToken temp = _outgoing.at(arg_slot);
_outgoing.remove_at(arg_slot); _outgoing.remove_at(arg_slot);
_outgoing.insert_before(dest_arg_slot + rotate_count - 1, temp); _outgoing.insert_before(dest_arg_slot + rotate_count - 1, temp);
} }
} else { // arg_slot > dest_arg_slot } else { // arg_slot > dest_arg_slot
for (int i = 0; i < rotate_count; i++) { for (int i = 0; i < rotate_count; i++) {
SlotState temp = _outgoing.at(arg_slot + rotate_count - 1); ArgToken temp = _outgoing.at(arg_slot + rotate_count - 1);
_outgoing.remove_at(arg_slot + rotate_count - 1); _outgoing.remove_at(arg_slot + rotate_count - 1);
_outgoing.insert_before(dest_arg_slot, temp); _outgoing.insert_before(dest_arg_slot, temp);
} }
} }
assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
break; break;
} }
...@@ -374,11 +529,11 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -374,11 +529,11 @@ MethodHandleWalker::walk(TRAPS) {
lose("bad dup count", CHECK_(empty)); lose("bad dup count", CHECK_(empty));
} }
for (int i = 0; i < dup_slots; i++) { for (int i = 0; i < dup_slots; i++) {
SlotState* dup = slot_state(arg_slot + 2*i); ArgToken dup = _outgoing.at(arg_slot + 2*i);
if (dup == NULL) break; // safety net if (dup.basic_type() != T_VOID) _outgoing_argc += 1;
if (dup->_type != T_VOID) _outgoing_argc += 1; _outgoing.insert_before(i, dup);
_outgoing.insert_before(i, (*dup));
} }
assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
break; break;
} }
...@@ -388,11 +543,11 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -388,11 +543,11 @@ MethodHandleWalker::walk(TRAPS) {
lose("bad drop count", CHECK_(empty)); lose("bad drop count", CHECK_(empty));
} }
for (int i = 0; i < drop_slots; i++) { for (int i = 0; i < drop_slots; i++) {
SlotState* drop = slot_state(arg_slot); ArgToken drop = _outgoing.at(arg_slot);
if (drop == NULL) break; // safety net if (drop.basic_type() != T_VOID) _outgoing_argc -= 1;
if (drop->_type != T_VOID) _outgoing_argc -= 1;
_outgoing.remove_at(arg_slot); _outgoing.remove_at(arg_slot);
} }
assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
break; break;
} }
...@@ -415,10 +570,10 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -415,10 +570,10 @@ MethodHandleWalker::walk(TRAPS) {
lose("bad fold/collect arg slot", CHECK_(empty)); lose("bad fold/collect arg slot", CHECK_(empty));
} }
for (int i = 0, slot = arg_slot + coll_slots - 1; slot >= arg_slot; slot--) { for (int i = 0, slot = arg_slot + coll_slots - 1; slot >= arg_slot; slot--) {
SlotState* arg_state = slot_state(slot); ArgToken arg_state = _outgoing.at(slot);
BasicType arg_type = arg_state->_type; BasicType arg_type = arg_state.basic_type();
if (arg_type == T_VOID) continue; if (arg_type == T_VOID) continue;
ArgToken arg = _outgoing.at(slot)._arg; ArgToken arg = _outgoing.at(slot);
if (i >= argc) { lose("bad fold/collect arg", CHECK_(empty)); } if (i >= argc) { lose("bad fold/collect arg", CHECK_(empty)); }
arglist[1+i] = arg; arglist[1+i] = arg;
if (!retain_original_args) if (!retain_original_args)
...@@ -466,8 +621,9 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -466,8 +621,9 @@ MethodHandleWalker::walk(TRAPS) {
debug_only(element_klass_oop = (klassOop)badOop); debug_only(element_klass_oop = (klassOop)badOop);
// Fetch the argument, which we will cast to the required array type. // Fetch the argument, which we will cast to the required array type.
assert(arg_state->_type == T_OBJECT, ""); ArgToken arg = _outgoing.at(arg_slot);
ArgToken array_arg = arg_state->_arg; assert(arg.basic_type() == T_OBJECT, "");
ArgToken array_arg = arg;
array_arg = make_conversion(T_OBJECT, array_klass(), Bytecodes::_checkcast, array_arg, CHECK_(empty)); array_arg = make_conversion(T_OBJECT, array_klass(), Bytecodes::_checkcast, array_arg, CHECK_(empty));
change_argument(T_OBJECT, arg_slot, T_VOID, ArgToken(tt_void)); change_argument(T_OBJECT, arg_slot, T_VOID, ArgToken(tt_void));
...@@ -534,10 +690,10 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -534,10 +690,10 @@ MethodHandleWalker::walk(TRAPS) {
} else { } else {
jvalue arg_value; jvalue arg_value;
BasicType bt = java_lang_boxing_object::get_value(arg_oop, &arg_value); BasicType bt = java_lang_boxing_object::get_value(arg_oop, &arg_value);
if (bt == arg_type) { if (bt == arg_type || (bt == T_INT && is_subword_type(arg_type))) {
arg = make_prim_constant(arg_type, &arg_value, CHECK_(empty)); arg = make_prim_constant(arg_type, &arg_value, CHECK_(empty));
} else { } else {
lose("bad bound value", CHECK_(empty)); lose(err_msg("bad bound value: arg_type %s boxing %s", type2name(arg_type), type2name(bt)), CHECK_(empty));
} }
} }
DEBUG_ONLY(arg_oop = badOop); DEBUG_ONLY(arg_oop = badOop);
...@@ -557,9 +713,9 @@ MethodHandleWalker::walk(TRAPS) { ...@@ -557,9 +713,9 @@ MethodHandleWalker::walk(TRAPS) {
ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, _outgoing.length() + 1); ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, _outgoing.length() + 1);
int ap = 0; int ap = 0;
for (int i = _outgoing.length() - 1; i >= 0; i--) { for (int i = _outgoing.length() - 1; i >= 0; i--) {
SlotState* arg_state = slot_state(i); ArgToken arg_state = _outgoing.at(i);
if (arg_state->_type == T_VOID) continue; if (arg_state.basic_type() == T_VOID) continue;
arglist[ap++] = _outgoing.at(i)._arg; arglist[ap++] = _outgoing.at(i);
} }
assert(ap == _outgoing_argc, ""); assert(ap == _outgoing_argc, "");
arglist[ap] = ArgToken(); // add a sentinel, for the sake of asserts arglist[ap] = ArgToken(); // add a sentinel, for the sake of asserts
...@@ -579,7 +735,7 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) { ...@@ -579,7 +735,7 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
_outgoing_argc = nptypes; _outgoing_argc = nptypes;
int argp = nptypes - 1; int argp = nptypes - 1;
if (argp >= 0) { if (argp >= 0) {
_outgoing.at_grow(argp, make_state(T_VOID, ArgToken(tt_void))); // presize _outgoing.at_grow(argp, ArgToken(tt_void)); // presize
} }
for (int i = 0; i < nptypes; i++) { for (int i = 0; i < nptypes; i++) {
klassOop arg_type_klass = NULL; klassOop arg_type_klass = NULL;
...@@ -587,10 +743,10 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) { ...@@ -587,10 +743,10 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
int index = new_local_index(arg_type); int index = new_local_index(arg_type);
ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK); ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK);
DEBUG_ONLY(arg_type_klass = (klassOop) NULL); DEBUG_ONLY(arg_type_klass = (klassOop) NULL);
_outgoing.at_put(argp, make_state(arg_type, arg)); _outgoing.at_put(argp, arg);
if (type2size[arg_type] == 2) { if (type2size[arg_type] == 2) {
// add the extra slot, so we can model the JVM stack // add the extra slot, so we can model the JVM stack
_outgoing.insert_before(argp+1, make_state(T_VOID, ArgToken(tt_void))); _outgoing.insert_before(argp+1, ArgToken(tt_void));
} }
--argp; --argp;
} }
...@@ -599,7 +755,29 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) { ...@@ -599,7 +755,29 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
BasicType ret_type = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(mtype()), &ret_type_klass); BasicType ret_type = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(mtype()), &ret_type_klass);
ArgToken ret = make_parameter(ret_type, ret_type_klass, -1, CHECK); ArgToken ret = make_parameter(ret_type, ret_type_klass, -1, CHECK);
// ignore ret; client can catch it if needed // ignore ret; client can catch it if needed
assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
verify_args_and_signature(CHECK);
}
#ifdef ASSERT
void MethodHandleWalker::verify_args_and_signature(TRAPS) {
int index = _outgoing.length() - 1;
objArrayOop ptypes = java_lang_invoke_MethodType::ptypes(chain().method_type_oop());
for (int i = 0, limit = ptypes->length(); i < limit; i++) {
BasicType t = java_lang_Class::as_BasicType(ptypes->obj_at(i));
if (t == T_ARRAY) t = T_OBJECT;
if (t == T_LONG || t == T_DOUBLE) {
assert(T_VOID == _outgoing.at(index).basic_type(), "types must match");
index--;
}
assert(t == _outgoing.at(index).basic_type(), "types must match");
index--;
}
} }
#endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -607,30 +785,31 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) { ...@@ -607,30 +785,31 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
// //
// This is messy because some kinds of arguments are paired with // This is messy because some kinds of arguments are paired with
// companion slots containing an empty value. // companion slots containing an empty value.
void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType new_type, void MethodHandleWalker::change_argument(BasicType old_type, int slot, const ArgToken& new_arg) {
const ArgToken& new_arg) { BasicType new_type = new_arg.basic_type();
int old_size = type2size[old_type]; int old_size = type2size[old_type];
int new_size = type2size[new_type]; int new_size = type2size[new_type];
if (old_size == new_size) { if (old_size == new_size) {
// simple case first // simple case first
_outgoing.at_put(slot, make_state(new_type, new_arg)); _outgoing.at_put(slot, new_arg);
} else if (old_size > new_size) { } else if (old_size > new_size) {
for (int i = old_size - 1; i >= new_size; i--) { for (int i = old_size - 1; i >= new_size; i--) {
assert((i != 0) == (_outgoing.at(slot + i)._type == T_VOID), ""); assert((i != 0) == (_outgoing.at(slot + i).basic_type() == T_VOID), "");
_outgoing.remove_at(slot + i); _outgoing.remove_at(slot + i);
} }
if (new_size > 0) if (new_size > 0)
_outgoing.at_put(slot, make_state(new_type, new_arg)); _outgoing.at_put(slot, new_arg);
else else
_outgoing_argc -= 1; // deleted a real argument _outgoing_argc -= 1; // deleted a real argument
} else { } else {
for (int i = old_size; i < new_size; i++) { for (int i = old_size; i < new_size; i++) {
_outgoing.insert_before(slot + i, make_state(T_VOID, ArgToken(tt_void))); _outgoing.insert_before(slot + i, ArgToken(tt_void));
} }
_outgoing.at_put(slot, make_state(new_type, new_arg)); _outgoing.at_put(slot, new_arg);
if (old_size == 0) if (old_size == 0)
_outgoing_argc += 1; // inserted a real argument _outgoing_argc += 1; // inserted a real argument
} }
assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
} }
...@@ -638,8 +817,15 @@ void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType ...@@ -638,8 +817,15 @@ void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType
int MethodHandleWalker::argument_count_slow() { int MethodHandleWalker::argument_count_slow() {
int args_seen = 0; int args_seen = 0;
for (int i = _outgoing.length() - 1; i >= 0; i--) { for (int i = _outgoing.length() - 1; i >= 0; i--) {
if (_outgoing.at(i)._type != T_VOID) { if (_outgoing.at(i).basic_type() != T_VOID) {
++args_seen; ++args_seen;
if (_outgoing.at(i).basic_type() == T_LONG ||
_outgoing.at(i).basic_type() == T_DOUBLE) {
assert(_outgoing.at(i + 1).basic_type() == T_VOID, "should only follow two word");
}
} else {
assert(_outgoing.at(i - 1).basic_type() == T_LONG ||
_outgoing.at(i - 1).basic_type() == T_DOUBLE, "should only follow two word");
} }
} }
return args_seen; return args_seen;
...@@ -663,7 +849,7 @@ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, boo ...@@ -663,7 +849,7 @@ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, boo
ArgToken arglist[2]; ArgToken arglist[2];
if (!for_return) { if (!for_return) {
// argument type conversion // argument type conversion
ArgToken arg = _outgoing.at(slot)._arg; ArgToken arg = _outgoing.at(slot);
assert(arg.token_type() >= tt_symbolic || src == arg.basic_type(), "sanity"); assert(arg.token_type() >= tt_symbolic || src == arg.basic_type(), "sanity");
arglist[0] = arg; // outgoing 'this' arglist[0] = arg; // outgoing 'this'
arglist[1] = ArgToken(); // sentinel arglist[1] = ArgToken(); // sentinel
...@@ -683,7 +869,7 @@ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, boo ...@@ -683,7 +869,7 @@ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, boo
// ref-to-prim: discard ref, push zero // ref-to-prim: discard ref, push zero
lose("requested ref-to-prim conversion not expected", CHECK); lose("requested ref-to-prim conversion not expected", CHECK);
} else { } else {
lose("requested raw conversion not allowed", CHECK); lose(err_msg("requested raw conversion not allowed: %s -> %s", type2name(src), type2name(dst)), CHECK);
} }
} }
} }
...@@ -963,6 +1149,7 @@ void MethodHandleCompiler::emit_store(BasicType bt, int index) { ...@@ -963,6 +1149,7 @@ void MethodHandleCompiler::emit_store(BasicType bt, int index) {
void MethodHandleCompiler::emit_load_constant(ArgToken arg) { void MethodHandleCompiler::emit_load_constant(ArgToken arg) {
BasicType bt = arg.basic_type(); BasicType bt = arg.basic_type();
if (is_subword_type(bt)) bt = T_INT;
switch (bt) { switch (bt) {
case T_INT: { case T_INT: {
jint value = arg.get_jint(); jint value = arg.get_jint();
...@@ -1066,11 +1253,15 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co ...@@ -1066,11 +1253,15 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co
emit_store(srctype, index); emit_store(srctype, index);
break; break;
case Bytecodes::_nop:
// nothing to do
return src;
default: default:
if (op == Bytecodes::_illegal) if (op == Bytecodes::_illegal)
lose("no such primitive conversion", THREAD); lose(err_msg("no such primitive conversion: %s -> %s", type2name(src.basic_type()), type2name(type)), THREAD);
else else
lose("bad primitive conversion op", THREAD); lose(err_msg("bad primitive conversion op: %s", Bytecodes::name(op)), THREAD);
return make_prim_constant(type, &zero_jvalue, THREAD); return make_prim_constant(type, &zero_jvalue, THREAD);
} }
...@@ -1300,7 +1491,7 @@ int MethodHandleCompiler::cpool_primitive_put(BasicType bt, jvalue* con) { ...@@ -1300,7 +1491,7 @@ int MethodHandleCompiler::cpool_primitive_put(BasicType bt, jvalue* con) {
// for (int i = 1, imax = _constants.length(); i < imax; i++) { // for (int i = 1, imax = _constants.length(); i < imax; i++) {
// ConstantValue* con = _constants.at(i); // ConstantValue* con = _constants.at(i);
// if (con != NULL && con->is_primitive() && con->_type == bt) { // if (con != NULL && con->is_primitive() && con.basic_type() == bt) {
// bool match = false; // bool match = false;
// switch (type2size[bt]) { // switch (type2size[bt]) {
// case 1: if (pcon->_value.i == con->i) match = true; break; // case 1: if (pcon->_value.i == con->i) match = true; break;
...@@ -1451,8 +1642,8 @@ private: ...@@ -1451,8 +1642,8 @@ private:
_strbuf.reset(); _strbuf.reset();
return s; return s;
} }
ArgToken token(const char* str) { ArgToken token(const char* str, BasicType type) {
return ArgToken(str); return ArgToken(str, type);
} }
const char* string(ArgToken token) { const char* string(ArgToken token) {
return token.str(); return token.str();
...@@ -1474,12 +1665,12 @@ private: ...@@ -1474,12 +1665,12 @@ private:
} }
ArgToken maybe_make_temp(const char* statement_op, BasicType type, const char* temp_name) { ArgToken maybe_make_temp(const char* statement_op, BasicType type, const char* temp_name) {
const char* value = strbuf(); const char* value = strbuf();
if (!_verbose) return token(value); if (!_verbose) return token(value, type);
// make an explicit binding for each separate value // make an explicit binding for each separate value
_strbuf.print("%s%d", temp_name, ++_temp_num); _strbuf.print("%s%d", temp_name, ++_temp_num);
const char* temp = strbuf(); const char* temp = strbuf();
_out->print("\n %s %s %s = %s;", statement_op, type2name(type), temp, value); _out->print("\n %s %s %s = %s;", statement_op, type2name(type), temp, value);
return token(temp); return token(temp, type);
} }
public: public:
...@@ -1495,7 +1686,7 @@ public: ...@@ -1495,7 +1686,7 @@ public:
virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
if (argnum < 0) { if (argnum < 0) {
end_params(); end_params();
return token("return"); return token("return", type);
} }
if ((_param_state & 1) == 0) { if ((_param_state & 1) == 0) {
_param_state |= 1; _param_state |= 1;
...@@ -1510,7 +1701,7 @@ public: ...@@ -1510,7 +1701,7 @@ public:
const char* arg = strbuf(); const char* arg = strbuf();
put_type_name(type, tk, _out); put_type_name(type, tk, _out);
_out->print(" %s", arg); _out->print(" %s", arg);
return token(arg); return token(arg, type);
} }
virtual ArgToken make_oop_constant(oop con, TRAPS) { virtual ArgToken make_oop_constant(oop con, TRAPS) {
if (con == NULL) if (con == NULL)
...@@ -1597,7 +1788,7 @@ public: ...@@ -1597,7 +1788,7 @@ public:
out->print("\n"); out->print("\n");
} }
static void print(Handle root, bool verbose = Verbose, outputStream* out = tty) { static void print(Handle root, bool verbose = Verbose, outputStream* out = tty) {
EXCEPTION_MARK; Thread* THREAD = Thread::current();
ResourceMark rm; ResourceMark rm;
MethodHandlePrinter printer(root, verbose, out, THREAD); MethodHandlePrinter printer(root, verbose, out, THREAD);
if (!HAS_PENDING_EXCEPTION) if (!HAS_PENDING_EXCEPTION)
......
...@@ -56,6 +56,10 @@ private: ...@@ -56,6 +56,10 @@ private:
int BoundMethodHandle_vmargslot() { return java_lang_invoke_BoundMethodHandle::vmargslot(method_handle_oop()); } int BoundMethodHandle_vmargslot() { return java_lang_invoke_BoundMethodHandle::vmargslot(method_handle_oop()); }
int AdapterMethodHandle_conversion() { return java_lang_invoke_AdapterMethodHandle::conversion(method_handle_oop()); } int AdapterMethodHandle_conversion() { return java_lang_invoke_AdapterMethodHandle::conversion(method_handle_oop()); }
#ifdef ASSERT
void print_impl(TRAPS);
#endif
public: public:
MethodHandleChain(Handle root, TRAPS) MethodHandleChain(Handle root, TRAPS)
: _root(root) : _root(root)
...@@ -99,6 +103,14 @@ public: ...@@ -99,6 +103,14 @@ public:
void lose(const char* msg, TRAPS); void lose(const char* msg, TRAPS);
const char* lose_message() { return _lose_message; } const char* lose_message() { return _lose_message; }
#ifdef ASSERT
// Print a symbolic description of a method handle chain, including
// the signature for each method. The signatures are printed in
// slot order to make it easier to understand.
void print();
static void print(Handle mh);
#endif
}; };
...@@ -126,7 +138,7 @@ public: ...@@ -126,7 +138,7 @@ public:
Handle _handle; Handle _handle;
public: public:
ArgToken(TokenType tt = tt_illegal) : _tt(tt) { ArgToken(TokenType tt = tt_illegal) : _tt(tt), _bt(tt == tt_void ? T_VOID : T_ILLEGAL) {
assert(tt == tt_illegal || tt == tt_void, "invalid token type"); assert(tt == tt_illegal || tt == tt_void, "invalid token type");
} }
...@@ -135,11 +147,11 @@ public: ...@@ -135,11 +147,11 @@ public:
_value.i = index; _value.i = index;
} }
ArgToken(BasicType bt, jvalue value) : _tt(tt_constant), _bt(bt), _value(value) {} ArgToken(BasicType bt, jvalue value) : _tt(tt_constant), _bt(bt), _value(value) { assert(_bt != T_OBJECT, "wrong constructor"); }
ArgToken(BasicType bt, Handle value) : _tt(tt_constant), _bt(bt), _handle(value) {} ArgToken(Handle handle) : _tt(tt_constant), _bt(T_OBJECT), _handle(handle) {}
ArgToken(const char* str) : _tt(tt_symbolic), _bt(T_LONG) { ArgToken(const char* str, BasicType type) : _tt(tt_symbolic), _bt(type) {
_value.j = (intptr_t)str; _value.j = (intptr_t)str;
} }
...@@ -147,27 +159,15 @@ public: ...@@ -147,27 +159,15 @@ public:
BasicType basic_type() const { return _bt; } BasicType basic_type() const { return _bt; }
bool has_index() const { return _tt == tt_parameter || _tt == tt_temporary; } bool has_index() const { return _tt == tt_parameter || _tt == tt_temporary; }
int index() const { assert(has_index(), "must have index");; return _value.i; } int index() const { assert(has_index(), "must have index");; return _value.i; }
Handle object() const { assert(_tt == tt_constant, "value type"); return _handle; } Handle object() const { assert(_bt == T_OBJECT, "wrong accessor"); assert(_tt == tt_constant, "value type"); return _handle; }
const char* str() const { assert(_tt == tt_symbolic, "string type"); return (const char*)_value.j; } const char* str() const { assert(_tt == tt_symbolic, "string type"); return (const char*)(intptr_t)_value.j; }
jint get_jint() const { assert(_tt == tt_constant, "value types"); return _value.i; } jint get_jint() const { assert(_bt == T_INT || is_subword_type(_bt), "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.i; }
jlong get_jlong() const { assert(_tt == tt_constant, "value types"); return _value.j; } jlong get_jlong() const { assert(_bt == T_LONG, "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.j; }
jfloat get_jfloat() const { assert(_tt == tt_constant, "value types"); return _value.f; } jfloat get_jfloat() const { assert(_bt == T_FLOAT, "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.f; }
jdouble get_jdouble() const { assert(_tt == tt_constant, "value types"); return _value.d; } jdouble get_jdouble() const { assert(_bt == T_DOUBLE, "wrong accessor"); assert(_tt == tt_constant, "value types"); return _value.d; }
}; };
// Abstract interpretation state:
struct SlotState {
BasicType _type;
ArgToken _arg;
SlotState() : _type(), _arg() {}
};
static SlotState make_state(BasicType type, ArgToken arg) {
SlotState ss;
ss._type = type; ss._arg = arg;
return ss;
}
private: private:
MethodHandleChain _chain; MethodHandleChain _chain;
bool _for_invokedynamic; bool _for_invokedynamic;
...@@ -177,33 +177,29 @@ private: ...@@ -177,33 +177,29 @@ private:
// TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array. // TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array.
// If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1). // If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1).
// If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID. // If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID.
GrowableArray<SlotState> _outgoing; // current outgoing parameter slots GrowableArray<ArgToken> _outgoing; // current outgoing parameter slots
int _outgoing_argc; // # non-empty outgoing slots int _outgoing_argc; // # non-empty outgoing slots
// Replace a value of type old_type at slot (and maybe slot+1) with the new value. // Replace a value of type old_type at slot (and maybe slot+1) with the new value.
// If old_type != T_VOID, remove the old argument at that point. // If old_type != T_VOID, remove the old argument at that point.
// If new_type != T_VOID, insert the new argument at that point. // If new_type != T_VOID, insert the new argument at that point.
// Insert or delete a second empty slot as needed. // Insert or delete a second empty slot as needed.
void change_argument(BasicType old_type, int slot, BasicType new_type, const ArgToken& new_arg); void change_argument(BasicType old_type, int slot, const ArgToken& new_arg);
void change_argument(BasicType old_type, int slot, BasicType type, const ArgToken& new_arg) {
assert(type == new_arg.basic_type(), "must agree");
change_argument(old_type, slot, new_arg);
}
// Raw retype conversions for OP_RAW_RETYPE. // Raw retype conversions for OP_RAW_RETYPE.
void retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS); void retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS);
void retype_raw_argument_type(BasicType src, BasicType dst, int slot, TRAPS) { retype_raw_conversion(src, dst, false, slot, CHECK); } void retype_raw_argument_type(BasicType src, BasicType dst, int slot, TRAPS) { retype_raw_conversion(src, dst, false, slot, CHECK); }
void retype_raw_return_type( BasicType src, BasicType dst, TRAPS) { retype_raw_conversion(src, dst, true, -1, CHECK); } void retype_raw_return_type( BasicType src, BasicType dst, TRAPS) { retype_raw_conversion(src, dst, true, -1, CHECK); }
SlotState* slot_state(int slot) { BasicType arg_type(int slot) {
if (slot < 0 || slot >= _outgoing.length()) return _outgoing.at(slot).basic_type();
return NULL;
return _outgoing.adr_at(slot);
}
BasicType slot_type(int slot) {
SlotState* ss = slot_state(slot);
if (ss == NULL)
return T_ILLEGAL;
return ss->_type;
} }
bool slot_has_argument(int slot) { bool has_argument(int slot) {
return slot_type(slot) < T_VOID; return arg_type(slot) < T_VOID;
} }
#ifdef ASSERT #ifdef ASSERT
...@@ -215,6 +211,8 @@ private: ...@@ -215,6 +211,8 @@ private:
void walk_incoming_state(TRAPS); void walk_incoming_state(TRAPS);
void verify_args_and_signature(TRAPS) NOT_DEBUG_RETURN;
public: public:
MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS) MethodHandleWalker(Handle root, bool for_invokedynamic, TRAPS)
: _chain(root, THREAD), : _chain(root, THREAD),
...@@ -421,7 +419,7 @@ private: ...@@ -421,7 +419,7 @@ private:
} }
virtual ArgToken make_oop_constant(oop con, TRAPS) { virtual ArgToken make_oop_constant(oop con, TRAPS) {
Handle h(THREAD, con); Handle h(THREAD, con);
return ArgToken(T_OBJECT, h); return ArgToken(h);
} }
virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) { virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
return ArgToken(type, *con); return ArgToken(type, *con);
......
...@@ -1305,6 +1305,7 @@ void MethodHandles::verify_vmargslot(Handle mh, int argnum, int argslot, TRAPS) ...@@ -1305,6 +1305,7 @@ void MethodHandles::verify_vmargslot(Handle mh, int argnum, int argslot, TRAPS)
// Verify that argslot points at the given argnum. // Verify that argslot points at the given argnum.
int check_slot = argument_slot(java_lang_invoke_MethodHandle::type(mh()), argnum); int check_slot = argument_slot(java_lang_invoke_MethodHandle::type(mh()), argnum);
if (argslot != check_slot || argslot < 0) { if (argslot != check_slot || argslot < 0) {
ResourceMark rm;
const char* fmt = "for argnum of %d, vmargslot is %d, should be %d"; const char* fmt = "for argnum of %d, vmargslot is %d, should be %d";
size_t msglen = strlen(fmt) + 3*11 + 1; size_t msglen = strlen(fmt) + 3*11 + 1;
char* msg = NEW_RESOURCE_ARRAY(char, msglen); char* msg = NEW_RESOURCE_ARRAY(char, msglen);
...@@ -1829,6 +1830,7 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum, ...@@ -1829,6 +1830,7 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum,
bool direct_to_method = false; bool direct_to_method = false;
if (OptimizeMethodHandles && if (OptimizeMethodHandles &&
target->klass() == SystemDictionary::DirectMethodHandle_klass() && target->klass() == SystemDictionary::DirectMethodHandle_klass() &&
(argnum != 0 || java_lang_invoke_BoundMethodHandle::argument(mh()) != NULL) &&
(argnum == 0 || java_lang_invoke_DirectMethodHandle::vmindex(target()) < 0)) { (argnum == 0 || java_lang_invoke_DirectMethodHandle::vmindex(target()) < 0)) {
KlassHandle receiver_limit; int decode_flags = 0; KlassHandle receiver_limit; int decode_flags = 0;
methodHandle m = decode_method(target(), receiver_limit, decode_flags); methodHandle m = decode_method(target(), receiver_limit, decode_flags);
...@@ -1980,7 +1982,6 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) { ...@@ -1980,7 +1982,6 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) {
err = "adapter requires src/dest conversion subfields for swap"; break; err = "adapter requires src/dest conversion subfields for swap"; break;
} }
int swap_size = type2size[src]; int swap_size = type2size[src];
int slot_limit = java_lang_invoke_MethodHandle::vmslots(target());
int src_slot = argslot; int src_slot = argslot;
int dest_slot = vminfo; int dest_slot = vminfo;
bool rotate_up = (src_slot > dest_slot); // upward rotation bool rotate_up = (src_slot > dest_slot); // upward rotation
...@@ -2333,7 +2334,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu ...@@ -2333,7 +2334,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
case _adapter_rot_args: case _adapter_rot_args:
{ {
int swap_slots = type2size[src]; int swap_slots = type2size[src];
int slot_limit = java_lang_invoke_AdapterMethodHandle::vmslots(mh());
int src_slot = argslot; int src_slot = argslot;
int dest_slot = vminfo; int dest_slot = vminfo;
int rotate = (ek_orig == _adapter_swap_args) ? 0 : (src_slot > dest_slot) ? 1 : -1; int rotate = (ek_orig == _adapter_swap_args) ? 0 : (src_slot > dest_slot) ? 1 : -1;
...@@ -2661,14 +2661,14 @@ JVM_ENTRY(void, MHN_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh, ...@@ -2661,14 +2661,14 @@ JVM_ENTRY(void, MHN_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh,
ResourceMark rm; // for error messages ResourceMark rm; // for error messages
// This is the guy we are initializing: // This is the guy we are initializing:
if (mh_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (mh_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "self is null"); }
Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh));
// Early returns out of this method leave the DMH in an unfinished state. // Early returns out of this method leave the DMH in an unfinished state.
assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null");
// which method are we really talking about? // which method are we really talking about?
if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
if (java_lang_invoke_MemberName::is_instance(target()) && if (java_lang_invoke_MemberName::is_instance(target()) &&
java_lang_invoke_MemberName::vmindex(target()) == VM_INDEX_UNINITIALIZED) { java_lang_invoke_MemberName::vmindex(target()) == VM_INDEX_UNINITIALIZED) {
...@@ -2722,13 +2722,13 @@ JVM_ENTRY(void, MHN_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh, ...@@ -2722,13 +2722,13 @@ JVM_ENTRY(void, MHN_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh,
ResourceMark rm; // for error messages ResourceMark rm; // for error messages
// This is the guy we are initializing: // This is the guy we are initializing:
if (mh_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (mh_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "self is null"); }
Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh));
// Early returns out of this method leave the BMH in an unfinished state. // Early returns out of this method leave the BMH in an unfinished state.
assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null"); assert(java_lang_invoke_MethodHandle::vmentry(mh()) == NULL, "must be safely null");
if (target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
if (!java_lang_invoke_MethodHandle::is_instance(target())) { if (!java_lang_invoke_MethodHandle::is_instance(target())) {
...@@ -2753,9 +2753,8 @@ JVM_END ...@@ -2753,9 +2753,8 @@ JVM_END
JVM_ENTRY(void, MHN_init_AMH(JNIEnv *env, jobject igcls, jobject mh_jh, JVM_ENTRY(void, MHN_init_AMH(JNIEnv *env, jobject igcls, jobject mh_jh,
jobject target_jh, int argnum)) { jobject target_jh, int argnum)) {
// This is the guy we are initializing: // This is the guy we are initializing:
if (mh_jh == NULL || target_jh == NULL) { if (mh_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "self is null"); }
THROW(vmSymbols::java_lang_InternalError()); if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
}
Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh)); Handle mh(THREAD, JNIHandles::resolve_non_null(mh_jh));
Handle target(THREAD, JNIHandles::resolve_non_null(target_jh)); Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
...@@ -2890,7 +2889,8 @@ JVM_END ...@@ -2890,7 +2889,8 @@ JVM_END
// void init(MemberName self, AccessibleObject ref) // void init(MemberName self, AccessibleObject ref)
JVM_ENTRY(void, MHN_init_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jobject target_jh)) { JVM_ENTRY(void, MHN_init_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jobject target_jh)) {
if (mname_jh == NULL || target_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); }
if (target_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
oop target_oop = JNIHandles::resolve_non_null(target_jh); oop target_oop = JNIHandles::resolve_non_null(target_jh);
MethodHandles::init_MemberName(mname(), target_oop); MethodHandles::init_MemberName(mname(), target_oop);
...@@ -2899,7 +2899,7 @@ JVM_END ...@@ -2899,7 +2899,7 @@ JVM_END
// void expand(MemberName self) // void expand(MemberName self)
JVM_ENTRY(void, MHN_expand_Mem(JNIEnv *env, jobject igcls, jobject mname_jh)) { JVM_ENTRY(void, MHN_expand_Mem(JNIEnv *env, jobject igcls, jobject mname_jh)) {
if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); }
Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
MethodHandles::expand_MemberName(mname, 0, CHECK); MethodHandles::expand_MemberName(mname, 0, CHECK);
} }
...@@ -2907,7 +2907,7 @@ JVM_END ...@@ -2907,7 +2907,7 @@ JVM_END
// void resolve(MemberName self, Class<?> caller) // void resolve(MemberName self, Class<?> caller)
JVM_ENTRY(void, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) { JVM_ENTRY(void, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) {
if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (mname_jh == NULL) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); }
Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
// The trusted Java code that calls this method should already have performed // The trusted Java code that calls this method should already have performed
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册