src/share/vm/prims/methodHandleWalk.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/prims/methodHandleWalk.cpp Thu May 12 14:03:28 2011
--- new/src/share/vm/prims/methodHandleWalk.cpp Thu May 12 14:03:28 2011
*** 29,38 ****
--- 29,43 ----
/*
* JSR 292 reference implementation: method handle structure analysis
*/
+ #ifdef PRODUCT
+ #define print_method_handle(mh) {}
+ #else //PRODUCT
+ extern "C" void print_method_handle(oop mh);
+ #endif //PRODUCT
// -----------------------------------------------------------------------------
// MethodHandleChain
void MethodHandleChain::set_method_handle(Handle mh, TRAPS) {
*** 204,268 ****
--- 209,260 ----
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
! switch (chain().adapter_conversion_op()) {
! switch (conv_op) {
case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_ONLY:
// No changes to arguments; pass the bits through.
break;
case java_lang_invoke_AdapterMethodHandle::OP_RETYPE_RAW: {
// To keep the verifier happy, emit bitwise ("raw") conversions as needed.
// See MethodHandles::same_basic_type_for_arguments for allowed conversions.
Handle incoming_mtype(THREAD, chain().method_type_oop());
+ Handle outgoing_mtype;
+ {
oop outgoing_mh_oop = chain().vmtarget_oop();
if (!java_lang_invoke_MethodHandle::is_instance(outgoing_mh_oop))
lose("outgoing target not a MethodHandle", CHECK_(empty));
! Handle outgoing_mtype(THREAD, java_lang_invoke_MethodHandle::type(outgoing_mh_oop));
outgoing_mh_oop = NULL; // GC safety
! outgoing_mtype = Handle(THREAD, java_lang_invoke_MethodHandle::type(outgoing_mh_oop));
+ }
int nptypes = java_lang_invoke_MethodType::ptype_count(outgoing_mtype());
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;
ArgToken arg = _outgoing.at(slot)._arg;
klassOop in_klass = NULL;
klassOop out_klass = NULL;
BasicType inpbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(incoming_mtype(), i), &in_klass);
BasicType outpbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::ptype(outgoing_mtype(), i), &out_klass);
assert(inpbt == arg.basic_type(), "sanity");
if (inpbt != outpbt) {
vmIntrinsics::ID iid = vmIntrinsics::for_raw_conversion(inpbt, outpbt);
if (iid == vmIntrinsics::_none) {
lose("no raw conversion method", CHECK_(empty));
}
ArgToken arglist[2];
arglist[0] = arg; // outgoing 'this'
arglist[1] = ArgToken(); // sentinel
arg = make_invoke(NULL, iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK_(empty));
change_argument(inpbt, slot, outpbt, arg);
}
+ 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);
+ retype_raw_argument_type(src, dst, slot, CHECK_(empty));
i++; // We need to skip void slots at the top of the loop.
}
BasicType inrbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(incoming_mtype()));
BasicType outrbt = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(outgoing_mtype()));
if (inrbt != outrbt) {
if (inrbt == T_INT && outrbt == T_VOID) {
// See comments in MethodHandles::same_basic_type_for_arguments.
} else {
assert(false, "IMPLEMENT ME");
lose("no raw conversion method", CHECK_(empty));
}
+ // Return type.
+ {
+ BasicType src = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(incoming_mtype()));
+ BasicType dst = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(outgoing_mtype()));
+ retype_raw_return_type(src, dst, CHECK_(empty));
}
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_CHECK_CAST: {
*** 271,281 ****
--- 263,273 ----
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.token_type() >= tt_symbolic || arg.index() == new_arg.index(), "should be the same index");
debug_only(dest_klass = (klassOop)badOop);
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_PRIM: {
*** 330,340 ****
--- 322,332 ----
lose("no boxing method", CHECK_(empty));
}
ArgToken arglist[2];
arglist[0] = arg; // outgoing value
arglist[1] = ArgToken(); // sentinel
! arg = make_invoke(NULL, boxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_(empty));
! arg = make_invoke(NULL, boxer, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK_(empty));
change_argument(src, arg_slot, T_OBJECT, arg);
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_SWAP_ARGS: {
*** 402,418 ****
--- 394,451 ----
_outgoing.remove_at(arg_slot);
}
break;
}
! case java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS: { //NYI, may GC
lose("unimplemented", CHECK_(empty));
break;
! case java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS:
+ retain_original_args = true; // and fall through:
+ case java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS: {
+ // call argument MH recursively
+ //{static int x; if (!x++) print_method_handle(chain().method_handle_oop()); --x;}
+ Handle recursive_mh(THREAD, chain().adapter_arg_oop());
+ if (!java_lang_invoke_MethodHandle::is_instance(recursive_mh())) {
+ lose("recursive target not a MethodHandle", CHECK_(empty));
+ }
+ Handle recursive_mtype(THREAD, java_lang_invoke_MethodHandle::type(recursive_mh()));
+ int argc = java_lang_invoke_MethodType::ptype_count(recursive_mtype());
+ int coll_slots = java_lang_invoke_MethodHandle::vmslots(recursive_mh());
+ BasicType rtype = java_lang_Class::as_BasicType(java_lang_invoke_MethodType::rtype(recursive_mtype()));
+ ArgToken* arglist = NEW_RESOURCE_ARRAY(ArgToken, 1 + argc + 1); // 1+: mh, +1: sentinel
+ 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));
}
case java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS: { //NYI, may GC
! lose("unimplemented", 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));
+ }
+ arglist[1+argc] = ArgToken(); // sentinel
+ oop invoker = java_lang_invoke_MethodTypeForm::vmlayout(
+ java_lang_invoke_MethodType::form(recursive_mtype()) );
+ if (invoker == NULL || !invoker->is_method()) {
+ lose("bad vmlayout slot", CHECK_(empty));
+ }
+ // FIXME: consider inlining the invokee at the bytecode level
+ ArgToken ret = make_invoke(methodOop(invoker), vmIntrinsics::_none,
+ Bytecodes::_invokevirtual, false, 1+argc, &arglist[0], CHECK_(empty));
+ DEBUG_ONLY(invoker = NULL);
+ if (rtype == T_OBJECT) {
+ klassOop rklass = java_lang_Class::as_klassOop( java_lang_invoke_MethodType::rtype(recursive_mtype()) );
+ if (rklass != SystemDictionary::Object_klass() &&
+ !Klass::cast(rklass)->is_interface()) {
+ // preserve type safety
+ ret = make_conversion(T_OBJECT, rklass, Bytecodes::_checkcast, ret, CHECK_(empty));
+ }
+ }
+ int ret_slot = arg_slot + (retain_original_args ? coll_slots : 0);
+ change_argument(T_VOID, ret_slot, rtype, ret);
break;
}
case java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS: {
klassOop array_klass_oop = NULL;
*** 502,512 ****
--- 535,545 ----
arg = make_prim_constant(arg_type, &arg_value, CHECK_(empty));
} else {
lose("bad bound value", CHECK_(empty));
}
}
! debug_only(arg_oop = badOop);
! DEBUG_ONLY(arg_oop = badOop);
change_argument(T_VOID, arg_slot, arg_type, arg);
}
// this test must come after the body of the loop
if (!chain().is_last()) {
*** 545,570 ****
--- 578,601 ----
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);
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);
! 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);
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
}
*** 612,621 ****
--- 643,694 ----
}
#endif
// -----------------------------------------------------------------------------
+ // MethodHandleWalker::retype_raw_conversion
+ //
+ // Do the raw retype conversions for OP_RETYPE_RAW.
+ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, bool for_return, int slot, TRAPS) {
+ if (src != dst) {
+ if (MethodHandles::same_basic_type_for_returns(src, dst, /*raw*/ true)) {
+ if (MethodHandles::is_float_fixed_reinterpretation_cast(src, dst)) {
+ if (for_return) Untested("MHW return raw conversion"); // still untested
+ vmIntrinsics::ID iid = vmIntrinsics::for_raw_conversion(src, dst);
+ if (iid == vmIntrinsics::_none) {
+ 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);
+ } else {
+ // return type conversion
+ klassOop arg_klass = NULL;
+ arglist[0] = make_parameter(src, arg_klass, -1, CHECK); // return value
+ arglist[1] = ArgToken(); // sentinel
+ (void) make_invoke(NULL, iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK);
+ }
+ } else {
+ // Nothing to do.
+ }
+ } 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);
+ }
+ }
+ }
+
+
+ // -----------------------------------------------------------------------------
// MethodHandleCompiler
MethodHandleCompiler::MethodHandleCompiler(Handle root, methodHandle callee, int invoke_count, bool is_invokedynamic, TRAPS)
: MethodHandleWalker(root, is_invokedynamic, THREAD),
_callee(callee),
*** 717,726 ****
--- 790,800 ----
case Bytecodes::_dstore_3:
case Bytecodes::_astore_0:
case Bytecodes::_astore_1:
case Bytecodes::_astore_2:
case Bytecodes::_astore_3:
+ case Bytecodes::_iand:
case Bytecodes::_i2l:
case Bytecodes::_i2f:
case Bytecodes::_i2d:
case Bytecodes::_i2b:
case Bytecodes::_i2c:
*** 943,976 ****
--- 1017,1056 ----
emit_bc(op, cpool_klass_put(tk));
emit_store(srctype, index);
break;
default:
ShouldNotReachHere();
+ 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);
}
// -----------------------------------------------------------------------------
// MethodHandleCompiler
//
static jvalue zero_jvalue;
+ // Values used by the compiler.
+ jvalue MethodHandleCompiler::zero_jvalue = { 0 };
+ jvalue MethodHandleCompiler::one_jvalue = { 1 };
// Emit bytecodes for the given invoke instruction.
MethodHandleWalker::ArgToken
MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
Bytecodes::Code op, bool tailcall,
int argc, MethodHandleWalker::ArgToken* argv,
TRAPS) {
+ ArgToken zero;
if (m == NULL) {
// Get the intrinsic methodOop.
m = vmIntrinsics::method_for(iid);
if (m == NULL) {
ArgToken zero;
lose(vmIntrinsics::name_at(iid), CHECK_(zero));
}
}
klassOop klass = m->method_holder();
*** 1039,1061 ****
--- 1119,1158 ----
ArgToken ret;
if (tailcall) {
if (rbt != _rtype) {
if (rbt == T_VOID) {
// push a zero of the right sort
ArgToken zero;
if (_rtype == T_OBJECT) {
zero = make_oop_constant(NULL, CHECK_(zero));
} else {
zero = make_prim_constant(_rtype, &zero_jvalue, CHECK_(zero));
}
emit_load_constant(zero);
} else if (_rtype == T_VOID) {
// We'll emit a _return with something on the stack.
// It's OK to ignore what's on the stack.
+ } else if (rbt == T_INT && is_subword_type(_rtype)) {
+ // Convert value to match return type.
+ switch (_rtype) {
+ case T_BOOLEAN: {
+ // boolean is treated as a one-bit unsigned integer.
+ // Cf. API documentation: java/lang/invoke/MethodHandles.html#explicitCastArguments
+ ArgToken one = make_prim_constant(T_INT, &one_jvalue, CHECK_(zero));
+ emit_load_constant(one);
+ emit_bc(Bytecodes::_iand);
+ break;
+ }
+ case T_BYTE: emit_bc(Bytecodes::_i2b); break;
+ case T_CHAR: emit_bc(Bytecodes::_i2c); break;
+ case T_SHORT: emit_bc(Bytecodes::_i2s); break;
+ default: ShouldNotReachHere();
+ }
+ } else if (is_subword_type(rbt) && (is_subword_type(_rtype) || (_rtype == T_INT))) {
+ // The subword type was returned as an int and will be passed
+ // on as an int.
} else {
! tty->print_cr("*** rbt=%d != rtype=%d", rbt, _rtype);
assert(false, "IMPLEMENT ME");
! lose("unknown conversion", CHECK_(zero));
}
}
switch (_rtype) {
case T_BOOLEAN: case T_BYTE: case T_CHAR: case T_SHORT:
case T_INT: emit_bc(Bytecodes::_ireturn); break;
*** 1214,1246 ****
--- 1311,1345 ----
m->set_size_of_parameters(_num_params);
typeArrayHandle exception_handlers(THREAD, Universe::the_empty_int_array());
m->set_exception_table(exception_handlers());
// Set the invocation counter's count to the invoke count of the
// original call site.
InvocationCounter* ic = m->invocation_counter();
ic->set(InvocationCounter::wait_for_compile, _invoke_count);
// Rewrite the method and set up the constant pool cache.
objArrayOop m_array = oopFactory::new_system_objArray(1, CHECK_(empty));
objArrayHandle methods(THREAD, m_array);
methods->obj_at_put(0, m());
Rewriter::rewrite(_target_klass(), cpool, methods, CHECK_(empty)); // Use fake class.
+ // Set the invocation counter's count to the invoke count of the
+ // original call site.
+ InvocationCounter* ic = m->invocation_counter();
+ ic->set(InvocationCounter::wait_for_compile, _invoke_count);
+
// Create a new MDO
{
methodDataOop mdo = oopFactory::new_methodData(m, CHECK_(empty));
assert(m->method_data() == NULL, "there should not be an MDO yet");
m->set_method_data(mdo);
// Iterate over all profile data and set the count of the counter
// data entries to the original call site counter.
! for (ProfileData* pd = mdo->first_data(); mdo->is_valid(pd); pd = mdo->next_data(pd)) {
if (pd->is_CounterData()) {
CounterData* cd = pd->as_CounterData();
cd->set_count(_invoke_count);
! for (ProfileData* profile_data = mdo->first_data();
+ mdo->is_valid(profile_data);
+ profile_data = mdo->next_data(profile_data)) {
+ if (profile_data->is_CounterData()) {
+ CounterData* counter_data = profile_data->as_CounterData();
+ counter_data->set_count(_invoke_count);
}
}
}
#ifndef PRODUCT
*** 1255,1287 ****
--- 1354,1393 ----
}
#ifndef PRODUCT
#if 0
// MH printer for debugging.
class MethodHandlePrinter : public MethodHandleWalker {
private:
outputStream* _out;
bool _verbose;
int _temp_num;
+ int _param_state;
stringStream _strbuf;
const char* strbuf() {
const char* s = _strbuf.as_string();
_strbuf.reset();
return s;
}
ArgToken token(const char* str) {
! return (ArgToken) str;
! jvalue string_con;
+ string_con.j = (intptr_t) str;
+ return ArgToken(tt_symbolic, T_LONG, string_con);
+ }
+ const char* string(ArgToken token) {
+ return (const char*) (intptr_t) token.get_jlong();
}
void start_params() {
+ _param_state <<= 1;
_out->print("(");
}
void end_params() {
if (_verbose) _out->print("\n");
_out->print(") => {");
+ _param_state >>= 1;
}
void put_type_name(BasicType type, klassOop tk, outputStream* s) {
const char* kname = NULL;
if (tk != NULL)
kname = Klass::cast(tk)->external_name();
*** 1297,1319 ****
--- 1403,1427 ----
return token(temp);
}
public:
MethodHandlePrinter(Handle root, bool verbose, outputStream* out, TRAPS)
! : MethodHandleWalker(root, false, THREAD),
_out(out),
_verbose(verbose),
+ _param_state(0),
_temp_num(0)
{
start_params();
}
virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) {
if (argnum < 0) {
end_params();
! return NULL;
! return token("return");
}
! if (argnum == 0) {
! if ((_param_state & 1) == 0) {
+ _param_state |= 1;
_out->print(_verbose ? "\n " : "");
} else {
_out->print(_verbose ? ",\n " : ", ");
}
if (argnum >= _temp_num)
*** 1339,1380 ****
--- 1447,1496 ----
}
virtual ArgToken make_prim_constant(BasicType type, jvalue* con, TRAPS) {
java_lang_boxing_object::print(type, con, &_strbuf);
return maybe_make_temp("constant", type, "k");
}
! virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS) {
_strbuf.print("%s(%s", Bytecodes::name(op), (const char*)src);
! void print_bytecode_name(Bytecodes::Code op) {
+ if (Bytecodes::is_defined(op))
+ _strbuf.print("%s", Bytecodes::name(op));
+ else
+ _strbuf.print("bytecode_%d", (int) op);
+ }
+ virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS) {
+ print_bytecode_name(op);
+ _strbuf.print("(%s", string(src));
if (tk != NULL) {
_strbuf.print(", ");
put_type_name(type, tk, &_strbuf);
}
_strbuf.print(")");
return maybe_make_temp("convert", type, "v");
}
! virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken base, ArgToken offset, TRAPS) {
! _strbuf.print("%s(%s, %s", Bytecodes::name(op), (const char*)base, (const char*)offset);
! virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS) {
! _strbuf.print("%s(%s, %s", Bytecodes::name(op), string(base), string(offset));
if (tk != NULL) {
_strbuf.print(", ");
put_type_name(type, tk, &_strbuf);
}
_strbuf.print(")");
return maybe_make_temp("fetch", type, "x");
}
virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid,
Bytecodes::Code op, bool tailcall,
int argc, ArgToken* argv, TRAPS) {
- Symbol* name, sig;
+ Symbol* sig;
if (m != NULL) {
name = m->name();
sig = m->signature();
} else {
name = vmSymbols::symbol_at(vmIntrinsics::name_for(iid));
sig = vmSymbols::symbol_at(vmIntrinsics::signature_for(iid));
}
_strbuf.print("%s %s%s(", Bytecodes::name(op), name->as_C_string(), sig->as_C_string());
for (int i = 0; i < argc; i++) {
! _strbuf.print("%s%s", (i > 0 ? ", " : ""), (const char*)argv[i]);
! _strbuf.print("%s%s", (i > 0 ? ", " : ""), string(argv[i]));
}
_strbuf.print(")");
if (!tailcall) {
BasicType rt = char2type(sig->byte_at(sig->utf8_length()-1));
if (rt == T_ILLEGAL) rt = T_OBJECT; // ';' at the end of '(...)L...;'
*** 1408,1435 ****
--- 1524,1547 ----
if (!HAS_PENDING_EXCEPTION)
printer.walk(THREAD);
if (HAS_PENDING_EXCEPTION) {
oop ex = PENDING_EXCEPTION;
CLEAR_PENDING_EXCEPTION;
! out->print("\n*** ");
! if (ex != Universe::virtual_machine_error_instance())
! ex->print_on(out);
else
out->print("lose: %s", printer.lose_message());
out->print("\n}\n");
! out->print(" *** ");
! if (printer.lose_message() != NULL) out->print("%s ", printer.lose_message());
! out->print("}");
}
out->print("\n");
}
};
#endif // 0
extern "C"
void print_method_handle(oop mh) {
if (!mh->is_oop()) {
- tty->print_cr("*** not a method handle: "INTPTR_FORMAT, (intptr_t)mh);
} else if (java_lang_invoke_MethodHandle::is_instance(mh)) {
- //MethodHandlePrinter::print(mh);
} else {
tty->print("*** not a method handle: ");
mh->print();
}
}
src/share/vm/prims/methodHandleWalk.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File