| Index: src/data-flow.cc
|
| diff --git a/src/data-flow.cc b/src/data-flow.cc
|
| index 0561677884a5790122e24a9fa173f30863849b02..434991c8dd34ece0251677f5bee159d32a5a74f2 100644
|
| --- a/src/data-flow.cc
|
| +++ b/src/data-flow.cc
|
| @@ -133,14 +133,14 @@ void BranchNode::Traverse(bool mark,
|
| ZoneList<Node*>* postorder) {
|
| ASSERT(successor0_ != NULL && successor1_ != NULL);
|
| preorder->Add(this);
|
| - if (!successor0_->IsMarkedWith(mark)) {
|
| - successor0_->MarkWith(mark);
|
| - successor0_->Traverse(mark, preorder, postorder);
|
| - }
|
| 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);
|
| }
|
|
|
| @@ -358,7 +358,10 @@ void FlowGraphBuilder::VisitAssignment(Assignment* expr) {
|
| ASSERT(var == NULL || prop == NULL);
|
| if (var != NULL) {
|
| Visit(expr->value());
|
| - if (var->IsStackAllocated()) definitions_.Add(expr);
|
| + if (var->IsStackAllocated()) {
|
| + expr->set_num(definitions_.length());
|
| + definitions_.Add(expr);
|
| + }
|
|
|
| } else if (prop != NULL) {
|
| Visit(prop->obj());
|
| @@ -434,6 +437,7 @@ void FlowGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| Visit(expr->expression());
|
| Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
|
| if (var != NULL && var->IsStackAllocated()) {
|
| + expr->set_num(definitions_.length());
|
| definitions_.Add(expr);
|
| }
|
|
|
| @@ -1483,7 +1487,10 @@ void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) {
|
| // only used for printing in debug mode.
|
| class TextInstructionPrinter: public AstVisitor {
|
| public:
|
| - TextInstructionPrinter() {}
|
| + TextInstructionPrinter() : number_(0) {}
|
| +
|
| + int NextNumber() { return number_; }
|
| + void AssignNumber(AstNode* node) { node->set_num(number_++); }
|
|
|
| private:
|
| // AST node visit functions.
|
| @@ -1491,6 +1498,8 @@ class TextInstructionPrinter: public AstVisitor {
|
| AST_NODE_LIST(DECLARE_VISIT)
|
| #undef DECLARE_VISIT
|
|
|
| + int number_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(TextInstructionPrinter);
|
| };
|
|
|
| @@ -1611,8 +1620,7 @@ void TextInstructionPrinter::VisitSlot(Slot* expr) {
|
| void TextInstructionPrinter::VisitVariableProxy(VariableProxy* expr) {
|
| Variable* var = expr->AsVariable();
|
| if (var != NULL) {
|
| - SmartPointer<char> name = var->name()->ToCString();
|
| - PrintF("%s", *name);
|
| + PrintF("%s", *var->name()->ToCString());
|
| } else {
|
| ASSERT(expr->AsProperty() != NULL);
|
| VisitProperty(expr->AsProperty());
|
| @@ -1651,9 +1659,8 @@ void TextInstructionPrinter::VisitAssignment(Assignment* expr) {
|
| Property* prop = expr->target()->AsProperty();
|
|
|
| if (var != NULL) {
|
| - SmartPointer<char> name = var->name()->ToCString();
|
| PrintF("%s %s @%d",
|
| - *name,
|
| + *var->name()->ToCString(),
|
| Token::String(expr->op()),
|
| expr->value()->num());
|
| } else if (prop != NULL) {
|
| @@ -1675,6 +1682,10 @@ void TextInstructionPrinter::VisitAssignment(Assignment* expr) {
|
| // Throw reference error.
|
| Visit(expr->target());
|
| }
|
| +
|
| + if (expr->num() != AstNode::kNoNumber) {
|
| + PrintF(" ;; D%d", expr->num());
|
| + }
|
| }
|
|
|
|
|
| @@ -1717,8 +1728,7 @@ void TextInstructionPrinter::VisitCallNew(CallNew* expr) {
|
|
|
|
|
| void TextInstructionPrinter::VisitCallRuntime(CallRuntime* expr) {
|
| - SmartPointer<char> name = expr->name()->ToCString();
|
| - PrintF("%s(", *name);
|
| + PrintF("%s(", *expr->name()->ToCString());
|
| ZoneList<Expression*>* arguments = expr->arguments();
|
| for (int i = 0, len = arguments->length(); i < len; i++) {
|
| if (i != 0) PrintF(", ");
|
| @@ -1739,6 +1749,10 @@ void TextInstructionPrinter::VisitCountOperation(CountOperation* expr) {
|
| } else {
|
| PrintF("@%d%s", expr->expression()->num(), Token::String(expr->op()));
|
| }
|
| +
|
| + if (expr->num() != AstNode::kNoNumber) {
|
| + PrintF(" ;; D%d", expr->num());
|
| + }
|
| }
|
|
|
|
|
| @@ -1770,31 +1784,66 @@ static int node_count = 0;
|
| static int instruction_count = 0;
|
|
|
|
|
| -void Node::AssignNumbers() {
|
| +void Node::AssignNodeNumber() {
|
| set_number(node_count++);
|
| }
|
|
|
|
|
| -void BlockNode::AssignNumbers() {
|
| - set_number(node_count++);
|
| - for (int i = 0, len = instructions_.length(); i < len; i++) {
|
| - instructions_[i]->set_num(instruction_count++);
|
| +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");
|
| }
|
| }
|
|
|
|
|
| void ExitNode::PrintText() {
|
| + PrintReachingDefinitions();
|
| PrintF("L%d: Exit\n\n", number());
|
| }
|
|
|
|
|
| void BlockNode::PrintText() {
|
| + PrintReachingDefinitions();
|
| // Print the instructions in the block.
|
| PrintF("L%d: Block\n", number());
|
| TextInstructionPrinter printer;
|
| for (int i = 0, len = instructions_.length(); i < len; i++) {
|
| - PrintF("%d ", instructions_[i]->num());
|
| + PrintF("%d ", printer.NextNumber());
|
| printer.Visit(instructions_[i]);
|
| + printer.AssignNumber(instructions_[i]);
|
| PrintF("\n");
|
| }
|
| PrintF("goto L%d\n\n", successor_->number());
|
| @@ -1802,12 +1851,14 @@ void BlockNode::PrintText() {
|
|
|
|
|
| void BranchNode::PrintText() {
|
| + PrintReachingDefinitions();
|
| PrintF("L%d: Branch\n", number());
|
| PrintF("goto (L%d, L%d)\n\n", successor0_->number(), successor1_->number());
|
| }
|
|
|
|
|
| void JoinNode::PrintText() {
|
| + PrintReachingDefinitions();
|
| PrintF("L%d: Join(", number());
|
| for (int i = 0, len = predecessors_.length(); i < len; i++) {
|
| if (i != 0) PrintF(", ");
|
| @@ -1824,7 +1875,7 @@ void FlowGraph::PrintText(ZoneList<Node*>* postorder) {
|
| node_count = 0;
|
| instruction_count = 0;
|
| for (int i = postorder->length() - 1; i >= 0; i--) {
|
| - postorder->at(i)->AssignNumbers();
|
| + postorder->at(i)->AssignNodeNumber();
|
| }
|
|
|
| // Print basic blocks in reverse postorder.
|
| @@ -1837,4 +1888,95 @@ void FlowGraph::PrintText(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) {
|
| + rd_.Initialize(definition_count);
|
| +}
|
| +
|
| +
|
| +void BlockNode::InitializeReachingDefinitions(int definition_count,
|
| + List<BitVector*>* variables) {
|
| + int instruction_count = instructions_.length();
|
| + int variable_count = variables->length();
|
| +
|
| + rd_.Initialize(definition_count);
|
| +
|
| + for (int i = 0; i < instruction_count; i++) {
|
| + Expression* expr = instructions_[i]->AsExpression();
|
| + if (expr == NULL) continue;
|
| + Variable* var = expr->AssignedVar();
|
| + if (var == NULL) 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());
|
| + }
|
| +}
|
| +
|
| +
|
| +void ReachingDefinitions::Compute() {
|
| + if (definitions_->is_empty()) return;
|
| +
|
| + int variable_count = variables_.length();
|
| + int definition_count = definitions_->length();
|
| + int block_count = postorder_->length();
|
| +
|
| + // Step 1: For each variable, identify the set of all its definitions in
|
| + // the body.
|
| + for (int i = 0; i < definition_count; i++) {
|
| + Variable* var = definitions_->at(i)->AssignedVar();
|
| + variables_[IndexFor(var, variable_count)]->Add(i);
|
| + }
|
| +
|
| + if (FLAG_print_graph_text) {
|
| + for (int i = 0; i < variable_count; i++) {
|
| + BitVector* def_set = variables_[i];
|
| + if (!def_set->IsEmpty()) {
|
| + // At least one definition.
|
| + bool first = true;
|
| + for (int j = 0; j < definition_count; j++) {
|
| + if (def_set->Contains(j)) {
|
| + if (first) {
|
| + Variable* var = definitions_->at(j)->AssignedVar();
|
| + ASSERT(var != NULL);
|
| + PrintF("Def[%s] = {%d", *var->name()->ToCString(), j);
|
| + first = false;
|
| + } else {
|
| + PrintF(", %d", j);
|
| + }
|
| + }
|
| + }
|
| + PrintF("}\n");
|
| + }
|
| + }
|
| + }
|
| +
|
| + // Step 2: Compute KILL and GEN for each block node, initialize RD.
|
| + for (int i = block_count - 1; i >= 0; i--) {
|
| + postorder_->at(i)->InitializeReachingDefinitions(definition_count,
|
| + &variables_);
|
| + }
|
| +}
|
| +
|
| +
|
| } } // namespace v8::internal
|
|
|