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

Side by Side Diff: runtime/vm/parser.cc

Issue 2030763002: Fix finally clause inlining for forward jumps (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 6 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
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/scopes.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 (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/parser.h" 5 #include "vm/parser.h"
6 #include "vm/flags.h" 6 #include "vm/flags.h"
7 7
8 #ifndef DART_PRECOMPILED_RUNTIME 8 #ifndef DART_PRECOMPILED_RUNTIME
9 9
10 #include "lib/invocation_mirror.h" 10 #include "lib/invocation_mirror.h"
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 TryStack* outer_try() const { return outer_try_; } 358 TryStack* outer_try() const { return outer_try_; }
359 Block* try_block() const { return try_block_; } 359 Block* try_block() const { return try_block_; }
360 intptr_t try_index() const { return try_index_; } 360 intptr_t try_index() const { return try_index_; }
361 bool inside_catch() const { return inside_catch_; } 361 bool inside_catch() const { return inside_catch_; }
362 void enter_catch() { inside_catch_ = true; } 362 void enter_catch() { inside_catch_ = true; }
363 bool inside_finally() const { return inside_finally_; } 363 bool inside_finally() const { return inside_finally_; }
364 void enter_finally() { inside_finally_ = true; } 364 void enter_finally() { inside_finally_ = true; }
365 void exit_finally() { inside_finally_ = false; } 365 void exit_finally() { inside_finally_ = false; }
366 366
367 void AddNodeForFinallyInlining(AstNode* node); 367 void AddNodeForFinallyInlining(AstNode* node);
368 void RemoveJumpToLabel(SourceLabel *label);
368 AstNode* GetNodeToInlineFinally(int index) { 369 AstNode* GetNodeToInlineFinally(int index) {
369 if (0 <= index && index < inlined_finally_nodes_.length()) { 370 if (0 <= index && index < inlined_finally_nodes_.length()) {
370 return inlined_finally_nodes_[index]; 371 return inlined_finally_nodes_[index];
371 } 372 }
372 return NULL; 373 return NULL;
373 } 374 }
374 375
375 private: 376 private:
376 Block* try_block_; 377 Block* try_block_;
377 GrowableArray<AstNode*> inlined_finally_nodes_; 378 GrowableArray<AstNode*> inlined_finally_nodes_;
378 TryStack* outer_try_; 379 TryStack* outer_try_;
379 const intptr_t try_index_; 380 const intptr_t try_index_;
380 bool inside_catch_; // True when parsing a catch clause of this try. 381 bool inside_catch_; // True when parsing a catch clause of this try.
381 bool inside_finally_; // True when parsing a finally clause of an inner try 382 bool inside_finally_; // True when parsing a finally clause of an inner try
382 // of this try. 383 // of this try.
383 384
384 DISALLOW_COPY_AND_ASSIGN(TryStack); 385 DISALLOW_COPY_AND_ASSIGN(TryStack);
385 }; 386 };
386 387
387 388
388 void Parser::TryStack::AddNodeForFinallyInlining(AstNode* node) { 389 void Parser::TryStack::AddNodeForFinallyInlining(AstNode* node) {
389 inlined_finally_nodes_.Add(node); 390 inlined_finally_nodes_.Add(node);
390 } 391 }
391 392
392 393
394 void Parser::TryStack::RemoveJumpToLabel(SourceLabel *label) {
395 int i = 0;
396 while (i < inlined_finally_nodes_.length()) {
397 if (inlined_finally_nodes_[i]->IsJumpNode()) {
398 JumpNode* jump = inlined_finally_nodes_[i]->AsJumpNode();
399 if (jump->label() == label) {
400 // Shift remaining entries left and delete last entry.
401 for (int j = i + 1; j < inlined_finally_nodes_.length(); j++) {
402 inlined_finally_nodes_[j - 1] = inlined_finally_nodes_[j];
403 }
404 inlined_finally_nodes_.RemoveLast();
405 continue;
406 }
407 }
408 i++;
409 }
410 }
411
412
393 // For parsing a compilation unit. 413 // For parsing a compilation unit.
394 Parser::Parser(const Script& script, 414 Parser::Parser(const Script& script,
395 const Library& library, 415 const Library& library,
396 TokenPosition token_pos) 416 TokenPosition token_pos)
397 : thread_(Thread::Current()), 417 : thread_(Thread::Current()),
398 isolate_(thread()->isolate()), 418 isolate_(thread()->isolate()),
399 script_(Script::Handle(zone(), script.raw())), 419 script_(Script::Handle(zone(), script.raw())),
400 tokens_iterator_(zone(), 420 tokens_iterator_(zone(),
401 TokenStream::Handle(zone(), script.tokens()), 421 TokenStream::Handle(zone(), script.tokens()),
402 token_pos), 422 token_pos),
(...skipping 8031 matching lines...) Expand 10 before | Expand all | Expand 10 after
8434 case_label = current_block_->scope->LocalLookupLabel(*label_name); 8454 case_label = current_block_->scope->LocalLookupLabel(*label_name);
8435 if (case_label == NULL) { 8455 if (case_label == NULL) {
8436 // Label does not exist yet. Add it to scope of switch statement. 8456 // Label does not exist yet. Add it to scope of switch statement.
8437 case_label = new(Z) SourceLabel( 8457 case_label = new(Z) SourceLabel(
8438 label_pos, *label_name, SourceLabel::kCase); 8458 label_pos, *label_name, SourceLabel::kCase);
8439 current_block_->scope->AddLabel(case_label); 8459 current_block_->scope->AddLabel(case_label);
8440 } else if (case_label->kind() == SourceLabel::kForward) { 8460 } else if (case_label->kind() == SourceLabel::kForward) {
8441 // We have seen a 'continue' with this label name. Resolve 8461 // We have seen a 'continue' with this label name. Resolve
8442 // the forward reference. 8462 // the forward reference.
8443 case_label->ResolveForwardReference(); 8463 case_label->ResolveForwardReference();
8464 RemoveNodesForFinallyInlining(case_label);
8444 } else { 8465 } else {
8445 ReportError(label_pos, "label '%s' already exists in scope", 8466 ReportError(label_pos, "label '%s' already exists in scope",
8446 label_name->ToCString()); 8467 label_name->ToCString());
8447 } 8468 }
8448 ASSERT(case_label->kind() == SourceLabel::kCase); 8469 ASSERT(case_label->kind() == SourceLabel::kCase);
8449 } 8470 }
8450 if (CurrentToken() == Token::kCASE || 8471 if (CurrentToken() == Token::kCASE ||
8451 CurrentToken() == Token::kDEFAULT) { 8472 CurrentToken() == Token::kDEFAULT) {
8452 if (default_seen) { 8473 if (default_seen) {
8453 ReportError("no case clauses allowed after default clause"); 8474 ReportError("no case clauses allowed after default clause");
(...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after
9342 // For continue and break node check if the target label is in scope. 9363 // For continue and break node check if the target label is in scope.
9343 if (node->IsJumpNode()) { 9364 if (node->IsJumpNode()) {
9344 SourceLabel* label = node->AsJumpNode()->label(); 9365 SourceLabel* label = node->AsJumpNode()->label();
9345 ASSERT(label != NULL); 9366 ASSERT(label != NULL);
9346 LocalScope* try_scope = iterator->try_block()->scope; 9367 LocalScope* try_scope = iterator->try_block()->scope;
9347 // If the label is defined in a scope which is a child (nested scope) 9368 // If the label is defined in a scope which is a child (nested scope)
9348 // of the try scope then we are not breaking out of this try block 9369 // of the try scope then we are not breaking out of this try block
9349 // so we do not need to inline the finally code. Otherwise we need 9370 // so we do not need to inline the finally code. Otherwise we need
9350 // to inline the finally code of this try block and then move on to the 9371 // to inline the finally code of this try block and then move on to the
9351 // next outer try block. 9372 // next outer try block.
9352 if (label->owner()->IsNestedWithin(try_scope)) { 9373 // For unresolved forward jumps to switch cases, we don't yet know
9374 // to which scope the label will be resolved. Tentatively add the
9375 // jump to all nested try statements and remove the outermost ones
9376 // when we know the exact jump target. (See
9377 // RemoveNodesForFinallyInlining below.)
9378 if (!label->IsUnresolved() && label->owner()->IsNestedWithin(try_scope)) {
9353 break; 9379 break;
9354 } 9380 }
9355 } 9381 }
9356 iterator->AddNodeForFinallyInlining(node); 9382 iterator->AddNodeForFinallyInlining(node);
9357 iterator = iterator->outer_try(); 9383 iterator = iterator->outer_try();
9358 } 9384 }
9359 } 9385 }
9360 9386
9361 9387
9388 void Parser::RemoveNodesForFinallyInlining(SourceLabel* label) {
9389 TryStack* iterator = try_stack_;
9390 const intptr_t func_level = FunctionLevel();
9391 while ((iterator != NULL) &&
9392 (iterator->try_block()->scope->function_level() == func_level)) {
9393 iterator->RemoveJumpToLabel(label);
9394 iterator = iterator->outer_try();
9395 }
9396 }
9397
9398
9362 // Add the inlined finally clause to the specified node. 9399 // Add the inlined finally clause to the specified node.
9363 void Parser::AddFinallyClauseToNode(bool is_async, 9400 void Parser::AddFinallyClauseToNode(bool is_async,
9364 AstNode* node, 9401 AstNode* node,
9365 InlinedFinallyNode* finally_clause) { 9402 InlinedFinallyNode* finally_clause) {
9366 ReturnNode* return_node = node->AsReturnNode(); 9403 ReturnNode* return_node = node->AsReturnNode();
9367 if (return_node != NULL) { 9404 if (return_node != NULL) {
9368 if (FunctionLevel() == 0) { 9405 if (FunctionLevel() == 0) {
9369 parsed_function()->EnsureFinallyReturnTemp(is_async); 9406 parsed_function()->EnsureFinallyReturnTemp(is_async);
9370 } 9407 }
9371 return_node->AddInlinedFinallyNode(finally_clause); 9408 return_node->AddInlinedFinallyNode(finally_clause);
(...skipping 5202 matching lines...) Expand 10 before | Expand all | Expand 10 after
14574 const ArgumentListNode& function_args, 14611 const ArgumentListNode& function_args,
14575 const LocalVariable* temp_for_last_arg, 14612 const LocalVariable* temp_for_last_arg,
14576 bool is_super_invocation) { 14613 bool is_super_invocation) {
14577 UNREACHABLE(); 14614 UNREACHABLE();
14578 return NULL; 14615 return NULL;
14579 } 14616 }
14580 14617
14581 } // namespace dart 14618 } // namespace dart
14582 14619
14583 #endif // DART_PRECOMPILED_RUNTIME 14620 #endif // DART_PRECOMPILED_RUNTIME
OLDNEW
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/scopes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698