src/share/vm/prims/methodHandleWalk.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
7047961 Cdiff src/share/vm/prims/methodHandleWalk.cpp
src/share/vm/prims/methodHandleWalk.cpp
Print this page
*** 139,156 ****
--- 139,301 ----
}
void MethodHandleChain::lose(const char* msg, TRAPS) {
_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) {
// throw a preallocated exception
THROW_OOP(Universe::virtual_machine_error_instance());
}
THROW_MSG(vmSymbols::java_lang_InternalError(), msg);
}
+ #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 < 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
Bytecodes::Code MethodHandleWalker::conversion_code(BasicType src, BasicType dest) {
if (is_subword_type(src)) {
*** 203,216 ****
assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
if (chain().is_adapter()) {
int conv_op = chain().adapter_conversion_op();
int arg_slot = chain().adapter_arg_slot();
! SlotState* arg_state = slot_state(arg_slot);
! if (arg_state == NULL
! && conv_op > java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW) {
! lose("bad argument index", CHECK_(empty));
}
bool retain_original_args = false; // used by fold/collect logic
// perform the adapter action
--- 348,367 ----
assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
if (chain().is_adapter()) {
int conv_op = chain().adapter_conversion_op();
int arg_slot = chain().adapter_arg_slot();
!
! // Check that the arg_slot is valid. In most cases it must be
! // within range of the current arguments but there are some
! // 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
// perform the adapter action
*** 235,246 ****
if (nptypes != java_lang_invoke_MethodType::ptype_count(incoming_mtype()))
lose("incoming and outgoing parameter count do not agree", CHECK_(empty));
// Argument types.
for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) {
! SlotState* arg_state = slot_state(slot);
! if (arg_state->_type == T_VOID) continue;
klassOop src_klass = NULL;
klassOop dst_klass = NULL;
BasicType src = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(incoming_mtype(), i), &src_klass);
BasicType dst = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(outgoing_mtype(), i), &dst_klass);
--- 386,396 ----
if (nptypes != java_lang_invoke_MethodType::ptype_count(incoming_mtype()))
lose("incoming and outgoing parameter count do not agree", CHECK_(empty));
// Argument types.
for (int i = 0, slot = _outgoing.length() - 1; slot >= 0; slot--) {
! if (arg_type(slot) == T_VOID) continue;
klassOop src_klass = NULL;
klassOop dst_klass = NULL;
BasicType src = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(incoming_mtype(), i), &src_klass);
BasicType dst = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(outgoing_mtype(), i), &dst_klass);
*** 260,271 ****
case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST: {
// checkcast the Nth outgoing argument in place
klassOop dest_klass = NULL;
BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass);
assert(dest == T_OBJECT, "");
! assert(dest == arg_state->_type, "");
! ArgToken arg = arg_state->_arg;
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");
debug_only(dest_klass = (klassOop)badOop);
break;
}
--- 410,421 ----
case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST: {
// checkcast the Nth outgoing argument in place
klassOop dest_klass = NULL;
BasicType dest = java_lang_Class::as_BasicType(chain().adapter_arg_oop(), &dest_klass);
assert(dest == T_OBJECT, "");
! ArgToken arg = _outgoing.at(arg_slot);
! assert(dest == arg.basic_type(), "");
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");
debug_only(dest_klass = (klassOop)badOop);
break;
}
*** 272,283 ****
case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM: {
// i2l, etc., on the Nth outgoing argument in place
BasicType src = chain().adapter_conversion_src_type(),
dest = chain().adapter_conversion_dest_type();
Bytecodes::Code bc = conversion_code(src, dest);
- ArgToken arg = arg_state->_arg;
if (bc == Bytecodes::_nop) {
break;
} else if (bc != Bytecodes::_illegal) {
arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty));
} else if (is_subword_type(dest)) {
--- 422,433 ----
case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM: {
// i2l, etc., on the Nth outgoing argument in place
BasicType src = chain().adapter_conversion_src_type(),
dest = chain().adapter_conversion_dest_type();
+ ArgToken arg = _outgoing.at(arg_slot);
Bytecodes::Code bc = conversion_code(src, dest);
if (bc == Bytecodes::_nop) {
break;
} else if (bc != Bytecodes::_illegal) {
arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty));
} else if (is_subword_type(dest)) {
*** 287,306 ****
bc = conversion_code(T_INT, dest);
arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty));
}
}
if (bc == Bytecodes::_illegal) {
! lose("bad primitive conversion", CHECK_(empty));
}
change_argument(src, arg_slot, dest, arg);
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM: {
// checkcast to wrapper type & call intValue, etc.
BasicType dest = chain().adapter_conversion_dest_type();
! ArgToken arg = arg_state->_arg;
arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest),
Bytecodes::_checkcast, arg, CHECK_(empty));
vmIntrinsics::ID unboxer = vmIntrinsics::for_unboxing(dest);
if (unboxer == vmIntrinsics::_none) {
lose("no unboxing method", CHECK_(empty));
--- 437,456 ----
bc = conversion_code(T_INT, dest);
arg = make_conversion(dest, NULL, bc, arg, CHECK_(empty));
}
}
if (bc == Bytecodes::_illegal) {
! lose(err_msg("bad primitive conversion for %s -> %s", type2name(src), type2name(dest)), CHECK_(empty));
}
change_argument(src, arg_slot, dest, arg);
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_REF_TO_PRIM: {
// checkcast to wrapper type & call intValue, etc.
BasicType dest = chain().adapter_conversion_dest_type();
! ArgToken arg = _outgoing.at(arg_slot);
arg = make_conversion(T_OBJECT, SystemDictionary::box_klass(dest),
Bytecodes::_checkcast, arg, CHECK_(empty));
vmIntrinsics::ID unboxer = vmIntrinsics::for_unboxing(dest);
if (unboxer == vmIntrinsics::_none) {
lose("no unboxing method", CHECK_(empty));
*** 314,328 ****
}
case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF: {
// call wrapper type.valueOf
BasicType src = chain().adapter_conversion_src_type();
- ArgToken arg = arg_state->_arg;
vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src);
if (boxer == vmIntrinsics::_none) {
lose("no boxing method", CHECK_(empty));
}
ArgToken arglist[2];
arglist[0] = arg; // outgoing value
arglist[1] = ArgToken(); // sentinel
arg = make_invoke(NULL, boxer, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK_(empty));
change_argument(src, arg_slot, T_OBJECT, arg);
--- 464,478 ----
}
case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF: {
// call wrapper type.valueOf
BasicType src = chain().adapter_conversion_src_type();
vmIntrinsics::ID boxer = vmIntrinsics::for_boxing(src);
if (boxer == vmIntrinsics::_none) {
lose("no boxing method", CHECK_(empty));
}
+ ArgToken arg = _outgoing.at(arg_slot);
ArgToken arglist[2];
arglist[0] = arg; // outgoing value
arglist[1] = ArgToken(); // sentinel
arg = make_invoke(NULL, boxer, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK_(empty));
change_argument(src, arg_slot, T_OBJECT, arg);
*** 329,400 ****
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: {
int dest_arg_slot = chain().adapter_conversion_vminfo();
! if (!slot_has_argument(dest_arg_slot)) {
lose("bad swap index", CHECK_(empty));
}
// a simple swap between two arguments
! SlotState* dest_arg_state = slot_state(dest_arg_slot);
! SlotState temp = (*dest_arg_state);
! (*dest_arg_state) = (*arg_state);
! (*arg_state) = temp;
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS: {
int dest_arg_slot = chain().adapter_conversion_vminfo();
! if (!slot_has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) {
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
// position occupied by the dest argument (plus following N slots).
! int rotate_count = type2size[dest_arg_state->_type];
// (no other rotate counts are currently supported)
if (arg_slot < dest_arg_slot) {
for (int i = 0; i < rotate_count; i++) {
! SlotState temp = _outgoing.at(arg_slot);
_outgoing.remove_at(arg_slot);
_outgoing.insert_before(dest_arg_slot + rotate_count - 1, temp);
}
} else { // arg_slot > dest_arg_slot
for (int i = 0; i < rotate_count; i++) {
! SlotState temp = _outgoing.at(arg_slot + rotate_count - 1);
_outgoing.remove_at(arg_slot + rotate_count - 1);
_outgoing.insert_before(dest_arg_slot, temp);
}
}
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS: {
int dup_slots = chain().adapter_conversion_stack_pushes();
if (dup_slots <= 0) {
lose("bad dup count", CHECK_(empty));
}
for (int i = 0; i < dup_slots; i++) {
! SlotState* dup = slot_state(arg_slot + 2*i);
! if (dup == NULL) break; // safety net
! if (dup->_type != T_VOID) _outgoing_argc += 1;
! _outgoing.insert_before(i, (*dup));
}
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS: {
int drop_slots = -chain().adapter_conversion_stack_pushes();
if (drop_slots <= 0) {
lose("bad drop count", CHECK_(empty));
}
for (int i = 0; i < drop_slots; i++) {
! SlotState* drop = slot_state(arg_slot);
! if (drop == NULL) break; // safety net
! if (drop->_type != T_VOID) _outgoing_argc -= 1;
_outgoing.remove_at(arg_slot);
}
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS:
retain_original_args = true; // and fall through:
--- 479,559 ----
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: {
int dest_arg_slot = chain().adapter_conversion_vminfo();
! if (!has_argument(dest_arg_slot)) {
lose("bad swap index", CHECK_(empty));
}
// a simple swap between two arguments
! if (arg_slot > dest_arg_slot) {
! int tmp = arg_slot;
! arg_slot = dest_arg_slot;
! 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;
}
case java_lang_invoke_AdapterMethodHandle::OP_ROT_ARGS: {
int dest_arg_slot = chain().adapter_conversion_vminfo();
! if (!has_argument(dest_arg_slot) || arg_slot == dest_arg_slot) {
lose("bad rotate index", CHECK_(empty));
}
// Rotate the source argument (plus following N slots) into the
// position occupied by the dest argument (plus following N slots).
! int rotate_count = type2size[chain().adapter_conversion_src_type()];
// (no other rotate counts are currently supported)
if (arg_slot < dest_arg_slot) {
for (int i = 0; i < rotate_count; i++) {
! ArgToken temp = _outgoing.at(arg_slot);
_outgoing.remove_at(arg_slot);
_outgoing.insert_before(dest_arg_slot + rotate_count - 1, temp);
}
} else { // arg_slot > dest_arg_slot
for (int i = 0; i < rotate_count; i++) {
! ArgToken temp = _outgoing.at(arg_slot + rotate_count - 1);
_outgoing.remove_at(arg_slot + rotate_count - 1);
_outgoing.insert_before(dest_arg_slot, temp);
}
}
+ assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_DUP_ARGS: {
int dup_slots = chain().adapter_conversion_stack_pushes();
if (dup_slots <= 0) {
lose("bad dup count", CHECK_(empty));
}
for (int i = 0; i < dup_slots; i++) {
! ArgToken dup = _outgoing.at(arg_slot + 2*i);
! // XXX should this be a dynamic check?
! // if (dup == NULL) break; // safety net
! if (dup.basic_type() != T_VOID) _outgoing_argc += 1;
! _outgoing.insert_before(i, dup);
}
+ assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_DROP_ARGS: {
int drop_slots = -chain().adapter_conversion_stack_pushes();
if (drop_slots <= 0) {
lose("bad drop count", CHECK_(empty));
}
for (int i = 0; i < drop_slots; i++) {
! ArgToken drop = _outgoing.at(arg_slot);
! // XXX should this be a dynamic check?
! // if (drop == NULL) break; // safety net
! if (drop.basic_type() != T_VOID) _outgoing_argc -= 1;
_outgoing.remove_at(arg_slot);
}
+ assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS:
retain_original_args = true; // and fall through:
*** 413,426 ****
arglist[0] = make_oop_constant(recursive_mh(), CHECK_(empty));
if (arg_slot < 0 || coll_slots < 0 || arg_slot + coll_slots > _outgoing.length()) {
lose("bad fold/collect arg slot", CHECK_(empty));
}
for (int i = 0, slot = arg_slot + coll_slots - 1; slot >= arg_slot; slot--) {
! SlotState* arg_state = slot_state(slot);
! BasicType arg_type = arg_state->_type;
if (arg_type == T_VOID) continue;
! ArgToken arg = _outgoing.at(slot)._arg;
if (i >= argc) { lose("bad fold/collect arg", CHECK_(empty)); }
arglist[1+i] = arg;
if (!retain_original_args)
change_argument(arg_type, slot, T_VOID, ArgToken(tt_void));
i++;
--- 572,585 ----
arglist[0] = make_oop_constant(recursive_mh(), CHECK_(empty));
if (arg_slot < 0 || coll_slots < 0 || arg_slot + coll_slots > _outgoing.length()) {
lose("bad fold/collect arg slot", CHECK_(empty));
}
for (int i = 0, slot = arg_slot + coll_slots - 1; slot >= arg_slot; slot--) {
! ArgToken arg_state = _outgoing.at(slot);
! BasicType arg_type = arg_state.basic_type();
if (arg_type == T_VOID) continue;
! ArgToken arg = _outgoing.at(slot);
if (i >= argc) { lose("bad fold/collect arg", CHECK_(empty)); }
arglist[1+i] = arg;
if (!retain_original_args)
change_argument(arg_type, slot, T_VOID, ArgToken(tt_void));
i++;
*** 464,475 ****
&element_klass_oop);
KlassHandle element_klass(THREAD, element_klass_oop);
debug_only(element_klass_oop = (klassOop)badOop);
// Fetch the argument, which we will cast to the required array type.
! assert(arg_state->_type == T_OBJECT, "");
! ArgToken array_arg = arg_state->_arg;
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));
// Check the required length.
int spread_slots = 1 + chain().adapter_conversion_stack_pushes();
--- 623,635 ----
&element_klass_oop);
KlassHandle element_klass(THREAD, element_klass_oop);
debug_only(element_klass_oop = (klassOop)badOop);
// Fetch the argument, which we will cast to the required array type.
! ArgToken arg = _outgoing.at(arg_slot);
! assert(arg.basic_type() == T_OBJECT, "");
! ArgToken array_arg = arg;
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));
// Check the required length.
int spread_slots = 1 + chain().adapter_conversion_stack_pushes();
*** 532,545 ****
if (arg_type == T_OBJECT) {
arg = make_oop_constant(arg_oop, CHECK_(empty));
} else {
jvalue arg_value;
BasicType bt = java_lang_boxing_object::get_value(arg_oop, &arg_value);
! if (bt == arg_type) {
arg = make_prim_constant(arg_type, &arg_value, CHECK_(empty));
} else {
! lose("bad bound value", CHECK_(empty));
}
}
DEBUG_ONLY(arg_oop = badOop);
change_argument(T_VOID, arg_slot, arg_type, arg);
}
--- 692,705 ----
if (arg_type == T_OBJECT) {
arg = make_oop_constant(arg_oop, CHECK_(empty));
} else {
jvalue arg_value;
BasicType bt = java_lang_boxing_object::get_value(arg_oop, &arg_value);
! if (bt == arg_type || (bt == T_INT && is_subword_type(arg_type))) {
arg = make_prim_constant(arg_type, &arg_value, CHECK_(empty));
} else {
! lose(err_msg("bad bound value: arg_type %s boxing %s", type2name(arg_type), type2name(bt)), CHECK_(empty));
}
}
DEBUG_ONLY(arg_oop = badOop);
change_argument(T_VOID, arg_slot, arg_type, arg);
}
*** 555,567 ****
// finish the sequence with a tail-call to the ultimate target
// parameters are passed in logical order (recv 1st), not slot order
ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, _outgoing.length() + 1);
int ap = 0;
for (int i = _outgoing.length() - 1; i >= 0; i--) {
! SlotState* arg_state = slot_state(i);
! if (arg_state->_type == T_VOID) continue;
! arglist[ap++] = _outgoing.at(i)._arg;
}
assert(ap == _outgoing_argc, "");
arglist[ap] = ArgToken(); // add a sentinel, for the sake of asserts
return make_invoke(chain().last_method_oop(),
vmIntrinsics::_none,
--- 715,727 ----
// finish the sequence with a tail-call to the ultimate target
// parameters are passed in logical order (recv 1st), not slot order
ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, _outgoing.length() + 1);
int ap = 0;
for (int i = _outgoing.length() - 1; i >= 0; i--) {
! ArgToken arg_state = _outgoing.at(i);
! if (arg_state.basic_type() == T_VOID) continue;
! arglist[ap++] = _outgoing.at(i);
}
assert(ap == _outgoing_argc, "");
arglist[ap] = ArgToken(); // add a sentinel, for the sake of asserts
return make_invoke(chain().last_method_oop(),
vmIntrinsics::_none,
*** 577,649 ****
Handle mtype(THREAD, chain().method_type_oop());
int nptypes = java_lang_invoke_MethodType::ptype_count(mtype());
_outgoing_argc = nptypes;
int argp = nptypes - 1;
if (argp >= 0) {
! _outgoing.at_grow(argp, make_state(T_VOID, ArgToken(tt_void))); // presize
}
for (int i = 0; i < nptypes; i++) {
klassOop arg_type_klass = NULL;
BasicType arg_type = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(mtype(), i), &arg_type_klass);
int index = new_local_index(arg_type);
ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK);
DEBUG_ONLY(arg_type_klass = (klassOop) NULL);
! _outgoing.at_put(argp, make_state(arg_type, arg));
if (type2size[arg_type] == 2) {
// add the extra slot, so we can model the JVM stack
! _outgoing.insert_before(argp+1, make_state(T_VOID, ArgToken(tt_void)));
}
--argp;
}
// call make_parameter at the end of the list for the return type
klassOop ret_type_klass = NULL;
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);
// ignore ret; client can catch it if needed
}
// -----------------------------------------------------------------------------
// MethodHandleWalker::change_argument
//
// This is messy because some kinds of arguments are paired with
// companion slots containing an empty value.
! void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType new_type,
! const ArgToken& new_arg) {
int old_size = type2size[old_type];
int new_size = type2size[new_type];
if (old_size == new_size) {
// simple case first
! _outgoing.at_put(slot, make_state(new_type, new_arg));
} else if (old_size > new_size) {
for (int i = old_size - 1; i >= new_size; i--) {
! assert((i != 0) == (_outgoing.at(slot + i)._type == T_VOID), "");
_outgoing.remove_at(slot + i);
}
if (new_size > 0)
! _outgoing.at_put(slot, make_state(new_type, new_arg));
else
_outgoing_argc -= 1; // deleted a real argument
} else {
for (int i = old_size; i < new_size; i++) {
! _outgoing.insert_before(slot + i, make_state(T_VOID, ArgToken(tt_void)));
}
! _outgoing.at_put(slot, make_state(new_type, new_arg));
if (old_size == 0)
_outgoing_argc += 1; // inserted a real argument
}
}
#ifdef ASSERT
int MethodHandleWalker::argument_count_slow() {
int args_seen = 0;
for (int i = _outgoing.length() - 1; i >= 0; i--) {
! if (_outgoing.at(i)._type != T_VOID) {
++args_seen;
}
}
return args_seen;
}
#endif
--- 737,839 ----
Handle mtype(THREAD, chain().method_type_oop());
int nptypes = java_lang_invoke_MethodType::ptype_count(mtype());
_outgoing_argc = nptypes;
int argp = nptypes - 1;
if (argp >= 0) {
! _outgoing.at_grow(argp, ArgToken(tt_void)); // presize
}
for (int i = 0; i < nptypes; i++) {
klassOop arg_type_klass = NULL;
BasicType arg_type = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(mtype(), i), &arg_type_klass);
int index = new_local_index(arg_type);
ArgToken arg = make_parameter(arg_type, arg_type_klass, index, CHECK);
DEBUG_ONLY(arg_type_klass = (klassOop) NULL);
! _outgoing.at_put(argp, arg);
if (type2size[arg_type] == 2) {
// add the extra slot, so we can model the JVM stack
! _outgoing.insert_before(argp+1, ArgToken(tt_void));
}
--argp;
}
// call make_parameter at the end of the list for the return type
klassOop ret_type_klass = NULL;
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);
// 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
+
+
// -----------------------------------------------------------------------------
// MethodHandleWalker::change_argument
//
// This is messy because some kinds of arguments are paired with
// companion slots containing an empty value.
! void MethodHandleWalker::change_argument(BasicType old_type, int slot, const ArgToken& new_arg) {
! BasicType new_type = new_arg.basic_type();
int old_size = type2size[old_type];
int new_size = type2size[new_type];
if (old_size == new_size) {
// simple case first
! _outgoing.at_put(slot, new_arg);
} else if (old_size > new_size) {
for (int i = old_size - 1; i >= new_size; i--) {
! assert((i != 0) == (_outgoing.at(slot + i).basic_type() == T_VOID), "");
_outgoing.remove_at(slot + i);
}
if (new_size > 0)
! _outgoing.at_put(slot, new_arg);
else
_outgoing_argc -= 1; // deleted a real argument
} else {
for (int i = old_size; i < new_size; i++) {
! _outgoing.insert_before(slot + i, ArgToken(tt_void));
}
! _outgoing.at_put(slot, new_arg);
if (old_size == 0)
_outgoing_argc += 1; // inserted a real argument
}
+ assert(_outgoing_argc == argument_count_slow(), "empty slots under control");
}
#ifdef ASSERT
int MethodHandleWalker::argument_count_slow() {
int args_seen = 0;
for (int i = _outgoing.length() - 1; i >= 0; i--) {
! if (_outgoing.at(i).basic_type() != T_VOID) {
++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;
}
#endif
*** 661,671 ****
lose("no raw conversion method", CHECK);
}
ArgToken arglist[2];
if (!for_return) {
// argument type conversion
! ArgToken arg = _outgoing.at(slot)._arg;
assert(arg.token_type() >= tt_symbolic || src == arg.basic_type(), "sanity");
arglist[0] = arg; // outgoing 'this'
arglist[1] = ArgToken(); // sentinel
arg = make_invoke(NULL, iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK);
change_argument(src, slot, dst, arg);
--- 851,861 ----
lose("no raw conversion method", CHECK);
}
ArgToken arglist[2];
if (!for_return) {
// argument type conversion
! ArgToken arg = _outgoing.at(slot);
assert(arg.token_type() >= tt_symbolic || src == arg.basic_type(), "sanity");
arglist[0] = arg; // outgoing 'this'
arglist[1] = ArgToken(); // sentinel
arg = make_invoke(NULL, iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK);
change_argument(src, slot, dst, arg);
*** 681,691 ****
}
} else if (src == T_OBJECT && is_java_primitive(dst)) {
// ref-to-prim: discard ref, push zero
lose("requested ref-to-prim conversion not expected", CHECK);
} else {
! lose("requested raw conversion not allowed", CHECK);
}
}
}
--- 871,881 ----
}
} else if (src == T_OBJECT && is_java_primitive(dst)) {
// ref-to-prim: discard ref, push zero
lose("requested ref-to-prim conversion not expected", CHECK);
} else {
! lose(err_msg("requested raw conversion not allowed: %s -> %s", type2name(src), type2name(dst)), CHECK);
}
}
}
*** 961,970 ****
--- 1151,1161 ----
}
void MethodHandleCompiler::emit_load_constant(ArgToken arg) {
BasicType bt = arg.basic_type();
+ if (is_subword_type(bt)) bt = T_INT;
switch (bt) {
case T_INT: {
jint value = arg.get_jint();
if (-1 <= value && value <= 5)
emit_bc(Bytecodes::cast(Bytecodes::_iconst_0 + value));
*** 1064,1078 ****
if (index == -1)
index = new_local_index(type);
emit_store(srctype, index);
break;
default:
if (op == Bytecodes::_illegal)
! lose("no such primitive conversion", THREAD);
else
! lose("bad primitive conversion op", THREAD);
return make_prim_constant(type, &zero_jvalue, THREAD);
}
return make_parameter(type, tk, index, THREAD);
}
--- 1255,1274 ----
if (index == -1)
index = new_local_index(type);
emit_store(srctype, index);
break;
+ case Bytecodes::_nop:
+ // nothing to do
+ assert(type == src.basic_type(), "must agree");
+ return src;
+
default:
if (op == Bytecodes::_illegal)
! lose(err_msg("no such primitive conversion: %s -> %s", type2name(src.basic_type()), type2name(type)), THREAD);
else
! lose(err_msg("bad primitive conversion op: %s", Bytecodes::name(op)), THREAD);
return make_prim_constant(type, &zero_jvalue, THREAD);
}
return make_parameter(type, tk, index, THREAD);
}
*** 1298,1308 ****
bt = T_INT;
}
// for (int i = 1, imax = _constants.length(); i < imax; i++) {
// ConstantValue* con = _constants.at(i);
! // if (con != NULL && con->is_primitive() && con->_type == bt) {
// bool match = false;
// switch (type2size[bt]) {
// case 1: if (pcon->_value.i == con->i) match = true; break;
// case 2: if (pcon->_value.j == con->j) match = true; break;
// }
--- 1494,1504 ----
bt = T_INT;
}
// for (int i = 1, imax = _constants.length(); i < imax; i++) {
// ConstantValue* con = _constants.at(i);
! // if (con != NULL && con->is_primitive() && con.basic_type() == bt) {
// bool match = false;
// switch (type2size[bt]) {
// case 1: if (pcon->_value.i == con->i) match = true; break;
// case 2: if (pcon->_value.j == con->j) match = true; break;
// }
*** 1449,1460 ****
const char* strbuf() {
const char* s = _strbuf.as_string();
_strbuf.reset();
return s;
}
! ArgToken token(const char* str) {
! return ArgToken(str);
}
const char* string(ArgToken token) {
return token.str();
}
void start_params() {
--- 1645,1656 ----
const char* strbuf() {
const char* s = _strbuf.as_string();
_strbuf.reset();
return s;
}
! ArgToken token(const char* str, BasicType type) {
! return ArgToken(str, type);
}
const char* string(ArgToken token) {
return token.str();
}
void start_params() {
*** 1472,1487 ****
kname = Klass::cast(tk)->external_name();
s->print("%s", (kname != NULL) ? kname : type2name(type));
}
ArgToken maybe_make_temp(const char* statement_op, BasicType type, const char* temp_name) {
const char* value = strbuf();
! if (!_verbose) return token(value);
// make an explicit binding for each separate value
_strbuf.print("%s%d", temp_name, ++_temp_num);
const char* temp = strbuf();
_out->print("\n %s %s %s = %s;", statement_op, type2name(type), temp, value);
! return token(temp);
}
public:
MethodHandlePrinter(Handle root, bool verbose, outputStream* out, TRAPS)
: MethodHandleWalker(root, false, THREAD),
--- 1668,1683 ----
kname = Klass::cast(tk)->external_name();
s->print("%s", (kname != NULL) ? kname : type2name(type));
}
ArgToken maybe_make_temp(const char* statement_op, BasicType type, const char* temp_name) {
const char* value = strbuf();
! if (!_verbose) return token(value, type);
// make an explicit binding for each separate value
_strbuf.print("%s%d", temp_name, ++_temp_num);
const char* temp = strbuf();
_out->print("\n %s %s %s = %s;", statement_op, type2name(type), temp, value);
! return token(temp, type);
}
public:
MethodHandlePrinter(Handle root, bool verbose, outputStream* out, TRAPS)
: MethodHandleWalker(root, false, THREAD),
*** 1493,1503 ****
start_params();
}
virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
if (argnum < 0) {
end_params();
! return token("return");
}
if ((_param_state & 1) == 0) {
_param_state |= 1;
_out->print(_verbose ? "\n " : "");
} else {
--- 1689,1699 ----
start_params();
}
virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
if (argnum < 0) {
end_params();
! return token("return", type);
}
if ((_param_state & 1) == 0) {
_param_state |= 1;
_out->print(_verbose ? "\n " : "");
} else {
*** 1508,1518 ****
// generate an argument name
_strbuf.print("a%d", argnum);
const char* arg = strbuf();
put_type_name(type, tk, _out);
_out->print(" %s", arg);
! return token(arg);
}
virtual ArgToken make_oop_constant(oop con, TRAPS) {
if (con == NULL)
_strbuf.print("null");
else
--- 1704,1714 ----
// generate an argument name
_strbuf.print("a%d", argnum);
const char* arg = strbuf();
put_type_name(type, tk, _out);
_out->print(" %s", arg);
! return token(arg, type);
}
virtual ArgToken make_oop_constant(oop con, TRAPS) {
if (con == NULL)
_strbuf.print("null");
else
*** 1595,1605 ****
MethodHandlePrinter printer(root, verbose, out, CHECK);
printer.walk(CHECK);
out->print("\n");
}
static void print(Handle root, bool verbose = Verbose, outputStream* out = tty) {
! EXCEPTION_MARK;
ResourceMark rm;
MethodHandlePrinter printer(root, verbose, out, THREAD);
if (!HAS_PENDING_EXCEPTION)
printer.walk(THREAD);
if (HAS_PENDING_EXCEPTION) {
--- 1791,1801 ----
MethodHandlePrinter printer(root, verbose, out, CHECK);
printer.walk(CHECK);
out->print("\n");
}
static void print(Handle root, bool verbose = Verbose, outputStream* out = tty) {
! Thread* THREAD = Thread::current();
ResourceMark rm;
MethodHandlePrinter printer(root, verbose, out, THREAD);
if (!HAS_PENDING_EXCEPTION)
printer.walk(THREAD);
if (HAS_PENDING_EXCEPTION) {
src/share/vm/prims/methodHandleWalk.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File