OLD | NEW |
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 part of ssa; | 5 part of ssa; |
6 | 6 |
7 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
(...skipping 1040 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1051 * Variables stored in the current activation. These variables are | 1051 * Variables stored in the current activation. These variables are |
1052 * being updated in try/catch blocks, and should be | 1052 * being updated in try/catch blocks, and should be |
1053 * accessed indirectly through [HLocalGet] and [HLocalSet]. | 1053 * accessed indirectly through [HLocalGet] and [HLocalSet]. |
1054 */ | 1054 */ |
1055 Map<Local, HLocalValue> activationVariables = | 1055 Map<Local, HLocalValue> activationVariables = |
1056 <Local, HLocalValue>{}; | 1056 <Local, HLocalValue>{}; |
1057 | 1057 |
1058 // We build the Ssa graph by simulating a stack machine. | 1058 // We build the Ssa graph by simulating a stack machine. |
1059 List<HInstruction> stack = <HInstruction>[]; | 1059 List<HInstruction> stack = <HInstruction>[]; |
1060 | 1060 |
| 1061 /// Returns `true` if the current element is an `async` function. |
| 1062 bool get isBuildingAsyncFunction { |
| 1063 Element element = sourceElement; |
| 1064 return (element is FunctionElement && |
| 1065 element.asyncMarker == AsyncMarker.ASYNC); |
| 1066 } |
| 1067 |
1061 SsaBuilder(JavaScriptBackend backend, | 1068 SsaBuilder(JavaScriptBackend backend, |
1062 CodegenWorkItem work, | 1069 CodegenWorkItem work, |
1063 this.nativeEmitter, | 1070 this.nativeEmitter, |
1064 this.generateSourceMap) | 1071 this.generateSourceMap) |
1065 : this.compiler = backend.compiler, | 1072 : this.compiler = backend.compiler, |
1066 this.backend = backend, | 1073 this.backend = backend, |
1067 this.constantSystem = backend.constantSystem, | 1074 this.constantSystem = backend.constantSystem, |
1068 this.work = work, | 1075 this.work = work, |
1069 this.rti = backend.rti, | 1076 this.rti = backend.rti, |
1070 super(work.resolutionTree) { | 1077 super(work.resolutionTree) { |
(...skipping 4101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5172 targetType = localsHandler.substInContext(targetType); | 5179 targetType = localsHandler.substInContext(targetType); |
5173 targetType.typeArguments.forEach((DartType argument) { | 5180 targetType.typeArguments.forEach((DartType argument) { |
5174 inputs.add(analyzeTypeArgument(argument)); | 5181 inputs.add(analyzeTypeArgument(argument)); |
5175 }); | 5182 }); |
5176 } | 5183 } |
5177 pushInvokeStatic(node, targetConstructor, inputs); | 5184 pushInvokeStatic(node, targetConstructor, inputs); |
5178 HInstruction value = pop(); | 5185 HInstruction value = pop(); |
5179 emitReturn(value, node); | 5186 emitReturn(value, node); |
5180 } | 5187 } |
5181 | 5188 |
| 5189 /// Returns true if the [type] is a valid return type for an asynchronous |
| 5190 /// function. |
| 5191 /// |
| 5192 /// Asynchronous functions return a `Future`, and a valid return is thus |
| 5193 /// either dynamic, Object, or Future. |
| 5194 /// |
| 5195 /// We do not accept the internal Future implementation class. |
| 5196 bool isValidAsyncReturnType(DartType type) { |
| 5197 assert (isBuildingAsyncFunction); |
| 5198 // TODO(sigurdm): In an internal library a function could be declared: |
| 5199 // |
| 5200 // _FutureImpl foo async => 1; |
| 5201 // |
| 5202 // This should be valid (because the actual value returned from an async |
| 5203 // function is a `_FutureImpl`), but currently false is returned in this |
| 5204 // case. |
| 5205 return type.isDynamic || |
| 5206 type.isObject || |
| 5207 (type is InterfaceType && |
| 5208 type.element == compiler.futureClass); |
| 5209 } |
| 5210 |
5182 visitReturn(ast.Return node) { | 5211 visitReturn(ast.Return node) { |
5183 if (identical(node.beginToken.stringValue, 'native')) { | 5212 if (identical(node.beginToken.stringValue, 'native')) { |
5184 native.handleSsaNative(this, node.expression); | 5213 native.handleSsaNative(this, node.expression); |
5185 return; | 5214 return; |
5186 } | 5215 } |
5187 HInstruction value; | 5216 HInstruction value; |
5188 if (node.expression == null) { | 5217 if (node.expression == null) { |
5189 value = graph.addConstantNull(compiler); | 5218 value = graph.addConstantNull(compiler); |
5190 } else { | 5219 } else { |
5191 visit(node.expression); | 5220 visit(node.expression); |
5192 value = pop(); | 5221 value = pop(); |
5193 value = potentiallyCheckOrTrustType(value, returnType); | 5222 if (isBuildingAsyncFunction) { |
| 5223 if (compiler.enableTypeAssertions && |
| 5224 !isValidAsyncReturnType(returnType)) { |
| 5225 String message = |
| 5226 "Async function returned a Future, " |
| 5227 "was declared to return a $returnType."; |
| 5228 generateTypeError(node, message); |
| 5229 pop(); |
| 5230 return; |
| 5231 } |
| 5232 } else { |
| 5233 value = potentiallyCheckOrTrustType(value, returnType); |
| 5234 } |
5194 } | 5235 } |
5195 | 5236 |
5196 handleInTryStatement(); | 5237 handleInTryStatement(); |
5197 emitReturn(value, node); | 5238 emitReturn(value, node); |
5198 } | 5239 } |
5199 | 5240 |
5200 visitThrow(ast.Throw node) { | 5241 visitThrow(ast.Throw node) { |
5201 visitThrowExpression(node.expression); | 5242 visitThrowExpression(node.expression); |
5202 if (isReachable) { | 5243 if (isReachable) { |
5203 handleInTryStatement(); | 5244 handleInTryStatement(); |
(...skipping 1670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6874 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6915 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
6875 unaliased.accept(this, builder); | 6916 unaliased.accept(this, builder); |
6876 } | 6917 } |
6877 | 6918 |
6878 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 6919 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
6879 JavaScriptBackend backend = builder.compiler.backend; | 6920 JavaScriptBackend backend = builder.compiler.backend; |
6880 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 6921 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
6881 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 6922 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
6882 } | 6923 } |
6883 } | 6924 } |
OLD | NEW |