< prev index next >
src/share/vm/code/compiledIC.cpp
Print this page
rev 12270 : 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:
*** 458,470 ****
// cleaning it immediately is harmless.
// assert(is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
}
! // is_optimized: Compiler has generated an optimized call (i.e., no inline
! // cache) static_bound: The call can be static bound (i.e, no need to use
! // inline cache)
void CompiledIC::compute_monomorphic_entry(const methodHandle& method,
KlassHandle receiver_klass,
bool is_optimized,
bool static_bound,
CompiledICInfo& info,
--- 458,472 ----
// cleaning it immediately is harmless.
// assert(is_call_to_compiled() || is_call_to_interpreted(), "sanity check");
}
! // is_optimized: Compiler has generated an optimized call (i.e. fixed, no inline cache)
! // static_bound: The call can be static bound. If it isn't also optimized, the property
! // wasn't provable at time of compilation. An optimized call will have any necessary
! // null check, while a static_bound won't. A static_bound (but not optimized) must
! // therefore use the unverified entry point.
void CompiledIC::compute_monomorphic_entry(const methodHandle& method,
KlassHandle receiver_klass,
bool is_optimized,
bool static_bound,
CompiledICInfo& info,
*** 473,524 ****
address entry = NULL;
if (method_code != NULL && method_code->is_in_use()) {
assert(method_code->is_compiled(), "must be compiled");
// Call to compiled code
! if (static_bound || is_optimized) {
entry = method_code->verified_entry_point();
} else {
entry = method_code->entry_point();
}
}
if (entry != NULL) {
// Call to compiled code
info.set_compiled_entry(entry, (static_bound || is_optimized) ? NULL : receiver_klass(), is_optimized);
} else {
- // Note: the following problem exists with Compiler1:
- // - at compile time we may or may not know if the destination is final
- // - if we know that the destination is final, we will emit an optimized
- // virtual call (no inline cache), and need a Method* to make a call
- // to the interpreter
- // - if we do not know if the destination is final, we emit a standard
- // virtual call, and use CompiledICHolder to call interpreted code
- // (no static call stub has been generated)
- // However in that case we will now notice it is static_bound
- // and convert the call into what looks to be an optimized
- // virtual call. This causes problems in verifying the IC because
- // it look vanilla but is optimized. Code in is_call_to_interpreted
- // is aware of this and weakens its asserts.
-
- // static_bound should imply is_optimized -- otherwise we have a
- // performance bug (statically-bindable method is called via
- // dynamically-dispatched call note: the reverse implication isn't
- // necessarily true -- the call may have been optimized based on compiler
- // analysis (static_bound is only based on "final" etc.)
- #ifdef COMPILER2
- #ifdef TIERED
- #if defined(ASSERT)
- // can't check the assert because we don't have the CompiledIC with which to
- // find the address if the call instruction.
- //
- // CodeBlob* cb = find_blob_unsafe(instruction_address());
- // assert(cb->is_compiled_by_c1() || !static_bound || is_optimized, "static_bound should imply is_optimized");
- #endif // ASSERT
- #else
- assert(!static_bound || is_optimized, "static_bound should imply is_optimized");
- #endif // TIERED
- #endif // COMPILER2
if (is_optimized) {
// Use stub entry
info.set_interpreter_entry(method()->get_c2i_entry(), method());
} else {
// Use icholder entry
--- 475,510 ----
address entry = NULL;
if (method_code != NULL && method_code->is_in_use()) {
assert(method_code->is_compiled(), "must be compiled");
// Call to compiled code
! //
! // Note: the following problem exists with Compiler1:
! // - at compile time we may or may not know if the destination is final
! // - if we know that the destination is final (is_optimized), we will emit
! // an optimized virtual call (no inline cache), and need a Method* to make
! // a call to the interpreter
! // - if we don't know if the destination is final, we emit a standard
! // virtual call, and use CompiledICHolder to call interpreted code
! // (no static call stub has been generated)
! // - In the case that we here notice the call is static bound we
! // convert the call into what looks to be an optimized virtual call,
! // but we must use the unverified entry point (since there will be no
! // null check on a call when the target isn't loaded).
! // This causes problems when verifying the IC because
! // it looks vanilla but is optimized. Code in is_call_to_interpreted
! // is aware of this and weakens its asserts.
! if (is_optimized) {
entry = method_code->verified_entry_point();
} else {
entry = method_code->entry_point();
}
}
if (entry != NULL) {
// Call to compiled code
info.set_compiled_entry(entry, (static_bound || is_optimized) ? NULL : receiver_klass(), is_optimized);
} else {
if (is_optimized) {
// Use stub entry
info.set_interpreter_entry(method()->get_c2i_entry(), method());
} else {
// Use icholder entry
< prev index next >