7126041: jdk7u4 b05 and b06 crash with RubyMine 3.2.4, works well with b04
Goto that replaces a If mistaken to be a back branch and triggers erroneous OSR compilation. Reviewed-by: never, iveresov
This commit is contained in:
parent
f9b7a3e692
commit
e6f3ba89ec
@ -594,6 +594,13 @@ static bool is_true(jlong x, If::Condition cond, jlong y) {
|
|||||||
return false;
|
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) {
|
void Canonicalizer::do_If(If* x) {
|
||||||
// move const to right
|
// move const to right
|
||||||
@ -614,7 +621,7 @@ void Canonicalizer::do_If(If* x) {
|
|||||||
case If::geq: sux = x->sux_for(true); break;
|
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.
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,7 +633,7 @@ void Canonicalizer::do_If(If* x) {
|
|||||||
x->sux_for(false));
|
x->sux_for(false));
|
||||||
if (sux != NULL) {
|
if (sux != NULL) {
|
||||||
// If is a safepoint then the debug information should come from the state_before of the If.
|
// 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) {
|
} else if (rt->as_IntConstant() != NULL) {
|
||||||
@ -694,10 +701,12 @@ void Canonicalizer::do_If(If* x) {
|
|||||||
}
|
}
|
||||||
} else if (rt == objectNull && (l->as_NewInstance() || l->as_NewArray())) {
|
} else if (rt == objectNull && (l->as_NewInstance() || l->as_NewArray())) {
|
||||||
if (x->cond() == Instruction::eql) {
|
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 {
|
} else {
|
||||||
assert(x->cond() == Instruction::neq, "only other valid case");
|
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 @@ void Canonicalizer::do_TableSwitch(TableSwitch* x) {
|
|||||||
if (v >= x->lo_key() && v <= x->hi_key()) {
|
if (v >= x->lo_key() && v <= x->hi_key()) {
|
||||||
sux = x->sux_at(v - x->lo_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) {
|
} else if (x->number_of_sux() == 1) {
|
||||||
// NOTE: Code permanently disabled for now since the switch statement's
|
// NOTE: Code permanently disabled for now since the switch statement's
|
||||||
// tag expression may produce side-effects in which case it must
|
// tag expression may produce side-effects in which case it must
|
||||||
@ -741,7 +750,7 @@ void Canonicalizer::do_LookupSwitch(LookupSwitch* x) {
|
|||||||
sux = x->sux_at(i);
|
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) {
|
} else if (x->number_of_sux() == 1) {
|
||||||
// NOTE: Code permanently disabled for now since the switch statement's
|
// NOTE: Code permanently disabled for now since the switch statement's
|
||||||
// tag expression may produce side-effects in which case it must
|
// tag expression may produce side-effects in which case it must
|
||||||
|
@ -1181,6 +1181,11 @@ void GraphBuilder::if_node(Value x, If::Condition cond, Value y, ValueStack* sta
|
|||||||
bool is_bb = tsux->bci() < stream()->cur_bci() || fsux->bci() < stream()->cur_bci();
|
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));
|
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 (is_profiling()) {
|
||||||
If* if_node = i->as_If();
|
If* if_node = i->as_If();
|
||||||
if (if_node != NULL) {
|
if (if_node != NULL) {
|
||||||
@ -1303,7 +1308,16 @@ void GraphBuilder::table_switch() {
|
|||||||
// add default successor
|
// add default successor
|
||||||
sux->at_put(i, block_at(bci() + sw.default_offset()));
|
sux->at_put(i, block_at(bci() + sw.default_offset()));
|
||||||
ValueStack* state_before = has_bb ? copy_state_before() : NULL;
|
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 @@ void GraphBuilder::lookup_switch() {
|
|||||||
// add default successor
|
// add default successor
|
||||||
sux->at_put(i, block_at(bci() + sw.default_offset()));
|
sux->at_put(i, block_at(bci() + sw.default_offset()));
|
||||||
ValueStack* state_before = has_bb ? copy_state_before() : NULL;
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user