# HG changeset patch # User Gary Benson # Date 1236944468 14400 # Node ID 3ef3b5ede304a1ecc4efc7cb8b0d06ebcbaef808 # Parent 8ad9d28381c535b4c4a80aa08b14e7e556875ccf 2009-03-13 Gary Benson PR icedtea/296: * ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp (SharkTopLevelBlock::do_branch): New method, to handle state propagation for blocks with one successor. * ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp (SharkTopLevelBlock::emit_IR): Move state propagation to the individual instructions. (SharkTopLevelBlock::do_branch): New method, to handle state propagation for blocks with one successor. (SharkTopLevelBlock::do_goto): Use do_branch. (SharkTopLevelBlock::do_jsr): Likewise. (SharkTopLevelBlock::do_ret): Likewise. (SharkTopLevelBlock::do_if): Add state propagation. (SharkTopLevelBlock::do_switch): Copy the state for all cases except the default. (SharkTopLevelBlock::handle_exception): Copy the state for all cases except the default (ie catch all/no handler). (SharkTopLevelBlock::add_incoming): Fix up assertion. * ports/hotspot/src/share/vm/shark/sharkState.hpp (SharkState::equal_to): New method. * ports/hotspot/src/share/vm/shark/sharkState.cpp (SharkState::equal_to): Likewise. (SharkState::initialize): Clone values in locals and stack rather than simply copying the pointers. * ports/hotspot/src/share/vm/shark/sharkValue.hpp (SharkValue::clone): New method. (SharkValue::equal_to): Likewise. (SharkNormalValue::clone): Likewise. (SharkNormalValue::equal_to): Likewise. (SharkAddressValue::clone): Likewise. (SharkAddressValue::equal_to): Likewise. (SharkValue::create_generic): Add a zero_checked argument. (SharkNormalValue::SharkNormalValue): Likewise. * ports/hotspot/src/share/vm/shark/sharkValue.cpp (SharkValue::clone): New method. (SharkValue::equal_to): Likewise. (SharkNormalValue::clone): Likewise. (SharkNormalValue::equal_to): Likewise. (SharkAddressValue::clone): Likewise. (SharkAddressValue::equal_to): Likewise. diff -r 8ad9d28381c5 -r 3ef3b5ede304 ChangeLog --- a/ChangeLog Fri Mar 13 05:43:37 2009 -0400 +++ b/ChangeLog Fri Mar 13 07:41:08 2009 -0400 @@ -1,3 +1,48 @@ +2009-03-13 Gary Benson + + PR icedtea/296: + * ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp + (SharkTopLevelBlock::do_branch): New method, to handle + state propagation for blocks with one successor. + * ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp + (SharkTopLevelBlock::emit_IR): Move state propagation to + the individual instructions. + (SharkTopLevelBlock::do_branch): New method, to handle + state propagation for blocks with one successor. + (SharkTopLevelBlock::do_goto): Use do_branch. + (SharkTopLevelBlock::do_jsr): Likewise. + (SharkTopLevelBlock::do_ret): Likewise. + (SharkTopLevelBlock::do_if): Add state propagation. + (SharkTopLevelBlock::do_switch): Copy the state for all + cases except the default. + (SharkTopLevelBlock::handle_exception): Copy the state for + all cases except the default (ie catch all/no handler). + (SharkTopLevelBlock::add_incoming): Fix up assertion. + + * ports/hotspot/src/share/vm/shark/sharkState.hpp + (SharkState::equal_to): New method. + * ports/hotspot/src/share/vm/shark/sharkState.cpp + (SharkState::equal_to): Likewise. + (SharkState::initialize): Clone values in locals and stack + rather than simply copying the pointers. + + * ports/hotspot/src/share/vm/shark/sharkValue.hpp + (SharkValue::clone): New method. + (SharkValue::equal_to): Likewise. + (SharkNormalValue::clone): Likewise. + (SharkNormalValue::equal_to): Likewise. + (SharkAddressValue::clone): Likewise. + (SharkAddressValue::equal_to): Likewise. + (SharkValue::create_generic): Add a zero_checked argument. + (SharkNormalValue::SharkNormalValue): Likewise. + * ports/hotspot/src/share/vm/shark/sharkValue.cpp + (SharkValue::clone): New method. + (SharkValue::equal_to): Likewise. + (SharkNormalValue::clone): Likewise. + (SharkNormalValue::equal_to): Likewise. + (SharkAddressValue::clone): Likewise. + (SharkAddressValue::equal_to): Likewise. + 2009-03-13 Gary Benson * ports/hotspot/src/share/vm/shark/sharkState.hpp diff -r 8ad9d28381c5 -r 3ef3b5ede304 ports/hotspot/src/share/vm/shark/sharkState.cpp --- a/ports/hotspot/src/share/vm/shark/sharkState.cpp Fri Mar 13 05:43:37 2009 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkState.cpp Fri Mar 13 07:41:08 2009 -0400 @@ -51,18 +51,81 @@ _locals = NEW_RESOURCE_ARRAY(SharkValue*, max_locals()); _stack = NEW_RESOURCE_ARRAY(SharkValue*, max_stack()); + NOT_PRODUCT(memset(_locals, 23, max_locals() * sizeof(SharkValue *))); + NOT_PRODUCT(memset(_stack, 23, max_stack() * sizeof(SharkValue *))); + _sp = _stack; + if (state) { - memcpy(_locals, state->_locals, max_locals() * sizeof(SharkValue *)); - memcpy(_stack, state->_stack, max_stack() * sizeof(SharkValue *)); - _sp = _stack + state->stack_depth(); + for (int i = 0; i < max_locals(); i++) { + SharkValue *value = state->local(i); + if (value) + value = value->clone(); + set_local(i, value); + } + + for (int i = state->stack_depth() - 1; i >= 0; i--) { + SharkValue *value = state->stack(i); + if (value) + value = value->clone(); + push(value); + } + } +} + +bool SharkState::equal_to(SharkState *other) +{ + if (block() != other->block()) + return false; + + if (function() != other->function()) + return false; + + if (method() != other->method()) + return false; + + if (max_locals() != other->max_locals()) + return false; + + if (stack_depth() != other->stack_depth()) + return false; + + for (int i = 0; i < max_locals(); i++) { + SharkValue *value = local(i); + SharkValue *other_value = other->local(i); + + if (value == NULL) { + if (other_value != NULL) + return false; + } + else { + if (other_value == NULL) + return false; + + if (!value->equal_to(other_value)) + return false; + } } - else { - _sp = _stack; + + for (int i = 0; i < stack_depth(); i++) { + SharkValue *value = stack(i); + SharkValue *other_value = other->stack(i); - NOT_PRODUCT(memset(_locals, 23, max_locals() * sizeof(SharkValue *))); - NOT_PRODUCT(memset(_stack, 23, max_stack() * sizeof(SharkValue *))); + if (value == NULL) { + if (other_value != NULL) + return false; + } + else { + if (other_value == NULL) + return false; + + if (!value->equal_to(other_value)) + return false; + } } + + return true; } + void SharkState::merge(SharkState* other, BasicBlock* other_block, BasicBlock* this_block) diff -r 8ad9d28381c5 -r 3ef3b5ede304 ports/hotspot/src/share/vm/shark/sharkState.hpp --- a/ports/hotspot/src/share/vm/shark/sharkState.hpp Fri Mar 13 05:43:37 2009 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkState.hpp Fri Mar 13 07:41:08 2009 -0400 @@ -70,6 +70,7 @@ { return _method; } + protected: void set_method(llvm::Value* method) { _method = method; @@ -128,6 +129,10 @@ _sp -= slots; } + // Comparison + public: + bool equal_to(SharkState* other); + // Copy and merge public: SharkState* copy() const diff -r 8ad9d28381c5 -r 3ef3b5ede304 ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp --- a/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp Fri Mar 13 05:43:37 2009 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp Fri Mar 13 07:41:08 2009 -0400 @@ -135,10 +135,12 @@ if (needs_phis()) { ((SharkPHIState *) entry_state())->add_incoming(incoming_state); } - else if (_entry_state != incoming_state) { - assert(_entry_state == NULL, "should be"); + else if (_entry_state == NULL) { _entry_state = incoming_state; } + else { + assert(entry_state()->equal_to(incoming_state), "should be"); + } } void SharkTopLevelBlock::enter(SharkTopLevelBlock* predecessor, @@ -231,21 +233,8 @@ // If this block falls through to the next then it won't have been // terminated by a bytecode and we have to add the branch ourselves - if (falls_through()) { - builder()->CreateBr(successor(ciTypeFlow::FALL_THROUGH)->entry_block()); - } - - // Process the successor states if not already done - switch (bc()) { - case Bytecodes::_tableswitch: - case Bytecodes::_lookupswitch: - // done by do_switch() - break; - - default: - for (int i = 0; i < num_successors(); i++) - successor(i)->add_incoming(current_state()); - } + if (falls_through()) + do_branch(ciTypeFlow::FALL_THROUGH); } SharkTopLevelBlock* SharkTopLevelBlock::bci_successor(int bci) const @@ -413,7 +402,7 @@ LLVMValue::jint_constant(i), handler->entry_block()); - handler->add_incoming(current_state()); + handler->add_incoming(current_state()->copy()); } builder()->SetInsertPoint(no_handler); @@ -768,23 +757,38 @@ void SharkTopLevelBlock::do_goto() { - builder()->CreateBr(successor(ciTypeFlow::GOTO_TARGET)->entry_block()); + do_branch(ciTypeFlow::GOTO_TARGET); } void SharkTopLevelBlock::do_jsr() { push(SharkValue::address_constant(iter()->next_bci())); - builder()->CreateBr(successor(ciTypeFlow::GOTO_TARGET)->entry_block()); + do_branch(ciTypeFlow::GOTO_TARGET); } void SharkTopLevelBlock::do_ret() { assert(local(iter()->get_index())->address_value() == successor(ciTypeFlow::GOTO_TARGET)->start(), "should be"); - builder()->CreateBr(successor(ciTypeFlow::GOTO_TARGET)->entry_block()); + do_branch(ciTypeFlow::GOTO_TARGET); } - -void SharkTopLevelBlock::do_if(ICmpInst::Predicate p, SharkValue *b, SharkValue *a) + +// All propagation of state from one block to the next (via +// dest->add_incoming) is handled by the next three methods +// (do_branch, do_if and do_switch) and by handle_exception. +// Where control flow forks, each successor must have its +// own copy of the state. + +void SharkTopLevelBlock::do_branch(int successor_index) +{ + SharkTopLevelBlock *dest = successor(successor_index); + builder()->CreateBr(dest->entry_block()); + dest->add_incoming(current_state()); +} + +void SharkTopLevelBlock::do_if(ICmpInst::Predicate p, + SharkValue* b, + SharkValue* a) { Value *llvm_a, *llvm_b; if (a->is_jobject()) { @@ -795,11 +799,16 @@ llvm_a = a->jint_value(); llvm_b = b->jint_value(); } - + + SharkTopLevelBlock *if_taken = successor(ciTypeFlow::IF_TAKEN); + SharkTopLevelBlock *not_taken = successor(ciTypeFlow::IF_NOT_TAKEN); + builder()->CreateCondBr( builder()->CreateICmp(p, llvm_a, llvm_b), - successor(ciTypeFlow::IF_TAKEN)->entry_block(), - successor(ciTypeFlow::IF_NOT_TAKEN)->entry_block()); + if_taken->entry_block(), not_taken->entry_block()); + + if_taken->add_incoming(current_state()); + not_taken->add_incoming(current_state()->copy()); } void SharkTopLevelBlock::do_switch() @@ -818,7 +827,7 @@ switchinst->addCase( LLVMValue::jint_constant(switch_key(i)), dest_block->entry_block()); - dest_block->add_incoming(current_state()); + dest_block->add_incoming(current_state()->copy()); } } } diff -r 8ad9d28381c5 -r 3ef3b5ede304 ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp --- a/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp Fri Mar 13 05:43:37 2009 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp Fri Mar 13 07:41:08 2009 -0400 @@ -188,6 +188,7 @@ void do_zero_check(SharkValue* value); llvm::Value* lookup_for_ldc(); llvm::Value* lookup_for_field_access(); + void do_branch(int successor_index); // VM calls private: diff -r 8ad9d28381c5 -r 3ef3b5ede304 ports/hotspot/src/share/vm/shark/sharkValue.cpp --- a/ports/hotspot/src/share/vm/shark/sharkValue.cpp Fri Mar 13 05:43:37 2009 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkValue.cpp Fri Mar 13 07:41:08 2009 -0400 @@ -28,6 +28,30 @@ using namespace llvm; +// Cloning + +SharkValue* SharkNormalValue::clone() const +{ + return SharkValue::create_generic(type(), generic_value(), zero_checked()); +} +SharkValue* SharkAddressValue::clone() const +{ + return SharkValue::address_constant(address_value()); +} + +// Comparison + +bool SharkNormalValue::equal_to(SharkValue *other) const +{ + return (this->type() == other->type() && + this->generic_value() == other->generic_value() && + this->zero_checked() == other->zero_checked()); +} +bool SharkAddressValue::equal_to(SharkValue *other) const +{ + return (this->address_value() == other->address_value()); +} + // Type access ciType* SharkValue::type() const @@ -189,7 +213,7 @@ } Value* SharkAddressValue::generic_value() const { - return LLVMValue::intptr_constant(_bci); + return LLVMValue::intptr_constant(address_value()); } Value* SharkValue::intptr_value(SharkBuilder* builder) const @@ -211,7 +235,7 @@ } void SharkAddressValue::addIncoming(SharkValue *value, BasicBlock* block) { - assert(_bci == value->address_value(), "should be"); + assert(this->equal_to(value), "should be"); } // Repeated null and divide-by-zero check removal diff -r 8ad9d28381c5 -r 3ef3b5ede304 ports/hotspot/src/share/vm/shark/sharkValue.hpp --- a/ports/hotspot/src/share/vm/shark/sharkValue.hpp Fri Mar 13 05:43:37 2009 -0400 +++ b/ports/hotspot/src/share/vm/shark/sharkValue.hpp Fri Mar 13 07:41:08 2009 -0400 @@ -39,6 +39,14 @@ protected: SharkValue() {} + // Cloning + public: + virtual SharkValue* clone() const = 0; + + // Comparison + public: + virtual bool equal_to(SharkValue* other) const = 0; + // Type access public: virtual BasicType basic_type() const = 0; @@ -175,7 +183,9 @@ virtual llvm::Value* generic_value() const = 0; virtual llvm::Value* intptr_value(SharkBuilder* builder) const; - static inline SharkValue* create_generic(ciType* type, llvm::Value* value); + static inline SharkValue* create_generic(ciType* type, + llvm::Value* value, + bool zero_checked = false); // Phi-style stuff public: @@ -191,8 +201,8 @@ friend class SharkValue; protected: - SharkNormalValue(ciType* type, llvm::Value* value) - : _type(type), _llvm_value(value), _zero_checked(false) {} + SharkNormalValue(ciType* type, llvm::Value* value, bool zero_checked) + : _type(type), _llvm_value(value), _zero_checked(zero_checked) {} private: ciType* _type; @@ -205,6 +215,14 @@ return _llvm_value; } + // Cloning + public: + SharkValue* clone() const; + + // Comparison + public: + bool equal_to(SharkValue* other) const; + // Type access public: ciType* type() const; @@ -243,9 +261,11 @@ void set_zero_checked(bool zero_checked); }; -inline SharkValue* SharkValue::create_generic(ciType* type, llvm::Value* value) +inline SharkValue* SharkValue::create_generic(ciType* type, + llvm::Value* value, + bool zero_checked) { - return new SharkNormalValue(type, value); + return new SharkNormalValue(type, value, zero_checked); } class SharkAddressValue : public SharkValue { @@ -258,6 +278,14 @@ private: int _bci; + // Cloning + public: + SharkValue* clone() const; + + // Comparison + public: + bool equal_to(SharkValue* other) const; + // Type access public: BasicType basic_type() const;