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 |