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