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

Side by Side Diff: pkg/compiler/lib/src/js/rewrite_async.dart

Issue 1848283002: dart2js: Do not use the async rewriter on nested functions. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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 | « no previous file | no next file » | 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) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 library rewrite_async; 5 library rewrite_async;
6 6
7 import "dart:math" show max; 7 import "dart:math" show max;
8 import 'dart:collection'; 8 import 'dart:collection';
9 9
10 import 'package:js_runtime/shared/async_await_error_codes.dart' 10 import 'package:js_runtime/shared/async_await_error_codes.dart'
11 as error_codes; 11 as error_codes;
12 12
13 import "js.dart" as js; 13 import "js.dart" as js;
14 14
15 import '../common.dart'; 15 import '../common.dart';
16 import '../util/util.dart' show 16 import '../util/util.dart' show
17 Pair; 17 Pair;
18 18
19 /// Rewrites a [js.Fun] with async/sync*/async* functions and await and yield 19 /// Rewrites a [js.Fun] with async/sync*/async* functions and await and yield
20 /// (with dart-like semantics) to an equivalent function without these. 20 /// (with dart-like semantics) to an equivalent function without these.
21 /// await-for is not handled and must be rewritten before. (Currently handled 21 /// await-for is not handled and must be rewritten before. (Currently handled
22 /// in ssa/builder.dart). 22 /// in ssa/builder.dart).
23 /// 23 ///
24 /// When generating the input to this, special care must be taken that 24 /// When generating the input to this, special care must be taken that
25 /// parameters to sync* functions that are mutated in the body must be boxed. 25 /// parameters to sync* functions that are mutated in the body must be boxed.
26 /// (Currently handled in closure.dart). 26 /// (Currently handled in closure.dart).
27 /// 27 ///
28 /// Look at [visitFun], [visitDartYield] and [visitAwait] for more explanation. 28 /// Look at [rewriteFunction], [visitDartYield] and [visitAwait] for more
29 /// explanation.
29 abstract class AsyncRewriterBase extends js.NodeVisitor { 30 abstract class AsyncRewriterBase extends js.NodeVisitor {
30 31
31 // Local variables are hoisted to the top of the function, so they are 32 // Local variables are hoisted to the top of the function, so they are
32 // collected here. 33 // collected here.
33 List<js.VariableDeclaration> localVariables = 34 List<js.VariableDeclaration> localVariables =
34 new List<js.VariableDeclaration>(); 35 new List<js.VariableDeclaration>();
35 36
36 Map<js.Node, int> continueLabels = new Map<js.Node, int>(); 37 Map<js.Node, int> continueLabels = new Map<js.Node, int>();
37 Map<js.Node, int> breakLabels = new Map<js.Node, int>(); 38 Map<js.Node, int> breakLabels = new Map<js.Node, int>();
38 39
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 gotoName = freshName("goto"); 201 gotoName = freshName("goto");
201 handlerName = freshName("handler"); 202 handlerName = freshName("handler");
202 nextName = freshName("next"); 203 nextName = freshName("next");
203 returnValueName = freshName("returnValue"); 204 returnValueName = freshName("returnValue");
204 currentErrorName = freshName("currentError"); 205 currentErrorName = freshName("currentError");
205 outerLabelName = freshName("outer"); 206 outerLabelName = freshName("outer");
206 selfName = freshName("self"); 207 selfName = freshName("self");
207 // Initialize names specific to the subclass. 208 // Initialize names specific to the subclass.
208 initializeNames(); 209 initializeNames();
209 210
210 return node.accept(this); 211 return rewriteFunction(node);
211 } 212 }
212 213
213 js.Expression get currentErrorHandler { 214 js.Expression get currentErrorHandler {
214 return js.number(handlerLabels[jumpTargets.lastWhere( 215 return js.number(handlerLabels[jumpTargets.lastWhere(
215 (node) => handlerLabels[node] != null)]); 216 (node) => handlerLabels[node] != null)]);
216 } 217 }
217 218
218 int allocateTempVar() { 219 int allocateTempVar() {
219 assert(tempVarHighWaterMark >= currentTempVarIndex); 220 assert(tempVarHighWaterMark >= currentTempVarIndex);
220 currentTempVarIndex++; 221 currentTempVarIndex++;
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 /// case 7: // return 659 /// case 7: // return
659 /// return thenHelper(returnValue, 0, completer); 660 /// return thenHelper(returnValue, 0, completer);
660 /// case 8: // Rethrow 661 /// case 8: // Rethrow
661 /// return thenHelper(currentError, 1, completer); 662 /// return thenHelper(currentError, 1, completer);
662 /// } 663 /// }
663 /// } 664 /// }
664 /// return thenHelper(null, helper, completer); 665 /// return thenHelper(null, helper, completer);
665 /// } 666 /// }
666 /// } 667 /// }
667 /// 668 ///
668 @override 669 js.Expression rewriteFunction(js.Fun node) {
669 js.Expression visitFun(js.Fun node) {
670 beginLabel(newLabel("Function start")); 670 beginLabel(newLabel("Function start"));
671 // AsyncStar needs a returnlabel for its handling of cancelation. See 671 // AsyncStar needs a returnlabel for its handling of cancelation. See
672 // [visitDartYield]. 672 // [visitDartYield].
673 exitLabel = (analysis.hasExplicitReturns || isAsyncStar) 673 exitLabel = (analysis.hasExplicitReturns || isAsyncStar)
674 ? newLabel("return") 674 ? newLabel("return")
675 : null; 675 : null;
676 rethrowLabel = newLabel("rethrow"); 676 rethrowLabel = newLabel("rethrow");
677 handlerLabels[node] = rethrowLabel; 677 handlerLabels[node] = rethrowLabel;
678 js.Statement body = node.body; 678 js.Statement body = node.body;
679 jumpTargets.add(node); 679 jumpTargets.add(node);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 })); 713 }));
714 variables.addAll(new Iterable.generate(tempVarHighWaterMark, 714 variables.addAll(new Iterable.generate(tempVarHighWaterMark,
715 (int i) => _makeVariableInitializer(useTempVar(i + 1).name, null))); 715 (int i) => _makeVariableInitializer(useTempVar(i + 1).name, null)));
716 js.VariableDeclarationList variableDeclarations = 716 js.VariableDeclarationList variableDeclarations =
717 new js.VariableDeclarationList(variables); 717 new js.VariableDeclarationList(variables);
718 718
719 return finishFunction(node.params, rewrittenBody, variableDeclarations); 719 return finishFunction(node.params, rewrittenBody, variableDeclarations);
720 } 720 }
721 721
722 @override 722 @override
723 js.Expression visitFun(js.Fun node) {
724 if (node.asyncModifier.isAsync || node.asyncModifier.isYielding) {
725 // The translation does not handle nested functions that are generators
726 // or asynchronous. These functions should only be ones that are
727 // introduced by JS foreign code from our own libraries.
728 reporter.internalError(spannable,
729 'Nested function is a generator or asynchronous.');
730 }
731 return node;
732 }
733
734 @override
723 js.Expression visitAccess(js.PropertyAccess node) { 735 js.Expression visitAccess(js.PropertyAccess node) {
724 return withExpression2(node.receiver, node.selector, 736 return withExpression2(node.receiver, node.selector,
725 (receiver, selector) => js.js('#[#]', [receiver, selector])); 737 (receiver, selector) => js.js('#[#]', [receiver, selector]));
726 } 738 }
727 739
728 @override 740 @override
729 js.Expression visitArrayHole(js.ArrayHole node) { 741 js.Expression visitArrayHole(js.ArrayHole node) {
730 return node; 742 return node;
731 } 743 }
732 744
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
765 }); 777 });
766 } else { 778 } else {
767 throw "Unexpected assignment left hand side $leftHandSide"; 779 throw "Unexpected assignment left hand side $leftHandSide";
768 } 780 }
769 } 781 }
770 782
771 js.Statement awaitStatement(js.Expression value); 783 js.Statement awaitStatement(js.Expression value);
772 784
773 /// An await is translated to an [awaitStatement]. 785 /// An await is translated to an [awaitStatement].
774 /// 786 ///
775 /// See the comments of [visitFun] for an example. 787 /// See the comments of [rewriteFunction] for an example.
776 @override 788 @override
777 js.Expression visitAwait(js.Await node) { 789 js.Expression visitAwait(js.Await node) {
778 assert(isAsync || isAsyncStar); 790 assert(isAsync || isAsyncStar);
779 int afterAwait = newLabel("returning from await."); 791 int afterAwait = newLabel("returning from await.");
780 withExpression(node.expression, (js.Expression value) { 792 withExpression(node.expression, (js.Expression value) {
781 addStatement(setGotoVariable(afterAwait)); 793 addStatement(setGotoVariable(afterAwait));
782 addStatement(awaitStatement(value)); 794 addStatement(awaitStatement(value));
783 }, store: false); 795 }, store: false);
784 beginLabel(afterAwait); 796 beginLabel(afterAwait);
785 return result; 797 return result;
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
922 } else { 934 } else {
923 addStatement(new js.Break(null)); 935 addStatement(new js.Break(null));
924 } 936 }
925 } 937 }
926 938
927 /// Common code for handling break, continue, return. 939 /// Common code for handling break, continue, return.
928 /// 940 ///
929 /// It is necessary to run all nesting finally-handlers between the jump and 941 /// It is necessary to run all nesting finally-handlers between the jump and
930 /// the target. For that [next] is used as a stack of places to go. 942 /// the target. For that [next] is used as a stack of places to go.
931 /// 943 ///
932 /// See also [visitFun]. 944 /// See also [rewriteFunction].
933 void translateJump(js.Node target, int targetLabel) { 945 void translateJump(js.Node target, int targetLabel) {
934 // Compute a stack of all the 'finally' nodes that must be visited before 946 // Compute a stack of all the 'finally' nodes that must be visited before
935 // the jump. 947 // the jump.
936 // The bottom of the stack is the label where the jump goes to. 948 // The bottom of the stack is the label where the jump goes to.
937 List<int> jumpStack = new List<int>(); 949 List<int> jumpStack = new List<int>();
938 for (js.Node node in jumpTargets.reversed) { 950 for (js.Node node in jumpTargets.reversed) {
939 if (finallyLabels[node] != null) { 951 if (finallyLabels[node] != null) {
940 jumpStack.add(finallyLabels[node]); 952 jumpStack.add(finallyLabels[node]);
941 } else if (node == target) { 953 } else if (node == target) {
942 jumpStack.add(targetLabel); 954 jumpStack.add(targetLabel);
(...skipping 482 matching lines...) Expand 10 before | Expand all | Expand 10 after
1425 break; 1437 break;
1426 } 1438 }
1427 int finallyLabel = finallyLabels[node]; 1439 int finallyLabel = finallyLabels[node];
1428 if (finallyLabel != null) { 1440 if (finallyLabel != null) {
1429 result.add(finallyLabel); 1441 result.add(finallyLabel);
1430 } 1442 }
1431 } 1443 }
1432 return result.reversed.toList(); 1444 return result.reversed.toList();
1433 } 1445 }
1434 1446
1435 /// See the comments of [visitFun] for more explanation. 1447 /// See the comments of [rewriteFunction] for more explanation.
1436 void visitTry(js.Try node) { 1448 void visitTry(js.Try node) {
1437 if (!shouldTransform(node)) { 1449 if (!shouldTransform(node)) {
1438 js.Block body = translateInBlock(node.body); 1450 js.Block body = translateInBlock(node.body);
1439 js.Catch catchPart = (node.catchPart == null) 1451 js.Catch catchPart = (node.catchPart == null)
1440 ? null 1452 ? null
1441 : new js.Catch(node.catchPart.declaration, 1453 : new js.Catch(node.catchPart.declaration,
1442 translateInBlock(node.catchPart.body)); 1454 translateInBlock(node.catchPart.body));
1443 js.Block finallyPart = (node.finallyPart == null) 1455 js.Block finallyPart = (node.finallyPart == null)
1444 ? null 1456 ? null
1445 : translateInBlock(node.finallyPart); 1457 : translateInBlock(node.finallyPart);
(...skipping 1135 matching lines...) Expand 10 before | Expand all | Expand 10 after
2581 return condition || body; 2593 return condition || body;
2582 } 2594 }
2583 2595
2584 @override 2596 @override
2585 bool visitDartYield(js.DartYield node) { 2597 bool visitDartYield(js.DartYield node) {
2586 hasYield = true; 2598 hasYield = true;
2587 visit(node.expression); 2599 visit(node.expression);
2588 return true; 2600 return true;
2589 } 2601 }
2590 } 2602 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698