Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(743)

Unified Diff: src/data-flow.cc

Issue 1253009: Move flow graph and helper classes to their own file. (Closed)
Patch Set: Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/data-flow.h ('k') | src/flow-graph.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/data-flow.cc
diff --git a/src/data-flow.cc b/src/data-flow.cc
index fe4b3db00e1e6bf1dddf19e53a5e42ae25545171..1bc77c033822fdc396f2f623e92a7dc17f83bc82 100644
--- a/src/data-flow.cc
+++ b/src/data-flow.cc
@@ -28,6 +28,7 @@
#include "v8.h"
#include "data-flow.h"
+#include "flow-graph.h"
#include "scopes.h"
namespace v8 {
@@ -50,561 +51,6 @@ void BitVector::Print() {
#endif
-void FlowGraph::AppendInstruction(AstNode* instruction) {
- // Add a (non-null) AstNode to the end of the graph fragment.
- ASSERT(instruction != NULL);
- if (exit()->IsExitNode()) return;
- if (!exit()->IsBlockNode()) AppendNode(new BlockNode());
- BlockNode::cast(exit())->AddInstruction(instruction);
-}
-
-
-void FlowGraph::AppendNode(Node* node) {
- // Add a node to the end of the graph. An empty block is added to
- // maintain edge-split form (that no join nodes or exit nodes as
- // successors to branch nodes).
- ASSERT(node != NULL);
- if (exit()->IsExitNode()) return;
- if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) {
- AppendNode(new BlockNode());
- }
- exit()->AddSuccessor(node);
- node->AddPredecessor(exit());
- exit_ = node;
-}
-
-
-void FlowGraph::AppendGraph(FlowGraph* graph) {
- // Add a flow graph fragment to the end of this one. An empty block is
- // added to maintain edge-split form (that no join nodes or exit nodes as
- // successors to branch nodes).
- ASSERT(graph != NULL);
- if (exit()->IsExitNode()) return;
- Node* node = graph->entry();
- if (exit()->IsBranchNode() && (node->IsJoinNode() || node->IsExitNode())) {
- AppendNode(new BlockNode());
- }
- exit()->AddSuccessor(node);
- node->AddPredecessor(exit());
- exit_ = graph->exit();
-}
-
-
-void FlowGraph::Split(BranchNode* branch,
- FlowGraph* left,
- FlowGraph* right,
- JoinNode* join) {
- // Add the branch node, left flowgraph, join node.
- AppendNode(branch);
- AppendGraph(left);
- AppendNode(join);
-
- // Splice in the right flowgraph.
- right->AppendNode(join);
- branch->AddSuccessor(right->entry());
- right->entry()->AddPredecessor(branch);
-}
-
-
-void FlowGraph::Loop(JoinNode* join,
- FlowGraph* condition,
- BranchNode* branch,
- FlowGraph* body) {
- // Add the join, condition and branch. Add join's predecessors in
- // left-to-right order.
- AppendNode(join);
- body->AppendNode(join);
- AppendGraph(condition);
- AppendNode(branch);
-
- // Splice in the body flowgraph.
- branch->AddSuccessor(body->entry());
- body->entry()->AddPredecessor(branch);
-}
-
-
-void ExitNode::Traverse(bool mark,
- ZoneList<Node*>* preorder,
- ZoneList<Node*>* postorder) {
- preorder->Add(this);
- postorder->Add(this);
-}
-
-
-void BlockNode::Traverse(bool mark,
- ZoneList<Node*>* preorder,
- ZoneList<Node*>* postorder) {
- ASSERT(successor_ != NULL);
- preorder->Add(this);
- if (!successor_->IsMarkedWith(mark)) {
- successor_->MarkWith(mark);
- successor_->Traverse(mark, preorder, postorder);
- }
- postorder->Add(this);
-}
-
-
-void BranchNode::Traverse(bool mark,
- ZoneList<Node*>* preorder,
- ZoneList<Node*>* postorder) {
- ASSERT(successor0_ != NULL && successor1_ != NULL);
- preorder->Add(this);
- if (!successor1_->IsMarkedWith(mark)) {
- successor1_->MarkWith(mark);
- successor1_->Traverse(mark, preorder, postorder);
- }
- if (!successor0_->IsMarkedWith(mark)) {
- successor0_->MarkWith(mark);
- successor0_->Traverse(mark, preorder, postorder);
- }
- postorder->Add(this);
-}
-
-
-void JoinNode::Traverse(bool mark,
- ZoneList<Node*>* preorder,
- ZoneList<Node*>* postorder) {
- ASSERT(successor_ != NULL);
- preorder->Add(this);
- if (!successor_->IsMarkedWith(mark)) {
- successor_->MarkWith(mark);
- successor_->Traverse(mark, preorder, postorder);
- }
- postorder->Add(this);
-}
-
-
-void FlowGraphBuilder::Build(FunctionLiteral* lit) {
- global_exit_ = new ExitNode();
- VisitStatements(lit->body());
-
- if (HasStackOverflow()) return;
-
- // The graph can end with a branch node (if the function ended with a
- // loop). Maintain edge-split form (no join nodes or exit nodes as
- // successors to branch nodes).
- if (graph_.exit()->IsBranchNode()) graph_.AppendNode(new BlockNode());
- graph_.AppendNode(global_exit_);
-
- // Build preorder and postorder traversal orders. All the nodes in
- // the graph have the same mark flag. For the traversal, use that
- // flag's negation. Traversal will flip all the flags.
- bool mark = graph_.entry()->IsMarkedWith(false);
- graph_.entry()->MarkWith(mark);
- graph_.entry()->Traverse(mark, &preorder_, &postorder_);
-}
-
-
-// This function peels off one iteration of a for-loop. The return value
-// is either a block statement containing the peeled loop or NULL in case
-// there is a stack overflow.
-static Statement* PeelForLoop(ForStatement* stmt) {
- // Mark this for-statement as processed.
- stmt->set_peel_this_loop(false);
-
- // Create new block containing the init statement of the for-loop and
- // an if-statement containing the peeled iteration and the original
- // loop without the init-statement.
- Block* block = new Block(NULL, 2, false);
- if (stmt->init() != NULL) {
- Statement* init = stmt->init();
- // The init statement gets the statement position of the for-loop
- // to make debugging of peeled loops possible.
- init->set_statement_pos(stmt->statement_pos());
- block->AddStatement(init);
- }
-
- // Copy the condition.
- CopyAstVisitor copy_visitor;
- Expression* cond_copy = stmt->cond() != NULL
- ? copy_visitor.DeepCopyExpr(stmt->cond())
- : new Literal(Factory::true_value());
- if (copy_visitor.HasStackOverflow()) return NULL;
-
- // Construct a block with the peeled body and the rest of the for-loop.
- Statement* body_copy = copy_visitor.DeepCopyStmt(stmt->body());
- if (copy_visitor.HasStackOverflow()) return NULL;
-
- Statement* next_copy = stmt->next() != NULL
- ? copy_visitor.DeepCopyStmt(stmt->next())
- : new EmptyStatement();
- if (copy_visitor.HasStackOverflow()) return NULL;
-
- Block* peeled_body = new Block(NULL, 3, false);
- peeled_body->AddStatement(body_copy);
- peeled_body->AddStatement(next_copy);
- peeled_body->AddStatement(stmt);
-
- // Remove the duplicated init statement from the for-statement.
- stmt->set_init(NULL);
-
- // Create new test at the top and add it to the newly created block.
- IfStatement* test = new IfStatement(cond_copy,
- peeled_body,
- new EmptyStatement());
- block->AddStatement(test);
- return block;
-}
-
-
-void FlowGraphBuilder::VisitStatements(ZoneList<Statement*>* stmts) {
- for (int i = 0, len = stmts->length(); i < len; i++) {
- stmts->at(i) = ProcessStatement(stmts->at(i));
- }
-}
-
-
-Statement* FlowGraphBuilder::ProcessStatement(Statement* stmt) {
- if (FLAG_loop_peeling &&
- stmt->AsForStatement() != NULL &&
- stmt->AsForStatement()->peel_this_loop()) {
- Statement* tmp_stmt = PeelForLoop(stmt->AsForStatement());
- if (tmp_stmt == NULL) {
- SetStackOverflow();
- } else {
- stmt = tmp_stmt;
- }
- }
- Visit(stmt);
- return stmt;
-}
-
-
-void FlowGraphBuilder::VisitDeclaration(Declaration* decl) {
- UNREACHABLE();
-}
-
-
-void FlowGraphBuilder::VisitBlock(Block* stmt) {
- VisitStatements(stmt->statements());
-}
-
-
-void FlowGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
- Visit(stmt->expression());
-}
-
-
-void FlowGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
- // Nothing to do.
-}
-
-
-void FlowGraphBuilder::VisitIfStatement(IfStatement* stmt) {
- Visit(stmt->condition());
-
- BranchNode* branch = new BranchNode();
- FlowGraph original = graph_;
- graph_ = FlowGraph::Empty();
- stmt->set_then_statement(ProcessStatement(stmt->then_statement()));
-
- FlowGraph left = graph_;
- graph_ = FlowGraph::Empty();
- stmt->set_else_statement(ProcessStatement(stmt->else_statement()));
-
- if (HasStackOverflow()) return;
- JoinNode* join = new JoinNode();
- original.Split(branch, &left, &graph_, join);
- graph_ = original;
-}
-
-
-void FlowGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitForStatement(ForStatement* stmt) {
- if (stmt->init() != NULL) stmt->set_init(ProcessStatement(stmt->init()));
-
- JoinNode* join = new JoinNode();
- FlowGraph original = graph_;
- graph_ = FlowGraph::Empty();
- if (stmt->cond() != NULL) Visit(stmt->cond());
-
- BranchNode* branch = new BranchNode();
- FlowGraph condition = graph_;
- graph_ = FlowGraph::Empty();
- stmt->set_body(ProcessStatement(stmt->body()));
-
- if (stmt->next() != NULL) stmt->set_next(ProcessStatement(stmt->next()));
-
- if (HasStackOverflow()) return;
- original.Loop(join, &condition, branch, &graph_);
- graph_ = original;
-}
-
-
-void FlowGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitSharedFunctionInfoLiteral(
- SharedFunctionInfoLiteral* expr) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitConditional(Conditional* expr) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitSlot(Slot* expr) {
- UNREACHABLE();
-}
-
-
-void FlowGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
- graph_.AppendInstruction(expr);
-}
-
-
-void FlowGraphBuilder::VisitLiteral(Literal* expr) {
- graph_.AppendInstruction(expr);
-}
-
-
-void FlowGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitAssignment(Assignment* expr) {
- Variable* var = expr->target()->AsVariableProxy()->AsVariable();
- Property* prop = expr->target()->AsProperty();
- // Left-hand side can be a variable or property (or reference error) but
- // not both.
- ASSERT(var == NULL || prop == NULL);
- if (var != NULL) {
- if (expr->is_compound()) Visit(expr->target());
- Visit(expr->value());
- if (var->IsStackAllocated()) {
- // The first definition in the body is numbered n, where n is the
- // number of parameters and stack-allocated locals.
- expr->set_num(body_definitions_.length() + variable_count_);
- body_definitions_.Add(expr);
- }
-
- } else if (prop != NULL) {
- Visit(prop->obj());
- if (!prop->key()->IsPropertyName()) Visit(prop->key());
- Visit(expr->value());
- }
-
- if (HasStackOverflow()) return;
- graph_.AppendInstruction(expr);
-}
-
-
-void FlowGraphBuilder::VisitThrow(Throw* expr) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitProperty(Property* expr) {
- Visit(expr->obj());
- if (!expr->key()->IsPropertyName()) Visit(expr->key());
-
- if (HasStackOverflow()) return;
- graph_.AppendInstruction(expr);
-}
-
-
-void FlowGraphBuilder::VisitCall(Call* expr) {
- Visit(expr->expression());
- ZoneList<Expression*>* arguments = expr->arguments();
- for (int i = 0, len = arguments->length(); i < len; i++) {
- Visit(arguments->at(i));
- }
-
- if (HasStackOverflow()) return;
- graph_.AppendInstruction(expr);
-}
-
-
-void FlowGraphBuilder::VisitCallNew(CallNew* expr) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
- SetStackOverflow();
-}
-
-
-void FlowGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
- switch (expr->op()) {
- case Token::NOT:
- case Token::BIT_NOT:
- case Token::DELETE:
- case Token::TYPEOF:
- case Token::VOID:
- SetStackOverflow();
- break;
-
- case Token::ADD:
- case Token::SUB:
- Visit(expr->expression());
- if (HasStackOverflow()) return;
- graph_.AppendInstruction(expr);
- break;
-
- default:
- UNREACHABLE();
- }
-}
-
-
-void FlowGraphBuilder::VisitCountOperation(CountOperation* expr) {
- Visit(expr->expression());
- Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
- if (var != NULL && var->IsStackAllocated()) {
- // The first definition in the body is numbered n, where n is the number
- // of parameters and stack-allocated locals.
- expr->set_num(body_definitions_.length() + variable_count_);
- body_definitions_.Add(expr);
- }
-
- if (HasStackOverflow()) return;
- graph_.AppendInstruction(expr);
-}
-
-
-void FlowGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
- switch (expr->op()) {
- case Token::COMMA:
- case Token::OR:
- case Token::AND:
- SetStackOverflow();
- break;
-
- case Token::BIT_OR:
- case Token::BIT_XOR:
- case Token::BIT_AND:
- case Token::SHL:
- case Token::SHR:
- case Token::ADD:
- case Token::SUB:
- case Token::MUL:
- case Token::DIV:
- case Token::MOD:
- case Token::SAR:
- Visit(expr->left());
- Visit(expr->right());
- if (HasStackOverflow()) return;
- graph_.AppendInstruction(expr);
- break;
-
- default:
- UNREACHABLE();
- }
-}
-
-
-void FlowGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
- switch (expr->op()) {
- case Token::EQ:
- case Token::NE:
- case Token::EQ_STRICT:
- case Token::NE_STRICT:
- case Token::INSTANCEOF:
- case Token::IN:
- SetStackOverflow();
- break;
-
- case Token::LT:
- case Token::GT:
- case Token::LTE:
- case Token::GTE:
- Visit(expr->left());
- Visit(expr->right());
- if (HasStackOverflow()) return;
- graph_.AppendInstruction(expr);
- break;
-
- default:
- UNREACHABLE();
- }
-}
-
-
-void FlowGraphBuilder::VisitThisFunction(ThisFunction* expr) {
- SetStackOverflow();
-}
-
-
void AstLabeler::Label(CompilationInfo* info) {
info_ = info;
VisitStatements(info_->function()->body());
@@ -1300,6 +746,387 @@ void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) {
}
+int ReachingDefinitions::IndexFor(Variable* var, int variable_count) {
+ // Parameters are numbered left-to-right from the beginning of the bit
+ // set. Stack-allocated locals are allocated right-to-left from the end.
+ ASSERT(var != NULL && var->IsStackAllocated());
+ Slot* slot = var->slot();
+ if (slot->type() == Slot::PARAMETER) {
+ return slot->index();
+ } else {
+ return (variable_count - 1) - slot->index();
+ }
+}
+
+
+void Node::InitializeReachingDefinitions(int definition_count,
+ List<BitVector*>* variables,
+ WorkList<Node>* worklist,
+ bool mark) {
+ ASSERT(!IsMarkedWith(mark));
+ rd_.Initialize(definition_count);
+ MarkWith(mark);
+ worklist->Insert(this);
+}
+
+
+void BlockNode::InitializeReachingDefinitions(int definition_count,
+ List<BitVector*>* variables,
+ WorkList<Node>* worklist,
+ bool mark) {
+ ASSERT(!IsMarkedWith(mark));
+ int instruction_count = instructions_.length();
+ int variable_count = variables->length();
+
+ rd_.Initialize(definition_count);
+ // The RD_in set for the entry node has a definition for each parameter
+ // and local.
+ if (predecessor_ == NULL) {
+ for (int i = 0; i < variable_count; i++) rd_.rd_in()->Add(i);
+ }
+
+ for (int i = 0; i < instruction_count; i++) {
+ Expression* expr = instructions_[i]->AsExpression();
+ if (expr == NULL) continue;
+ Variable* var = expr->AssignedVariable();
+ if (var == NULL || !var->IsStackAllocated()) continue;
+
+ // All definitions of this variable are killed.
+ BitVector* def_set =
+ variables->at(ReachingDefinitions::IndexFor(var, variable_count));
+ rd_.kill()->Union(*def_set);
+
+ // All previously generated definitions are not generated.
+ rd_.gen()->Subtract(*def_set);
+
+ // This one is generated.
+ rd_.gen()->Add(expr->num());
+ }
+
+ // Add all blocks except the entry node to the worklist.
+ if (predecessor_ != NULL) {
+ MarkWith(mark);
+ worklist->Insert(this);
+ }
+}
+
+
+void ExitNode::ComputeRDOut(BitVector* result) {
+ // Should not be the predecessor of any node.
+ UNREACHABLE();
+}
+
+
+void BlockNode::ComputeRDOut(BitVector* result) {
+ // All definitions reaching this block ...
+ *result = *rd_.rd_in();
+ // ... except those killed by the block ...
+ result->Subtract(*rd_.kill());
+ // ... but including those generated by the block.
+ result->Union(*rd_.gen());
+}
+
+
+void BranchNode::ComputeRDOut(BitVector* result) {
+ // Branch nodes don't kill or generate definitions.
+ *result = *rd_.rd_in();
+}
+
+
+void JoinNode::ComputeRDOut(BitVector* result) {
+ // Join nodes don't kill or generate definitions.
+ *result = *rd_.rd_in();
+}
+
+
+void ExitNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
+ // The exit node has no successors so we can just update in place. New
+ // RD_in is the union over all predecessors.
+ int definition_count = rd_.rd_in()->length();
+ rd_.rd_in()->Clear();
+
+ BitVector temp(definition_count);
+ for (int i = 0, len = predecessors_.length(); i < len; i++) {
+ // Because ComputeRDOut always overwrites temp and its value is
+ // always read out before calling ComputeRDOut again, we do not
+ // have to clear it on each iteration of the loop.
+ predecessors_[i]->ComputeRDOut(&temp);
+ rd_.rd_in()->Union(temp);
+ }
+}
+
+
+void BlockNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
+ // The entry block has no predecessor. Its RD_in does not change.
+ if (predecessor_ == NULL) return;
+
+ BitVector new_rd_in(rd_.rd_in()->length());
+ predecessor_->ComputeRDOut(&new_rd_in);
+
+ if (rd_.rd_in()->Equals(new_rd_in)) return;
+
+ // Update 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);
+ worklist->Insert(successor_);
+ }
+}
+
+
+void BranchNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
+ BitVector new_rd_in(rd_.rd_in()->length());
+ predecessor_->ComputeRDOut(&new_rd_in);
+
+ if (rd_.rd_in()->Equals(new_rd_in)) return;
+
+ // Update 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);
+ worklist->Insert(successor0_);
+ }
+ if (!successor1_->IsMarkedWith(mark)) {
+ successor1_->MarkWith(mark);
+ worklist->Insert(successor1_);
+ }
+}
+
+
+void JoinNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
+ int definition_count = rd_.rd_in()->length();
+ BitVector new_rd_in(definition_count);
+
+ // New RD_in is the union over all predecessors.
+ BitVector temp(definition_count);
+ for (int i = 0, len = predecessors_.length(); i < len; i++) {
+ predecessors_[i]->ComputeRDOut(&temp);
+ new_rd_in.Union(temp);
+ }
+
+ if (rd_.rd_in()->Equals(new_rd_in)) return;
+
+ // Update 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);
+ worklist->Insert(successor_);
+ }
+}
+
+
+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->AssignedVariable();
+ 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() {
+ // The definitions in the body plus an implicit definition for each
+ // variable at function entry.
+ int definition_count = body_definitions_->length() + variable_count_;
+ int node_count = postorder_->length();
+
+ // Step 1: For each stack-allocated variable, identify the set of all its
+ // definitions.
+ List<BitVector*> variables;
+ for (int i = 0; i < variable_count_; i++) {
+ // Add the initial definition for each variable.
+ BitVector* initial = new BitVector(definition_count);
+ initial->Add(i);
+ variables.Add(initial);
+ }
+ for (int i = 0, len = body_definitions_->length(); i < len; i++) {
+ // Account for each definition in the body as a definition of the
+ // defined variable.
+ Variable* var = body_definitions_->at(i)->AssignedVariable();
+ variables[IndexFor(var, variable_count_)]->Add(i + variable_count_);
+ }
+
+ // Step 2: Compute KILL and GEN for each block node, initialize RD_in for
+ // all nodes, and mark and add all nodes to the worklist in reverse
+ // postorder. All nodes should currently have the same mark.
+ bool mark = postorder_->at(0)->IsMarkedWith(false); // Negation of current.
+ WorkList<Node> worklist(node_count);
+ for (int i = node_count - 1; i >= 0; i--) {
+ postorder_->at(i)->InitializeReachingDefinitions(definition_count,
+ &variables,
+ &worklist,
+ mark);
+ }
+
+ // Step 3: Until the worklist is empty, remove an item compute and update
+ // its rd_in based on its predecessor's rd_out. If rd_in has changed, add
+ // all necessary successors to the worklist.
+ while (!worklist.is_empty()) {
+ Node* node = worklist.Remove();
+ 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);
+ }
+}
+
+
+bool TypeAnalyzer::IsPrimitiveDef(int def_num) {
+ if (def_num < param_count_) return false;
+ if (def_num < variable_count_) return true;
+ return body_definitions_->at(def_num - variable_count_)->IsPrimitive();
+}
+
+
+void TypeAnalyzer::Compute() {
+ bool changed;
+ int count = 0;
+
+ do {
+ changed = false;
+
+ if (FLAG_print_graph_text) {
+ PrintF("TypeAnalyzer::Compute - iteration %d\n", count++);
+ }
+
+ for (int i = postorder_->length() - 1; i >= 0; --i) {
+ Node* node = postorder_->at(i);
+ if (node->IsBlockNode()) {
+ BlockNode* block = BlockNode::cast(node);
+ for (int j = 0; j < block->instructions()->length(); j++) {
+ Expression* expr = block->instructions()->at(j)->AsExpression();
+ if (expr != NULL) {
+ // For variable uses: Compute new type from reaching definitions.
+ VariableProxy* proxy = expr->AsVariableProxy();
+ if (proxy != NULL && proxy->reaching_definitions() != NULL) {
+ BitVector* rd = proxy->reaching_definitions();
+ bool prim_type = true;
+ // TODO(fsc): A sparse set representation of reaching
+ // definitions would speed up iterating here.
+ for (int k = 0; k < rd->length(); k++) {
+ if (rd->Contains(k) && !IsPrimitiveDef(k)) {
+ prim_type = false;
+ break;
+ }
+ }
+ // Reset changed flag if new type information was computed.
+ if (prim_type != proxy->IsPrimitive()) {
+ changed = true;
+ proxy->SetIsPrimitive(prim_type);
+ }
+ }
+ }
+ }
+ }
+ }
+ } while (changed);
+}
+
+
+void Node::MarkCriticalInstructions(
+ List<AstNode*>* stack,
+ ZoneList<Expression*>* body_definitions,
+ int variable_count) {
+}
+
+
+void BlockNode::MarkCriticalInstructions(
+ List<AstNode*>* stack,
+ ZoneList<Expression*>* body_definitions,
+ int variable_count) {
+ for (int i = instructions_.length() - 1; i >= 0; i--) {
+ // Only expressions can appear in the flow graph for now.
+ Expression* expr = instructions_[i]->AsExpression();
+ if (expr != NULL && !expr->is_live() &&
+ (expr->is_loop_condition() || expr->IsCritical())) {
+ expr->mark_as_live();
+ expr->ProcessNonLiveChildren(stack, body_definitions, variable_count);
+ }
+ }
+}
+
+
+void MarkLiveCode(ZoneList<Node*>* nodes,
+ ZoneList<Expression*>* body_definitions,
+ int variable_count) {
+ List<AstNode*> stack(20);
+
+ // Mark the critical AST nodes as live; mark their dependencies and
+ // add them to the marking stack.
+ for (int i = nodes->length() - 1; i >= 0; i--) {
+ nodes->at(i)->MarkCriticalInstructions(&stack, body_definitions,
+ variable_count);
+ }
+
+ // Continue marking dependencies until no more.
+ while (!stack.is_empty()) {
+ // Only expressions can appear in the flow graph for now.
+ Expression* expr = stack.RemoveLast()->AsExpression();
+ if (expr != NULL) {
+ expr->ProcessNonLiveChildren(&stack, body_definitions, variable_count);
+ }
+ }
+}
+
+
#ifdef DEBUG
// Print a textual representation of an instruction in a flow graph. Using
@@ -1714,389 +1541,7 @@ void FlowGraph::PrintText(FunctionLiteral* fun, ZoneList<Node*>* postorder) {
}
}
-
-#endif // defined(DEBUG)
-
-
-int ReachingDefinitions::IndexFor(Variable* var, int variable_count) {
- // Parameters are numbered left-to-right from the beginning of the bit
- // set. Stack-allocated locals are allocated right-to-left from the end.
- ASSERT(var != NULL && var->IsStackAllocated());
- Slot* slot = var->slot();
- if (slot->type() == Slot::PARAMETER) {
- return slot->index();
- } else {
- return (variable_count - 1) - slot->index();
- }
-}
-
-
-void Node::InitializeReachingDefinitions(int definition_count,
- List<BitVector*>* variables,
- WorkList<Node>* worklist,
- bool mark) {
- ASSERT(!IsMarkedWith(mark));
- rd_.Initialize(definition_count);
- MarkWith(mark);
- worklist->Insert(this);
-}
-
-
-void BlockNode::InitializeReachingDefinitions(int definition_count,
- List<BitVector*>* variables,
- WorkList<Node>* worklist,
- bool mark) {
- ASSERT(!IsMarkedWith(mark));
- int instruction_count = instructions_.length();
- int variable_count = variables->length();
-
- rd_.Initialize(definition_count);
- // The RD_in set for the entry node has a definition for each parameter
- // and local.
- if (predecessor_ == NULL) {
- for (int i = 0; i < variable_count; i++) rd_.rd_in()->Add(i);
- }
-
- for (int i = 0; i < instruction_count; i++) {
- Expression* expr = instructions_[i]->AsExpression();
- if (expr == NULL) continue;
- Variable* var = expr->AssignedVariable();
- if (var == NULL || !var->IsStackAllocated()) continue;
-
- // All definitions of this variable are killed.
- BitVector* def_set =
- variables->at(ReachingDefinitions::IndexFor(var, variable_count));
- rd_.kill()->Union(*def_set);
-
- // All previously generated definitions are not generated.
- rd_.gen()->Subtract(*def_set);
-
- // This one is generated.
- rd_.gen()->Add(expr->num());
- }
-
- // Add all blocks except the entry node to the worklist.
- if (predecessor_ != NULL) {
- MarkWith(mark);
- worklist->Insert(this);
- }
-}
-
-
-void ExitNode::ComputeRDOut(BitVector* result) {
- // Should not be the predecessor of any node.
- UNREACHABLE();
-}
-
-
-void BlockNode::ComputeRDOut(BitVector* result) {
- // All definitions reaching this block ...
- *result = *rd_.rd_in();
- // ... except those killed by the block ...
- result->Subtract(*rd_.kill());
- // ... but including those generated by the block.
- result->Union(*rd_.gen());
-}
-
-
-void BranchNode::ComputeRDOut(BitVector* result) {
- // Branch nodes don't kill or generate definitions.
- *result = *rd_.rd_in();
-}
-
-
-void JoinNode::ComputeRDOut(BitVector* result) {
- // Join nodes don't kill or generate definitions.
- *result = *rd_.rd_in();
-}
-
-
-void ExitNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
- // The exit node has no successors so we can just update in place. New
- // RD_in is the union over all predecessors.
- int definition_count = rd_.rd_in()->length();
- rd_.rd_in()->Clear();
-
- BitVector temp(definition_count);
- for (int i = 0, len = predecessors_.length(); i < len; i++) {
- // Because ComputeRDOut always overwrites temp and its value is
- // always read out before calling ComputeRDOut again, we do not
- // have to clear it on each iteration of the loop.
- predecessors_[i]->ComputeRDOut(&temp);
- rd_.rd_in()->Union(temp);
- }
-}
-
-
-void BlockNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
- // The entry block has no predecessor. Its RD_in does not change.
- if (predecessor_ == NULL) return;
-
- BitVector new_rd_in(rd_.rd_in()->length());
- predecessor_->ComputeRDOut(&new_rd_in);
-
- if (rd_.rd_in()->Equals(new_rd_in)) return;
-
- // Update 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);
- worklist->Insert(successor_);
- }
-}
-
-
-void BranchNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
- BitVector new_rd_in(rd_.rd_in()->length());
- predecessor_->ComputeRDOut(&new_rd_in);
-
- if (rd_.rd_in()->Equals(new_rd_in)) return;
-
- // Update 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);
- worklist->Insert(successor0_);
- }
- if (!successor1_->IsMarkedWith(mark)) {
- successor1_->MarkWith(mark);
- worklist->Insert(successor1_);
- }
-}
-
-
-void JoinNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
- int definition_count = rd_.rd_in()->length();
- BitVector new_rd_in(definition_count);
-
- // New RD_in is the union over all predecessors.
- BitVector temp(definition_count);
- for (int i = 0, len = predecessors_.length(); i < len; i++) {
- predecessors_[i]->ComputeRDOut(&temp);
- new_rd_in.Union(temp);
- }
-
- if (rd_.rd_in()->Equals(new_rd_in)) return;
-
- // Update 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);
- worklist->Insert(successor_);
- }
-}
-
-
-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->AssignedVariable();
- 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() {
- // The definitions in the body plus an implicit definition for each
- // variable at function entry.
- int definition_count = body_definitions_->length() + variable_count_;
- int node_count = postorder_->length();
-
- // Step 1: For each stack-allocated variable, identify the set of all its
- // definitions.
- List<BitVector*> variables;
- for (int i = 0; i < variable_count_; i++) {
- // Add the initial definition for each variable.
- BitVector* initial = new BitVector(definition_count);
- initial->Add(i);
- variables.Add(initial);
- }
- for (int i = 0, len = body_definitions_->length(); i < len; i++) {
- // Account for each definition in the body as a definition of the
- // defined variable.
- Variable* var = body_definitions_->at(i)->AssignedVariable();
- variables[IndexFor(var, variable_count_)]->Add(i + variable_count_);
- }
-
- // Step 2: Compute KILL and GEN for each block node, initialize RD_in for
- // all nodes, and mark and add all nodes to the worklist in reverse
- // postorder. All nodes should currently have the same mark.
- bool mark = postorder_->at(0)->IsMarkedWith(false); // Negation of current.
- WorkList<Node> worklist(node_count);
- for (int i = node_count - 1; i >= 0; i--) {
- postorder_->at(i)->InitializeReachingDefinitions(definition_count,
- &variables,
- &worklist,
- mark);
- }
-
- // Step 3: Until the worklist is empty, remove an item compute and update
- // its rd_in based on its predecessor's rd_out. If rd_in has changed, add
- // all necessary successors to the worklist.
- while (!worklist.is_empty()) {
- Node* node = worklist.Remove();
- 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);
- }
-}
-
-
-bool TypeAnalyzer::IsPrimitiveDef(int def_num) {
- if (def_num < param_count_) return false;
- if (def_num < variable_count_) return true;
- return body_definitions_->at(def_num - variable_count_)->IsPrimitive();
-}
-
-
-void TypeAnalyzer::Compute() {
- bool changed;
- int count = 0;
-
- do {
- changed = false;
-
- if (FLAG_print_graph_text) {
- PrintF("TypeAnalyzer::Compute - iteration %d\n", count++);
- }
-
- for (int i = postorder_->length() - 1; i >= 0; --i) {
- Node* node = postorder_->at(i);
- if (node->IsBlockNode()) {
- BlockNode* block = BlockNode::cast(node);
- for (int j = 0; j < block->instructions()->length(); j++) {
- Expression* expr = block->instructions()->at(j)->AsExpression();
- if (expr != NULL) {
- // For variable uses: Compute new type from reaching definitions.
- VariableProxy* proxy = expr->AsVariableProxy();
- if (proxy != NULL && proxy->reaching_definitions() != NULL) {
- BitVector* rd = proxy->reaching_definitions();
- bool prim_type = true;
- // TODO(fsc): A sparse set representation of reaching
- // definitions would speed up iterating here.
- for (int k = 0; k < rd->length(); k++) {
- if (rd->Contains(k) && !IsPrimitiveDef(k)) {
- prim_type = false;
- break;
- }
- }
- // Reset changed flag if new type information was computed.
- if (prim_type != proxy->IsPrimitive()) {
- changed = true;
- proxy->SetIsPrimitive(prim_type);
- }
- }
- }
- }
- }
- }
- } while (changed);
-}
-
-
-void Node::MarkCriticalInstructions(
- List<AstNode*>* stack,
- ZoneList<Expression*>* body_definitions,
- int variable_count) {
-}
-
-
-void BlockNode::MarkCriticalInstructions(
- List<AstNode*>* stack,
- ZoneList<Expression*>* body_definitions,
- int variable_count) {
- for (int i = instructions_.length() - 1; i >= 0; i--) {
- // Only expressions can appear in the flow graph for now.
- Expression* expr = instructions_[i]->AsExpression();
- if (expr != NULL && !expr->is_live() &&
- (expr->is_loop_condition() || expr->IsCritical())) {
- expr->mark_as_live();
- expr->ProcessNonLiveChildren(stack, body_definitions, variable_count);
- }
- }
-}
-
-
-void MarkLiveCode(ZoneList<Node*>* nodes,
- ZoneList<Expression*>* body_definitions,
- int variable_count) {
- List<AstNode*> stack(20);
-
- // Mark the critical AST nodes as live; mark their dependencies and
- // add them to the marking stack.
- for (int i = nodes->length() - 1; i >= 0; i--) {
- nodes->at(i)->MarkCriticalInstructions(&stack, body_definitions,
- variable_count);
- }
-
- // Continue marking dependencies until no more.
- while (!stack.is_empty()) {
- // Only expressions can appear in the flow graph for now.
- Expression* expr = stack.RemoveLast()->AsExpression();
- if (expr != NULL) {
- expr->ProcessNonLiveChildren(&stack, body_definitions, variable_count);
- }
- }
-}
+#endif // DEBUG
} } // namespace v8::internal
« no previous file with comments | « src/data-flow.h ('k') | src/flow-graph.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698