6986046: C1 valuestack cleanup

Fixes an historical oddity in C1 with inlining where all of the expression stacks are kept in the topmost ValueStack instead of being in their respective ValueStacks.

Reviewed-by: never
This commit is contained in:
Christian Wimmer 2009-12-29 19:08:54 +01:00 committed by Roland Westrelin
parent bce771e0fe
commit 9b131fbbb8
24 changed files with 728 additions and 1056 deletions

View file

@ -29,13 +29,6 @@
// Implementation of Instruction
#ifdef ASSERT
void Instruction::create_hi_word() {
assert(type()->is_double_word() && _hi_word == NULL, "only double word has high word");
_hi_word = new HiWord(this);
}
#endif
Instruction::Condition Instruction::mirror(Condition cond) {
switch (cond) {
case eql: return eql;
@ -63,6 +56,15 @@ Instruction::Condition Instruction::negate(Condition cond) {
return eql;
}
void Instruction::update_exception_state(ValueStack* state) {
if (state != NULL && (state->kind() == ValueStack::EmptyExceptionState || state->kind() == ValueStack::ExceptionState)) {
assert(state->kind() == ValueStack::EmptyExceptionState || Compilation::current()->env()->jvmti_can_access_local_variables(), "unexpected state kind");
_exception_state = state;
} else {
_exception_state = NULL;
}
}
Instruction* Instruction::prev(BlockBegin* block) {
Instruction* p = NULL;
@ -75,7 +77,24 @@ Instruction* Instruction::prev(BlockBegin* block) {
}
void Instruction::state_values_do(ValueVisitor* f) {
if (state_before() != NULL) {
state_before()->values_do(f);
}
if (exception_state() != NULL){
exception_state()->values_do(f);
}
}
#ifndef PRODUCT
void Instruction::check_state(ValueStack* state) {
if (state != NULL) {
state->verify();
}
}
void Instruction::print() {
InstructionPrinter ip;
print(ip);
@ -190,35 +209,6 @@ ciType* CheckCast::exact_type() const {
return NULL;
}
void ArithmeticOp::other_values_do(ValueVisitor* f) {
if (lock_stack() != NULL) lock_stack()->values_do(f);
}
void NullCheck::other_values_do(ValueVisitor* f) {
lock_stack()->values_do(f);
}
void AccessArray::other_values_do(ValueVisitor* f) {
if (lock_stack() != NULL) lock_stack()->values_do(f);
}
// Implementation of AccessField
void AccessField::other_values_do(ValueVisitor* f) {
if (state_before() != NULL) state_before()->values_do(f);
if (lock_stack() != NULL) lock_stack()->values_do(f);
}
// Implementation of StoreIndexed
IRScope* StoreIndexed::scope() const {
return lock_stack()->scope();
}
// Implementation of ArithmeticOp
bool ArithmeticOp::is_commutative() const {
@ -266,13 +256,6 @@ bool LogicOp::is_commutative() const {
}
// Implementation of CompareOp
void CompareOp::other_values_do(ValueVisitor* f) {
if (state_before() != NULL) state_before()->values_do(f);
}
// Implementation of IfOp
bool IfOp::is_commutative() const {
@ -301,6 +284,7 @@ IRScope* StateSplit::scope() const {
void StateSplit::state_values_do(ValueVisitor* f) {
Instruction::state_values_do(f);
if (state() != NULL) state()->values_do(f);
}
@ -316,30 +300,17 @@ void BlockBegin::state_values_do(ValueVisitor* f) {
}
void MonitorEnter::state_values_do(ValueVisitor* f) {
StateSplit::state_values_do(f);
_lock_stack_before->values_do(f);
}
void Intrinsic::state_values_do(ValueVisitor* f) {
StateSplit::state_values_do(f);
if (lock_stack() != NULL) lock_stack()->values_do(f);
}
// Implementation of Invoke
Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args,
int vtable_index, ciMethod* target, ValueStack* state_before)
: StateSplit(result_type)
: StateSplit(result_type, state_before)
, _code(code)
, _recv(recv)
, _args(args)
, _vtable_index(vtable_index)
, _target(target)
, _state_before(state_before)
{
set_flag(TargetIsLoadedFlag, target->is_loaded());
set_flag(TargetIsFinalFlag, target_is_loaded() && target->is_final_method());
@ -376,7 +347,7 @@ void Invoke::state_values_do(ValueVisitor* f) {
// Implementation of Contant
intx Constant::hash() const {
if (_state == NULL) {
if (state_before() == NULL) {
switch (type()->tag()) {
case intTag:
return HASH2(name(), type()->as_IntConstant()->value());
@ -499,25 +470,6 @@ BlockBegin* Constant::compare(Instruction::Condition cond, Value right,
}
void Constant::other_values_do(ValueVisitor* f) {
if (state() != NULL) state()->values_do(f);
}
// Implementation of NewArray
void NewArray::other_values_do(ValueVisitor* f) {
if (state_before() != NULL) state_before()->values_do(f);
}
// Implementation of TypeCheck
void TypeCheck::other_values_do(ValueVisitor* f) {
if (state_before() != NULL) state_before()->values_do(f);
}
// Implementation of BlockBegin
void BlockBegin::set_end(BlockEnd* end) {
@ -604,23 +556,14 @@ void BlockBegin::substitute_sux(BlockBegin* old_sux, BlockBegin* new_sux) {
// of the inserted block, without recomputing the values of the other blocks
// in the CFG. Therefore the value of "depth_first_number" in BlockBegin becomes meaningless.
BlockBegin* BlockBegin::insert_block_between(BlockBegin* sux) {
// Try to make the bci close to a block with a single pred or sux,
// since this make the block layout algorithm work better.
int bci = -1;
if (sux->number_of_preds() == 1) {
bci = sux->bci();
} else {
bci = end()->bci();
}
BlockBegin* new_sux = new BlockBegin(bci);
BlockBegin* new_sux = new BlockBegin(-99);
// mark this block (special treatment when block order is computed)
new_sux->set(critical_edge_split_flag);
// This goto is not a safepoint.
Goto* e = new Goto(sux, false);
new_sux->set_next(e, bci);
new_sux->set_next(e, end()->state()->bci());
new_sux->set_end(e);
// setup states
ValueStack* s = end()->state();
@ -763,7 +706,7 @@ bool BlockBegin::try_merge(ValueStack* new_state) {
}
// copy state because it is altered
new_state = new_state->copy();
new_state = new_state->copy(ValueStack::BlockBeginState, bci());
// Use method liveness to invalidate dead locals
MethodLivenessResult liveness = new_state->scope()->method()->liveness_at_bci(bci());
@ -800,19 +743,9 @@ bool BlockBegin::try_merge(ValueStack* new_state) {
// initialize state of block
set_state(new_state);
} else if (existing_state->is_same_across_scopes(new_state)) {
} else if (existing_state->is_same(new_state)) {
TRACE_PHI(tty->print_cr("exisiting state found"));
// Inlining may cause the local state not to match up, so walk up
// the new state until we get to the same scope as the
// existing and then start processing from there.
while (existing_state->scope() != new_state->scope()) {
new_state = new_state->caller_state();
assert(new_state != NULL, "could not match up scopes");
assert(false, "check if this is necessary");
}
assert(existing_state->scope() == new_state->scope(), "not matching");
assert(existing_state->locals_size() == new_state->locals_size(), "not matching");
assert(existing_state->stack_size() == new_state->stack_size(), "not matching");
@ -969,11 +902,6 @@ void BlockEnd::substitute_sux(BlockBegin* old_sux, BlockBegin* new_sux) {
}
void BlockEnd::other_values_do(ValueVisitor* f) {
if (state_before() != NULL) state_before()->values_do(f);
}
// Implementation of Phi
// Normal phi functions take their operands from the last instruction of the
@ -1006,11 +934,6 @@ int Phi::operand_count() const {
}
// Implementation of Throw
void Throw::state_values_do(ValueVisitor* f) {
BlockEnd::state_values_do(f);
}
void ProfileInvoke::state_values_do(ValueVisitor* f) {
if (state() != NULL) state()->values_do(f);