| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/ast.h" | 8 #include "src/ast.h" |
| 9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
| 10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 | 322 |
| 323 | 323 |
| 324 // ---------------------------------------------------------------------------- | 324 // ---------------------------------------------------------------------------- |
| 325 // Target is a support class to facilitate manipulation of the | 325 // Target is a support class to facilitate manipulation of the |
| 326 // Parser's target_stack_ (the stack of potential 'break' and | 326 // Parser's target_stack_ (the stack of potential 'break' and |
| 327 // 'continue' statement targets). Upon construction, a new target is | 327 // 'continue' statement targets). Upon construction, a new target is |
| 328 // added; it is removed upon destruction. | 328 // added; it is removed upon destruction. |
| 329 | 329 |
| 330 class Target BASE_EMBEDDED { | 330 class Target BASE_EMBEDDED { |
| 331 public: | 331 public: |
| 332 Target(Target** variable, AstNode* node) | 332 Target(Target** variable, BreakableStatement* statement) |
| 333 : variable_(variable), node_(node), previous_(*variable) { | 333 : variable_(variable), statement_(statement), previous_(*variable) { |
| 334 *variable = this; | 334 *variable = this; |
| 335 } | 335 } |
| 336 | 336 |
| 337 ~Target() { | 337 ~Target() { |
| 338 *variable_ = previous_; | 338 *variable_ = previous_; |
| 339 } | 339 } |
| 340 | 340 |
| 341 Target* previous() { return previous_; } | 341 Target* previous() { return previous_; } |
| 342 AstNode* node() { return node_; } | 342 BreakableStatement* statement() { return statement_; } |
| 343 | 343 |
| 344 private: | 344 private: |
| 345 Target** variable_; | 345 Target** variable_; |
| 346 AstNode* node_; | 346 BreakableStatement* statement_; |
| 347 Target* previous_; | 347 Target* previous_; |
| 348 }; | 348 }; |
| 349 | 349 |
| 350 | 350 |
| 351 class TargetScope BASE_EMBEDDED { | 351 class TargetScope BASE_EMBEDDED { |
| 352 public: | 352 public: |
| 353 explicit TargetScope(Target** variable) | 353 explicit TargetScope(Target** variable) |
| 354 : variable_(variable), previous_(*variable) { | 354 : variable_(variable), previous_(*variable) { |
| 355 *variable = NULL; | 355 *variable = NULL; |
| 356 } | 356 } |
| (...skipping 939 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1296 if (FLAG_print_interface_details) PrintF("# Literal "); | 1296 if (FLAG_print_interface_details) PrintF("# Literal "); |
| 1297 #endif | 1297 #endif |
| 1298 Scope* scope = NewScope(scope_, MODULE_SCOPE); | 1298 Scope* scope = NewScope(scope_, MODULE_SCOPE); |
| 1299 | 1299 |
| 1300 Expect(Token::LBRACE, CHECK_OK); | 1300 Expect(Token::LBRACE, CHECK_OK); |
| 1301 scope->set_start_position(scanner()->location().beg_pos); | 1301 scope->set_start_position(scanner()->location().beg_pos); |
| 1302 scope->SetStrictMode(STRICT); | 1302 scope->SetStrictMode(STRICT); |
| 1303 | 1303 |
| 1304 { | 1304 { |
| 1305 BlockState block_state(&scope_, scope); | 1305 BlockState block_state(&scope_, scope); |
| 1306 TargetCollector collector(zone()); | 1306 Target target(&this->target_stack_, body); |
| 1307 Target target(&this->target_stack_, &collector); | |
| 1308 Target target_body(&this->target_stack_, body); | |
| 1309 | 1307 |
| 1310 while (peek() != Token::RBRACE) { | 1308 while (peek() != Token::RBRACE) { |
| 1311 Statement* stat = ParseModuleElement(NULL, CHECK_OK); | 1309 Statement* stat = ParseModuleElement(NULL, CHECK_OK); |
| 1312 if (stat && !stat->IsEmpty()) { | 1310 if (stat && !stat->IsEmpty()) { |
| 1313 body->AddStatement(stat, zone()); | 1311 body->AddStatement(stat, zone()); |
| 1314 } | 1312 } |
| 1315 } | 1313 } |
| 1316 } | 1314 } |
| 1317 | 1315 |
| 1318 Expect(Token::RBRACE, CHECK_OK); | 1316 Expect(Token::RBRACE, CHECK_OK); |
| (...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2057 | 2055 |
| 2058 // Construct block expecting 16 statements. | 2056 // Construct block expecting 16 statements. |
| 2059 Block* body = | 2057 Block* body = |
| 2060 factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition); | 2058 factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition); |
| 2061 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); | 2059 Scope* block_scope = NewScope(scope_, BLOCK_SCOPE); |
| 2062 | 2060 |
| 2063 // Parse the statements and collect escaping labels. | 2061 // Parse the statements and collect escaping labels. |
| 2064 Expect(Token::LBRACE, CHECK_OK); | 2062 Expect(Token::LBRACE, CHECK_OK); |
| 2065 block_scope->set_start_position(scanner()->location().beg_pos); | 2063 block_scope->set_start_position(scanner()->location().beg_pos); |
| 2066 { BlockState block_state(&scope_, block_scope); | 2064 { BlockState block_state(&scope_, block_scope); |
| 2067 TargetCollector collector(zone()); | 2065 Target target(&this->target_stack_, body); |
| 2068 Target target(&this->target_stack_, &collector); | |
| 2069 Target target_body(&this->target_stack_, body); | |
| 2070 | 2066 |
| 2071 while (peek() != Token::RBRACE) { | 2067 while (peek() != Token::RBRACE) { |
| 2072 Statement* stat = ParseBlockElement(NULL, CHECK_OK); | 2068 Statement* stat = ParseBlockElement(NULL, CHECK_OK); |
| 2073 if (stat && !stat->IsEmpty()) { | 2069 if (stat && !stat->IsEmpty()) { |
| 2074 body->AddStatement(stat, zone()); | 2070 body->AddStatement(stat, zone()); |
| 2075 } | 2071 } |
| 2076 } | 2072 } |
| 2077 } | 2073 } |
| 2078 Expect(Token::RBRACE, CHECK_OK); | 2074 Expect(Token::RBRACE, CHECK_OK); |
| 2079 block_scope->set_end_position(scanner()->location().end_pos); | 2075 block_scope->set_end_position(scanner()->location().end_pos); |
| (...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2755 // | 2751 // |
| 2756 // Catch :: | 2752 // Catch :: |
| 2757 // 'catch' '(' Identifier ')' Block | 2753 // 'catch' '(' Identifier ')' Block |
| 2758 // | 2754 // |
| 2759 // Finally :: | 2755 // Finally :: |
| 2760 // 'finally' Block | 2756 // 'finally' Block |
| 2761 | 2757 |
| 2762 Expect(Token::TRY, CHECK_OK); | 2758 Expect(Token::TRY, CHECK_OK); |
| 2763 int pos = position(); | 2759 int pos = position(); |
| 2764 | 2760 |
| 2765 TargetCollector try_collector(zone()); | 2761 Block* try_block = ParseBlock(NULL, CHECK_OK); |
| 2766 Block* try_block; | |
| 2767 | |
| 2768 { Target target(&this->target_stack_, &try_collector); | |
| 2769 try_block = ParseBlock(NULL, CHECK_OK); | |
| 2770 } | |
| 2771 | 2762 |
| 2772 Token::Value tok = peek(); | 2763 Token::Value tok = peek(); |
| 2773 if (tok != Token::CATCH && tok != Token::FINALLY) { | 2764 if (tok != Token::CATCH && tok != Token::FINALLY) { |
| 2774 ReportMessage("no_catch_or_finally"); | 2765 ReportMessage("no_catch_or_finally"); |
| 2775 *ok = false; | 2766 *ok = false; |
| 2776 return NULL; | 2767 return NULL; |
| 2777 } | 2768 } |
| 2778 | 2769 |
| 2779 // If we can break out from the catch block and there is a finally block, | |
| 2780 // then we will need to collect escaping targets from the catch | |
| 2781 // block. Since we don't know yet if there will be a finally block, we | |
| 2782 // always collect the targets. | |
| 2783 TargetCollector catch_collector(zone()); | |
| 2784 Scope* catch_scope = NULL; | 2770 Scope* catch_scope = NULL; |
| 2785 Variable* catch_variable = NULL; | 2771 Variable* catch_variable = NULL; |
| 2786 Block* catch_block = NULL; | 2772 Block* catch_block = NULL; |
| 2787 const AstRawString* name = NULL; | 2773 const AstRawString* name = NULL; |
| 2788 if (tok == Token::CATCH) { | 2774 if (tok == Token::CATCH) { |
| 2789 Consume(Token::CATCH); | 2775 Consume(Token::CATCH); |
| 2790 | 2776 |
| 2791 Expect(Token::LPAREN, CHECK_OK); | 2777 Expect(Token::LPAREN, CHECK_OK); |
| 2792 catch_scope = NewScope(scope_, CATCH_SCOPE); | 2778 catch_scope = NewScope(scope_, CATCH_SCOPE); |
| 2793 catch_scope->set_start_position(scanner()->location().beg_pos); | 2779 catch_scope->set_start_position(scanner()->location().beg_pos); |
| 2794 name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); | 2780 name = ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); |
| 2795 | 2781 |
| 2796 Expect(Token::RPAREN, CHECK_OK); | 2782 Expect(Token::RPAREN, CHECK_OK); |
| 2797 | 2783 |
| 2798 Target target(&this->target_stack_, &catch_collector); | |
| 2799 catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized); | 2784 catch_variable = catch_scope->DeclareLocal(name, VAR, kCreatedInitialized); |
| 2800 BlockState block_state(&scope_, catch_scope); | 2785 BlockState block_state(&scope_, catch_scope); |
| 2801 catch_block = ParseBlock(NULL, CHECK_OK); | 2786 catch_block = ParseBlock(NULL, CHECK_OK); |
| 2802 | 2787 |
| 2803 catch_scope->set_end_position(scanner()->location().end_pos); | 2788 catch_scope->set_end_position(scanner()->location().end_pos); |
| 2804 tok = peek(); | 2789 tok = peek(); |
| 2805 } | 2790 } |
| 2806 | 2791 |
| 2807 Block* finally_block = NULL; | 2792 Block* finally_block = NULL; |
| 2808 DCHECK(tok == Token::FINALLY || catch_block != NULL); | 2793 DCHECK(tok == Token::FINALLY || catch_block != NULL); |
| 2809 if (tok == Token::FINALLY) { | 2794 if (tok == Token::FINALLY) { |
| 2810 Consume(Token::FINALLY); | 2795 Consume(Token::FINALLY); |
| 2811 finally_block = ParseBlock(NULL, CHECK_OK); | 2796 finally_block = ParseBlock(NULL, CHECK_OK); |
| 2812 } | 2797 } |
| 2813 | 2798 |
| 2814 // Simplify the AST nodes by converting: | 2799 // Simplify the AST nodes by converting: |
| 2815 // 'try B0 catch B1 finally B2' | 2800 // 'try B0 catch B1 finally B2' |
| 2816 // to: | 2801 // to: |
| 2817 // 'try { try B0 catch B1 } finally B2' | 2802 // 'try { try B0 catch B1 } finally B2' |
| 2818 | 2803 |
| 2819 if (catch_block != NULL && finally_block != NULL) { | 2804 if (catch_block != NULL && finally_block != NULL) { |
| 2820 // If we have both, create an inner try/catch. | 2805 // If we have both, create an inner try/catch. |
| 2821 DCHECK(catch_scope != NULL && catch_variable != NULL); | 2806 DCHECK(catch_scope != NULL && catch_variable != NULL); |
| 2822 int index = function_state_->NextHandlerIndex(); | 2807 int index = function_state_->NextHandlerIndex(); |
| 2823 TryCatchStatement* statement = factory()->NewTryCatchStatement( | 2808 TryCatchStatement* statement = factory()->NewTryCatchStatement( |
| 2824 index, try_block, catch_scope, catch_variable, catch_block, | 2809 index, try_block, catch_scope, catch_variable, catch_block, |
| 2825 RelocInfo::kNoPosition); | 2810 RelocInfo::kNoPosition); |
| 2826 statement->set_escaping_targets(try_collector.targets()); | |
| 2827 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); | 2811 try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition); |
| 2828 try_block->AddStatement(statement, zone()); | 2812 try_block->AddStatement(statement, zone()); |
| 2829 catch_block = NULL; // Clear to indicate it's been handled. | 2813 catch_block = NULL; // Clear to indicate it's been handled. |
| 2830 } | 2814 } |
| 2831 | 2815 |
| 2832 TryStatement* result = NULL; | 2816 TryStatement* result = NULL; |
| 2833 if (catch_block != NULL) { | 2817 if (catch_block != NULL) { |
| 2834 DCHECK(finally_block == NULL); | 2818 DCHECK(finally_block == NULL); |
| 2835 DCHECK(catch_scope != NULL && catch_variable != NULL); | 2819 DCHECK(catch_scope != NULL && catch_variable != NULL); |
| 2836 int index = function_state_->NextHandlerIndex(); | 2820 int index = function_state_->NextHandlerIndex(); |
| 2837 result = factory()->NewTryCatchStatement( | 2821 result = factory()->NewTryCatchStatement( |
| 2838 index, try_block, catch_scope, catch_variable, catch_block, pos); | 2822 index, try_block, catch_scope, catch_variable, catch_block, pos); |
| 2839 } else { | 2823 } else { |
| 2840 DCHECK(finally_block != NULL); | 2824 DCHECK(finally_block != NULL); |
| 2841 int index = function_state_->NextHandlerIndex(); | 2825 int index = function_state_->NextHandlerIndex(); |
| 2842 result = factory()->NewTryFinallyStatement( | 2826 result = factory()->NewTryFinallyStatement( |
| 2843 index, try_block, finally_block, pos); | 2827 index, try_block, finally_block, pos); |
| 2844 // Combine the jump targets of the try block and the possible catch block. | |
| 2845 try_collector.targets()->AddAll(*catch_collector.targets(), zone()); | |
| 2846 } | 2828 } |
| 2847 | 2829 |
| 2848 result->set_escaping_targets(try_collector.targets()); | |
| 2849 return result; | 2830 return result; |
| 2850 } | 2831 } |
| 2851 | 2832 |
| 2852 | 2833 |
| 2853 DoWhileStatement* Parser::ParseDoWhileStatement( | 2834 DoWhileStatement* Parser::ParseDoWhileStatement( |
| 2854 ZoneList<const AstRawString*>* labels, bool* ok) { | 2835 ZoneList<const AstRawString*>* labels, bool* ok) { |
| 2855 // DoStatement :: | 2836 // DoStatement :: |
| 2856 // 'do' Statement 'while' '(' Expression ')' ';' | 2837 // 'do' Statement 'while' '(' Expression ')' ';' |
| 2857 | 2838 |
| 2858 DoWhileStatement* loop = | 2839 DoWhileStatement* loop = |
| (...skipping 1287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4146 } | 4127 } |
| 4147 } | 4128 } |
| 4148 | 4129 |
| 4149 | 4130 |
| 4150 // ---------------------------------------------------------------------------- | 4131 // ---------------------------------------------------------------------------- |
| 4151 // Parser support | 4132 // Parser support |
| 4152 | 4133 |
| 4153 | 4134 |
| 4154 bool Parser::TargetStackContainsLabel(const AstRawString* label) { | 4135 bool Parser::TargetStackContainsLabel(const AstRawString* label) { |
| 4155 for (Target* t = target_stack_; t != NULL; t = t->previous()) { | 4136 for (Target* t = target_stack_; t != NULL; t = t->previous()) { |
| 4156 BreakableStatement* stat = t->node()->AsBreakableStatement(); | 4137 if (ContainsLabel(t->statement()->labels(), label)) return true; |
| 4157 if (stat != NULL && ContainsLabel(stat->labels(), label)) | |
| 4158 return true; | |
| 4159 } | 4138 } |
| 4160 return false; | 4139 return false; |
| 4161 } | 4140 } |
| 4162 | 4141 |
| 4163 | 4142 |
| 4164 BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label, | 4143 BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label, |
| 4165 bool* ok) { | 4144 bool* ok) { |
| 4166 bool anonymous = label == NULL; | 4145 bool anonymous = label == NULL; |
| 4167 for (Target* t = target_stack_; t != NULL; t = t->previous()) { | 4146 for (Target* t = target_stack_; t != NULL; t = t->previous()) { |
| 4168 BreakableStatement* stat = t->node()->AsBreakableStatement(); | 4147 BreakableStatement* stat = t->statement(); |
| 4169 if (stat == NULL) continue; | |
| 4170 if ((anonymous && stat->is_target_for_anonymous()) || | 4148 if ((anonymous && stat->is_target_for_anonymous()) || |
| 4171 (!anonymous && ContainsLabel(stat->labels(), label))) { | 4149 (!anonymous && ContainsLabel(stat->labels(), label))) { |
| 4172 RegisterTargetUse(stat->break_target(), t->previous()); | |
| 4173 return stat; | 4150 return stat; |
| 4174 } | 4151 } |
| 4175 } | 4152 } |
| 4176 return NULL; | 4153 return NULL; |
| 4177 } | 4154 } |
| 4178 | 4155 |
| 4179 | 4156 |
| 4180 IterationStatement* Parser::LookupContinueTarget(const AstRawString* label, | 4157 IterationStatement* Parser::LookupContinueTarget(const AstRawString* label, |
| 4181 bool* ok) { | 4158 bool* ok) { |
| 4182 bool anonymous = label == NULL; | 4159 bool anonymous = label == NULL; |
| 4183 for (Target* t = target_stack_; t != NULL; t = t->previous()) { | 4160 for (Target* t = target_stack_; t != NULL; t = t->previous()) { |
| 4184 IterationStatement* stat = t->node()->AsIterationStatement(); | 4161 IterationStatement* stat = t->statement()->AsIterationStatement(); |
| 4185 if (stat == NULL) continue; | 4162 if (stat == NULL) continue; |
| 4186 | 4163 |
| 4187 DCHECK(stat->is_target_for_anonymous()); | 4164 DCHECK(stat->is_target_for_anonymous()); |
| 4188 if (anonymous || ContainsLabel(stat->labels(), label)) { | 4165 if (anonymous || ContainsLabel(stat->labels(), label)) { |
| 4189 RegisterTargetUse(stat->continue_target(), t->previous()); | |
| 4190 return stat; | 4166 return stat; |
| 4191 } | 4167 } |
| 4192 } | 4168 } |
| 4193 return NULL; | 4169 return NULL; |
| 4194 } | 4170 } |
| 4195 | 4171 |
| 4196 | 4172 |
| 4197 void Parser::RegisterTargetUse(Label* target, Target* stop) { | |
| 4198 // Register that a break target found at the given stop in the | |
| 4199 // target stack has been used from the top of the target stack. Add | |
| 4200 // the break target to any TargetCollectors passed on the stack. | |
| 4201 for (Target* t = target_stack_; t != stop; t = t->previous()) { | |
| 4202 TargetCollector* collector = t->node()->AsTargetCollector(); | |
| 4203 if (collector != NULL) collector->AddTarget(target, zone()); | |
| 4204 } | |
| 4205 } | |
| 4206 | |
| 4207 | |
| 4208 void Parser::HandleSourceURLComments() { | 4173 void Parser::HandleSourceURLComments() { |
| 4209 if (scanner_.source_url()->length() > 0) { | 4174 if (scanner_.source_url()->length() > 0) { |
| 4210 Handle<String> source_url = scanner_.source_url()->Internalize(isolate()); | 4175 Handle<String> source_url = scanner_.source_url()->Internalize(isolate()); |
| 4211 info_->script()->set_source_url(*source_url); | 4176 info_->script()->set_source_url(*source_url); |
| 4212 } | 4177 } |
| 4213 if (scanner_.source_mapping_url()->length() > 0) { | 4178 if (scanner_.source_mapping_url()->length() > 0) { |
| 4214 Handle<String> source_mapping_url = | 4179 Handle<String> source_mapping_url = |
| 4215 scanner_.source_mapping_url()->Internalize(isolate()); | 4180 scanner_.source_mapping_url()->Internalize(isolate()); |
| 4216 info_->script()->set_source_mapping_url(*source_mapping_url); | 4181 info_->script()->set_source_mapping_url(*source_mapping_url); |
| 4217 } | 4182 } |
| (...skipping 1152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5370 } else { | 5335 } else { |
| 5371 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); | 5336 const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data()); |
| 5372 running_hash = StringHasher::ComputeRunningHash(running_hash, data, | 5337 running_hash = StringHasher::ComputeRunningHash(running_hash, data, |
| 5373 raw_string->length()); | 5338 raw_string->length()); |
| 5374 } | 5339 } |
| 5375 } | 5340 } |
| 5376 | 5341 |
| 5377 return running_hash; | 5342 return running_hash; |
| 5378 } | 5343 } |
| 5379 } } // namespace v8::internal | 5344 } } // namespace v8::internal |
| OLD | NEW |