JDK-6828024 : verification of fixed interval usage is too weak
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: hs16
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_9
  • CPU: sparc
  • Submitted: 2009-04-08
  • Updated: 2010-04-02
  • Resolved: 2009-05-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7 Other
6u18Fixed 7Fixed hs16Fixed
Description
Generation of LIR has the subtle invariant that fixed intervals containing oops should never be alive across a safepoint.  The current logic that checks this is too weak.

Comments
EVALUATION http://hg.openjdk.java.net/jdk7/hotspot-comp/hotspot/rev/a134d9824964
17-04-2009

EVALUATION The purpose of the assert is to check that there are no live intervals using fixed registers spanning a safepoint that aren't used by the op itself. So we walk to current op id and find all the fixed intervals that are live across the current op. Then we scan the op itself to see if it is using that interval. If it is then the interval is safe. If it's not then there's a bug because that fixed interval won't show up in an oop map. Basically we're checking that the set of live fixed intervals is subset of the intervals used by the op.
08-04-2009

SUGGESTED FIX diff --git a/src/share/vm/c1/c1_LinearScan.cpp b/src/share/vm/c1/c1_LinearScan.cpp --- a/src/share/vm/c1/c1_LinearScan.cpp +++ b/src/share/vm/c1/c1_LinearScan.cpp @@ -2956,9 +2956,11 @@ void LinearScan::do_linear_scan() { NOT_PRODUCT(print_intervals("After Register Allocation")); NOT_PRODUCT(print_lir(2, "LIR after register allocation:")); + + sort_intervals_after_allocation(); + DEBUG_ONLY(verify()); - sort_intervals_after_allocation(); eliminate_spill_moves(); assign_reg_num(); CHECK_BAILOUT(); @@ -3147,6 +3149,16 @@ void LinearScan::verify_intervals() { void LinearScan::verify_no_oops_in_fixed_intervals() { + Interval* fixed_intervals; + Interval* other_intervals; + create_unhandled_lists(&fixed_intervals, &other_intervals, is_precolored_cpu_interval, NULL); + + // to ensure a walking until the last instruction id, add a dummy interval + // with a high operation id + other_intervals = new Interval(any_reg); + other_intervals->add_range(max_jint - 2, max_jint - 1); + IntervalWalker* iw = new IntervalWalker(this, fixed_intervals, other_intervals); + LIR_OpVisitState visitor; for (int i = 0; i < block_count(); i++) { BlockBegin* block = block_at(i); @@ -3158,6 +3170,46 @@ void LinearScan::verify_no_oops_in_fixed int op_id = op->id(); visitor.visit(op); + + if (visitor.info_count() > 0) { + iw->walk_before(op->id()); + bool check_live = true; + if (op->code() == lir_move) { + LIR_Op1* move = (LIR_Op1*)op; + check_live = move->patch_code() == lir_patch_none; + } + LIR_OpBranch* branch = op->as_OpBranch(); + if (branch != NULL && branch->stub() != NULL && branch->stub()->is_exception_throw_stub()) { + check_live = false; + } + + // Make sure none of the fixed registers is live across an oopmap since we can't handle that correctly + if (check_live) { + for (Interval* interval = iw->active_first(fixedKind); interval != Interval::end(); interval = interval->next()) { + if (interval->current_to() > op->id() + 1) { + bool ok = false; + for_each_visitor_mode(mode) { + int n = visitor.opr_count(mode); + for (int k = 0; k < n; k++) { + LIR_Opr opr = visitor.opr_at(mode, k); + if (opr->is_fixed_cpu()) { + if (interval_at(reg_num(opr)) == interval) { + ok = true; + break; + } + int hi = reg_numHi(opr); + if (hi != -1 && interval_at(hi) == interval) { + ok = true; + break; + } + } + } + } + assert(ok, "fixed intervals should never be live across an oopmap point"); + } + } + } + } // oop-maps at calls do not contain registers, so check is not needed if (!visitor.has_call()) {
08-04-2009