# HG changeset patch # User roland # Date 1329295396 -3600 # Node ID cfb5950b770624eb320929268e5f6591cb39a338 # Parent bf7e38b95cebbb3f5f25f72a4c7de511cae52da3 7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04 Summary: Goto that replaces a If mistaken to be a back branch and triggers erroneous OSR compilation. Reviewed-by: never, iveresov diff -r bf7e38b95ceb -r cfb5950b7706 hotspot/src/share/vm/c1/c1_Canonicalizer.cpp --- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Tue Feb 14 15:43:56 2012 -0800 +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp Wed Feb 15 09:43:16 2012 +0100 @@ -594,6 +594,13 @@ return false; } +static bool is_safepoint(BlockEnd* x, BlockBegin* sux) { + // An Instruction with multiple successors, x, is replaced by a Goto + // to a single successor, sux. Is a safepoint check needed = was the + // instruction being replaced a safepoint and the single remaining + // successor a back branch? + return x->is_safepoint() && (sux->bci() < x->state_before()->bci()); +} void Canonicalizer::do_If(If* x) { // move const to right @@ -614,7 +621,7 @@ case If::geq: sux = x->sux_for(true); break; } // If is a safepoint then the debug information should come from the state_before of the If. - set_canonical(new Goto(sux, x->state_before(), x->is_safepoint())); + set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); return; } @@ -626,7 +633,7 @@ x->sux_for(false)); if (sux != NULL) { // If is a safepoint then the debug information should come from the state_before of the If. - set_canonical(new Goto(sux, x->state_before(), x->is_safepoint())); + set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); } } } else if (rt->as_IntConstant() != NULL) { @@ -694,10 +701,12 @@ } } else if (rt == objectNull && (l->as_NewInstance() || l->as_NewArray())) { if (x->cond() == Instruction::eql) { - set_canonical(new Goto(x->fsux(), x->state_before(), x->is_safepoint())); + BlockBegin* sux = x->fsux(); + set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); } else { assert(x->cond() == Instruction::neq, "only other valid case"); - set_canonical(new Goto(x->tsux(), x->state_before(), x->is_safepoint())); + BlockBegin* sux = x->tsux(); + set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); } } } @@ -710,7 +719,7 @@ if (v >= x->lo_key() && v <= x->hi_key()) { sux = x->sux_at(v - x->lo_key()); } - set_canonical(new Goto(sux, x->state_before(), x->is_safepoint())); + set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); } else if (x->number_of_sux() == 1) { // NOTE: Code permanently disabled for now since the switch statement's // tag expression may produce side-effects in which case it must @@ -741,7 +750,7 @@ sux = x->sux_at(i); } } - set_canonical(new Goto(sux, x->state_before(), x->is_safepoint())); + set_canonical(new Goto(sux, x->state_before(), is_safepoint(x, sux))); } else if (x->number_of_sux() == 1) { // NOTE: Code permanently disabled for now since the switch statement's // tag expression may produce side-effects in which case it must diff -r bf7e38b95ceb -r cfb5950b7706 hotspot/src/share/vm/c1/c1_GraphBuilder.cpp --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Tue Feb 14 15:43:56 2012 -0800 +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Feb 15 09:43:16 2012 +0100 @@ -1181,6 +1181,11 @@ bool is_bb = tsux->bci() < stream()->cur_bci() || fsux->bci() < stream()->cur_bci(); Instruction *i = append(new If(x, cond, false, y, tsux, fsux, is_bb ? state_before : NULL, is_bb)); + assert(i->as_Goto() == NULL || + (i->as_Goto()->sux_at(0) == tsux && i->as_Goto()->is_safepoint() == tsux->bci() < stream()->cur_bci()) || + (i->as_Goto()->sux_at(0) == fsux && i->as_Goto()->is_safepoint() == fsux->bci() < stream()->cur_bci()), + "safepoint state of Goto returned by canonicalizer incorrect"); + if (is_profiling()) { If* if_node = i->as_If(); if (if_node != NULL) { @@ -1303,7 +1308,16 @@ // add default successor sux->at_put(i, block_at(bci() + sw.default_offset())); ValueStack* state_before = has_bb ? copy_state_before() : NULL; - append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb)); + Instruction* res = append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb)); +#ifdef ASSERT + if (res->as_Goto()) { + for (i = 0; i < l; i++) { + if (sux->at(i) == res->as_Goto()->sux_at(0)) { + assert(res->as_Goto()->is_safepoint() == sw.dest_offset_at(i) < 0, "safepoint state of Goto returned by canonicalizer incorrect"); + } + } + } +#endif } } @@ -1338,7 +1352,16 @@ // add default successor sux->at_put(i, block_at(bci() + sw.default_offset())); ValueStack* state_before = has_bb ? copy_state_before() : NULL; - append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb)); + Instruction* res = append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb)); +#ifdef ASSERT + if (res->as_Goto()) { + for (i = 0; i < l; i++) { + if (sux->at(i) == res->as_Goto()->sux_at(0)) { + assert(res->as_Goto()->is_safepoint() == sw.pair_at(i).offset() < 0, "safepoint state of Goto returned by canonicalizer incorrect"); + } + } + } +#endif } }