OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
825 Handle<FixedArray> elements = factory->NewFixedArray(args.length()); | 825 Handle<FixedArray> elements = factory->NewFixedArray(args.length()); |
826 for (int i = 0; i < args.length(); i++) { | 826 for (int i = 0; i < args.length(); i++) { |
827 elements->set(i, *args[i]); | 827 elements->set(i, *args[i]); |
828 } | 828 } |
829 Handle<JSArray> array = factory->NewJSArrayWithElements(elements); | 829 Handle<JSArray> array = factory->NewJSArrayWithElements(elements); |
830 Handle<Object> result = factory->NewSyntaxError(type, array); | 830 Handle<Object> result = factory->NewSyntaxError(type, array); |
831 isolate()->Throw(*result, &location); | 831 isolate()->Throw(*result, &location); |
832 } | 832 } |
833 | 833 |
834 | 834 |
835 // Base class containing common code for the different finder classes used by | |
836 // the parser. | |
837 class ParserFinder { | |
838 protected: | |
839 ParserFinder() {} | |
840 static Assignment* AsAssignment(Statement* stat) { | |
841 if (stat == NULL) return NULL; | |
842 ExpressionStatement* exp_stat = stat->AsExpressionStatement(); | |
843 if (exp_stat == NULL) return NULL; | |
844 return exp_stat->expression()->AsAssignment(); | |
845 } | |
846 }; | |
847 | |
848 | |
849 // An InitializationBlockFinder finds and marks sequences of statements of the | |
850 // form expr.a = ...; expr.b = ...; etc. | |
851 class InitializationBlockFinder : public ParserFinder { | |
852 public: | |
853 // We find and mark the initialization blocks in top level | |
854 // non-looping code only. This is because the optimization prevents | |
855 // reuse of the map transitions, so it should be used only for code | |
856 // that will only be run once. | |
857 InitializationBlockFinder(Scope* top_scope, Target* target) | |
858 : enabled_(top_scope->DeclarationScope()->is_global_scope() && | |
859 !IsLoopTarget(target)), | |
860 first_in_block_(NULL), | |
861 last_in_block_(NULL), | |
862 block_size_(0) {} | |
863 | |
864 ~InitializationBlockFinder() { | |
865 if (!enabled_) return; | |
866 if (InBlock()) EndBlock(); | |
867 } | |
868 | |
869 void Update(Statement* stat) { | |
870 if (!enabled_) return; | |
871 Assignment* assignment = AsAssignment(stat); | |
872 if (InBlock()) { | |
873 if (BlockContinues(assignment)) { | |
874 UpdateBlock(assignment); | |
875 } else { | |
876 EndBlock(); | |
877 } | |
878 } | |
879 if (!InBlock() && (assignment != NULL) && | |
880 (assignment->op() == Token::ASSIGN)) { | |
881 StartBlock(assignment); | |
882 } | |
883 } | |
884 | |
885 private: | |
886 // The minimum number of contiguous assignment that will | |
887 // be treated as an initialization block. Benchmarks show that | |
888 // the overhead exceeds the savings below this limit. | |
889 static const int kMinInitializationBlock = 3; | |
890 | |
891 static bool IsLoopTarget(Target* target) { | |
892 while (target != NULL) { | |
893 if (target->node()->AsIterationStatement() != NULL) return true; | |
894 target = target->previous(); | |
895 } | |
896 return false; | |
897 } | |
898 | |
899 // Returns true if the expressions appear to denote the same object. | |
900 // In the context of initialization blocks, we only consider expressions | |
901 // of the form 'expr.x' or expr["x"]. | |
902 static bool SameObject(Expression* e1, Expression* e2) { | |
903 VariableProxy* v1 = e1->AsVariableProxy(); | |
904 VariableProxy* v2 = e2->AsVariableProxy(); | |
905 if (v1 != NULL && v2 != NULL) { | |
906 return v1->name()->Equals(*v2->name()); | |
907 } | |
908 Property* p1 = e1->AsProperty(); | |
909 Property* p2 = e2->AsProperty(); | |
910 if ((p1 == NULL) || (p2 == NULL)) return false; | |
911 Literal* key1 = p1->key()->AsLiteral(); | |
912 Literal* key2 = p2->key()->AsLiteral(); | |
913 if ((key1 == NULL) || (key2 == NULL)) return false; | |
914 if (!key1->handle()->IsString() || !key2->handle()->IsString()) { | |
915 return false; | |
916 } | |
917 String* name1 = String::cast(*key1->handle()); | |
918 String* name2 = String::cast(*key2->handle()); | |
919 if (!name1->Equals(name2)) return false; | |
920 return SameObject(p1->obj(), p2->obj()); | |
921 } | |
922 | |
923 // Returns true if the expressions appear to denote different properties | |
924 // of the same object. | |
925 static bool PropertyOfSameObject(Expression* e1, Expression* e2) { | |
926 Property* p1 = e1->AsProperty(); | |
927 Property* p2 = e2->AsProperty(); | |
928 if ((p1 == NULL) || (p2 == NULL)) return false; | |
929 return SameObject(p1->obj(), p2->obj()); | |
930 } | |
931 | |
932 bool BlockContinues(Assignment* assignment) { | |
933 if ((assignment == NULL) || (first_in_block_ == NULL)) return false; | |
934 if (assignment->op() != Token::ASSIGN) return false; | |
935 return PropertyOfSameObject(first_in_block_->target(), | |
936 assignment->target()); | |
937 } | |
938 | |
939 void StartBlock(Assignment* assignment) { | |
940 first_in_block_ = assignment; | |
941 last_in_block_ = assignment; | |
942 block_size_ = 1; | |
943 } | |
944 | |
945 void UpdateBlock(Assignment* assignment) { | |
946 last_in_block_ = assignment; | |
947 ++block_size_; | |
948 } | |
949 | |
950 void EndBlock() { | |
951 if (block_size_ >= kMinInitializationBlock) { | |
952 first_in_block_->mark_block_start(); | |
953 last_in_block_->mark_block_end(); | |
954 } | |
955 last_in_block_ = first_in_block_ = NULL; | |
956 block_size_ = 0; | |
957 } | |
958 | |
959 bool InBlock() { return first_in_block_ != NULL; } | |
960 | |
961 const bool enabled_; | |
962 Assignment* first_in_block_; | |
963 Assignment* last_in_block_; | |
964 int block_size_; | |
965 | |
966 DISALLOW_COPY_AND_ASSIGN(InitializationBlockFinder); | |
967 }; | |
968 | |
969 | |
970 // A ThisNamedPropertyAssignmentFinder finds and marks statements of the form | 835 // A ThisNamedPropertyAssignmentFinder finds and marks statements of the form |
971 // this.x = ...;, where x is a named property. It also determines whether a | 836 // this.x = ...;, where x is a named property. It also determines whether a |
972 // function contains only assignments of this type. | 837 // function contains only assignments of this type. |
973 class ThisNamedPropertyAssignmentFinder : public ParserFinder { | 838 class ThisNamedPropertyAssignmentFinder { |
974 public: | 839 public: |
975 ThisNamedPropertyAssignmentFinder(Isolate* isolate, Zone* zone) | 840 ThisNamedPropertyAssignmentFinder(Isolate* isolate, Zone* zone) |
976 : isolate_(isolate), | 841 : isolate_(isolate), |
977 only_simple_this_property_assignments_(true), | 842 only_simple_this_property_assignments_(true), |
978 names_(0, zone), | 843 names_(0, zone), |
979 assigned_arguments_(0, zone), | 844 assigned_arguments_(0, zone), |
980 assigned_constants_(0, zone), | 845 assigned_constants_(0, zone), |
981 zone_(zone) { | 846 zone_(zone) { |
982 } | 847 } |
983 | 848 |
| 849 static Assignment* AsAssignment(Statement* stat) { |
| 850 if (stat == NULL) return NULL; |
| 851 ExpressionStatement* exp_stat = stat->AsExpressionStatement(); |
| 852 if (exp_stat == NULL) return NULL; |
| 853 return exp_stat->expression()->AsAssignment(); |
| 854 } |
| 855 |
984 void Update(Scope* scope, Statement* stat) { | 856 void Update(Scope* scope, Statement* stat) { |
985 // Bail out if function already has property assignment that are | 857 // Bail out if function already has property assignment that are |
986 // not simple this property assignments. | 858 // not simple this property assignments. |
987 if (!only_simple_this_property_assignments_) { | 859 if (!only_simple_this_property_assignments_) { |
988 return; | 860 return; |
989 } | 861 } |
990 | 862 |
991 // Check whether this statement is of the form this.x = ...; | 863 // Check whether this statement is of the form this.x = ...; |
992 Assignment* assignment = AsAssignment(stat); | 864 Assignment* assignment = AsAssignment(stat); |
993 if (IsThisPropertyAssignment(assignment)) { | 865 if (IsThisPropertyAssignment(assignment)) { |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1139 // SourceElements :: | 1011 // SourceElements :: |
1140 // (ModuleElement)* <end_token> | 1012 // (ModuleElement)* <end_token> |
1141 | 1013 |
1142 // Allocate a target stack to use for this set of source | 1014 // Allocate a target stack to use for this set of source |
1143 // elements. This way, all scripts and functions get their own | 1015 // elements. This way, all scripts and functions get their own |
1144 // target stack thus avoiding illegal breaks and continues across | 1016 // target stack thus avoiding illegal breaks and continues across |
1145 // functions. | 1017 // functions. |
1146 TargetScope scope(&this->target_stack_); | 1018 TargetScope scope(&this->target_stack_); |
1147 | 1019 |
1148 ASSERT(processor != NULL); | 1020 ASSERT(processor != NULL); |
1149 InitializationBlockFinder block_finder(top_scope_, target_stack_); | |
1150 ThisNamedPropertyAssignmentFinder this_property_assignment_finder(isolate(), | 1021 ThisNamedPropertyAssignmentFinder this_property_assignment_finder(isolate(), |
1151 zone()); | 1022 zone()); |
1152 bool directive_prologue = true; // Parsing directive prologue. | 1023 bool directive_prologue = true; // Parsing directive prologue. |
1153 | 1024 |
1154 while (peek() != end_token) { | 1025 while (peek() != end_token) { |
1155 if (directive_prologue && peek() != Token::STRING) { | 1026 if (directive_prologue && peek() != Token::STRING) { |
1156 directive_prologue = false; | 1027 directive_prologue = false; |
1157 } | 1028 } |
1158 | 1029 |
1159 Scanner::Location token_loc = scanner().peek_location(); | 1030 Scanner::Location token_loc = scanner().peek_location(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1194 ? EXTENDED_MODE : STRICT_MODE); | 1065 ? EXTENDED_MODE : STRICT_MODE); |
1195 // "use strict" is the only directive for now. | 1066 // "use strict" is the only directive for now. |
1196 directive_prologue = false; | 1067 directive_prologue = false; |
1197 } | 1068 } |
1198 } else { | 1069 } else { |
1199 // End of the directive prologue. | 1070 // End of the directive prologue. |
1200 directive_prologue = false; | 1071 directive_prologue = false; |
1201 } | 1072 } |
1202 } | 1073 } |
1203 | 1074 |
1204 block_finder.Update(stat); | |
1205 // Find and mark all assignments to named properties in this (this.x =) | 1075 // Find and mark all assignments to named properties in this (this.x =) |
1206 if (top_scope_->is_function_scope()) { | 1076 if (top_scope_->is_function_scope()) { |
1207 this_property_assignment_finder.Update(top_scope_, stat); | 1077 this_property_assignment_finder.Update(top_scope_, stat); |
1208 } | 1078 } |
1209 processor->Add(stat, zone()); | 1079 processor->Add(stat, zone()); |
1210 } | 1080 } |
1211 | 1081 |
1212 // Propagate the collected information on this property assignments. | 1082 // Propagate the collected information on this property assignments. |
1213 if (top_scope_->is_function_scope()) { | 1083 if (top_scope_->is_function_scope()) { |
1214 bool only_simple_this_property_assignments = | 1084 bool only_simple_this_property_assignments = |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1347 | 1217 |
1348 Expect(Token::LBRACE, CHECK_OK); | 1218 Expect(Token::LBRACE, CHECK_OK); |
1349 scope->set_start_position(scanner().location().beg_pos); | 1219 scope->set_start_position(scanner().location().beg_pos); |
1350 scope->SetLanguageMode(EXTENDED_MODE); | 1220 scope->SetLanguageMode(EXTENDED_MODE); |
1351 | 1221 |
1352 { | 1222 { |
1353 BlockState block_state(this, scope); | 1223 BlockState block_state(this, scope); |
1354 TargetCollector collector(zone()); | 1224 TargetCollector collector(zone()); |
1355 Target target(&this->target_stack_, &collector); | 1225 Target target(&this->target_stack_, &collector); |
1356 Target target_body(&this->target_stack_, body); | 1226 Target target_body(&this->target_stack_, body); |
1357 InitializationBlockFinder block_finder(top_scope_, target_stack_); | |
1358 | 1227 |
1359 while (peek() != Token::RBRACE) { | 1228 while (peek() != Token::RBRACE) { |
1360 Statement* stat = ParseModuleElement(NULL, CHECK_OK); | 1229 Statement* stat = ParseModuleElement(NULL, CHECK_OK); |
1361 if (stat && !stat->IsEmpty()) { | 1230 if (stat && !stat->IsEmpty()) { |
1362 body->AddStatement(stat, zone()); | 1231 body->AddStatement(stat, zone()); |
1363 block_finder.Update(stat); | |
1364 } | 1232 } |
1365 } | 1233 } |
1366 } | 1234 } |
1367 | 1235 |
1368 Expect(Token::RBRACE, CHECK_OK); | 1236 Expect(Token::RBRACE, CHECK_OK); |
1369 scope->set_end_position(scanner().location().end_pos); | 1237 scope->set_end_position(scanner().location().end_pos); |
1370 body->set_scope(scope); | 1238 body->set_scope(scope); |
1371 | 1239 |
1372 // Check that all exports are bound. | 1240 // Check that all exports are bound. |
1373 Interface* interface = scope->interface(); | 1241 Interface* interface = scope->interface(); |
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2029 // Block :: | 1897 // Block :: |
2030 // '{' Statement* '}' | 1898 // '{' Statement* '}' |
2031 | 1899 |
2032 // Note that a Block does not introduce a new execution scope! | 1900 // Note that a Block does not introduce a new execution scope! |
2033 // (ECMA-262, 3rd, 12.2) | 1901 // (ECMA-262, 3rd, 12.2) |
2034 // | 1902 // |
2035 // Construct block expecting 16 statements. | 1903 // Construct block expecting 16 statements. |
2036 Block* result = factory()->NewBlock(labels, 16, false); | 1904 Block* result = factory()->NewBlock(labels, 16, false); |
2037 Target target(&this->target_stack_, result); | 1905 Target target(&this->target_stack_, result); |
2038 Expect(Token::LBRACE, CHECK_OK); | 1906 Expect(Token::LBRACE, CHECK_OK); |
2039 InitializationBlockFinder block_finder(top_scope_, target_stack_); | |
2040 while (peek() != Token::RBRACE) { | 1907 while (peek() != Token::RBRACE) { |
2041 Statement* stat = ParseStatement(NULL, CHECK_OK); | 1908 Statement* stat = ParseStatement(NULL, CHECK_OK); |
2042 if (stat && !stat->IsEmpty()) { | 1909 if (stat && !stat->IsEmpty()) { |
2043 result->AddStatement(stat, zone()); | 1910 result->AddStatement(stat, zone()); |
2044 block_finder.Update(stat); | |
2045 } | 1911 } |
2046 } | 1912 } |
2047 Expect(Token::RBRACE, CHECK_OK); | 1913 Expect(Token::RBRACE, CHECK_OK); |
2048 return result; | 1914 return result; |
2049 } | 1915 } |
2050 | 1916 |
2051 | 1917 |
2052 Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { | 1918 Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { |
2053 // The harmony mode uses block elements instead of statements. | 1919 // The harmony mode uses block elements instead of statements. |
2054 // | 1920 // |
2055 // Block :: | 1921 // Block :: |
2056 // '{' BlockElement* '}' | 1922 // '{' BlockElement* '}' |
2057 | 1923 |
2058 // Construct block expecting 16 statements. | 1924 // Construct block expecting 16 statements. |
2059 Block* body = factory()->NewBlock(labels, 16, false); | 1925 Block* body = factory()->NewBlock(labels, 16, false); |
2060 Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE); | 1926 Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE); |
2061 | 1927 |
2062 // Parse the statements and collect escaping labels. | 1928 // Parse the statements and collect escaping labels. |
2063 Expect(Token::LBRACE, CHECK_OK); | 1929 Expect(Token::LBRACE, CHECK_OK); |
2064 block_scope->set_start_position(scanner().location().beg_pos); | 1930 block_scope->set_start_position(scanner().location().beg_pos); |
2065 { BlockState block_state(this, block_scope); | 1931 { BlockState block_state(this, block_scope); |
2066 TargetCollector collector(zone()); | 1932 TargetCollector collector(zone()); |
2067 Target target(&this->target_stack_, &collector); | 1933 Target target(&this->target_stack_, &collector); |
2068 Target target_body(&this->target_stack_, body); | 1934 Target target_body(&this->target_stack_, body); |
2069 InitializationBlockFinder block_finder(top_scope_, target_stack_); | |
2070 | 1935 |
2071 while (peek() != Token::RBRACE) { | 1936 while (peek() != Token::RBRACE) { |
2072 Statement* stat = ParseBlockElement(NULL, CHECK_OK); | 1937 Statement* stat = ParseBlockElement(NULL, CHECK_OK); |
2073 if (stat && !stat->IsEmpty()) { | 1938 if (stat && !stat->IsEmpty()) { |
2074 body->AddStatement(stat, zone()); | 1939 body->AddStatement(stat, zone()); |
2075 block_finder.Update(stat); | |
2076 } | 1940 } |
2077 } | 1941 } |
2078 } | 1942 } |
2079 Expect(Token::RBRACE, CHECK_OK); | 1943 Expect(Token::RBRACE, CHECK_OK); |
2080 block_scope->set_end_position(scanner().location().end_pos); | 1944 block_scope->set_end_position(scanner().location().end_pos); |
2081 block_scope = block_scope->FinalizeBlockScope(); | 1945 block_scope = block_scope->FinalizeBlockScope(); |
2082 body->set_scope(block_scope); | 1946 body->set_scope(block_scope); |
2083 return body; | 1947 return body; |
2084 } | 1948 } |
2085 | 1949 |
(...skipping 4018 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6104 ASSERT(info->isolate()->has_pending_exception()); | 5968 ASSERT(info->isolate()->has_pending_exception()); |
6105 } else { | 5969 } else { |
6106 result = parser.ParseProgram(); | 5970 result = parser.ParseProgram(); |
6107 } | 5971 } |
6108 } | 5972 } |
6109 info->SetFunction(result); | 5973 info->SetFunction(result); |
6110 return (result != NULL); | 5974 return (result != NULL); |
6111 } | 5975 } |
6112 | 5976 |
6113 } } // namespace v8::internal | 5977 } } // namespace v8::internal |
OLD | NEW |