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

Side by Side Diff: pkg/kernel/lib/transformations/continuation.dart

Issue 2659393002: VM: [Kernel] Fix checked mode issues with await/async transformer (Closed)
Patch Set: small changes Created 3 years, 10 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) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, 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 kernel.transformations.continuation; 5 library kernel.transformations.continuation;
6 6
7 import 'dart:math' as math; 7 import 'dart:math' as math;
8 8
9 import '../ast.dart'; 9 import '../ast.dart';
10 import '../core_types.dart';
10 import '../visitor.dart'; 11 import '../visitor.dart';
11 12
12 import 'async.dart'; 13 import 'async.dart';
13 14
14 Program transformProgram(Program program) { 15 Program transformProgram(Program program) {
15 var helper = new HelperNodes.fromProgram(program); 16 var helper = new HelperNodes.fromProgram(program);
16 var rewriter = new RecursiveContinuationRewriter(helper); 17 var rewriter = new RecursiveContinuationRewriter(helper);
17 return rewriter.rewriteProgram(program); 18 return rewriter.rewriteProgram(program);
18 } 19 }
19 20
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 new VariableDeclaration(":stack_trace${depth}"), 106 new VariableDeclaration(":stack_trace${depth}"),
106 ]); 107 ]);
107 108
108 List<VariableDeclaration> variableDeclarations() => 109 List<VariableDeclaration> variableDeclarations() =>
109 [asyncJumpVariable, asyncContextVariable] 110 [asyncJumpVariable, asyncContextVariable]
110 ..addAll(createCapturedTryVariables()) 111 ..addAll(createCapturedTryVariables())
111 ..addAll(createCapturedCatchVariables()); 112 ..addAll(createCapturedCatchVariables());
112 } 113 }
113 114
114 class SyncStarFunctionRewriter extends ContinuationRewriterBase { 115 class SyncStarFunctionRewriter extends ContinuationRewriterBase {
115 final VariableDeclaration iteratorVariable = 116 final VariableDeclaration iteratorVariable;
116 new VariableDeclaration(":iterator");
117 117
118 SyncStarFunctionRewriter(helper, enclosingFunction) 118 SyncStarFunctionRewriter(helper, enclosingFunction)
119 : super(helper, enclosingFunction); 119 : iteratorVariable = new VariableDeclaration(':iterator')
120 ..type = helper.iteratorClass.rawType,
121 super(helper, enclosingFunction);
120 122
121 FunctionNode rewrite() { 123 FunctionNode rewrite() {
122 // :sync_body(:iterator) { 124 // :sync_body(:iterator) {
123 // modified <node.body>; 125 // modified <node.body>;
124 // } 126 // }
125 final nestedClosureVariable = new VariableDeclaration(":sync_op"); 127 final nestedClosureVariable = new VariableDeclaration(":sync_op");
126 final function = new FunctionNode(buildClosureBody(), 128 final function = new FunctionNode(buildClosureBody(),
127 positionalParameters: [iteratorVariable], 129 positionalParameters: [iteratorVariable],
128 requiredParameterCount: 1, 130 requiredParameterCount: 1,
129 asyncMarker: AsyncMarker.SyncYielding) 131 asyncMarker: AsyncMarker.SyncYielding)
130 ..fileOffset = enclosingFunction.fileOffset 132 ..fileOffset = enclosingFunction.fileOffset
131 ..fileEndOffset = enclosingFunction.fileEndOffset; 133 ..fileEndOffset = enclosingFunction.fileEndOffset
134 ..returnType = helper.coreTypes.boolClass.rawType;
135
132 final closureFunction = 136 final closureFunction =
133 new FunctionDeclaration(nestedClosureVariable, function) 137 new FunctionDeclaration(nestedClosureVariable, function)
134 ..fileOffset = enclosingFunction.parent.fileOffset; 138 ..fileOffset = enclosingFunction.parent.fileOffset;
135 139
136 // return new _SyncIterable(:sync_body); 140 // return new _SyncIterable(:sync_body);
137 final arguments = new Arguments([new VariableGet(nestedClosureVariable)]); 141 final arguments = new Arguments([new VariableGet(nestedClosureVariable)]);
138 final returnStatement = new ReturnStatement( 142 final returnStatement = new ReturnStatement(
139 new ConstructorInvocation(helper.syncIterableConstructor, arguments)); 143 new ConstructorInvocation(helper.syncIterableConstructor, arguments));
140 144
141 enclosingFunction.body = new Block([] 145 enclosingFunction.body = new Block([]
142 ..addAll(variableDeclarations()) 146 ..addAll(variableDeclarations())
143 ..addAll([closureFunction, returnStatement])); 147 ..addAll([closureFunction, returnStatement]));
144 enclosingFunction.body.parent = enclosingFunction; 148 enclosingFunction.body.parent = enclosingFunction;
145 enclosingFunction.asyncMarker = AsyncMarker.Sync; 149 enclosingFunction.asyncMarker = AsyncMarker.Sync;
146 return enclosingFunction; 150 return enclosingFunction;
147 } 151 }
148 152
149 Statement buildClosureBody() { 153 Statement buildClosureBody() {
150 // The body will insert calls to 154 // The body will insert calls to
151 // :iterator.current_= 155 // :iterator.current_=
152 // :iterator.isYieldEach= 156 // :iterator.isYieldEach=
153 // and return `true` as long as it did something and `false` when it's done. 157 // and return `true` as long as it did something and `false` when it's done.
154 return enclosingFunction.body.accept(this); 158 return new Block([
159 enclosingFunction.body.accept(this),
160 new ReturnStatement(new BoolLiteral(false))
161 ]);
155 } 162 }
156 163
157 visitYieldStatement(YieldStatement node) { 164 visitYieldStatement(YieldStatement node) {
158 var transformedExpression = node.expression.accept(this); 165 var transformedExpression = node.expression.accept(this);
159 166
160 var statements = <Statement>[]; 167 var statements = <Statement>[];
161 if (node.isYieldStar) { 168 if (node.isYieldStar) {
162 var markYieldEach = new ExpressionStatement(new PropertySet( 169 var markYieldEach = new ExpressionStatement(new PropertySet(
163 new VariableGet(iteratorVariable), 170 new VariableGet(iteratorVariable),
164 new Name("isYieldEach", helper.coreLibrary), 171 new Name("isYieldEach", helper.coreLibrary),
165 new BoolLiteral(true))); 172 new BoolLiteral(true)));
166 statements.add(markYieldEach); 173 statements.add(markYieldEach);
167 } 174 }
168 175
169 var setCurrentIteratorValue = new ExpressionStatement(new PropertySet( 176 var setCurrentIteratorValue = new ExpressionStatement(new PropertySet(
170 new VariableGet(iteratorVariable), 177 new VariableGet(iteratorVariable),
171 new Name("_current", helper.coreLibrary), 178 new Name("_current", helper.coreLibrary),
172 transformedExpression)); 179 transformedExpression));
173 180
174 statements.add(setCurrentIteratorValue); 181 statements.add(setCurrentIteratorValue);
175 statements.add(createContinuationPoint(new BoolLiteral(true))); 182 statements.add(createContinuationPoint(new BoolLiteral(true)));
176 return new Block(statements); 183 return new Block(statements);
177 } 184 }
185
186 TreeNode visitReturnStatement(ReturnStatement node) {
187 // sync* functions cannot return a value.
188 assert(node.expression == null || node.expression is NullLiteral);
189 node.expression = new BoolLiteral(false)..parent = node;
190 return node;
191 }
178 } 192 }
179 193
180 abstract class AsyncRewriterBase extends ContinuationRewriterBase { 194 abstract class AsyncRewriterBase extends ContinuationRewriterBase {
181 final VariableDeclaration nestedClosureVariable = 195 final VariableDeclaration nestedClosureVariable =
182 new VariableDeclaration(":async_op"); 196 new VariableDeclaration(":async_op");
183 final VariableDeclaration thenContinuationVariable = 197 final VariableDeclaration thenContinuationVariable =
184 new VariableDeclaration(":async_op_then"); 198 new VariableDeclaration(":async_op_then");
185 final VariableDeclaration catchErrorContinuationVariable = 199 final VariableDeclaration catchErrorContinuationVariable =
186 new VariableDeclaration(":async_op_error"); 200 new VariableDeclaration(":async_op_error");
187 201
(...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 class AsyncFunctionRewriter extends AsyncRewriterBase { 762 class AsyncFunctionRewriter extends AsyncRewriterBase {
749 VariableDeclaration completerVariable; 763 VariableDeclaration completerVariable;
750 VariableDeclaration returnVariable; 764 VariableDeclaration returnVariable;
751 765
752 AsyncFunctionRewriter(helper, enclosingFunction) 766 AsyncFunctionRewriter(helper, enclosingFunction)
753 : super(helper, enclosingFunction); 767 : super(helper, enclosingFunction);
754 768
755 FunctionNode rewrite() { 769 FunctionNode rewrite() {
756 var statements = <Statement>[]; 770 var statements = <Statement>[];
757 771
758 // var :completer = new Completer.sync(); 772 // The original function return type should be Future<T> because the
773 // function is async. If it was, we make a Completer<T>. Otherwise
774 // We will make a malformed type.
775 var future_type = enclosingFunction.returnType;
776 DartType returnType = const DynamicType();
777 if (future_type is InterfaceType) {
778 if (future_type.classNode == helper.futureClass) {
779 if (future_type.typeArguments.length == 0) {
780 returnType = const DynamicType();
781 } else if (future_type.typeArguments.length == 1) {
782 returnType = future_type.typeArguments[0];
783 } else {
784 returnType = const InvalidType();
785 }
786 }
787 }
788 var completerTypeArguments = <DartType>[returnType];
789 var completerType = new InterfaceType(
790 helper.completerClass, completerTypeArguments);
791
792 // final Completer<T> :completer = new Completer<T>.sync();
759 completerVariable = new VariableDeclaration(":completer", 793 completerVariable = new VariableDeclaration(":completer",
760 initializer: new StaticInvocation(helper.completerConstructor, 794 initializer: new StaticInvocation(helper.completerConstructor,
761 new Arguments([], types: [const DynamicType()])) 795 new Arguments([], types: completerTypeArguments))
762 ..fileOffset = enclosingFunction.body.fileOffset, 796 ..fileOffset = enclosingFunction.body.fileOffset,
763 isFinal: true); 797 isFinal: true,
798 type: completerType);
764 statements.add(completerVariable); 799 statements.add(completerVariable);
765 800
766 returnVariable = new VariableDeclaration(":return_value"); 801 returnVariable = new VariableDeclaration(
802 ":return_value", type: returnType);
767 statements.add(returnVariable); 803 statements.add(returnVariable);
768 804
769 setupAsyncContinuations(statements); 805 setupAsyncContinuations(statements);
770 806
771 // new Future.microtask(:async_op); 807 // new Future.microtask(:async_op);
772 var newMicrotaskStatement = new ExpressionStatement(new StaticInvocation( 808 var newMicrotaskStatement = new ExpressionStatement(new StaticInvocation(
773 helper.futureMicrotaskConstructor, 809 helper.futureMicrotaskConstructor,
774 new Arguments([new VariableGet(nestedClosureVariable)], 810 new Arguments([new VariableGet(nestedClosureVariable)],
775 types: [const DynamicType()])) 811 types: [const DynamicType()]))
776 ..fileOffset = enclosingFunction.fileOffset); 812 ..fileOffset = enclosingFunction.fileOffset);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
820 .add(new ExpressionStatement(new VariableSet(returnVariable, expr))); 856 .add(new ExpressionStatement(new VariableSet(returnVariable, expr)));
821 statements 857 statements
822 .add(new BreakStatement(labeledBody)..fileOffset = node.fileOffset); 858 .add(new BreakStatement(labeledBody)..fileOffset = node.fileOffset);
823 return null; 859 return null;
824 } 860 }
825 } 861 }
826 862
827 class HelperNodes { 863 class HelperNodes {
828 final Library asyncLibrary; 864 final Library asyncLibrary;
829 final Library coreLibrary; 865 final Library coreLibrary;
866 final Class iteratorClass;
867 final Class futureClass;
868 final Class completerClass;
830 final Procedure printProcedure; 869 final Procedure printProcedure;
831 final Procedure completerConstructor; 870 final Procedure completerConstructor;
832 final Procedure futureMicrotaskConstructor; 871 final Procedure futureMicrotaskConstructor;
833 final Constructor streamControllerConstructor; 872 final Constructor streamControllerConstructor;
834 final Constructor syncIterableConstructor; 873 final Constructor syncIterableConstructor;
835 final Constructor streamIteratorConstructor; 874 final Constructor streamIteratorConstructor;
836 final Procedure asyncThenWrapper; 875 final Procedure asyncThenWrapper;
837 final Procedure asyncErrorWrapper; 876 final Procedure asyncErrorWrapper;
838 final Procedure awaitHelper; 877 final Procedure awaitHelper;
878 final CoreTypes coreTypes;
839 879
840 HelperNodes( 880 HelperNodes(
841 this.asyncLibrary, 881 this.asyncLibrary,
842 this.coreLibrary, 882 this.coreLibrary,
883 this.iteratorClass,
884 this.futureClass,
885 this.completerClass,
843 this.printProcedure, 886 this.printProcedure,
844 this.completerConstructor, 887 this.completerConstructor,
845 this.syncIterableConstructor, 888 this.syncIterableConstructor,
846 this.streamIteratorConstructor, 889 this.streamIteratorConstructor,
847 this.futureMicrotaskConstructor, 890 this.futureMicrotaskConstructor,
848 this.streamControllerConstructor, 891 this.streamControllerConstructor,
849 this.asyncThenWrapper, 892 this.asyncThenWrapper,
850 this.asyncErrorWrapper, 893 this.asyncErrorWrapper,
851 this.awaitHelper); 894 this.awaitHelper,
895 this.coreTypes);
852 896
853 factory HelperNodes.fromProgram(Program program) { 897 factory HelperNodes.fromProgram(Program program) {
854 Library findLibrary(String name) { 898 Library findLibrary(String name) {
855 Uri uri = Uri.parse(name); 899 Uri uri = Uri.parse(name);
856 for (var library in program.libraries) { 900 for (var library in program.libraries) {
857 if (library.importUri == uri) return library; 901 if (library.importUri == uri) return library;
858 } 902 }
859 throw 'Library "$name" not found'; 903 throw 'Library "$name" not found';
860 } 904 }
861 905
(...skipping 26 matching lines...) Expand all
888 } 932 }
889 } 933 }
890 throw 'Procedure "$name" not found'; 934 throw 'Procedure "$name" not found';
891 } 935 }
892 936
893 var asyncLibrary = findLibrary('dart:async'); 937 var asyncLibrary = findLibrary('dart:async');
894 var coreLibrary = findLibrary('dart:core'); 938 var coreLibrary = findLibrary('dart:core');
895 939
896 var completerClass = findClass(asyncLibrary, 'Completer'); 940 var completerClass = findClass(asyncLibrary, 'Completer');
897 var futureClass = findClass(asyncLibrary, 'Future'); 941 var futureClass = findClass(asyncLibrary, 'Future');
942 var iteratorClass = findClass(coreLibrary, 'Iterator');
898 943
899 // The VM's dart:async implementation has renamed _StreamIteratorImpl to 944 // The VM's dart:async implementation has renamed _StreamIteratorImpl to
900 // _StreamIterator. To support both old and new library implementations we 945 // _StreamIterator. To support both old and new library implementations we
901 // look for the old name first and then the new name. 946 // look for the old name first and then the new name.
902 var streamIteratorClass; 947 var streamIteratorClass;
903 try { 948 try {
904 streamIteratorClass = findClass(asyncLibrary, '_StreamIteratorImpl'); 949 streamIteratorClass = findClass(asyncLibrary, '_StreamIteratorImpl');
905 } catch (e) { 950 } catch (e) {
906 if (e == 'Class "_StreamIteratorImpl" not found') { 951 if (e == 'Class "_StreamIteratorImpl" not found') {
907 streamIteratorClass = findClass(asyncLibrary, '_StreamIterator'); 952 streamIteratorClass = findClass(asyncLibrary, '_StreamIterator');
908 } else { 953 } else {
909 rethrow; 954 rethrow;
910 } 955 }
911 } 956 }
912 957
913 var syncIterableClass = findClass(coreLibrary, '_SyncIterable'); 958 var syncIterableClass = findClass(coreLibrary, '_SyncIterable');
914 var streamControllerClass = 959 var streamControllerClass =
915 findClass(asyncLibrary, '_AsyncStarStreamController'); 960 findClass(asyncLibrary, '_AsyncStarStreamController');
916 961
917 return new HelperNodes( 962 return new HelperNodes(
918 asyncLibrary, 963 asyncLibrary,
919 coreLibrary, 964 coreLibrary,
965 iteratorClass,
966 futureClass,
967 completerClass,
920 findProcedure(coreLibrary, 'print'), 968 findProcedure(coreLibrary, 'print'),
921 findFactoryConstructor(completerClass, 'sync'), 969 findFactoryConstructor(completerClass, 'sync'),
922 findConstructor(syncIterableClass, ''), 970 findConstructor(syncIterableClass, ''),
923 findConstructor(streamIteratorClass, ''), 971 findConstructor(streamIteratorClass, ''),
924 findFactoryConstructor(futureClass, 'microtask'), 972 findFactoryConstructor(futureClass, 'microtask'),
925 findConstructor(streamControllerClass, ''), 973 findConstructor(streamControllerClass, ''),
926 findProcedure(asyncLibrary, '_asyncThenWrapperHelper'), 974 findProcedure(asyncLibrary, '_asyncThenWrapperHelper'),
927 findProcedure(asyncLibrary, '_asyncErrorWrapperHelper'), 975 findProcedure(asyncLibrary, '_asyncErrorWrapperHelper'),
928 findProcedure(asyncLibrary, '_awaitHelper')); 976 findProcedure(asyncLibrary, '_awaitHelper'),
977 new CoreTypes(program));
929 } 978 }
930 } 979 }
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