< prev index next >
hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
Print this page
rev 11908 : 8160543: C1: Crash in java.lang.String.indexOf in some java.sql tests
Summary: C1 must use unverified entry point for unloaded methods.
Reviewed-by:
@@ -1797,24 +1797,23 @@
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");
+ assert(will_link == target->is_loaded(), "Check");
ciInstanceKlass* klass = target->holder();
- // Make sure there are no evident problems with linking the instruction.
- bool is_resolved = true;
- if (klass->is_loaded() && !target->is_loaded()) {
- is_resolved = false; // method not found
- }
-
// check if CHA possible: if so, change the code to invoke_special
ciInstanceKlass* calling_klass = method()->holder();
ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder);
ciInstanceKlass* actual_recv = callee_holder;
+ if (target->is_loaded()) {
+ assert(klass->is_loaded(), "sanity");
+ }
+
CompileLog* log = compilation()->log();
if (log != NULL)
log->elem("call method='%d' instr='%s'",
log->identify(target),
Bytecodes::name(code));
@@ -1972,11 +1971,11 @@
}
code = Bytecodes::_invokespecial;
}
// check if we could do inlining
- if (!PatchALot && Inline && is_resolved &&
+ if (!PatchALot && Inline &&
klass->is_loaded() && target->is_loaded() &&
(klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized())
&& !patch_for_appendix) {
// callee is known => check if we have static binding
if (code == Bytecodes::_invokestatic ||
@@ -2016,11 +2015,10 @@
// corrupting the graph. (We currently bail out with a non-empty
// stack at a ret in these situations.)
CHECK_BAILOUT();
// inlining not successful => standard invoke
- bool is_loaded = target->is_loaded();
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.
const bool has_receiver =
@@ -2033,11 +2031,11 @@
#ifdef SPARC
// Currently only supported on Sparc.
// The UseInlineCaches only controls dispatch to invokevirtuals for
// loaded classes which we weren't able to statically bind.
- if (!UseInlineCaches && is_resolved && is_loaded && code == Bytecodes::_invokevirtual
+ if (!UseInlineCaches && target->is_loaded() && code == Bytecodes::_invokevirtual
&& !target->can_be_statically_bound()) {
// Find a vtable index if one is available
// For arrays, callee_holder is Object. Resolving the call with
// Object would allow an illegal call to finalize() on an
// array. We use holder instead: illegal calls to finalize() won't
@@ -2046,22 +2044,22 @@
// either.
vtable_index = target->resolve_vtable_index(calling_klass, holder);
}
#endif
- if (is_resolved) {
+
// invokespecial always needs a NULL check. invokevirtual where the target is
// final or where it's not known whether the target is final requires a NULL check.
// Otherwise normal invokevirtual will perform the null check during the lookup
// logic or the unverified entry point. Profiling of calls requires that
// the null check is performed in all cases.
+
bool do_null_check = (recv != NULL) &&
- (code == Bytecodes::_invokespecial || !is_loaded || target->is_final() || (is_profiling() && profile_calls()));
+ (code == Bytecodes::_invokespecial || (target->is_loaded() && (target->is_final() || (is_profiling() && profile_calls()))));
if (do_null_check) {
null_check(recv);
- }
if (is_profiling()) {
// Note that we'd collect profile data in this method if we wanted it.
compilation()->set_would_profile(true);
@@ -2074,13 +2072,10 @@
target_klass = exact_target->holder();
}
profile_call(target, recv, target_klass, collect_args_for_profiling(args, NULL, false), false);
}
}
- } else {
- // No need in null check or profiling: linkage error will be thrown at runtime
- // during resolution.
}
Invoke* result = new Invoke(code, result_type, recv, args, vtable_index, target, state_before);
// push result
append_split(result);
< prev index next >