| 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  | 
|   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  Loading... | 
|  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  Loading... | 
|  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  Loading... | 
|  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  Loading... | 
|  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  Loading... | 
|  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 | 
| OLD | NEW |