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

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: Update comments 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 for (int j = i + 1; j < inlined_finally_nodes_.length(); j++) {
401 inlined_finally_nodes_[i] = inlined_finally_nodes_[j];
regis 2016/06/02 01:13:25 Did you mean j-1 instead of i, which is not increm
hausner 2016/06/02 15:38:51 Ahem, yes. Good catch, thank you!
402 }
403 inlined_finally_nodes_.RemoveLast();
404 continue;
405 }
406 }
407 i++;
408 }
409 }
410
411
393 // For parsing a compilation unit. 412 // For parsing a compilation unit.
394 Parser::Parser(const Script& script, 413 Parser::Parser(const Script& script,
395 const Library& library, 414 const Library& library,
396 TokenPosition token_pos) 415 TokenPosition token_pos)
397 : thread_(Thread::Current()), 416 : thread_(Thread::Current()),
398 isolate_(thread()->isolate()), 417 isolate_(thread()->isolate()),
399 script_(Script::Handle(zone(), script.raw())), 418 script_(Script::Handle(zone(), script.raw())),
400 tokens_iterator_(zone(), 419 tokens_iterator_(zone(),
401 TokenStream::Handle(zone(), script.tokens()), 420 TokenStream::Handle(zone(), script.tokens()),
402 token_pos), 421 token_pos),
(...skipping 8031 matching lines...) Expand 10 before | Expand all | Expand 10 after
8434 case_label = current_block_->scope->LocalLookupLabel(*label_name); 8453 case_label = current_block_->scope->LocalLookupLabel(*label_name);
8435 if (case_label == NULL) { 8454 if (case_label == NULL) {
8436 // Label does not exist yet. Add it to scope of switch statement. 8455 // Label does not exist yet. Add it to scope of switch statement.
8437 case_label = new(Z) SourceLabel( 8456 case_label = new(Z) SourceLabel(
8438 label_pos, *label_name, SourceLabel::kCase); 8457 label_pos, *label_name, SourceLabel::kCase);
8439 current_block_->scope->AddLabel(case_label); 8458 current_block_->scope->AddLabel(case_label);
8440 } else if (case_label->kind() == SourceLabel::kForward) { 8459 } else if (case_label->kind() == SourceLabel::kForward) {
8441 // We have seen a 'continue' with this label name. Resolve 8460 // We have seen a 'continue' with this label name. Resolve
8442 // the forward reference. 8461 // the forward reference.
8443 case_label->ResolveForwardReference(); 8462 case_label->ResolveForwardReference();
8463 RemoveNodesForFinallyInlining(case_label);
8444 } else { 8464 } else {
8445 ReportError(label_pos, "label '%s' already exists in scope", 8465 ReportError(label_pos, "label '%s' already exists in scope",
8446 label_name->ToCString()); 8466 label_name->ToCString());
8447 } 8467 }
8448 ASSERT(case_label->kind() == SourceLabel::kCase); 8468 ASSERT(case_label->kind() == SourceLabel::kCase);
8449 } 8469 }
8450 if (CurrentToken() == Token::kCASE || 8470 if (CurrentToken() == Token::kCASE ||
8451 CurrentToken() == Token::kDEFAULT) { 8471 CurrentToken() == Token::kDEFAULT) {
8452 if (default_seen) { 8472 if (default_seen) {
8453 ReportError("no case clauses allowed after default clause"); 8473 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. 9362 // For continue and break node check if the target label is in scope.
9343 if (node->IsJumpNode()) { 9363 if (node->IsJumpNode()) {
9344 SourceLabel* label = node->AsJumpNode()->label(); 9364 SourceLabel* label = node->AsJumpNode()->label();
9345 ASSERT(label != NULL); 9365 ASSERT(label != NULL);
9346 LocalScope* try_scope = iterator->try_block()->scope; 9366 LocalScope* try_scope = iterator->try_block()->scope;
9347 // If the label is defined in a scope which is a child (nested scope) 9367 // 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 9368 // 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 9369 // 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 9370 // to inline the finally code of this try block and then move on to the
9351 // next outer try block. 9371 // next outer try block.
9352 if (label->owner()->IsNestedWithin(try_scope)) { 9372 // For unresolved forward jumps to switch cases, we don't yet know
9373 // to which scope the label will be resolved. Tentatively add the
9374 // jump to all nested try statements and remove the outermost ones
9375 // when we know the exact jump target. (See
9376 // RemoveNodesForFinallyInlining below.)
9377 if (!label->IsUnresolved() && label->owner()->IsNestedWithin(try_scope)) {
9353 break; 9378 break;
9354 } 9379 }
9355 } 9380 }
9356 iterator->AddNodeForFinallyInlining(node); 9381 iterator->AddNodeForFinallyInlining(node);
9357 iterator = iterator->outer_try(); 9382 iterator = iterator->outer_try();
9358 } 9383 }
9359 } 9384 }
9360 9385
9361 9386
9387 void Parser::RemoveNodesForFinallyInlining(SourceLabel* label) {
9388 TryStack* iterator = try_stack_;
9389 const intptr_t func_level = FunctionLevel();
9390 while ((iterator != NULL) &&
9391 (iterator->try_block()->scope->function_level() == func_level)) {
9392 iterator->RemoveJumpToLabel(label);
9393 iterator = iterator->outer_try();
9394 }
9395 }
9396
9397
9362 // Add the inlined finally clause to the specified node. 9398 // Add the inlined finally clause to the specified node.
9363 void Parser::AddFinallyClauseToNode(bool is_async, 9399 void Parser::AddFinallyClauseToNode(bool is_async,
9364 AstNode* node, 9400 AstNode* node,
9365 InlinedFinallyNode* finally_clause) { 9401 InlinedFinallyNode* finally_clause) {
9366 ReturnNode* return_node = node->AsReturnNode(); 9402 ReturnNode* return_node = node->AsReturnNode();
9367 if (return_node != NULL) { 9403 if (return_node != NULL) {
9368 if (FunctionLevel() == 0) { 9404 if (FunctionLevel() == 0) {
9369 parsed_function()->EnsureFinallyReturnTemp(is_async); 9405 parsed_function()->EnsureFinallyReturnTemp(is_async);
9370 } 9406 }
9371 return_node->AddInlinedFinallyNode(finally_clause); 9407 return_node->AddInlinedFinallyNode(finally_clause);
(...skipping 5202 matching lines...) Expand 10 before | Expand all | Expand 10 after
14574 const ArgumentListNode& function_args, 14610 const ArgumentListNode& function_args,
14575 const LocalVariable* temp_for_last_arg, 14611 const LocalVariable* temp_for_last_arg,
14576 bool is_super_invocation) { 14612 bool is_super_invocation) {
14577 UNREACHABLE(); 14613 UNREACHABLE();
14578 return NULL; 14614 return NULL;
14579 } 14615 }
14580 14616
14581 } // namespace dart 14617 } // namespace dart
14582 14618
14583 #endif // DART_PRECOMPILED_RUNTIME 14619 #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