aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/opto
diff options
context:
space:
mode:
authortwisti <none@none>2012-08-28 15:24:39 -0700
committertwisti <none@none>2012-08-28 15:24:39 -0700
commita90ddc3cc6c48de44a7a7f4c9220252715f7165c (patch)
tree17db3b8962654be7d70416ee81350b73a45b088d /src/share/vm/opto
parent3239730d7312a1cb79879580cc53bda5d65897bf (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.cpp46
-rw-r--r--src/share/vm/opto/graphKit.cpp12
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;