aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm
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
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')
-rw-r--r--src/share/vm/c1/c1_GraphBuilder.cpp16
-rw-r--r--src/share/vm/c1/c1_GraphBuilder.hpp2
-rw-r--r--src/share/vm/ci/bcEscapeAnalyzer.cpp29
-rw-r--r--src/share/vm/ci/ciEnv.cpp152
-rw-r--r--src/share/vm/ci/ciEnv.hpp3
-rw-r--r--src/share/vm/ci/ciMethod.cpp5
-rw-r--r--src/share/vm/ci/ciStreams.cpp45
-rw-r--r--src/share/vm/ci/ciStreams.hpp6
-rw-r--r--src/share/vm/ci/ciTypeFlow.cpp29
-rw-r--r--src/share/vm/interpreter/bytecodes.hpp2
-rw-r--r--src/share/vm/opto/doCall.cpp46
-rw-r--r--src/share/vm/opto/graphKit.cpp12
12 files changed, 165 insertions, 182 deletions
diff --git a/src/share/vm/c1/c1_GraphBuilder.cpp b/src/share/vm/c1/c1_GraphBuilder.cpp
index 1865e9c4b..c447382f1 100644
--- a/src/share/vm/c1/c1_GraphBuilder.cpp
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp
@@ -1646,15 +1646,15 @@ Dependencies* GraphBuilder::dependency_recorder() const {
void GraphBuilder::invoke(Bytecodes::Code code) {
- const bool is_invokedynamic = (code == Bytecodes::_invokedynamic);
-
bool will_link;
- ciMethod* target = stream()->get_method(will_link);
+ ciSignature* declared_signature = NULL;
+ ciMethod* target = stream()->get_method(will_link, &declared_signature);
ciKlass* holder = stream()->get_declared_method_holder();
const Bytecodes::Code bc_raw = stream()->cur_bc_raw();
+ assert(declared_signature != NULL, "cannot be null");
// FIXME bail out for now
- if ((bc_raw == Bytecodes::_invokehandle || is_invokedynamic) && !will_link) {
+ if (Bytecodes::has_optional_appendix(bc_raw) && !will_link) {
BAILOUT("unlinked call site (FIXME needs patching or recompile support)");
}
@@ -1840,7 +1840,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
bool success = false;
if (target->is_method_handle_intrinsic()) {
// method handle invokes
- success = for_method_handle_inline(target);
+ success = try_method_handle_inline(target);
} else {
// static binding => check if callee is ok
success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL), code, better_receiver);
@@ -1877,7 +1877,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
// inlining not successful => standard invoke
bool is_loaded = target->is_loaded();
- ValueType* result_type = as_ValueType(target->return_type());
+ ValueType* result_type = as_ValueType(declared_signature->return_type());
ValueStack* state_before = copy_state_exhandling();
// The bytecode (code) might change in this method so we are checking this very late.
@@ -3823,7 +3823,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode
}
-bool GraphBuilder::for_method_handle_inline(ciMethod* callee) {
+bool GraphBuilder::try_method_handle_inline(ciMethod* callee) {
ValueStack* state_before = state()->copy_for_parsing();
vmIntrinsics::ID iid = callee->intrinsic_id();
switch (iid) {
@@ -3858,7 +3858,7 @@ bool GraphBuilder::for_method_handle_inline(ciMethod* callee) {
// If the target is another method handle invoke try recursivly to get
// a better target.
if (target->is_method_handle_intrinsic()) {
- if (for_method_handle_inline(target)) {
+ if (try_method_handle_inline(target)) {
return true;
}
} else {
diff --git a/src/share/vm/c1/c1_GraphBuilder.hpp b/src/share/vm/c1/c1_GraphBuilder.hpp
index e54863e0d..8d7e7de34 100644
--- a/src/share/vm/c1/c1_GraphBuilder.hpp
+++ b/src/share/vm/c1/c1_GraphBuilder.hpp
@@ -346,7 +346,7 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
const char* should_not_inline(ciMethod* callee) const;
// JSR 292 support
- bool for_method_handle_inline(ciMethod* callee);
+ bool try_method_handle_inline(ciMethod* callee);
// helpers
void inline_bailout(const char* msg);
diff --git a/src/share/vm/ci/bcEscapeAnalyzer.cpp b/src/share/vm/ci/bcEscapeAnalyzer.cpp
index 20ad22ea6..31bd06c26 100644
--- a/src/share/vm/ci/bcEscapeAnalyzer.cpp
+++ b/src/share/vm/ci/bcEscapeAnalyzer.cpp
@@ -236,12 +236,16 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod*
ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder);
ciInstanceKlass* actual_recv = callee_holder;
- // some methods are obviously bindable without any type checks so
- // convert them directly to an invokespecial.
+ // Some methods are obviously bindable without any type checks so
+ // convert them directly to an invokespecial or invokestatic.
if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) {
switch (code) {
- case Bytecodes::_invokevirtual: code = Bytecodes::_invokespecial; break;
- case Bytecodes::_invokehandle: code = Bytecodes::_invokestatic; break;
+ case Bytecodes::_invokevirtual:
+ code = Bytecodes::_invokespecial;
+ break;
+ case Bytecodes::_invokehandle:
+ code = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokespecial;
+ break;
}
}
@@ -826,8 +830,8 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
break;
case Bytecodes::_getstatic:
case Bytecodes::_getfield:
- { bool will_link;
- ciField* field = s.get_field(will_link);
+ { bool ignored_will_link;
+ ciField* field = s.get_field(ignored_will_link);
BasicType field_type = field->type()->basic_type();
if (s.cur_bc() != Bytecodes::_getstatic) {
set_method_escape(state.apop());
@@ -865,16 +869,21 @@ void BCEscapeAnalyzer::iterate_one_block(ciBlock *blk, StateInfo &state, Growabl
case Bytecodes::_invokestatic:
case Bytecodes::_invokedynamic:
case Bytecodes::_invokeinterface:
- { bool will_link;
- ciMethod* target = s.get_method(will_link);
- ciKlass* holder = s.get_declared_method_holder();
+ { bool ignored_will_link;
+ ciSignature* declared_signature = NULL;
+ ciMethod* target = s.get_method(ignored_will_link, &declared_signature);
+ ciKlass* holder = s.get_declared_method_holder();
+ assert(declared_signature != NULL, "cannot be null");
// Push appendix argument, if one.
if (s.has_appendix()) {
state.apush(unknown_obj);
}
// Pass in raw bytecode because we need to see invokehandle instructions.
invoke(state, s.cur_bc_raw(), target, holder);
- ciType* return_type = target->return_type();
+ // We are using the return type of the declared signature here because
+ // it might be a more concrete type than the one from the target (for
+ // e.g. invokedynamic and invokehandle).
+ ciType* return_type = declared_signature->return_type();
if (!return_type->is_primitive_type()) {
state.apush(unknown_obj);
} else if (return_type->is_one_word()) {
diff --git a/src/share/vm/ci/ciEnv.cpp b/src/share/vm/ci/ciEnv.cpp
index 30a54a32a..947c72e24 100644
--- a/src/share/vm/ci/ciEnv.cpp
+++ b/src/share/vm/ci/ciEnv.cpp
@@ -738,91 +738,81 @@ methodOop ciEnv::lookup_method(instanceKlass* accessor,
ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool,
int index, Bytecodes::Code bc,
ciInstanceKlass* accessor) {
- int holder_index = cpool->klass_ref_index_at(index);
- bool holder_is_accessible;
- ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
- ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
-
- // Get the method's name and signature.
- Symbol* name_sym = cpool->name_ref_at(index);
- Symbol* sig_sym = cpool->signature_ref_at(index);
-
- if (cpool->has_preresolution()
- || (holder == ciEnv::MethodHandle_klass() &&
- MethodHandles::is_signature_polymorphic_name(holder->get_klassOop(), name_sym))) {
- // Short-circuit lookups for JSR 292-related call sites.
- // That is, do not rely only on name-based lookups, because they may fail
- // if the names are not resolvable in the boot class loader (7056328).
- switch (bc) {
- case Bytecodes::_invokevirtual:
- case Bytecodes::_invokeinterface:
- case Bytecodes::_invokespecial:
- case Bytecodes::_invokestatic:
- {
- oop appendix_oop = NULL;
- methodOop m = constantPoolOopDesc::method_at_if_loaded(cpool, index);
- if (m != NULL) {
- return get_object(m)->as_method();
- }
- }
- break;
- }
- }
-
- if (holder_is_accessible) { // Our declared holder is loaded.
- instanceKlass* lookup = declared_holder->get_instanceKlass();
- methodOop m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc);
- if (m != NULL &&
- (bc == Bytecodes::_invokestatic
- ? instanceKlass::cast(m->method_holder())->is_not_initialized()
- : !instanceKlass::cast(m->method_holder())->is_loaded())) {
- m = NULL;
- }
- if (m != NULL) {
- // We found the method.
- return get_object(m)->as_method();
+ if (bc == Bytecodes::_invokedynamic) {
+ ConstantPoolCacheEntry* secondary_entry = cpool->cache()->secondary_entry_at(index);
+ const bool is_resolved = !secondary_entry->is_f1_null();
+ // FIXME: code generation could allow for null (unlinked) call site
+ // The call site could be made patchable as follows:
+ // Load the appendix argument from the constant pool.
+ // Test the appendix argument and jump to a known deopt routine if it is null.
+ // Jump through a patchable call site, which is initially a deopt routine.
+ // Patch the call site to the nmethod entry point of the static compiled lambda form.
+ // As with other two-component call sites, both values must be independently verified.
+
+ if (is_resolved) {
+ // Get the invoker methodOop and the extra argument from the constant pool.
+ methodOop adapter = secondary_entry->f2_as_vfinal_method();
+ return get_object(adapter)->as_method();
}
- }
-
- // Either the declared holder was not loaded, or the method could
- // not be found. Create a dummy ciMethod to represent the failed
- // lookup.
- ciSymbol* name = get_symbol(name_sym);
- ciSymbol* signature = get_symbol(sig_sym);
- return get_unloaded_method(declared_holder, name, signature, accessor);
-}
-
-// ------------------------------------------------------------------
-// ciEnv::get_fake_invokedynamic_method_impl
-ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
- int index, Bytecodes::Code bc,
- ciInstanceKlass* accessor) {
- // Compare the following logic with InterpreterRuntime::resolve_invokedynamic.
- assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic");
-
- ConstantPoolCacheEntry* secondary_entry = cpool->cache()->secondary_entry_at(index);
- bool is_resolved = !secondary_entry->is_f1_null();
- // FIXME: code generation could allow for null (unlinked) call site
- // The call site could be made patchable as follows:
- // Load the appendix argument from the constant pool.
- // Test the appendix argument and jump to a known deopt routine if it is null.
- // Jump through a patchable call site, which is initially a deopt routine.
- // Patch the call site to the nmethod entry point of the static compiled lambda form.
- // As with other two-component call sites, both values must be independently verified.
-
- // Call site might not be resolved yet.
- // Stop the code path here with an unlinked method.
- if (!is_resolved) {
+ // Fake a method that is equivalent to a declared method.
ciInstanceKlass* holder = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass();
ciSymbol* name = ciSymbol::invokeBasic_name();
ciSymbol* signature = get_symbol(cpool->signature_ref_at(index));
return get_unloaded_method(holder, name, signature, accessor);
- }
+ } else {
+ const int holder_index = cpool->klass_ref_index_at(index);
+ bool holder_is_accessible;
+ ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
+ ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
+
+ // Get the method's name and signature.
+ Symbol* name_sym = cpool->name_ref_at(index);
+ Symbol* sig_sym = cpool->signature_ref_at(index);
+
+ if (cpool->has_preresolution()
+ || (holder == ciEnv::MethodHandle_klass() &&
+ MethodHandles::is_signature_polymorphic_name(holder->get_klassOop(), name_sym))) {
+ // Short-circuit lookups for JSR 292-related call sites.
+ // That is, do not rely only on name-based lookups, because they may fail
+ // if the names are not resolvable in the boot class loader (7056328).
+ switch (bc) {
+ case Bytecodes::_invokevirtual:
+ case Bytecodes::_invokeinterface:
+ case Bytecodes::_invokespecial:
+ case Bytecodes::_invokestatic:
+ {
+ methodOop m = constantPoolOopDesc::method_at_if_loaded(cpool, index);
+ if (m != NULL) {
+ return get_object(m)->as_method();
+ }
+ }
+ break;
+ }
+ }
+
+ if (holder_is_accessible) { // Our declared holder is loaded.
+ instanceKlass* lookup = declared_holder->get_instanceKlass();
+ methodOop m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc);
+ if (m != NULL &&
+ (bc == Bytecodes::_invokestatic
+ ? instanceKlass::cast(m->method_holder())->is_not_initialized()
+ : !instanceKlass::cast(m->method_holder())->is_loaded())) {
+ m = NULL;
+ }
+ if (m != NULL) {
+ // We found the method.
+ return get_object(m)->as_method();
+ }
+ }
- // Get the invoker methodOop and the extra argument from the constant pool.
- methodOop adapter = secondary_entry->f2_as_vfinal_method();
- return get_object(adapter)->as_method();
+ // Either the declared holder was not loaded, or the method could
+ // not be found. Create a dummy ciMethod to represent the failed
+ // lookup.
+ ciSymbol* name = get_symbol(name_sym);
+ ciSymbol* signature = get_symbol(sig_sym);
+ return get_unloaded_method(declared_holder, name, signature, accessor);
+ }
}
@@ -853,11 +843,7 @@ ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* m
ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool,
int index, Bytecodes::Code bc,
ciInstanceKlass* accessor) {
- if (bc == Bytecodes::_invokedynamic) {
- GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc, accessor);)
- } else {
- GUARDED_VM_ENTRY(return get_method_by_index_impl( cpool, index, bc, accessor);)
- }
+ GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);)
}
diff --git a/src/share/vm/ci/ciEnv.hpp b/src/share/vm/ci/ciEnv.hpp
index d00c9f78b..57323a6f1 100644
--- a/src/share/vm/ci/ciEnv.hpp
+++ b/src/share/vm/ci/ciEnv.hpp
@@ -152,9 +152,6 @@ private:
ciMethod* get_method_by_index_impl(constantPoolHandle cpool,
int method_index, Bytecodes::Code bc,
ciInstanceKlass* loading_klass);
- ciMethod* get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
- int index, Bytecodes::Code bc,
- ciInstanceKlass* accessor);
// Helper methods
bool check_klass_accessibility(ciKlass* accessing_klass,
diff --git a/src/share/vm/ci/ciMethod.cpp b/src/share/vm/ci/ciMethod.cpp
index 579e1de47..fcadab76d 100644
--- a/src/share/vm/ci/ciMethod.cpp
+++ b/src/share/vm/ci/ciMethod.cpp
@@ -1215,9 +1215,10 @@ void ciMethod::print_impl(outputStream* st) {
holder()->print_name_on(st);
st->print(" signature=");
signature()->as_symbol()->print_symbol_on(st);
- st->print(" arg_size=%d", arg_size());
if (is_loaded()) {
- st->print(" loaded=true flags=");
+ st->print(" loaded=true");
+ st->print(" arg_size=%d", arg_size());
+ st->print(" flags=");
flags().print_member_flags(st);
} else {
st->print(" loaded=false");
diff --git a/src/share/vm/ci/ciStreams.cpp b/src/share/vm/ci/ciStreams.cpp
index 23dc891bf..92ab59d60 100644
--- a/src/share/vm/ci/ciStreams.cpp
+++ b/src/share/vm/ci/ciStreams.cpp
@@ -355,11 +355,23 @@ int ciBytecodeStream::get_method_index() {
// ciBytecodeStream::get_method
//
// If this is a method invocation bytecode, get the invoked method.
-ciMethod* ciBytecodeStream::get_method(bool& will_link) {
+// Additionally return the declared signature to get more concrete
+// type information if required (Cf. invokedynamic and invokehandle).
+ciMethod* ciBytecodeStream::get_method(bool& will_link, ciSignature* *declared_signature_result) {
VM_ENTRY_MARK;
+ ciEnv* env = CURRENT_ENV;
constantPoolHandle cpool(_method->get_methodOop()->constants());
- ciMethod* m = CURRENT_ENV->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder);
+ ciMethod* m = env->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder);
will_link = m->is_loaded();
+ // Get declared method signature and return it.
+ if (has_optional_appendix()) {
+ const int sig_index = get_method_signature_index();
+ Symbol* sig_sym = cpool->symbol_at(sig_index);
+ ciKlass* pool_holder = env->get_object(cpool->pool_holder())->as_klass();
+ (*declared_signature_result) = new (env->arena()) ciSignature(pool_holder, cpool, env->get_symbol(sig_sym));
+ } else {
+ (*declared_signature_result) = m->signature();
+ }
return m;
}
@@ -419,35 +431,18 @@ int ciBytecodeStream::get_method_holder_index() {
}
// ------------------------------------------------------------------
-// ciBytecodeStream::get_declared_method_signature
-//
-// Get the declared signature of the currently referenced method.
-//
-// This is always the same as the signature of the resolved method
-// itself, except for _invokehandle and _invokedynamic calls.
-//
-ciSignature* ciBytecodeStream::get_declared_method_signature() {
- int sig_index = get_method_signature_index();
- VM_ENTRY_MARK;
- ciEnv* env = CURRENT_ENV;
- constantPoolHandle cpool(_method->get_methodOop()->constants());
- Symbol* sig_sym = cpool->symbol_at(sig_index);
- ciKlass* pool_holder = env->get_object(cpool->pool_holder())->as_klass();
- return new (env->arena()) ciSignature(pool_holder, cpool, env->get_symbol(sig_sym));
-}
-
-// ------------------------------------------------------------------
// ciBytecodeStream::get_method_signature_index
//
// Get the constant pool index of the signature of the method
// referenced by the current bytecode. Used for generating
// deoptimization information.
int ciBytecodeStream::get_method_signature_index() {
- VM_ENTRY_MARK;
- constantPoolOop cpool = _holder->get_instanceKlass()->constants();
- int method_index = get_method_index();
- int name_and_type_index = cpool->name_and_type_ref_index_at(method_index);
- return cpool->signature_ref_index_at(name_and_type_index);
+ GUARDED_VM_ENTRY(
+ constantPoolOop cpool = _holder->get_instanceKlass()->constants();
+ const int method_index = get_method_index();
+ const int name_and_type_index = cpool->name_and_type_ref_index_at(method_index);
+ return cpool->signature_ref_index_at(name_and_type_index);
+ )
}
// ------------------------------------------------------------------
diff --git a/src/share/vm/ci/ciStreams.hpp b/src/share/vm/ci/ciStreams.hpp
index 5689d4ca1..0f442539e 100644
--- a/src/share/vm/ci/ciStreams.hpp
+++ b/src/share/vm/ci/ciStreams.hpp
@@ -151,6 +151,8 @@ public:
// Does this instruction contain an index which refes into the CP cache?
bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); }
+ bool has_optional_appendix() { return Bytecodes::has_optional_appendix(cur_bc_raw()); }
+
int get_index_u1() const {
return bytecode().get_index_u1(cur_bc_raw());
}
@@ -257,13 +259,11 @@ public:
int get_field_holder_index();
int get_field_signature_index();
- // If this is a method invocation bytecode, get the invoked method.
- ciMethod* get_method(bool& will_link);
+ ciMethod* get_method(bool& will_link, ciSignature* *declared_signature_result);
bool has_appendix();
ciObject* get_appendix();
ciKlass* get_declared_method_holder();
int get_method_holder_index();
- ciSignature* get_declared_method_signature();
int get_method_signature_index();
ciCPCache* get_cpcache() const;
diff --git a/src/share/vm/ci/ciTypeFlow.cpp b/src/share/vm/ci/ciTypeFlow.cpp
index 94c6123c9..d28ed53d2 100644
--- a/src/share/vm/ci/ciTypeFlow.cpp
+++ b/src/share/vm/ci/ciTypeFlow.cpp
@@ -643,9 +643,11 @@ void ciTypeFlow::StateVector::do_getstatic(ciBytecodeStream* str) {
// ------------------------------------------------------------------
// ciTypeFlow::StateVector::do_invoke
void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str,
- bool has_receiver_foo) {
+ bool has_receiver) {
bool will_link;
- ciMethod* callee = str->get_method(will_link);
+ ciSignature* declared_signature = NULL;
+ ciMethod* callee = str->get_method(will_link, &declared_signature);
+ assert(declared_signature != NULL, "cannot be null");
if (!will_link) {
// We weren't able to find the method.
if (str->cur_bc() == Bytecodes::_invokedynamic) {
@@ -658,22 +660,12 @@ void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str,
trap(str, unloaded_holder, str->get_method_holder_index());
}
} else {
- // TODO Use Bytecode_invoke after metadata changes.
- //Bytecode_invoke inv(str->method(), str->cur_bci());
- //const bool has_receiver = callee->is_loaded() ? !callee->is_static() : inv.has_receiver();
- Bytecode inv(str);
- Bytecodes::Code code = inv.invoke_code();
- const bool has_receiver = callee->is_loaded() ? !callee->is_static() : code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic;
-
- ciSignature* signature = callee->signature();
- ciSignatureStream sigstr(signature);
- // Push appendix argument, if one.
- if (str->has_appendix()) {
- ciObject* appendix = str->get_appendix();
- push_object(appendix->klass());
- }
- int arg_size = signature->size();
- int stack_base = stack_size() - arg_size;
+ // We are using the declared signature here because it might be
+ // different from the callee signature (Cf. invokedynamic and
+ // invokehandle).
+ ciSignatureStream sigstr(declared_signature);
+ const int arg_size = declared_signature->size();
+ const int stack_base = stack_size() - arg_size;
int i = 0;
for( ; !sigstr.at_return_type(); sigstr.next()) {
ciType* type = sigstr.type();
@@ -689,7 +681,6 @@ void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str,
for (int j = 0; j < arg_size; j++) {
pop();
}
- assert(!callee->is_loaded() || has_receiver == !callee->is_static(), "mismatch");
if (has_receiver) {
// Check this?
pop_object();
diff --git a/src/share/vm/interpreter/bytecodes.hpp b/src/share/vm/interpreter/bytecodes.hpp
index 4d6e173aa..4cd078a30 100644
--- a/src/share/vm/interpreter/bytecodes.hpp
+++ b/src/share/vm/interpreter/bytecodes.hpp
@@ -424,6 +424,8 @@ class Bytecodes: AllStatic {
|| code == _fconst_0 || code == _dconst_0); }
static bool is_invoke (Code code) { return (_invokevirtual <= code && code <= _invokedynamic); }
+ static bool has_optional_appendix(Code code) { return code == _invokedynamic || code == _invokehandle; }
+
static int compute_flags (const char* format, int more_flags = 0); // compute the flags
static int flags (int code, bool is_wide) {
assert(code == (u_char)code, "must be a byte");
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;