diff options
author | twisti <none@none> | 2012-08-28 15:24:39 -0700 |
---|---|---|
committer | twisti <none@none> | 2012-08-28 15:24:39 -0700 |
commit | a90ddc3cc6c48de44a7a7f4c9220252715f7165c (patch) | |
tree | 17db3b8962654be7d70416ee81350b73a45b088d /src/share/vm/opto | |
parent | 3239730d7312a1cb79879580cc53bda5d65897bf (diff) |
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
Reviewed-by: kvn
Diffstat (limited to 'src/share/vm/opto')
-rw-r--r-- | src/share/vm/opto/doCall.cpp | 46 | ||||
-rw-r--r-- | src/share/vm/opto/graphKit.cpp | 12 |
2 files changed, 30 insertions, 28 deletions
diff --git a/src/share/vm/opto/doCall.cpp b/src/share/vm/opto/doCall.cpp index 580740b9f..a34870509 100644 --- a/src/share/vm/opto/doCall.cpp +++ b/src/share/vm/opto/doCall.cpp @@ -341,25 +341,26 @@ void Parse::do_call() { kill_dead_locals(); // Set frequently used booleans - bool is_virtual = bc() == Bytecodes::_invokevirtual; - bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface; - bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial; - bool is_invokedynamic = bc() == Bytecodes::_invokedynamic; + const bool is_virtual = bc() == Bytecodes::_invokevirtual; + const bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface; + const bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial; // Find target being called bool will_link; - ciMethod* bc_callee = iter().get_method(will_link); // actual callee from bytecode - ciInstanceKlass* holder_klass = bc_callee->holder(); - ciKlass* holder = iter().get_declared_method_holder(); + ciSignature* declared_signature = NULL; + ciMethod* orig_callee = iter().get_method(will_link, &declared_signature); // callee in the bytecode + ciInstanceKlass* holder_klass = orig_callee->holder(); + ciKlass* holder = iter().get_declared_method_holder(); ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder); + assert(declared_signature != NULL, "cannot be null"); // uncommon-trap when callee is unloaded, uninitialized or will not link // bailout when too many arguments for register representation - if (!will_link || can_not_compile_call_site(bc_callee, klass)) { + if (!will_link || can_not_compile_call_site(orig_callee, klass)) { #ifndef PRODUCT if (PrintOpto && (Verbose || WizardMode)) { method()->print_name(); tty->print_cr(" can not compile call at bci %d to:", bci()); - bc_callee->print_name(); tty->cr(); + orig_callee->print_name(); tty->cr(); } #endif return; @@ -372,7 +373,7 @@ void Parse::do_call() { // Note: In the absence of miranda methods, an abstract class K can perform // an invokevirtual directly on an interface method I.m if K implements I. - const int nargs = bc_callee->arg_size(); + const int nargs = orig_callee->arg_size(); // Push appendix argument (MethodType, CallSite, etc.), if one. if (iter().has_appendix()) { @@ -392,13 +393,13 @@ void Parse::do_call() { // Choose call strategy. bool call_is_virtual = is_virtual_or_interface; int vtable_index = methodOopDesc::invalid_vtable_index; - ciMethod* callee = bc_callee; + ciMethod* callee = orig_callee; // Try to get the most accurate receiver type if (is_virtual_or_interface) { Node* receiver_node = stack(sp() - nargs); const TypeOopPtr* receiver_type = _gvn.type(receiver_node)->isa_oopptr(); - ciMethod* optimized_virtual_method = optimize_inlining(method(), bci(), klass, bc_callee, receiver_type); + ciMethod* optimized_virtual_method = optimize_inlining(method(), bci(), klass, orig_callee, receiver_type); // Have the call been sufficiently improved such that it is no longer a virtual? if (optimized_virtual_method != NULL) { @@ -425,7 +426,8 @@ void Parse::do_call() { // It decides whether inlining is desirable or not. CallGenerator* cg = C->call_generator(callee, vtable_index, call_is_virtual, jvms, try_inline, prof_factor()); - bc_callee = callee = NULL; // don't use bc_callee and callee after this point + // NOTE: Don't use orig_callee and callee after this point! Use cg->method() instead. + orig_callee = callee = NULL; // --------------------- // Round double arguments before call @@ -497,9 +499,9 @@ void Parse::do_call() { round_double_result(cg->method()); ciType* rtype = cg->method()->return_type(); - if (iter().cur_bc_raw() == Bytecodes::_invokehandle || is_invokedynamic) { + if (Bytecodes::has_optional_appendix(iter().cur_bc_raw())) { // Be careful here with return types. - ciType* ctype = iter().get_declared_method_signature()->return_type(); + ciType* ctype = declared_signature->return_type(); if (ctype != rtype) { BasicType rt = rtype->basic_type(); BasicType ct = ctype->basic_type(); @@ -528,15 +530,13 @@ void Parse::do_call() { } else if (rt == T_OBJECT || rt == T_ARRAY) { assert(ct == T_OBJECT || ct == T_ARRAY, err_msg_res("rt=%s, ct=%s", type2name(rt), type2name(ct))); if (ctype->is_loaded()) { - Node* if_fail = top(); - retnode = gen_checkcast(retnode, makecon(TypeKlassPtr::make(ctype->as_klass())), &if_fail); - if (if_fail != top()) { - PreserveJVMState pjvms(this); - set_control(if_fail); - builtin_throw(Deoptimization::Reason_class_check); + const TypeOopPtr* arg_type = TypeOopPtr::make_from_klass(rtype->as_klass()); + const Type* sig_type = TypeOopPtr::make_from_klass(ctype->as_klass()); + if (arg_type != NULL && !arg_type->higher_equal(sig_type)) { + Node* cast_obj = _gvn.transform(new (C, 2) CheckCastPPNode(control(), retnode, sig_type)); + pop(); + push(cast_obj); } - pop(); - push(retnode); } } else { assert(ct == rt, err_msg_res("unexpected mismatch rt=%d, ct=%d", rt, ct)); diff --git a/src/share/vm/opto/graphKit.cpp b/src/share/vm/opto/graphKit.cpp index da24dc369..f844eaaa4 100644 --- a/src/share/vm/opto/graphKit.cpp +++ b/src/share/vm/opto/graphKit.cpp @@ -1006,11 +1006,11 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth, bool for_parse) { case Bytecodes::_putfield: { bool is_get = (depth >= 0), is_static = (depth & 1); - bool ignore; ciBytecodeStream iter(method()); iter.reset_to_bci(bci()); iter.next(); - ciField* field = iter.get_field(ignore); + bool ignored_will_link; + ciField* field = iter.get_field(ignored_will_link); int size = field->type()->size(); inputs = (is_static ? 0 : 1); if (is_get) { @@ -1028,11 +1028,13 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth, bool for_parse) { case Bytecodes::_invokedynamic: case Bytecodes::_invokeinterface: { - bool ignore; ciBytecodeStream iter(method()); iter.reset_to_bci(bci()); iter.next(); - ciMethod* callee = iter.get_method(ignore); + bool ignored_will_link; + ciSignature* declared_signature = NULL; + ciMethod* callee = iter.get_method(ignored_will_link, &declared_signature); + assert(declared_signature != NULL, "cannot be null"); // (Do not use ciMethod::arg_size(), because // it might be an unloaded method, which doesn't // know whether it is static or not.) @@ -1046,7 +1048,7 @@ bool GraphKit::compute_stack_effects(int& inputs, int& depth, bool for_parse) { // remove any appendix arguments that were popped. inputs = callee->invoke_arg_size(code) - (callee->has_member_arg() ? 1 : 0); } - int size = callee->return_type()->size(); + int size = declared_signature->return_type()->size(); depth = size - inputs; } break; |