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

Side by Side Diff: src/parser.cc

Issue 11035053: Rollback trunk to bleeding_edge revision 12525 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
Patch Set: Created 8 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « src/parser.h ('k') | src/runtime.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
835 // A ThisNamedPropertyAssignmentFinder finds and marks statements of the form 970 // A ThisNamedPropertyAssignmentFinder finds and marks statements of the form
836 // this.x = ...;, where x is a named property. It also determines whether a 971 // this.x = ...;, where x is a named property. It also determines whether a
837 // function contains only assignments of this type. 972 // function contains only assignments of this type.
838 class ThisNamedPropertyAssignmentFinder { 973 class ThisNamedPropertyAssignmentFinder : public ParserFinder {
839 public: 974 public:
840 ThisNamedPropertyAssignmentFinder(Isolate* isolate, Zone* zone) 975 ThisNamedPropertyAssignmentFinder(Isolate* isolate, Zone* zone)
841 : isolate_(isolate), 976 : isolate_(isolate),
842 only_simple_this_property_assignments_(true), 977 only_simple_this_property_assignments_(true),
843 names_(0, zone), 978 names_(0, zone),
844 assigned_arguments_(0, zone), 979 assigned_arguments_(0, zone),
845 assigned_constants_(0, zone), 980 assigned_constants_(0, zone),
846 zone_(zone) { 981 zone_(zone) {
847 } 982 }
848 983
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
856 void Update(Scope* scope, Statement* stat) { 984 void Update(Scope* scope, Statement* stat) {
857 // Bail out if function already has property assignment that are 985 // Bail out if function already has property assignment that are
858 // not simple this property assignments. 986 // not simple this property assignments.
859 if (!only_simple_this_property_assignments_) { 987 if (!only_simple_this_property_assignments_) {
860 return; 988 return;
861 } 989 }
862 990
863 // Check whether this statement is of the form this.x = ...; 991 // Check whether this statement is of the form this.x = ...;
864 Assignment* assignment = AsAssignment(stat); 992 Assignment* assignment = AsAssignment(stat);
865 if (IsThisPropertyAssignment(assignment)) { 993 if (IsThisPropertyAssignment(assignment)) {
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 // SourceElements :: 1139 // SourceElements ::
1012 // (ModuleElement)* <end_token> 1140 // (ModuleElement)* <end_token>
1013 1141
1014 // Allocate a target stack to use for this set of source 1142 // Allocate a target stack to use for this set of source
1015 // elements. This way, all scripts and functions get their own 1143 // elements. This way, all scripts and functions get their own
1016 // target stack thus avoiding illegal breaks and continues across 1144 // target stack thus avoiding illegal breaks and continues across
1017 // functions. 1145 // functions.
1018 TargetScope scope(&this->target_stack_); 1146 TargetScope scope(&this->target_stack_);
1019 1147
1020 ASSERT(processor != NULL); 1148 ASSERT(processor != NULL);
1149 InitializationBlockFinder block_finder(top_scope_, target_stack_);
1021 ThisNamedPropertyAssignmentFinder this_property_assignment_finder(isolate(), 1150 ThisNamedPropertyAssignmentFinder this_property_assignment_finder(isolate(),
1022 zone()); 1151 zone());
1023 bool directive_prologue = true; // Parsing directive prologue. 1152 bool directive_prologue = true; // Parsing directive prologue.
1024 1153
1025 while (peek() != end_token) { 1154 while (peek() != end_token) {
1026 if (directive_prologue && peek() != Token::STRING) { 1155 if (directive_prologue && peek() != Token::STRING) {
1027 directive_prologue = false; 1156 directive_prologue = false;
1028 } 1157 }
1029 1158
1030 Scanner::Location token_loc = scanner().peek_location(); 1159 Scanner::Location token_loc = scanner().peek_location();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1065 ? EXTENDED_MODE : STRICT_MODE); 1194 ? EXTENDED_MODE : STRICT_MODE);
1066 // "use strict" is the only directive for now. 1195 // "use strict" is the only directive for now.
1067 directive_prologue = false; 1196 directive_prologue = false;
1068 } 1197 }
1069 } else { 1198 } else {
1070 // End of the directive prologue. 1199 // End of the directive prologue.
1071 directive_prologue = false; 1200 directive_prologue = false;
1072 } 1201 }
1073 } 1202 }
1074 1203
1204 block_finder.Update(stat);
1075 // Find and mark all assignments to named properties in this (this.x =) 1205 // Find and mark all assignments to named properties in this (this.x =)
1076 if (top_scope_->is_function_scope()) { 1206 if (top_scope_->is_function_scope()) {
1077 this_property_assignment_finder.Update(top_scope_, stat); 1207 this_property_assignment_finder.Update(top_scope_, stat);
1078 } 1208 }
1079 processor->Add(stat, zone()); 1209 processor->Add(stat, zone());
1080 } 1210 }
1081 1211
1082 // Propagate the collected information on this property assignments. 1212 // Propagate the collected information on this property assignments.
1083 if (top_scope_->is_function_scope()) { 1213 if (top_scope_->is_function_scope()) {
1084 bool only_simple_this_property_assignments = 1214 bool only_simple_this_property_assignments =
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1217 1347
1218 Expect(Token::LBRACE, CHECK_OK); 1348 Expect(Token::LBRACE, CHECK_OK);
1219 scope->set_start_position(scanner().location().beg_pos); 1349 scope->set_start_position(scanner().location().beg_pos);
1220 scope->SetLanguageMode(EXTENDED_MODE); 1350 scope->SetLanguageMode(EXTENDED_MODE);
1221 1351
1222 { 1352 {
1223 BlockState block_state(this, scope); 1353 BlockState block_state(this, scope);
1224 TargetCollector collector(zone()); 1354 TargetCollector collector(zone());
1225 Target target(&this->target_stack_, &collector); 1355 Target target(&this->target_stack_, &collector);
1226 Target target_body(&this->target_stack_, body); 1356 Target target_body(&this->target_stack_, body);
1357 InitializationBlockFinder block_finder(top_scope_, target_stack_);
1227 1358
1228 while (peek() != Token::RBRACE) { 1359 while (peek() != Token::RBRACE) {
1229 Statement* stat = ParseModuleElement(NULL, CHECK_OK); 1360 Statement* stat = ParseModuleElement(NULL, CHECK_OK);
1230 if (stat && !stat->IsEmpty()) { 1361 if (stat && !stat->IsEmpty()) {
1231 body->AddStatement(stat, zone()); 1362 body->AddStatement(stat, zone());
1363 block_finder.Update(stat);
1232 } 1364 }
1233 } 1365 }
1234 } 1366 }
1235 1367
1236 Expect(Token::RBRACE, CHECK_OK); 1368 Expect(Token::RBRACE, CHECK_OK);
1237 scope->set_end_position(scanner().location().end_pos); 1369 scope->set_end_position(scanner().location().end_pos);
1238 body->set_scope(scope); 1370 body->set_scope(scope);
1239 1371
1240 // Check that all exports are bound. 1372 // Check that all exports are bound.
1241 Interface* interface = scope->interface(); 1373 Interface* interface = scope->interface();
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after
1897 // Block :: 2029 // Block ::
1898 // '{' Statement* '}' 2030 // '{' Statement* '}'
1899 2031
1900 // Note that a Block does not introduce a new execution scope! 2032 // Note that a Block does not introduce a new execution scope!
1901 // (ECMA-262, 3rd, 12.2) 2033 // (ECMA-262, 3rd, 12.2)
1902 // 2034 //
1903 // Construct block expecting 16 statements. 2035 // Construct block expecting 16 statements.
1904 Block* result = factory()->NewBlock(labels, 16, false); 2036 Block* result = factory()->NewBlock(labels, 16, false);
1905 Target target(&this->target_stack_, result); 2037 Target target(&this->target_stack_, result);
1906 Expect(Token::LBRACE, CHECK_OK); 2038 Expect(Token::LBRACE, CHECK_OK);
2039 InitializationBlockFinder block_finder(top_scope_, target_stack_);
1907 while (peek() != Token::RBRACE) { 2040 while (peek() != Token::RBRACE) {
1908 Statement* stat = ParseStatement(NULL, CHECK_OK); 2041 Statement* stat = ParseStatement(NULL, CHECK_OK);
1909 if (stat && !stat->IsEmpty()) { 2042 if (stat && !stat->IsEmpty()) {
1910 result->AddStatement(stat, zone()); 2043 result->AddStatement(stat, zone());
2044 block_finder.Update(stat);
1911 } 2045 }
1912 } 2046 }
1913 Expect(Token::RBRACE, CHECK_OK); 2047 Expect(Token::RBRACE, CHECK_OK);
1914 return result; 2048 return result;
1915 } 2049 }
1916 2050
1917 2051
1918 Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { 2052 Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
1919 // The harmony mode uses block elements instead of statements. 2053 // The harmony mode uses block elements instead of statements.
1920 // 2054 //
1921 // Block :: 2055 // Block ::
1922 // '{' BlockElement* '}' 2056 // '{' BlockElement* '}'
1923 2057
1924 // Construct block expecting 16 statements. 2058 // Construct block expecting 16 statements.
1925 Block* body = factory()->NewBlock(labels, 16, false); 2059 Block* body = factory()->NewBlock(labels, 16, false);
1926 Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE); 2060 Scope* block_scope = NewScope(top_scope_, BLOCK_SCOPE);
1927 2061
1928 // Parse the statements and collect escaping labels. 2062 // Parse the statements and collect escaping labels.
1929 Expect(Token::LBRACE, CHECK_OK); 2063 Expect(Token::LBRACE, CHECK_OK);
1930 block_scope->set_start_position(scanner().location().beg_pos); 2064 block_scope->set_start_position(scanner().location().beg_pos);
1931 { BlockState block_state(this, block_scope); 2065 { BlockState block_state(this, block_scope);
1932 TargetCollector collector(zone()); 2066 TargetCollector collector(zone());
1933 Target target(&this->target_stack_, &collector); 2067 Target target(&this->target_stack_, &collector);
1934 Target target_body(&this->target_stack_, body); 2068 Target target_body(&this->target_stack_, body);
2069 InitializationBlockFinder block_finder(top_scope_, target_stack_);
1935 2070
1936 while (peek() != Token::RBRACE) { 2071 while (peek() != Token::RBRACE) {
1937 Statement* stat = ParseBlockElement(NULL, CHECK_OK); 2072 Statement* stat = ParseBlockElement(NULL, CHECK_OK);
1938 if (stat && !stat->IsEmpty()) { 2073 if (stat && !stat->IsEmpty()) {
1939 body->AddStatement(stat, zone()); 2074 body->AddStatement(stat, zone());
2075 block_finder.Update(stat);
1940 } 2076 }
1941 } 2077 }
1942 } 2078 }
1943 Expect(Token::RBRACE, CHECK_OK); 2079 Expect(Token::RBRACE, CHECK_OK);
1944 block_scope->set_end_position(scanner().location().end_pos); 2080 block_scope->set_end_position(scanner().location().end_pos);
1945 block_scope = block_scope->FinalizeBlockScope(); 2081 block_scope = block_scope->FinalizeBlockScope();
1946 body->set_scope(block_scope); 2082 body->set_scope(block_scope);
1947 return body; 2083 return body;
1948 } 2084 }
1949 2085
(...skipping 4018 matching lines...) Expand 10 before | Expand all | Expand 10 after
5968 ASSERT(info->isolate()->has_pending_exception()); 6104 ASSERT(info->isolate()->has_pending_exception());
5969 } else { 6105 } else {
5970 result = parser.ParseProgram(); 6106 result = parser.ParseProgram();
5971 } 6107 }
5972 } 6108 }
5973 info->SetFunction(result); 6109 info->SetFunction(result);
5974 return (result != NULL); 6110 return (result != NULL);
5975 } 6111 }
5976 6112
5977 } } // namespace v8::internal 6113 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698