Propagate reaching definitions to the instuctions of a block.
authorkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Mar 2010 10:54:02 +0000 (10:54 +0000)
committerkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 16 Mar 2010 10:54:02 +0000 (10:54 +0000)
After computing RD_in for all flow graph nodes, push the reaching
definitions through the basic blocks to annotate all variable
references in the AST.

Review URL: http://codereview.chromium.org/889003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4143 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ast.cc
src/ast.h
src/data-flow.cc
src/data-flow.h

index 339cfa140e834d8d43fd60c0d6e8e755a72e90d0..9fc4af0dba022827ed1b822ba18954f4837f653b 100644 (file)
@@ -78,14 +78,16 @@ VariableProxy::VariableProxy(Handle<String> name,
     var_(NULL),
     is_this_(is_this),
     inside_with_(inside_with),
-    is_trivial_(false) {
+    is_trivial_(false),
+    reaching_definitions_(NULL) {
   // names must be canonicalized for fast equality checks
   ASSERT(name->IsSymbol());
 }
 
 
 VariableProxy::VariableProxy(bool is_this)
-  : is_this_(is_this) {
+  : is_this_(is_this),
+    reaching_definitions_(NULL) {
 }
 
 
index 9377f5e0880186bdba321413f2bc7f458e93939f..ac39cabe0d4647aef6afa9edff1ea07ccecc5649 100644 (file)
--- a/src/ast.h
+++ b/src/ast.h
@@ -103,6 +103,7 @@ namespace internal {
 class TargetCollector;
 class MaterializedLiteral;
 class DefinitionInfo;
+class BitVector;
 
 #define DEF_FORWARD_DECLARATION(type) class type;
 AST_NODE_LIST(DEF_FORWARD_DECLARATION)
@@ -1041,6 +1042,9 @@ class VariableProxy: public Expression {
   bool is_trivial() { return is_trivial_; }
   void set_is_trivial(bool b) { is_trivial_ = b; }
 
+  BitVector* reaching_definitions() { return reaching_definitions_; }
+  void set_reaching_definitions(BitVector* rd) { reaching_definitions_ = rd; }
+
   // Bind this proxy to the variable var.
   void BindTo(Variable* var);
 
@@ -1050,6 +1054,7 @@ class VariableProxy: public Expression {
   bool is_this_;
   bool inside_with_;
   bool is_trivial_;
+  BitVector* reaching_definitions_;
 
   VariableProxy(Handle<String> name, bool is_this, bool inside_with);
   explicit VariableProxy(bool is_this);
index f6ccef1a13c4c278ff7c3a87d0305da97cfcfa13..3ac952078f089e8b9d20850661de6599b873b19c 100644 (file)
@@ -34,6 +34,22 @@ namespace v8 {
 namespace internal {
 
 
+#ifdef DEBUG
+void BitVector::Print() {
+  bool first = true;
+  PrintF("{");
+  for (int i = 0; i < length(); i++) {
+    if (Contains(i)) {
+      if (!first) PrintF(",");
+      first = false;
+      PrintF("%d");
+    }
+  }
+  PrintF("}");
+}
+#endif
+
+
 void FlowGraph::AppendInstruction(AstNode* instruction) {
   // Add a (non-null) AstNode to the end of the graph fragment.
   ASSERT(instruction != NULL);
@@ -357,6 +373,7 @@ void FlowGraphBuilder::VisitAssignment(Assignment* expr) {
   // not both.
   ASSERT(var == NULL || prop == NULL);
   if (var != NULL) {
+    if (expr->is_compound()) Visit(expr->target());
     Visit(expr->value());
     if (var->IsStackAllocated()) {
       expr->set_num(definitions_.length());
@@ -1333,7 +1350,7 @@ void AssignedVariablesAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) {
     result.Union(av_);
     av_.Clear();
   }
-  av_.CopyFrom(result);
+  av_ = result;
 }
 
 
@@ -1345,7 +1362,7 @@ void AssignedVariablesAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) {
     result.Union(av_);
     av_.Clear();
   }
-  av_.CopyFrom(result);
+  av_ = result;
 }
 
 
@@ -1405,7 +1422,7 @@ void AssignedVariablesAnalyzer::VisitCall(Call* expr) {
     Visit(expr->arguments()->at(i));
     result.Union(av_);
   }
-  av_.CopyFrom(result);
+  av_ = result;
 }
 
 
@@ -1418,7 +1435,7 @@ void AssignedVariablesAnalyzer::VisitCallNew(CallNew* expr) {
     Visit(expr->arguments()->at(i));
     result.Union(av_);
   }
-  av_.CopyFrom(result);
+  av_ = result;
 }
 
 
@@ -1430,7 +1447,7 @@ void AssignedVariablesAnalyzer::VisitCallRuntime(CallRuntime* expr) {
     Visit(expr->arguments()->at(i));
     result.Union(av_);
   }
-  av_.CopyFrom(result);
+  av_ = result;
 }
 
 
@@ -1626,6 +1643,9 @@ void TextInstructionPrinter::VisitVariableProxy(VariableProxy* expr) {
   Variable* var = expr->AsVariable();
   if (var != NULL) {
     PrintF("%s", *var->name()->ToCString());
+    if (var->IsStackAllocated() && expr->reaching_definitions() != NULL) {
+      expr->reaching_definitions()->Print();
+    }
   } else {
     ASSERT(expr->AsProperty() != NULL);
     VisitProperty(expr->AsProperty());
@@ -1663,31 +1683,51 @@ void TextInstructionPrinter::VisitAssignment(Assignment* expr) {
   Variable* var = expr->target()->AsVariableProxy()->AsVariable();
   Property* prop = expr->target()->AsProperty();
 
+  if (var == NULL && prop == NULL) {
+    // Throw reference error.
+    Visit(expr->target());
+    return;
+  }
+
+  // Print the left-hand side.
   if (var != NULL) {
-    PrintF("%s %s @%d",
-           *var->name()->ToCString(),
-           Token::String(expr->op()),
-           expr->value()->num());
+    PrintF("%s", *var->name()->ToCString());
   } else if (prop != NULL) {
+    PrintF("@%d", prop->obj()->num());
     if (prop->key()->IsPropertyName()) {
-      PrintF("@%d.", prop->obj()->num());
+      PrintF(".");
       ASSERT(prop->key()->AsLiteral() != NULL);
       prop->key()->AsLiteral()->handle()->Print();
-      PrintF(" %s @%d",
-             Token::String(expr->op()),
-             expr->value()->num());
     } else {
-      PrintF("@%d[@%d] %s @%d",
-             prop->obj()->num(),
-             prop->key()->num(),
-             Token::String(expr->op()),
-             expr->value()->num());
+      PrintF("[@%d]", prop->key()->num());
+    }
+  }
+
+  // Print the operation.
+  if (expr->is_compound()) {
+    PrintF(" = ");
+    // Print the left-hand side again when compound.
+    if (var != NULL) {
+      PrintF("@%d", expr->target()->num());
+    } else {
+      PrintF("@%d", prop->obj()->num());
+      if (prop->key()->IsPropertyName()) {
+        PrintF(".");
+        ASSERT(prop->key()->AsLiteral() != NULL);
+        prop->key()->AsLiteral()->handle()->Print();
+      } else {
+        PrintF("[@%d]", prop->key()->num());
+      }
     }
+    // Print the corresponding binary operator.
+    PrintF(" %s ", Token::String(expr->binary_op()));
   } else {
-    // Throw reference error.
-    Visit(expr->target());
+    PrintF(" %s ", Token::String(expr->op()));
   }
 
+  // Print the right-hand side.
+  PrintF("@%d", expr->value()->num());
+
   if (expr->num() != AstNode::kNoNumber) {
     PrintF(" ;; D%d", expr->num());
   }
@@ -1798,38 +1838,17 @@ void Node::PrintReachingDefinitions() {
   if (rd_.rd_in() != NULL) {
     ASSERT(rd_.kill() != NULL && rd_.gen() != NULL);
 
-    PrintF("RD_in = {");
-    bool first = true;
-    for (int i = 0; i < rd_.rd_in()->length(); i++) {
-      if (rd_.rd_in()->Contains(i)) {
-        if (!first) PrintF(",");
-        PrintF("%d");
-        first = false;
-      }
-    }
-    PrintF("}\n");
-
-    PrintF("RD_kill = {");
-    first = true;
-    for (int i = 0; i < rd_.kill()->length(); i++) {
-      if (rd_.kill()->Contains(i)) {
-        if (!first) PrintF(",");
-        PrintF("%d");
-        first = false;
-      }
-    }
-    PrintF("}\n");
-
-    PrintF("RD_gen = {");
-    first = true;
-    for (int i = 0; i < rd_.gen()->length(); i++) {
-      if (rd_.gen()->Contains(i)) {
-        if (!first) PrintF(",");
-        PrintF("%d");
-        first = false;
-      }
-    }
-    PrintF("}\n");
+    PrintF("RD_in = ");
+    rd_.rd_in()->Print();
+    PrintF("\n");
+
+    PrintF("RD_kill = ");
+    rd_.kill()->Print();
+    PrintF("\n");
+
+    PrintF("RD_gen = ");
+    rd_.gen()->Print();
+    PrintF("\n");
   }
 }
 
@@ -1961,7 +1980,7 @@ void ExitNode::ComputeRDOut(BitVector* result) {
 
 void BlockNode::ComputeRDOut(BitVector* result) {
   // All definitions reaching this block ...
-  result->CopyFrom(*rd_.rd_in());
+  *result = *rd_.rd_in();
   // ... except those killed by the block ...
   result->Subtract(*rd_.kill());
   // ... but including those generated by the block.
@@ -1971,13 +1990,13 @@ void BlockNode::ComputeRDOut(BitVector* result) {
 
 void BranchNode::ComputeRDOut(BitVector* result) {
   // Branch nodes don't kill or generate definitions.
-  result->CopyFrom(*rd_.rd_in());
+  *result = *rd_.rd_in();
 }
 
 
 void JoinNode::ComputeRDOut(BitVector* result) {
   // Join nodes don't kill or generate definitions.
-  result->CopyFrom(*rd_.rd_in());
+  *result = *rd_.rd_in();
 }
 
 
@@ -2008,7 +2027,7 @@ void BlockNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
   if (rd_.rd_in()->Equals(new_rd_in)) return;
 
   // Update RD_in.
-  rd_.rd_in()->CopyFrom(new_rd_in);
+  *rd_.rd_in() = new_rd_in;
   // Add the successor to the worklist if not already present.
   if (!successor_->IsMarkedWith(mark)) {
     successor_->MarkWith(mark);
@@ -2024,7 +2043,7 @@ void BranchNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
   if (rd_.rd_in()->Equals(new_rd_in)) return;
 
   // Update RD_in.
-  rd_.rd_in()->CopyFrom(new_rd_in);
+  *rd_.rd_in() = new_rd_in;
   // Add the successors to the worklist if not already present.
   if (!successor0_->IsMarkedWith(mark)) {
     successor0_->MarkWith(mark);
@@ -2051,7 +2070,7 @@ void JoinNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
   if (rd_.rd_in()->Equals(new_rd_in)) return;
 
   // Update RD_in.
-  rd_.rd_in()->CopyFrom(new_rd_in);
+  *rd_.rd_in() = new_rd_in;
   // Add the successor to the worklist if not already present.
   if (!successor_->IsMarkedWith(mark)) {
     successor_->MarkWith(mark);
@@ -2060,6 +2079,66 @@ void JoinNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
 }
 
 
+void Node::PropagateReachingDefinitions(List<BitVector*>* variables) {
+  // Nothing to do.
+}
+
+
+void BlockNode::PropagateReachingDefinitions(List<BitVector*>* variables) {
+  // Propagate RD_in from the start of the block to all the variable
+  // references.
+  int variable_count = variables->length();
+  BitVector rd = *rd_.rd_in();
+  for (int i = 0, len = instructions_.length(); i < len; i++) {
+    Expression* expr = instructions_[i]->AsExpression();
+    if (expr == NULL) continue;
+
+    // Look for a variable reference to record its reaching definitions.
+    VariableProxy* proxy = expr->AsVariableProxy();
+    if (proxy == NULL) {
+      // Not a VariableProxy?  Maybe it's a count operation.
+      CountOperation* count_operation = expr->AsCountOperation();
+      if (count_operation != NULL) {
+        proxy = count_operation->expression()->AsVariableProxy();
+      }
+    }
+    if (proxy == NULL) {
+      // OK, Maybe it's a compound assignment.
+      Assignment* assignment = expr->AsAssignment();
+      if (assignment != NULL && assignment->is_compound()) {
+        proxy = assignment->target()->AsVariableProxy();
+      }
+    }
+
+    if (proxy != NULL &&
+        proxy->var()->IsStackAllocated() &&
+        !proxy->var()->is_this()) {
+      // All definitions for this variable.
+      BitVector* definitions =
+          variables->at(ReachingDefinitions::IndexFor(proxy->var(),
+                                                      variable_count));
+      BitVector* reaching_definitions = new BitVector(*definitions);
+      // Intersected with all definitions (of any variable) reaching this
+      // instruction.
+      reaching_definitions->Intersect(rd);
+      proxy->set_reaching_definitions(reaching_definitions);
+    }
+
+    // It may instead (or also) be a definition.  If so update the running
+    // value of reaching definitions for the block.
+    Variable* var = expr->AssignedVar();
+    if (var == NULL || !var->IsStackAllocated()) continue;
+
+    // All definitions of this variable are killed.
+    BitVector* def_set =
+        variables->at(ReachingDefinitions::IndexFor(var, variable_count));
+    rd.Subtract(*def_set);
+    // This definition is generated.
+    rd.Add(expr->num());
+  }
+}
+
+
 void ReachingDefinitions::Compute() {
   ASSERT(!definitions_->is_empty());
 
@@ -2088,7 +2167,7 @@ void ReachingDefinitions::Compute() {
               PrintF("Def[%s] = {%d", *var->name()->ToCString(), j);
               first = false;
             } else {
-              PrintF(", %d", j);
+              PrintF(",%d", j);
             }
           }
         }
@@ -2117,6 +2196,12 @@ void ReachingDefinitions::Compute() {
     node->MarkWith(!mark);
     node->UpdateRDIn(&worklist, mark);
   }
+
+  // Step 4: Based on RD_in for block nodes, propagate reaching definitions
+  // to all variable uses in the block.
+  for (int i = 0; i < node_count; i++) {
+    postorder_->at(i)->PropagateReachingDefinitions(&variables_);
+  }
 }
 
 
index 236d0ad44107611dda65546198ce4163bb388359..97020137a7098cac610cad6889b360421282b823 100644 (file)
@@ -129,6 +129,10 @@ class BitVector: public ZoneObject {
 
   int length() const { return length_; }
 
+#ifdef DEBUG
+  void Print();
+#endif
+
  private:
   int length_;
   int data_length_;
@@ -235,6 +239,7 @@ class Node: public ZoneObject {
                                              bool mark);
   virtual void ComputeRDOut(BitVector* result) = 0;
   virtual void UpdateRDIn(WorkList<Node>* worklist, bool mark) = 0;
+  virtual void PropagateReachingDefinitions(List<BitVector*>* variables);
 
 #ifdef DEBUG
   void AssignNodeNumber();
@@ -324,6 +329,7 @@ class BlockNode: public Node {
                                      bool mark);
   void ComputeRDOut(BitVector* result);
   void UpdateRDIn(WorkList<Node>* worklist, bool mark);
+  void PropagateReachingDefinitions(List<BitVector*>* variables);
 
 #ifdef DEBUG
   void PrintText();