Index: src/data-flow.cc |
diff --git a/src/data-flow.cc b/src/data-flow.cc |
index ac12502c071b5dea3a50423805feb88579c4a39f..b0f6255adcef934e310c0cf85ec6eb30a5fad369 100644 |
--- a/src/data-flow.cc |
+++ b/src/data-flow.cc |
@@ -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,69 @@ 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()) { |
+ // 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); |
+ continue; |
+ } |
+ |
+ Assignment* assignment = expr->AsAssignment(); |
+ if (assignment != NULL) { |
+ } |
fschneider
2010/03/15 10:11:15
Misplaced brackets?
|
+ |
+ // For an assignment, 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() { |
if (definitions_->is_empty()) return; |
@@ -2088,7 +2170,7 @@ void ReachingDefinitions::Compute() { |
PrintF("Def[%s] = {%d", *var->name()->ToCString(), j); |
first = false; |
} else { |
- PrintF(", %d", j); |
+ PrintF(",%d", j); |
} |
} |
} |
@@ -2117,6 +2199,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_); |
+ } |
} |