| 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 | 
|---|