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

Side by Side Diff: src/data-flow.cc

Issue 1530003: Rework flow graph construction. (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 unified diff | Download patch
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 10 matching lines...) Expand all
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "data-flow.h" 30 #include "data-flow.h"
31 #include "flow-graph.h"
32 #include "scopes.h" 31 #include "scopes.h"
33 32
34 namespace v8 { 33 namespace v8 {
35 namespace internal { 34 namespace internal {
36 35
37 36
38 #ifdef DEBUG 37 #ifdef DEBUG
39 void BitVector::Print() { 38 void BitVector::Print() {
40 bool first = true; 39 bool first = true;
41 PrintF("{"); 40 PrintF("{");
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after
614 CatchExtensionObject* expr) { 613 CatchExtensionObject* expr) {
615 ASSERT(av_.IsEmpty()); 614 ASSERT(av_.IsEmpty());
616 Visit(expr->key()); 615 Visit(expr->key());
617 ProcessExpression(expr->value()); 616 ProcessExpression(expr->value());
618 } 617 }
619 618
620 619
621 void AssignedVariablesAnalyzer::VisitAssignment(Assignment* expr) { 620 void AssignedVariablesAnalyzer::VisitAssignment(Assignment* expr) {
622 ASSERT(av_.IsEmpty()); 621 ASSERT(av_.IsEmpty());
623 622
624 if (expr->target()->AsProperty() != NULL) { 623 // There are three kinds of assignments: variable assignments, property
625 // Visit receiver and key of property store and rhs. 624 // assignments, and reference errors (invalid left-hand sides).
626 Visit(expr->target()->AsProperty()->obj()); 625 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
627 ProcessExpression(expr->target()->AsProperty()->key()); 626 Property* prop = expr->target()->AsProperty();
628 ProcessExpression(expr->value()); 627 ASSERT(var == NULL || prop == NULL);
629 628
630 // If we have a variable as a receiver in a property store, check if 629 if (var != NULL) {
631 // we can mark it as trivial. 630 MarkIfTrivial(expr->value());
632 MarkIfTrivial(expr->target()->AsProperty()->obj()); 631 Visit(expr->value());
632 if (expr->is_compound()) {
633 // Left-hand side occurs also as an rvalue.
634 MarkIfTrivial(expr->target());
635 ProcessExpression(expr->target());
636 }
637 RecordAssignedVar(var);
638
639 } else if (prop != NULL) {
640 MarkIfTrivial(expr->value());
641 Visit(expr->value());
642 if (!prop->key()->IsPropertyName()) {
643 MarkIfTrivial(prop->key());
644 ProcessExpression(prop->key());
645 }
646 MarkIfTrivial(prop->obj());
647 ProcessExpression(prop->obj());
648
633 } else { 649 } else {
634 Visit(expr->target()); 650 Visit(expr->target());
635 ProcessExpression(expr->value());
636
637 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
638 if (var != NULL) RecordAssignedVar(var);
639 } 651 }
640 } 652 }
641 653
642 654
643 void AssignedVariablesAnalyzer::VisitThrow(Throw* expr) { 655 void AssignedVariablesAnalyzer::VisitThrow(Throw* expr) {
644 ASSERT(av_.IsEmpty()); 656 ASSERT(av_.IsEmpty());
645 Visit(expr->exception()); 657 Visit(expr->exception());
646 } 658 }
647 659
648 660
649 void AssignedVariablesAnalyzer::VisitProperty(Property* expr) { 661 void AssignedVariablesAnalyzer::VisitProperty(Property* expr) {
650 ASSERT(av_.IsEmpty()); 662 ASSERT(av_.IsEmpty());
651 Visit(expr->obj()); 663 if (!expr->key()->IsPropertyName()) {
664 MarkIfTrivial(expr->key());
665 Visit(expr->key());
666 }
667 MarkIfTrivial(expr->obj());
652 ProcessExpression(expr->key()); 668 ProcessExpression(expr->key());
fschneider 2010/03/29 13:49:59 That should be ProcessExpression(expr->obj());
Kevin Millikin (Chromium) 2010/03/29 14:22:53 Thank you.
653
654 // In case we have a variable as a receiver, check if we can mark
655 // it as trivial.
656 MarkIfTrivial(expr->obj());
657 } 669 }
658 670
659 671
660 void AssignedVariablesAnalyzer::VisitCall(Call* expr) { 672 void AssignedVariablesAnalyzer::VisitCall(Call* expr) {
661 ASSERT(av_.IsEmpty()); 673 ASSERT(av_.IsEmpty());
662 Visit(expr->expression()); 674 Visit(expr->expression());
663 BitVector result(av_); 675 BitVector result(av_);
664 for (int i = 0; i < expr->arguments()->length(); i++) { 676 for (int i = 0; i < expr->arguments()->length(); i++) {
665 av_.Clear(); 677 av_.Clear();
666 Visit(expr->arguments()->at(i)); 678 Visit(expr->arguments()->at(i));
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 718
707 Visit(expr->expression()); 719 Visit(expr->expression());
708 720
709 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 721 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
710 if (var != NULL) RecordAssignedVar(var); 722 if (var != NULL) RecordAssignedVar(var);
711 } 723 }
712 724
713 725
714 void AssignedVariablesAnalyzer::VisitBinaryOperation(BinaryOperation* expr) { 726 void AssignedVariablesAnalyzer::VisitBinaryOperation(BinaryOperation* expr) {
715 ASSERT(av_.IsEmpty()); 727 ASSERT(av_.IsEmpty());
716 Visit(expr->left()); 728 MarkIfTrivial(expr->right());
717 729 Visit(expr->right());
718 ProcessExpression(expr->right());
719
720 // In case we have a variable on the left side, check if we can mark
721 // it as trivial.
722 MarkIfTrivial(expr->left()); 730 MarkIfTrivial(expr->left());
731 ProcessExpression(expr->left());
723 } 732 }
724 733
725 734
726 void AssignedVariablesAnalyzer::VisitCompareOperation(CompareOperation* expr) { 735 void AssignedVariablesAnalyzer::VisitCompareOperation(CompareOperation* expr) {
727 ASSERT(av_.IsEmpty()); 736 ASSERT(av_.IsEmpty());
728 Visit(expr->left()); 737 MarkIfTrivial(expr->right());
729 738 Visit(expr->right());
730 ProcessExpression(expr->right());
731
732 // In case we have a variable on the left side, check if we can mark
733 // it as trivial.
734 MarkIfTrivial(expr->left()); 739 MarkIfTrivial(expr->left());
740 ProcessExpression(expr->left());
735 } 741 }
736 742
737 743
738 void AssignedVariablesAnalyzer::VisitThisFunction(ThisFunction* expr) { 744 void AssignedVariablesAnalyzer::VisitThisFunction(ThisFunction* expr) {
739 // Nothing to do. 745 // Nothing to do.
740 ASSERT(av_.IsEmpty()); 746 ASSERT(av_.IsEmpty());
741 } 747 }
742 748
743 749
744 void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) { 750 void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) {
745 UNREACHABLE(); 751 UNREACHABLE();
746 } 752 }
747 753
748 754
749 int ReachingDefinitions::IndexFor(Variable* var, int variable_count) {
750 // Parameters are numbered left-to-right from the beginning of the bit
751 // set. Stack-allocated locals are allocated right-to-left from the end.
752 ASSERT(var != NULL && var->IsStackAllocated());
753 Slot* slot = var->slot();
754 if (slot->type() == Slot::PARAMETER) {
755 return slot->index();
756 } else {
757 return (variable_count - 1) - slot->index();
758 }
759 }
760
761
762 void Node::InitializeReachingDefinitions(int definition_count,
763 List<BitVector*>* variables,
764 WorkList<Node>* worklist,
765 bool mark) {
766 ASSERT(!IsMarkedWith(mark));
767 rd_.Initialize(definition_count);
768 MarkWith(mark);
769 worklist->Insert(this);
770 }
771
772
773 void BlockNode::InitializeReachingDefinitions(int definition_count,
774 List<BitVector*>* variables,
775 WorkList<Node>* worklist,
776 bool mark) {
777 ASSERT(!IsMarkedWith(mark));
778 int instruction_count = instructions_.length();
779 int variable_count = variables->length();
780
781 rd_.Initialize(definition_count);
782 // The RD_in set for the entry node has a definition for each parameter
783 // and local.
784 if (predecessor_ == NULL) {
785 for (int i = 0; i < variable_count; i++) rd_.rd_in()->Add(i);
786 }
787
788 for (int i = 0; i < instruction_count; i++) {
789 Expression* expr = instructions_[i]->AsExpression();
790 if (expr == NULL) continue;
791 Variable* var = expr->AssignedVariable();
792 if (var == NULL || !var->IsStackAllocated()) continue;
793
794 // All definitions of this variable are killed.
795 BitVector* def_set =
796 variables->at(ReachingDefinitions::IndexFor(var, variable_count));
797 rd_.kill()->Union(*def_set);
798
799 // All previously generated definitions are not generated.
800 rd_.gen()->Subtract(*def_set);
801
802 // This one is generated.
803 rd_.gen()->Add(expr->num());
804 }
805
806 // Add all blocks except the entry node to the worklist.
807 if (predecessor_ != NULL) {
808 MarkWith(mark);
809 worklist->Insert(this);
810 }
811 }
812
813
814 void ExitNode::ComputeRDOut(BitVector* result) {
815 // Should not be the predecessor of any node.
816 UNREACHABLE();
817 }
818
819
820 void BlockNode::ComputeRDOut(BitVector* result) {
821 // All definitions reaching this block ...
822 *result = *rd_.rd_in();
823 // ... except those killed by the block ...
824 result->Subtract(*rd_.kill());
825 // ... but including those generated by the block.
826 result->Union(*rd_.gen());
827 }
828
829
830 void BranchNode::ComputeRDOut(BitVector* result) {
831 // Branch nodes don't kill or generate definitions.
832 *result = *rd_.rd_in();
833 }
834
835
836 void JoinNode::ComputeRDOut(BitVector* result) {
837 // Join nodes don't kill or generate definitions.
838 *result = *rd_.rd_in();
839 }
840
841
842 void ExitNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
843 // The exit node has no successors so we can just update in place. New
844 // RD_in is the union over all predecessors.
845 int definition_count = rd_.rd_in()->length();
846 rd_.rd_in()->Clear();
847
848 BitVector temp(definition_count);
849 for (int i = 0, len = predecessors_.length(); i < len; i++) {
850 // Because ComputeRDOut always overwrites temp and its value is
851 // always read out before calling ComputeRDOut again, we do not
852 // have to clear it on each iteration of the loop.
853 predecessors_[i]->ComputeRDOut(&temp);
854 rd_.rd_in()->Union(temp);
855 }
856 }
857
858
859 void BlockNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
860 // The entry block has no predecessor. Its RD_in does not change.
861 if (predecessor_ == NULL) return;
862
863 BitVector new_rd_in(rd_.rd_in()->length());
864 predecessor_->ComputeRDOut(&new_rd_in);
865
866 if (rd_.rd_in()->Equals(new_rd_in)) return;
867
868 // Update RD_in.
869 *rd_.rd_in() = new_rd_in;
870 // Add the successor to the worklist if not already present.
871 if (!successor_->IsMarkedWith(mark)) {
872 successor_->MarkWith(mark);
873 worklist->Insert(successor_);
874 }
875 }
876
877
878 void BranchNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
879 BitVector new_rd_in(rd_.rd_in()->length());
880 predecessor_->ComputeRDOut(&new_rd_in);
881
882 if (rd_.rd_in()->Equals(new_rd_in)) return;
883
884 // Update RD_in.
885 *rd_.rd_in() = new_rd_in;
886 // Add the successors to the worklist if not already present.
887 if (!successor0_->IsMarkedWith(mark)) {
888 successor0_->MarkWith(mark);
889 worklist->Insert(successor0_);
890 }
891 if (!successor1_->IsMarkedWith(mark)) {
892 successor1_->MarkWith(mark);
893 worklist->Insert(successor1_);
894 }
895 }
896
897
898 void JoinNode::UpdateRDIn(WorkList<Node>* worklist, bool mark) {
899 int definition_count = rd_.rd_in()->length();
900 BitVector new_rd_in(definition_count);
901
902 // New RD_in is the union over all predecessors.
903 BitVector temp(definition_count);
904 for (int i = 0, len = predecessors_.length(); i < len; i++) {
905 predecessors_[i]->ComputeRDOut(&temp);
906 new_rd_in.Union(temp);
907 }
908
909 if (rd_.rd_in()->Equals(new_rd_in)) return;
910
911 // Update RD_in.
912 *rd_.rd_in() = new_rd_in;
913 // Add the successor to the worklist if not already present.
914 if (!successor_->IsMarkedWith(mark)) {
915 successor_->MarkWith(mark);
916 worklist->Insert(successor_);
917 }
918 }
919
920
921 void Node::PropagateReachingDefinitions(List<BitVector*>* variables) {
922 // Nothing to do.
923 }
924
925
926 void BlockNode::PropagateReachingDefinitions(List<BitVector*>* variables) {
927 // Propagate RD_in from the start of the block to all the variable
928 // references.
929 int variable_count = variables->length();
930 BitVector rd = *rd_.rd_in();
931 for (int i = 0, len = instructions_.length(); i < len; i++) {
932 Expression* expr = instructions_[i]->AsExpression();
933 if (expr == NULL) continue;
934
935 // Look for a variable reference to record its reaching definitions.
936 VariableProxy* proxy = expr->AsVariableProxy();
937 if (proxy == NULL) {
938 // Not a VariableProxy? Maybe it's a count operation.
939 CountOperation* count_operation = expr->AsCountOperation();
940 if (count_operation != NULL) {
941 proxy = count_operation->expression()->AsVariableProxy();
942 }
943 }
944 if (proxy == NULL) {
945 // OK, Maybe it's a compound assignment.
946 Assignment* assignment = expr->AsAssignment();
947 if (assignment != NULL && assignment->is_compound()) {
948 proxy = assignment->target()->AsVariableProxy();
949 }
950 }
951
952 if (proxy != NULL &&
953 proxy->var()->IsStackAllocated() &&
954 !proxy->var()->is_this()) {
955 // All definitions for this variable.
956 BitVector* definitions =
957 variables->at(ReachingDefinitions::IndexFor(proxy->var(),
958 variable_count));
959 BitVector* reaching_definitions = new BitVector(*definitions);
960 // Intersected with all definitions (of any variable) reaching this
961 // instruction.
962 reaching_definitions->Intersect(rd);
963 proxy->set_reaching_definitions(reaching_definitions);
964 }
965
966 // It may instead (or also) be a definition. If so update the running
967 // value of reaching definitions for the block.
968 Variable* var = expr->AssignedVariable();
969 if (var == NULL || !var->IsStackAllocated()) continue;
970
971 // All definitions of this variable are killed.
972 BitVector* def_set =
973 variables->at(ReachingDefinitions::IndexFor(var, variable_count));
974 rd.Subtract(*def_set);
975 // This definition is generated.
976 rd.Add(expr->num());
977 }
978 }
979
980
981 void ReachingDefinitions::Compute() {
982 // The definitions in the body plus an implicit definition for each
983 // variable at function entry.
984 int definition_count = body_definitions_->length() + variable_count_;
985 int node_count = postorder_->length();
986
987 // Step 1: For each stack-allocated variable, identify the set of all its
988 // definitions.
989 List<BitVector*> variables;
990 for (int i = 0; i < variable_count_; i++) {
991 // Add the initial definition for each variable.
992 BitVector* initial = new BitVector(definition_count);
993 initial->Add(i);
994 variables.Add(initial);
995 }
996 for (int i = 0, len = body_definitions_->length(); i < len; i++) {
997 // Account for each definition in the body as a definition of the
998 // defined variable.
999 Variable* var = body_definitions_->at(i)->AssignedVariable();
1000 variables[IndexFor(var, variable_count_)]->Add(i + variable_count_);
1001 }
1002
1003 // Step 2: Compute KILL and GEN for each block node, initialize RD_in for
1004 // all nodes, and mark and add all nodes to the worklist in reverse
1005 // postorder. All nodes should currently have the same mark.
1006 bool mark = postorder_->at(0)->IsMarkedWith(false); // Negation of current.
1007 WorkList<Node> worklist(node_count);
1008 for (int i = node_count - 1; i >= 0; i--) {
1009 postorder_->at(i)->InitializeReachingDefinitions(definition_count,
1010 &variables,
1011 &worklist,
1012 mark);
1013 }
1014
1015 // Step 3: Until the worklist is empty, remove an item compute and update
1016 // its rd_in based on its predecessor's rd_out. If rd_in has changed, add
1017 // all necessary successors to the worklist.
1018 while (!worklist.is_empty()) {
1019 Node* node = worklist.Remove();
1020 node->MarkWith(!mark);
1021 node->UpdateRDIn(&worklist, mark);
1022 }
1023
1024 // Step 4: Based on RD_in for block nodes, propagate reaching definitions
1025 // to all variable uses in the block.
1026 for (int i = 0; i < node_count; i++) {
1027 postorder_->at(i)->PropagateReachingDefinitions(&variables);
1028 }
1029 }
1030
1031
1032 bool TypeAnalyzer::IsPrimitiveDef(int def_num) {
1033 if (def_num < param_count_) return false;
1034 if (def_num < variable_count_) return true;
1035 return body_definitions_->at(def_num - variable_count_)->IsPrimitive();
1036 }
1037
1038
1039 void TypeAnalyzer::Compute() {
1040 bool changed;
1041 int count = 0;
1042
1043 do {
1044 changed = false;
1045
1046 if (FLAG_print_graph_text) {
1047 PrintF("TypeAnalyzer::Compute - iteration %d\n", count++);
1048 }
1049
1050 for (int i = postorder_->length() - 1; i >= 0; --i) {
1051 Node* node = postorder_->at(i);
1052 if (node->IsBlockNode()) {
1053 BlockNode* block = BlockNode::cast(node);
1054 for (int j = 0; j < block->instructions()->length(); j++) {
1055 Expression* expr = block->instructions()->at(j)->AsExpression();
1056 if (expr != NULL) {
1057 // For variable uses: Compute new type from reaching definitions.
1058 VariableProxy* proxy = expr->AsVariableProxy();
1059 if (proxy != NULL && proxy->reaching_definitions() != NULL) {
1060 BitVector* rd = proxy->reaching_definitions();
1061 bool prim_type = true;
1062 // TODO(fsc): A sparse set representation of reaching
1063 // definitions would speed up iterating here.
1064 for (int k = 0; k < rd->length(); k++) {
1065 if (rd->Contains(k) && !IsPrimitiveDef(k)) {
1066 prim_type = false;
1067 break;
1068 }
1069 }
1070 // Reset changed flag if new type information was computed.
1071 if (prim_type != proxy->IsPrimitive()) {
1072 changed = true;
1073 proxy->SetIsPrimitive(prim_type);
1074 }
1075 }
1076 }
1077 }
1078 }
1079 }
1080 } while (changed);
1081 }
1082
1083
1084 void Node::MarkCriticalInstructions(
1085 List<AstNode*>* stack,
1086 ZoneList<Expression*>* body_definitions,
1087 int variable_count) {
1088 }
1089
1090
1091 void BlockNode::MarkCriticalInstructions(
1092 List<AstNode*>* stack,
1093 ZoneList<Expression*>* body_definitions,
1094 int variable_count) {
1095 for (int i = instructions_.length() - 1; i >= 0; i--) {
1096 // Only expressions can appear in the flow graph for now.
1097 Expression* expr = instructions_[i]->AsExpression();
1098 if (expr != NULL && !expr->is_live() &&
1099 (expr->is_loop_condition() || expr->IsCritical())) {
1100 expr->mark_as_live();
1101 expr->ProcessNonLiveChildren(stack, body_definitions, variable_count);
1102 }
1103 }
1104 }
1105
1106
1107 void MarkLiveCode(ZoneList<Node*>* nodes,
1108 ZoneList<Expression*>* body_definitions,
1109 int variable_count) {
1110 List<AstNode*> stack(20);
1111
1112 // Mark the critical AST nodes as live; mark their dependencies and
1113 // add them to the marking stack.
1114 for (int i = nodes->length() - 1; i >= 0; i--) {
1115 nodes->at(i)->MarkCriticalInstructions(&stack, body_definitions,
1116 variable_count);
1117 }
1118
1119 // Continue marking dependencies until no more.
1120 while (!stack.is_empty()) {
1121 // Only expressions can appear in the flow graph for now.
1122 Expression* expr = stack.RemoveLast()->AsExpression();
1123 if (expr != NULL) {
1124 expr->ProcessNonLiveChildren(&stack, body_definitions, variable_count);
1125 }
1126 }
1127 }
1128
1129
1130 #ifdef DEBUG
1131
1132 // Print a textual representation of an instruction in a flow graph. Using
1133 // the AstVisitor is overkill because there is no recursion here. It is
1134 // only used for printing in debug mode.
1135 class TextInstructionPrinter: public AstVisitor {
1136 public:
1137 TextInstructionPrinter() : number_(0) {}
1138
1139 int NextNumber() { return number_; }
1140 void AssignNumber(AstNode* node) { node->set_num(number_++); }
1141
1142 private:
1143 // AST node visit functions.
1144 #define DECLARE_VISIT(type) virtual void Visit##type(type* node);
1145 AST_NODE_LIST(DECLARE_VISIT)
1146 #undef DECLARE_VISIT
1147
1148 int number_;
1149
1150 DISALLOW_COPY_AND_ASSIGN(TextInstructionPrinter);
1151 };
1152
1153
1154 void TextInstructionPrinter::VisitDeclaration(Declaration* decl) {
1155 UNREACHABLE();
1156 }
1157
1158
1159 void TextInstructionPrinter::VisitBlock(Block* stmt) {
1160 PrintF("Block");
1161 }
1162
1163
1164 void TextInstructionPrinter::VisitExpressionStatement(
1165 ExpressionStatement* stmt) {
1166 PrintF("ExpressionStatement");
1167 }
1168
1169
1170 void TextInstructionPrinter::VisitEmptyStatement(EmptyStatement* stmt) {
1171 PrintF("EmptyStatement");
1172 }
1173
1174
1175 void TextInstructionPrinter::VisitIfStatement(IfStatement* stmt) {
1176 PrintF("IfStatement");
1177 }
1178
1179
1180 void TextInstructionPrinter::VisitContinueStatement(ContinueStatement* stmt) {
1181 UNREACHABLE();
1182 }
1183
1184
1185 void TextInstructionPrinter::VisitBreakStatement(BreakStatement* stmt) {
1186 UNREACHABLE();
1187 }
1188
1189
1190 void TextInstructionPrinter::VisitReturnStatement(ReturnStatement* stmt) {
1191 PrintF("return @%d", stmt->expression()->num());
1192 }
1193
1194
1195 void TextInstructionPrinter::VisitWithEnterStatement(WithEnterStatement* stmt) {
1196 PrintF("WithEnterStatement");
1197 }
1198
1199
1200 void TextInstructionPrinter::VisitWithExitStatement(WithExitStatement* stmt) {
1201 PrintF("WithExitStatement");
1202 }
1203
1204
1205 void TextInstructionPrinter::VisitSwitchStatement(SwitchStatement* stmt) {
1206 UNREACHABLE();
1207 }
1208
1209
1210 void TextInstructionPrinter::VisitDoWhileStatement(DoWhileStatement* stmt) {
1211 PrintF("DoWhileStatement");
1212 }
1213
1214
1215 void TextInstructionPrinter::VisitWhileStatement(WhileStatement* stmt) {
1216 PrintF("WhileStatement");
1217 }
1218
1219
1220 void TextInstructionPrinter::VisitForStatement(ForStatement* stmt) {
1221 PrintF("ForStatement");
1222 }
1223
1224
1225 void TextInstructionPrinter::VisitForInStatement(ForInStatement* stmt) {
1226 PrintF("ForInStatement");
1227 }
1228
1229
1230 void TextInstructionPrinter::VisitTryCatchStatement(TryCatchStatement* stmt) {
1231 UNREACHABLE();
1232 }
1233
1234
1235 void TextInstructionPrinter::VisitTryFinallyStatement(
1236 TryFinallyStatement* stmt) {
1237 UNREACHABLE();
1238 }
1239
1240
1241 void TextInstructionPrinter::VisitDebuggerStatement(DebuggerStatement* stmt) {
1242 PrintF("DebuggerStatement");
1243 }
1244
1245
1246 void TextInstructionPrinter::VisitFunctionLiteral(FunctionLiteral* expr) {
1247 PrintF("FunctionLiteral");
1248 }
1249
1250
1251 void TextInstructionPrinter::VisitSharedFunctionInfoLiteral(
1252 SharedFunctionInfoLiteral* expr) {
1253 PrintF("SharedFunctionInfoLiteral");
1254 }
1255
1256
1257 void TextInstructionPrinter::VisitConditional(Conditional* expr) {
1258 PrintF("Conditional");
1259 }
1260
1261
1262 void TextInstructionPrinter::VisitSlot(Slot* expr) {
1263 UNREACHABLE();
1264 }
1265
1266
1267 void TextInstructionPrinter::VisitVariableProxy(VariableProxy* expr) {
1268 Variable* var = expr->AsVariable();
1269 if (var != NULL) {
1270 PrintF("%s", *var->name()->ToCString());
1271 if (var->IsStackAllocated() && expr->reaching_definitions() != NULL) {
1272 expr->reaching_definitions()->Print();
1273 }
1274 } else {
1275 ASSERT(expr->AsProperty() != NULL);
1276 VisitProperty(expr->AsProperty());
1277 }
1278 }
1279
1280
1281 void TextInstructionPrinter::VisitLiteral(Literal* expr) {
1282 expr->handle()->ShortPrint();
1283 }
1284
1285
1286 void TextInstructionPrinter::VisitRegExpLiteral(RegExpLiteral* expr) {
1287 PrintF("RegExpLiteral");
1288 }
1289
1290
1291 void TextInstructionPrinter::VisitObjectLiteral(ObjectLiteral* expr) {
1292 PrintF("ObjectLiteral");
1293 }
1294
1295
1296 void TextInstructionPrinter::VisitArrayLiteral(ArrayLiteral* expr) {
1297 PrintF("ArrayLiteral");
1298 }
1299
1300
1301 void TextInstructionPrinter::VisitCatchExtensionObject(
1302 CatchExtensionObject* expr) {
1303 PrintF("CatchExtensionObject");
1304 }
1305
1306
1307 void TextInstructionPrinter::VisitAssignment(Assignment* expr) {
1308 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
1309 Property* prop = expr->target()->AsProperty();
1310
1311 if (var == NULL && prop == NULL) {
1312 // Throw reference error.
1313 Visit(expr->target());
1314 return;
1315 }
1316
1317 // Print the left-hand side.
1318 if (var != NULL) {
1319 PrintF("%s", *var->name()->ToCString());
1320 } else if (prop != NULL) {
1321 PrintF("@%d", prop->obj()->num());
1322 if (prop->key()->IsPropertyName()) {
1323 PrintF(".");
1324 ASSERT(prop->key()->AsLiteral() != NULL);
1325 prop->key()->AsLiteral()->handle()->Print();
1326 } else {
1327 PrintF("[@%d]", prop->key()->num());
1328 }
1329 }
1330
1331 // Print the operation.
1332 if (expr->is_compound()) {
1333 PrintF(" = ");
1334 // Print the left-hand side again when compound.
1335 if (var != NULL) {
1336 PrintF("@%d", expr->target()->num());
1337 } else {
1338 PrintF("@%d", prop->obj()->num());
1339 if (prop->key()->IsPropertyName()) {
1340 PrintF(".");
1341 ASSERT(prop->key()->AsLiteral() != NULL);
1342 prop->key()->AsLiteral()->handle()->Print();
1343 } else {
1344 PrintF("[@%d]", prop->key()->num());
1345 }
1346 }
1347 // Print the corresponding binary operator.
1348 PrintF(" %s ", Token::String(expr->binary_op()));
1349 } else {
1350 PrintF(" %s ", Token::String(expr->op()));
1351 }
1352
1353 // Print the right-hand side.
1354 PrintF("@%d", expr->value()->num());
1355
1356 if (expr->num() != AstNode::kNoNumber) {
1357 PrintF(" ;; D%d", expr->num());
1358 }
1359 }
1360
1361
1362 void TextInstructionPrinter::VisitThrow(Throw* expr) {
1363 PrintF("throw @%d", expr->exception()->num());
1364 }
1365
1366
1367 void TextInstructionPrinter::VisitProperty(Property* expr) {
1368 if (expr->key()->IsPropertyName()) {
1369 PrintF("@%d.", expr->obj()->num());
1370 ASSERT(expr->key()->AsLiteral() != NULL);
1371 expr->key()->AsLiteral()->handle()->Print();
1372 } else {
1373 PrintF("@%d[@%d]", expr->obj()->num(), expr->key()->num());
1374 }
1375 }
1376
1377
1378 void TextInstructionPrinter::VisitCall(Call* expr) {
1379 PrintF("@%d(", expr->expression()->num());
1380 ZoneList<Expression*>* arguments = expr->arguments();
1381 for (int i = 0, len = arguments->length(); i < len; i++) {
1382 if (i != 0) PrintF(", ");
1383 PrintF("@%d", arguments->at(i)->num());
1384 }
1385 PrintF(")");
1386 }
1387
1388
1389 void TextInstructionPrinter::VisitCallNew(CallNew* expr) {
1390 PrintF("new @%d(", expr->expression()->num());
1391 ZoneList<Expression*>* arguments = expr->arguments();
1392 for (int i = 0, len = arguments->length(); i < len; i++) {
1393 if (i != 0) PrintF(", ");
1394 PrintF("@%d", arguments->at(i)->num());
1395 }
1396 PrintF(")");
1397 }
1398
1399
1400 void TextInstructionPrinter::VisitCallRuntime(CallRuntime* expr) {
1401 PrintF("%s(", *expr->name()->ToCString());
1402 ZoneList<Expression*>* arguments = expr->arguments();
1403 for (int i = 0, len = arguments->length(); i < len; i++) {
1404 if (i != 0) PrintF(", ");
1405 PrintF("@%d", arguments->at(i)->num());
1406 }
1407 PrintF(")");
1408 }
1409
1410
1411 void TextInstructionPrinter::VisitUnaryOperation(UnaryOperation* expr) {
1412 PrintF("%s(@%d)", Token::String(expr->op()), expr->expression()->num());
1413 }
1414
1415
1416 void TextInstructionPrinter::VisitCountOperation(CountOperation* expr) {
1417 if (expr->is_prefix()) {
1418 PrintF("%s@%d", Token::String(expr->op()), expr->expression()->num());
1419 } else {
1420 PrintF("@%d%s", expr->expression()->num(), Token::String(expr->op()));
1421 }
1422
1423 if (expr->num() != AstNode::kNoNumber) {
1424 PrintF(" ;; D%d", expr->num());
1425 }
1426 }
1427
1428
1429 void TextInstructionPrinter::VisitBinaryOperation(BinaryOperation* expr) {
1430 ASSERT(expr->op() != Token::COMMA);
1431 ASSERT(expr->op() != Token::OR);
1432 ASSERT(expr->op() != Token::AND);
1433 PrintF("@%d %s @%d",
1434 expr->left()->num(),
1435 Token::String(expr->op()),
1436 expr->right()->num());
1437 }
1438
1439
1440 void TextInstructionPrinter::VisitCompareOperation(CompareOperation* expr) {
1441 PrintF("@%d %s @%d",
1442 expr->left()->num(),
1443 Token::String(expr->op()),
1444 expr->right()->num());
1445 }
1446
1447
1448 void TextInstructionPrinter::VisitThisFunction(ThisFunction* expr) {
1449 PrintF("ThisFunction");
1450 }
1451
1452
1453 static int node_count = 0;
1454 static int instruction_count = 0;
1455
1456
1457 void Node::AssignNodeNumber() {
1458 set_number(node_count++);
1459 }
1460
1461
1462 void Node::PrintReachingDefinitions() {
1463 if (rd_.rd_in() != NULL) {
1464 ASSERT(rd_.kill() != NULL && rd_.gen() != NULL);
1465
1466 PrintF("RD_in = ");
1467 rd_.rd_in()->Print();
1468 PrintF("\n");
1469
1470 PrintF("RD_kill = ");
1471 rd_.kill()->Print();
1472 PrintF("\n");
1473
1474 PrintF("RD_gen = ");
1475 rd_.gen()->Print();
1476 PrintF("\n");
1477 }
1478 }
1479
1480
1481 void ExitNode::PrintText() {
1482 PrintReachingDefinitions();
1483 PrintF("L%d: Exit\n\n", number());
1484 }
1485
1486
1487 void BlockNode::PrintText() {
1488 PrintReachingDefinitions();
1489 // Print the instructions in the block.
1490 PrintF("L%d: Block\n", number());
1491 TextInstructionPrinter printer;
1492 for (int i = 0, len = instructions_.length(); i < len; i++) {
1493 AstNode* instr = instructions_[i];
1494 // Print a star next to dead instructions.
1495 if (instr->AsExpression() != NULL && instr->AsExpression()->is_live()) {
1496 PrintF(" ");
1497 } else {
1498 PrintF("* ");
1499 }
1500 PrintF("%d ", printer.NextNumber());
1501 printer.Visit(instr);
1502 printer.AssignNumber(instr);
1503 PrintF("\n");
1504 }
1505 PrintF("goto L%d\n\n", successor_->number());
1506 }
1507
1508
1509 void BranchNode::PrintText() {
1510 PrintReachingDefinitions();
1511 PrintF("L%d: Branch\n", number());
1512 PrintF("goto (L%d, L%d)\n\n", successor0_->number(), successor1_->number());
1513 }
1514
1515
1516 void JoinNode::PrintText() {
1517 PrintReachingDefinitions();
1518 PrintF("L%d: Join(", number());
1519 for (int i = 0, len = predecessors_.length(); i < len; i++) {
1520 if (i != 0) PrintF(", ");
1521 PrintF("L%d", predecessors_[i]->number());
1522 }
1523 PrintF(")\ngoto L%d\n\n", successor_->number());
1524 }
1525
1526
1527 void FlowGraph::PrintText(FunctionLiteral* fun, ZoneList<Node*>* postorder) {
1528 PrintF("\n========\n");
1529 PrintF("name = %s\n", *fun->name()->ToCString());
1530
1531 // Number nodes and instructions in reverse postorder.
1532 node_count = 0;
1533 instruction_count = 0;
1534 for (int i = postorder->length() - 1; i >= 0; i--) {
1535 postorder->at(i)->AssignNodeNumber();
1536 }
1537
1538 // Print basic blocks in reverse postorder.
1539 for (int i = postorder->length() - 1; i >= 0; i--) {
1540 postorder->at(i)->PrintText();
1541 }
1542 }
1543
1544 #endif // DEBUG
1545
1546
1547 } } // namespace v8::internal 755 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/data-flow.h ('k') | src/flow-graph.h » ('j') | src/flow-graph.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698