changeset 1755:3ef3b5ede304

2009-03-13 Gary Benson <gbenson@redhat.com> 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.
author Gary Benson <gbenson@redhat.com>
date Fri, 13 Mar 2009 07:41:08 -0400
parents 8ad9d28381c5
children 5a1daec06e6d
files ChangeLog ports/hotspot/src/share/vm/shark/sharkState.cpp ports/hotspot/src/share/vm/shark/sharkState.hpp ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.cpp ports/hotspot/src/share/vm/shark/sharkTopLevelBlock.hpp ports/hotspot/src/share/vm/shark/sharkValue.cpp ports/hotspot/src/share/vm/shark/sharkValue.hpp
diffstat 7 files changed, 216 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- 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  <gbenson@redhat.com>
+
+	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  <gbenson@redhat.com>
 
 	* ports/hotspot/src/share/vm/shark/sharkState.hpp
--- 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)
--- 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
--- 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());      
     }
   }
 }
--- 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:
--- 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
--- 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;