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

Unified 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, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/parser.h ('k') | runtime/vm/scopes.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/parser.cc
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 1c526729885dd2e6c84107fec63d6ee46ac7557f..f2a6422d17c4e74fda206aa5d0cef4d6bd4d472c 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -365,6 +365,7 @@ class Parser::TryStack : public ZoneAllocated {
void exit_finally() { inside_finally_ = false; }
void AddNodeForFinallyInlining(AstNode* node);
+ void RemoveJumpToLabel(SourceLabel *label);
AstNode* GetNodeToInlineFinally(int index) {
if (0 <= index && index < inlined_finally_nodes_.length()) {
return inlined_finally_nodes_[index];
@@ -390,6 +391,25 @@ void Parser::TryStack::AddNodeForFinallyInlining(AstNode* node) {
}
+void Parser::TryStack::RemoveJumpToLabel(SourceLabel *label) {
+ int i = 0;
+ while (i < inlined_finally_nodes_.length()) {
+ if (inlined_finally_nodes_[i]->IsJumpNode()) {
+ JumpNode* jump = inlined_finally_nodes_[i]->AsJumpNode();
+ if (jump->label() == label) {
+ // Shift remaining entries left and delete last entry.
+ for (int j = i + 1; j < inlined_finally_nodes_.length(); j++) {
+ inlined_finally_nodes_[j - 1] = inlined_finally_nodes_[j];
+ }
+ inlined_finally_nodes_.RemoveLast();
+ continue;
+ }
+ }
+ i++;
+ }
+}
+
+
// For parsing a compilation unit.
Parser::Parser(const Script& script,
const Library& library,
@@ -8441,6 +8461,7 @@ AstNode* Parser::ParseSwitchStatement(String* label_name) {
// We have seen a 'continue' with this label name. Resolve
// the forward reference.
case_label->ResolveForwardReference();
+ RemoveNodesForFinallyInlining(case_label);
} else {
ReportError(label_pos, "label '%s' already exists in scope",
label_name->ToCString());
@@ -9349,7 +9370,12 @@ void Parser::AddNodeForFinallyInlining(AstNode* node) {
// so we do not need to inline the finally code. Otherwise we need
// to inline the finally code of this try block and then move on to the
// next outer try block.
- if (label->owner()->IsNestedWithin(try_scope)) {
+ // For unresolved forward jumps to switch cases, we don't yet know
+ // to which scope the label will be resolved. Tentatively add the
+ // jump to all nested try statements and remove the outermost ones
+ // when we know the exact jump target. (See
+ // RemoveNodesForFinallyInlining below.)
+ if (!label->IsUnresolved() && label->owner()->IsNestedWithin(try_scope)) {
break;
}
}
@@ -9359,6 +9385,17 @@ void Parser::AddNodeForFinallyInlining(AstNode* node) {
}
+void Parser::RemoveNodesForFinallyInlining(SourceLabel* label) {
+ TryStack* iterator = try_stack_;
+ const intptr_t func_level = FunctionLevel();
+ while ((iterator != NULL) &&
+ (iterator->try_block()->scope->function_level() == func_level)) {
+ iterator->RemoveJumpToLabel(label);
+ iterator = iterator->outer_try();
+ }
+}
+
+
// Add the inlined finally clause to the specified node.
void Parser::AddFinallyClauseToNode(bool is_async,
AstNode* node,
« 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