OLD | NEW |
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 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
6 | 6 |
7 import '../closure.dart'; | 7 import '../closure.dart'; |
8 import '../common.dart'; | 8 import '../common.dart'; |
9 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 9 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
10 import '../common/names.dart'; | 10 import '../common/names.dart'; |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 closeFunction(); | 201 closeFunction(); |
202 } | 202 } |
203 | 203 |
204 /// Pops the most recent instruction from the stack and 'boolifies' it. | 204 /// Pops the most recent instruction from the stack and 'boolifies' it. |
205 /// | 205 /// |
206 /// Boolification is checking if the value is '=== true'. | 206 /// Boolification is checking if the value is '=== true'. |
207 @override | 207 @override |
208 HInstruction popBoolified() { | 208 HInstruction popBoolified() { |
209 HInstruction value = pop(); | 209 HInstruction value = pop(); |
210 if (typeBuilder.checkOrTrustTypes) { | 210 if (typeBuilder.checkOrTrustTypes) { |
211 ResolutionInterfaceType type = compiler.commonElements.boolType; | 211 ResolutionInterfaceType type = commonElements.boolType; |
212 return typeBuilder.potentiallyCheckOrTrustType(value, type, | 212 return typeBuilder.potentiallyCheckOrTrustType(value, type, |
213 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); | 213 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); |
214 } | 214 } |
215 HInstruction result = new HBoolify(value, commonMasks.boolType); | 215 HInstruction result = new HBoolify(value, commonMasks.boolType); |
216 add(result); | 216 add(result); |
217 return result; | 217 return result; |
218 } | 218 } |
219 | 219 |
220 void _addClassTypeVariablesIfNeeded(ir.Member constructor) { | 220 void _addClassTypeVariablesIfNeeded(ir.Member constructor) { |
221 var enclosing = constructor.enclosingClass; | 221 var enclosing = constructor.enclosingClass; |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 } | 594 } |
595 | 595 |
596 @override | 596 @override |
597 void visitBlock(ir.Block block) { | 597 void visitBlock(ir.Block block) { |
598 assert(!isAborted()); | 598 assert(!isAborted()); |
599 for (ir.Statement statement in block.statements) { | 599 for (ir.Statement statement in block.statements) { |
600 statement.accept(this); | 600 statement.accept(this); |
601 if (!isReachable) { | 601 if (!isReachable) { |
602 // The block has been aborted by a return or a throw. | 602 // The block has been aborted by a return or a throw. |
603 if (stack.isNotEmpty) { | 603 if (stack.isNotEmpty) { |
604 compiler.reporter.internalError( | 604 reporter.internalError( |
605 NO_LOCATION_SPANNABLE, 'Non-empty instruction stack.'); | 605 NO_LOCATION_SPANNABLE, 'Non-empty instruction stack.'); |
606 } | 606 } |
607 return; | 607 return; |
608 } | 608 } |
609 } | 609 } |
610 assert(!current.isClosed()); | 610 assert(!current.isClosed()); |
611 if (stack.isNotEmpty) { | 611 if (stack.isNotEmpty) { |
612 compiler.reporter | 612 reporter.internalError( |
613 .internalError(NO_LOCATION_SPANNABLE, 'Non-empty instruction stack'); | 613 NO_LOCATION_SPANNABLE, 'Non-empty instruction stack'); |
614 } | 614 } |
615 } | 615 } |
616 | 616 |
617 @override | 617 @override |
618 void visitEmptyStatement(ir.EmptyStatement statement) { | 618 void visitEmptyStatement(ir.EmptyStatement statement) { |
619 // Empty statement adds no instructions to current block. | 619 // Empty statement adds no instructions to current block. |
620 } | 620 } |
621 | 621 |
622 @override | 622 @override |
623 void visitExpressionStatement(ir.ExpressionStatement exprStatement) { | 623 void visitExpressionStatement(ir.ExpressionStatement exprStatement) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 @override | 657 @override |
658 void visitReturnStatement(ir.ReturnStatement returnStatement) { | 658 void visitReturnStatement(ir.ReturnStatement returnStatement) { |
659 HInstruction value; | 659 HInstruction value; |
660 if (returnStatement.expression == null) { | 660 if (returnStatement.expression == null) { |
661 value = graph.addConstantNull(closedWorld); | 661 value = graph.addConstantNull(closedWorld); |
662 } else { | 662 } else { |
663 assert(_targetFunction != null && _targetFunction is ir.FunctionNode); | 663 assert(_targetFunction != null && _targetFunction is ir.FunctionNode); |
664 returnStatement.expression.accept(this); | 664 returnStatement.expression.accept(this); |
665 value = pop(); | 665 value = pop(); |
666 if (_targetFunction.asyncMarker == ir.AsyncMarker.Async) { | 666 if (_targetFunction.asyncMarker == ir.AsyncMarker.Async) { |
667 if (compiler.options.enableTypeAssertions && | 667 if (options.enableTypeAssertions && |
668 !isValidAsyncReturnType(_targetFunction.returnType)) { | 668 !isValidAsyncReturnType(_targetFunction.returnType)) { |
669 generateTypeError( | 669 generateTypeError( |
670 returnStatement, | 670 returnStatement, |
671 "Async function returned a Future," | 671 "Async function returned a Future," |
672 " was declared to return a ${_targetFunction.returnType}."); | 672 " was declared to return a ${_targetFunction.returnType}."); |
673 pop(); | 673 pop(); |
674 return; | 674 return; |
675 } | 675 } |
676 } else { | 676 } else { |
677 value = typeBuilder.potentiallyCheckOrTrustType( | 677 value = typeBuilder.potentiallyCheckOrTrustType( |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1117 visitElse: () => ifStatement.otherwise?.accept(this)); | 1117 visitElse: () => ifStatement.otherwise?.accept(this)); |
1118 } | 1118 } |
1119 | 1119 |
1120 void handleIf( | 1120 void handleIf( |
1121 {ir.Node node, | 1121 {ir.Node node, |
1122 void visitCondition(), | 1122 void visitCondition(), |
1123 void visitThen(), | 1123 void visitThen(), |
1124 void visitElse(), | 1124 void visitElse(), |
1125 SourceInformation sourceInformation}) { | 1125 SourceInformation sourceInformation}) { |
1126 SsaBranchBuilder branchBuilder = new SsaBranchBuilder( | 1126 SsaBranchBuilder branchBuilder = new SsaBranchBuilder( |
1127 this, compiler, node == null ? node : astAdapter.getNode(node)); | 1127 this, node == null ? node : astAdapter.getNode(node)); |
1128 branchBuilder.handleIf(visitCondition, visitThen, visitElse, | 1128 branchBuilder.handleIf(visitCondition, visitThen, visitElse, |
1129 sourceInformation: sourceInformation); | 1129 sourceInformation: sourceInformation); |
1130 } | 1130 } |
1131 | 1131 |
1132 @override | 1132 @override |
1133 void visitAsExpression(ir.AsExpression asExpression) { | 1133 void visitAsExpression(ir.AsExpression asExpression) { |
1134 asExpression.operand.accept(this); | 1134 asExpression.operand.accept(this); |
1135 HInstruction expressionInstruction = pop(); | 1135 HInstruction expressionInstruction = pop(); |
1136 | 1136 |
1137 if (asExpression.type is ir.InvalidType) { | 1137 if (asExpression.type is ir.InvalidType) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1169 _pushStaticInvocation(procedure, [errorMessage], typeMask); | 1169 _pushStaticInvocation(procedure, [errorMessage], typeMask); |
1170 } | 1170 } |
1171 | 1171 |
1172 void generateTypeError(ir.Node node, String message) { | 1172 void generateTypeError(ir.Node node, String message) { |
1173 generateError(node, astAdapter.throwTypeError, message, | 1173 generateError(node, astAdapter.throwTypeError, message, |
1174 astAdapter.throwTypeErrorType); | 1174 astAdapter.throwTypeErrorType); |
1175 } | 1175 } |
1176 | 1176 |
1177 @override | 1177 @override |
1178 void visitAssertStatement(ir.AssertStatement assertStatement) { | 1178 void visitAssertStatement(ir.AssertStatement assertStatement) { |
1179 if (!compiler.options.enableUserAssertions) return; | 1179 if (!options.enableUserAssertions) return; |
1180 if (assertStatement.message == null) { | 1180 if (assertStatement.message == null) { |
1181 assertStatement.condition.accept(this); | 1181 assertStatement.condition.accept(this); |
1182 _pushStaticInvocation(astAdapter.assertHelper, <HInstruction>[pop()], | 1182 _pushStaticInvocation(astAdapter.assertHelper, <HInstruction>[pop()], |
1183 astAdapter.assertHelperReturnType); | 1183 astAdapter.assertHelperReturnType); |
1184 pop(); | 1184 pop(); |
1185 return; | 1185 return; |
1186 } | 1186 } |
1187 | 1187 |
1188 // if (assertTest(condition)) assertThrow(message); | 1188 // if (assertTest(condition)) assertThrow(message); |
1189 void buildCondition() { | 1189 void buildCondition() { |
(...skipping 17 matching lines...) Expand all Loading... |
1207 /// a special "null handler" is returned. | 1207 /// a special "null handler" is returned. |
1208 /// | 1208 /// |
1209 /// [isLoopJump] is true when the jump handler is for a loop. This is used | 1209 /// [isLoopJump] is true when the jump handler is for a loop. This is used |
1210 /// to distinguish the synthesized loop created for a switch statement with | 1210 /// to distinguish the synthesized loop created for a switch statement with |
1211 /// continue statements from simple switch statements. | 1211 /// continue statements from simple switch statements. |
1212 JumpHandler createJumpHandler(ir.TreeNode node, {bool isLoopJump: false}) { | 1212 JumpHandler createJumpHandler(ir.TreeNode node, {bool isLoopJump: false}) { |
1213 JumpTarget target = astAdapter.getJumpTarget(node); | 1213 JumpTarget target = astAdapter.getJumpTarget(node); |
1214 assert(target is KernelJumpTarget); | 1214 assert(target is KernelJumpTarget); |
1215 if (target == null) { | 1215 if (target == null) { |
1216 // No breaks or continues to this node. | 1216 // No breaks or continues to this node. |
1217 return new NullJumpHandler(compiler.reporter); | 1217 return new NullJumpHandler(reporter); |
1218 } | 1218 } |
1219 if (isLoopJump && node is ir.SwitchStatement) { | 1219 if (isLoopJump && node is ir.SwitchStatement) { |
1220 return new KernelSwitchCaseJumpHandler(this, target, node, astAdapter); | 1220 return new KernelSwitchCaseJumpHandler(this, target, node, astAdapter); |
1221 } | 1221 } |
1222 | 1222 |
1223 return new JumpHandler(this, target); | 1223 return new JumpHandler(this, target); |
1224 } | 1224 } |
1225 | 1225 |
1226 @override | 1226 @override |
1227 void visitBreakStatement(ir.BreakStatement breakStatement) { | 1227 void visitBreakStatement(ir.BreakStatement breakStatement) { |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1471 // is only possible for the last case.) | 1471 // is only possible for the last case.) |
1472 jumpTargets[switchTarget].generateBreak(); | 1472 jumpTargets[switchTarget].generateBreak(); |
1473 } | 1473 } |
1474 } | 1474 } |
1475 | 1475 |
1476 // Pass a [NullJumpHandler] because the target for the contained break | 1476 // Pass a [NullJumpHandler] because the target for the contained break |
1477 // is not the generated switch statement but instead the loop generated | 1477 // is not the generated switch statement but instead the loop generated |
1478 // in the call to [handleLoop] below. | 1478 // in the call to [handleLoop] below. |
1479 _handleSwitch( | 1479 _handleSwitch( |
1480 switchStatement, // nor is buildExpression. | 1480 switchStatement, // nor is buildExpression. |
1481 new NullJumpHandler(compiler.reporter), | 1481 new NullJumpHandler(reporter), |
1482 buildExpression, | 1482 buildExpression, |
1483 switchStatement.cases, | 1483 switchStatement.cases, |
1484 getConstants, | 1484 getConstants, |
1485 (_) => false, // No case is default. | 1485 (_) => false, // No case is default. |
1486 buildSwitchCase); | 1486 buildSwitchCase); |
1487 } | 1487 } |
1488 | 1488 |
1489 void buildLoop() { | 1489 void buildLoop() { |
1490 loopHandler.handleLoop( | 1490 loopHandler.handleLoop( |
1491 switchStatement, () {}, buildCondition, () {}, buildSwitch); | 1491 switchStatement, () {}, buildCondition, () {}, buildSwitch); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1616 expressionStart.setBlockFlow( | 1616 expressionStart.setBlockFlow( |
1617 new HSwitchBlockInformation( | 1617 new HSwitchBlockInformation( |
1618 expressionInfo, statements, jumpHandler.target, jumpHandler.labels), | 1618 expressionInfo, statements, jumpHandler.target, jumpHandler.labels), |
1619 joinBlock); | 1619 joinBlock); |
1620 | 1620 |
1621 jumpHandler.close(); | 1621 jumpHandler.close(); |
1622 } | 1622 } |
1623 | 1623 |
1624 @override | 1624 @override |
1625 void visitConditionalExpression(ir.ConditionalExpression conditional) { | 1625 void visitConditionalExpression(ir.ConditionalExpression conditional) { |
1626 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler); | 1626 SsaBranchBuilder brancher = new SsaBranchBuilder(this); |
1627 brancher.handleConditional( | 1627 brancher.handleConditional( |
1628 () => conditional.condition.accept(this), | 1628 () => conditional.condition.accept(this), |
1629 () => conditional.then.accept(this), | 1629 () => conditional.then.accept(this), |
1630 () => conditional.otherwise.accept(this)); | 1630 () => conditional.otherwise.accept(this)); |
1631 } | 1631 } |
1632 | 1632 |
1633 @override | 1633 @override |
1634 void visitLogicalExpression(ir.LogicalExpression logicalExpression) { | 1634 void visitLogicalExpression(ir.LogicalExpression logicalExpression) { |
1635 SsaBranchBuilder brancher = new SsaBranchBuilder(this, compiler); | 1635 SsaBranchBuilder brancher = new SsaBranchBuilder(this); |
1636 brancher.handleLogicalBinary(() => logicalExpression.left.accept(this), | 1636 brancher.handleLogicalBinary(() => logicalExpression.left.accept(this), |
1637 () => logicalExpression.right.accept(this), | 1637 () => logicalExpression.right.accept(this), |
1638 isAnd: logicalExpression.operator == '&&'); | 1638 isAnd: logicalExpression.operator == '&&'); |
1639 } | 1639 } |
1640 | 1640 |
1641 @override | 1641 @override |
1642 void visitIntLiteral(ir.IntLiteral intLiteral) { | 1642 void visitIntLiteral(ir.IntLiteral intLiteral) { |
1643 stack.add(graph.addConstantInt(intLiteral.value, closedWorld)); | 1643 stack.add(graph.addConstantInt(intLiteral.value, closedWorld)); |
1644 } | 1644 } |
1645 | 1645 |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2104 handleForeignJsBuiltin(invocation); | 2104 handleForeignJsBuiltin(invocation); |
2105 } else if (name == 'JS_GET_FLAG') { | 2105 } else if (name == 'JS_GET_FLAG') { |
2106 handleForeignJsGetFlag(invocation); | 2106 handleForeignJsGetFlag(invocation); |
2107 } else if (name == 'JS_EFFECT') { | 2107 } else if (name == 'JS_EFFECT') { |
2108 stack.add(graph.addConstantNull(closedWorld)); | 2108 stack.add(graph.addConstantNull(closedWorld)); |
2109 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { | 2109 } else if (name == 'JS_INTERCEPTOR_CONSTANT') { |
2110 handleJsInterceptorConstant(invocation); | 2110 handleJsInterceptorConstant(invocation); |
2111 } else if (name == 'JS_STRING_CONCAT') { | 2111 } else if (name == 'JS_STRING_CONCAT') { |
2112 handleJsStringConcat(invocation); | 2112 handleJsStringConcat(invocation); |
2113 } else { | 2113 } else { |
2114 compiler.reporter.internalError( | 2114 reporter.internalError( |
2115 astAdapter.getNode(invocation), "Unknown foreign: ${name}"); | 2115 astAdapter.getNode(invocation), "Unknown foreign: ${name}"); |
2116 } | 2116 } |
2117 } | 2117 } |
2118 | 2118 |
2119 bool _unexpectedForeignArguments( | 2119 bool _unexpectedForeignArguments( |
2120 ir.StaticInvocation invocation, int minPositional, | 2120 ir.StaticInvocation invocation, int minPositional, |
2121 [int maxPositional]) { | 2121 [int maxPositional]) { |
2122 String pluralizeArguments(int count) { | 2122 String pluralizeArguments(int count) { |
2123 if (count == 0) return 'no arguments'; | 2123 if (count == 0) return 'no arguments'; |
2124 if (count == 1) return 'one argument'; | 2124 if (count == 1) return 'one argument'; |
2125 if (count == 2) return 'two arguments'; | 2125 if (count == 2) return 'two arguments'; |
2126 return '$count arguments'; | 2126 return '$count arguments'; |
2127 } | 2127 } |
2128 | 2128 |
2129 String name() => invocation.target.name.name; | 2129 String name() => invocation.target.name.name; |
2130 | 2130 |
2131 ir.Arguments arguments = invocation.arguments; | 2131 ir.Arguments arguments = invocation.arguments; |
2132 bool bad = false; | 2132 bool bad = false; |
2133 if (arguments.types.isNotEmpty) { | 2133 if (arguments.types.isNotEmpty) { |
2134 compiler.reporter.reportErrorMessage( | 2134 reporter.reportErrorMessage( |
2135 astAdapter.getNode(invocation), | 2135 astAdapter.getNode(invocation), |
2136 MessageKind.GENERIC, | 2136 MessageKind.GENERIC, |
2137 {'text': "Error: '${name()}' does not take type arguments."}); | 2137 {'text': "Error: '${name()}' does not take type arguments."}); |
2138 bad = true; | 2138 bad = true; |
2139 } | 2139 } |
2140 if (arguments.positional.length < minPositional) { | 2140 if (arguments.positional.length < minPositional) { |
2141 String phrase = pluralizeArguments(minPositional); | 2141 String phrase = pluralizeArguments(minPositional); |
2142 if (maxPositional != minPositional) phrase = 'at least $phrase'; | 2142 if (maxPositional != minPositional) phrase = 'at least $phrase'; |
2143 compiler.reporter.reportErrorMessage( | 2143 reporter.reportErrorMessage( |
2144 astAdapter.getNode(invocation), | 2144 astAdapter.getNode(invocation), |
2145 MessageKind.GENERIC, | 2145 MessageKind.GENERIC, |
2146 {'text': "Error: Too few arguments. '${name()}' takes $phrase."}); | 2146 {'text': "Error: Too few arguments. '${name()}' takes $phrase."}); |
2147 bad = true; | 2147 bad = true; |
2148 } | 2148 } |
2149 if (maxPositional != null && arguments.positional.length > maxPositional) { | 2149 if (maxPositional != null && arguments.positional.length > maxPositional) { |
2150 String phrase = pluralizeArguments(maxPositional); | 2150 String phrase = pluralizeArguments(maxPositional); |
2151 if (maxPositional != minPositional) phrase = 'at most $phrase'; | 2151 if (maxPositional != minPositional) phrase = 'at most $phrase'; |
2152 compiler.reporter.reportErrorMessage( | 2152 reporter.reportErrorMessage( |
2153 astAdapter.getNode(invocation), | 2153 astAdapter.getNode(invocation), |
2154 MessageKind.GENERIC, | 2154 MessageKind.GENERIC, |
2155 {'text': "Error: Too many arguments. '${name()}' takes $phrase."}); | 2155 {'text': "Error: Too many arguments. '${name()}' takes $phrase."}); |
2156 bad = true; | 2156 bad = true; |
2157 } | 2157 } |
2158 if (arguments.named.isNotEmpty) { | 2158 if (arguments.named.isNotEmpty) { |
2159 compiler.reporter.reportErrorMessage( | 2159 reporter.reportErrorMessage( |
2160 astAdapter.getNode(invocation), | 2160 astAdapter.getNode(invocation), |
2161 MessageKind.GENERIC, | 2161 MessageKind.GENERIC, |
2162 {'text': "Error: '${name()}' does not take named arguments."}); | 2162 {'text': "Error: '${name()}' does not take named arguments."}); |
2163 bad = true; | 2163 bad = true; |
2164 } | 2164 } |
2165 return bad; | 2165 return bad; |
2166 } | 2166 } |
2167 | 2167 |
2168 /// Returns the value of the string argument. The argument must evaluate to a | 2168 /// Returns the value of the string argument. The argument must evaluate to a |
2169 /// constant. If there is an error, the error is reported and `null` is | 2169 /// constant. If there is an error, the error is reported and `null` is |
2170 /// returned. | 2170 /// returned. |
2171 String _foreignConstantStringArgument( | 2171 String _foreignConstantStringArgument( |
2172 ir.StaticInvocation invocation, int position, String methodName, | 2172 ir.StaticInvocation invocation, int position, String methodName, |
2173 [String adjective = '']) { | 2173 [String adjective = '']) { |
2174 ir.Expression argument = invocation.arguments.positional[position]; | 2174 ir.Expression argument = invocation.arguments.positional[position]; |
2175 argument.accept(this); | 2175 argument.accept(this); |
2176 HInstruction instruction = pop(); | 2176 HInstruction instruction = pop(); |
2177 | 2177 |
2178 if (!instruction.isConstantString()) { | 2178 if (!instruction.isConstantString()) { |
2179 compiler.reporter.reportErrorMessage( | 2179 reporter.reportErrorMessage( |
2180 astAdapter.getNode(argument), MessageKind.GENERIC, { | 2180 astAdapter.getNode(argument), MessageKind.GENERIC, { |
2181 'text': "Error: Expected String constant as ${adjective}argument " | 2181 'text': "Error: Expected String constant as ${adjective}argument " |
2182 "to '$methodName'." | 2182 "to '$methodName'." |
2183 }); | 2183 }); |
2184 return null; | 2184 return null; |
2185 } | 2185 } |
2186 | 2186 |
2187 HConstant hConstant = instruction; | 2187 HConstant hConstant = instruction; |
2188 StringConstantValue stringConstant = hConstant.constant; | 2188 StringConstantValue stringConstant = hConstant.constant; |
2189 return stringConstant.primitiveValue.slowToString(); | 2189 return stringConstant.primitiveValue.slowToString(); |
(...skipping 12 matching lines...) Expand all Loading... |
2202 String name = backend.namer.staticStateHolder; | 2202 String name = backend.namer.staticStateHolder; |
2203 push(new HForeignCode( | 2203 push(new HForeignCode( |
2204 js.js.parseForeignJS(name), commonMasks.dynamicType, <HInstruction>[], | 2204 js.js.parseForeignJS(name), commonMasks.dynamicType, <HInstruction>[], |
2205 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); | 2205 nativeBehavior: native.NativeBehavior.DEPENDS_OTHER)); |
2206 } else { | 2206 } else { |
2207 // Call a helper method from the isolate library. The isolate library uses | 2207 // Call a helper method from the isolate library. The isolate library uses |
2208 // its own isolate structure that encapsulates the isolate structure used | 2208 // its own isolate structure that encapsulates the isolate structure used |
2209 // for binding to methods. | 2209 // for binding to methods. |
2210 ir.Procedure target = astAdapter.currentIsolate; | 2210 ir.Procedure target = astAdapter.currentIsolate; |
2211 if (target == null) { | 2211 if (target == null) { |
2212 compiler.reporter.internalError(astAdapter.getNode(invocation), | 2212 reporter.internalError(astAdapter.getNode(invocation), |
2213 'Isolate library and compiler mismatch.'); | 2213 'Isolate library and compiler mismatch.'); |
2214 } | 2214 } |
2215 _pushStaticInvocation(target, <HInstruction>[], commonMasks.dynamicType); | 2215 _pushStaticInvocation(target, <HInstruction>[], commonMasks.dynamicType); |
2216 } | 2216 } |
2217 } | 2217 } |
2218 | 2218 |
2219 void handleForeignJsCallInIsolate(ir.StaticInvocation invocation) { | 2219 void handleForeignJsCallInIsolate(ir.StaticInvocation invocation) { |
2220 if (_unexpectedForeignArguments(invocation, 2, 2)) { | 2220 if (_unexpectedForeignArguments(invocation, 2, 2)) { |
2221 // Result expected on stack. | 2221 // Result expected on stack. |
2222 stack.add(graph.addConstantNull(closedWorld)); | 2222 stack.add(graph.addConstantNull(closedWorld)); |
2223 return; | 2223 return; |
2224 } | 2224 } |
2225 | 2225 |
2226 List<HInstruction> inputs = _visitPositionalArguments(invocation.arguments); | 2226 List<HInstruction> inputs = _visitPositionalArguments(invocation.arguments); |
2227 | 2227 |
2228 if (!backend.backendUsage.isIsolateInUse) { | 2228 if (!backend.backendUsage.isIsolateInUse) { |
2229 // If the isolate library is not used, we ignore the isolate argument and | 2229 // If the isolate library is not used, we ignore the isolate argument and |
2230 // just invoke the closure. | 2230 // just invoke the closure. |
2231 push(new HInvokeClosure(new Selector.callClosure(0), | 2231 push(new HInvokeClosure(new Selector.callClosure(0), |
2232 <HInstruction>[inputs[1]], commonMasks.dynamicType)); | 2232 <HInstruction>[inputs[1]], commonMasks.dynamicType)); |
2233 } else { | 2233 } else { |
2234 // Call a helper method from the isolate library. | 2234 // Call a helper method from the isolate library. |
2235 ir.Procedure callInIsolate = astAdapter.callInIsolate; | 2235 ir.Procedure callInIsolate = astAdapter.callInIsolate; |
2236 if (callInIsolate == null) { | 2236 if (callInIsolate == null) { |
2237 compiler.reporter.internalError(astAdapter.getNode(invocation), | 2237 reporter.internalError(astAdapter.getNode(invocation), |
2238 'Isolate library and compiler mismatch.'); | 2238 'Isolate library and compiler mismatch.'); |
2239 } | 2239 } |
2240 _pushStaticInvocation(callInIsolate, inputs, commonMasks.dynamicType); | 2240 _pushStaticInvocation(callInIsolate, inputs, commonMasks.dynamicType); |
2241 } | 2241 } |
2242 } | 2242 } |
2243 | 2243 |
2244 void handleForeignDartClosureToJs( | 2244 void handleForeignDartClosureToJs( |
2245 ir.StaticInvocation invocation, String name) { | 2245 ir.StaticInvocation invocation, String name) { |
2246 // TODO(sra): Do we need to wrap the closure in something that saves the | 2246 // TODO(sra): Do we need to wrap the closure in something that saves the |
2247 // current isolate? | 2247 // current isolate? |
(...skipping 26 matching lines...) Expand all Loading... |
2274 <HInstruction>[], | 2274 <HInstruction>[], |
2275 nativeBehavior: native.NativeBehavior.PURE, | 2275 nativeBehavior: native.NativeBehavior.PURE, |
2276 foreignFunction: astAdapter.getMethod(staticTarget))); | 2276 foreignFunction: astAdapter.getMethod(staticTarget))); |
2277 return; | 2277 return; |
2278 } | 2278 } |
2279 problem = 'does not handle a closure with optional parameters'; | 2279 problem = 'does not handle a closure with optional parameters'; |
2280 } | 2280 } |
2281 } | 2281 } |
2282 } | 2282 } |
2283 | 2283 |
2284 compiler.reporter.reportErrorMessage(astAdapter.getNode(invocation), | 2284 reporter.reportErrorMessage(astAdapter.getNode(invocation), |
2285 MessageKind.GENERIC, {'text': "'$name' $problem."}); | 2285 MessageKind.GENERIC, {'text': "'$name' $problem."}); |
2286 stack.add(graph.addConstantNull(closedWorld)); // Result expected on stack. | 2286 stack.add(graph.addConstantNull(closedWorld)); // Result expected on stack. |
2287 return; | 2287 return; |
2288 } | 2288 } |
2289 | 2289 |
2290 void handleForeignJsSetStaticState(ir.StaticInvocation invocation) { | 2290 void handleForeignJsSetStaticState(ir.StaticInvocation invocation) { |
2291 if (_unexpectedForeignArguments(invocation, 1, 1)) { | 2291 if (_unexpectedForeignArguments(invocation, 1, 1)) { |
2292 // Result expected on stack. | 2292 // Result expected on stack. |
2293 stack.add(graph.addConstantNull(closedWorld)); | 2293 stack.add(graph.addConstantNull(closedWorld)); |
2294 return; | 2294 return; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2328 argument.accept(this); | 2328 argument.accept(this); |
2329 HInstruction instruction = pop(); | 2329 HInstruction instruction = pop(); |
2330 | 2330 |
2331 if (instruction is HConstant) { | 2331 if (instruction is HConstant) { |
2332 js.Name name = | 2332 js.Name name = |
2333 astAdapter.getNameForJsGetName(argument, instruction.constant); | 2333 astAdapter.getNameForJsGetName(argument, instruction.constant); |
2334 stack.add(graph.addConstantStringFromName(name, closedWorld)); | 2334 stack.add(graph.addConstantStringFromName(name, closedWorld)); |
2335 return; | 2335 return; |
2336 } | 2336 } |
2337 | 2337 |
2338 compiler.reporter.reportErrorMessage( | 2338 reporter.reportErrorMessage( |
2339 astAdapter.getNode(argument), | 2339 astAdapter.getNode(argument), |
2340 MessageKind.GENERIC, | 2340 MessageKind.GENERIC, |
2341 {'text': 'Error: Expected a JsGetName enum value.'}); | 2341 {'text': 'Error: Expected a JsGetName enum value.'}); |
2342 // Result expected on stack. | 2342 // Result expected on stack. |
2343 stack.add(graph.addConstantNull(closedWorld)); | 2343 stack.add(graph.addConstantNull(closedWorld)); |
2344 } | 2344 } |
2345 | 2345 |
2346 void handleForeignJsEmbeddedGlobal(ir.StaticInvocation invocation) { | 2346 void handleForeignJsEmbeddedGlobal(ir.StaticInvocation invocation) { |
2347 if (_unexpectedForeignArguments(invocation, 2, 2)) { | 2347 if (_unexpectedForeignArguments(invocation, 2, 2)) { |
2348 // Result expected on stack. | 2348 // Result expected on stack. |
(...skipping 27 matching lines...) Expand all Loading... |
2376 ir.Expression nameArgument = arguments[1]; | 2376 ir.Expression nameArgument = arguments[1]; |
2377 | 2377 |
2378 nameArgument.accept(this); | 2378 nameArgument.accept(this); |
2379 HInstruction instruction = pop(); | 2379 HInstruction instruction = pop(); |
2380 | 2380 |
2381 js.Template template; | 2381 js.Template template; |
2382 if (instruction is HConstant) { | 2382 if (instruction is HConstant) { |
2383 template = astAdapter.getJsBuiltinTemplate(instruction.constant); | 2383 template = astAdapter.getJsBuiltinTemplate(instruction.constant); |
2384 } | 2384 } |
2385 if (template == null) { | 2385 if (template == null) { |
2386 compiler.reporter.reportErrorMessage( | 2386 reporter.reportErrorMessage( |
2387 astAdapter.getNode(nameArgument), | 2387 astAdapter.getNode(nameArgument), |
2388 MessageKind.GENERIC, | 2388 MessageKind.GENERIC, |
2389 {'text': 'Error: Expected a JsBuiltin enum value.'}); | 2389 {'text': 'Error: Expected a JsBuiltin enum value.'}); |
2390 // Result expected on stack. | 2390 // Result expected on stack. |
2391 stack.add(graph.addConstantNull(closedWorld)); | 2391 stack.add(graph.addConstantNull(closedWorld)); |
2392 return; | 2392 return; |
2393 } | 2393 } |
2394 | 2394 |
2395 List<HInstruction> inputs = <HInstruction>[]; | 2395 List<HInstruction> inputs = <HInstruction>[]; |
2396 for (ir.Expression argument in arguments.skip(2)) { | 2396 for (ir.Expression argument in arguments.skip(2)) { |
(...skipping 19 matching lines...) Expand all Loading... |
2416 graph.addConstantBool(false, closedWorld)); | 2416 graph.addConstantBool(false, closedWorld)); |
2417 return; | 2417 return; |
2418 } | 2418 } |
2419 String name = _foreignConstantStringArgument(invocation, 0, 'JS_GET_FLAG'); | 2419 String name = _foreignConstantStringArgument(invocation, 0, 'JS_GET_FLAG'); |
2420 bool value = false; | 2420 bool value = false; |
2421 switch (name) { | 2421 switch (name) { |
2422 case 'MUST_RETAIN_METADATA': | 2422 case 'MUST_RETAIN_METADATA': |
2423 value = backend.mirrorsData.mustRetainMetadata; | 2423 value = backend.mirrorsData.mustRetainMetadata; |
2424 break; | 2424 break; |
2425 case 'USE_CONTENT_SECURITY_POLICY': | 2425 case 'USE_CONTENT_SECURITY_POLICY': |
2426 value = compiler.options.useContentSecurityPolicy; | 2426 value = options.useContentSecurityPolicy; |
2427 break; | 2427 break; |
2428 default: | 2428 default: |
2429 compiler.reporter.reportErrorMessage( | 2429 reporter.reportErrorMessage( |
2430 astAdapter.getNode(invocation), | 2430 astAdapter.getNode(invocation), |
2431 MessageKind.GENERIC, | 2431 MessageKind.GENERIC, |
2432 {'text': 'Error: Unknown internal flag "$name".'}); | 2432 {'text': 'Error: Unknown internal flag "$name".'}); |
2433 } | 2433 } |
2434 stack.add(graph.addConstantBool(value, closedWorld)); | 2434 stack.add(graph.addConstantBool(value, closedWorld)); |
2435 } | 2435 } |
2436 | 2436 |
2437 void handleJsInterceptorConstant(ir.StaticInvocation invocation) { | 2437 void handleJsInterceptorConstant(ir.StaticInvocation invocation) { |
2438 // Single argument must be a TypeConstant which is converted into a | 2438 // Single argument must be a TypeConstant which is converted into a |
2439 // InterceptorConstant. | 2439 // InterceptorConstant. |
(...skipping 11 matching lines...) Expand all Loading... |
2451 argumentConstant.representedType is ResolutionInterfaceType) { | 2451 argumentConstant.representedType is ResolutionInterfaceType) { |
2452 ResolutionInterfaceType type = argumentConstant.representedType; | 2452 ResolutionInterfaceType type = argumentConstant.representedType; |
2453 // TODO(sra): Check that type is a subclass of [Interceptor]. | 2453 // TODO(sra): Check that type is a subclass of [Interceptor]. |
2454 ConstantValue constant = new InterceptorConstantValue(type.element); | 2454 ConstantValue constant = new InterceptorConstantValue(type.element); |
2455 HInstruction instruction = graph.addConstant(constant, closedWorld); | 2455 HInstruction instruction = graph.addConstant(constant, closedWorld); |
2456 stack.add(instruction); | 2456 stack.add(instruction); |
2457 return; | 2457 return; |
2458 } | 2458 } |
2459 } | 2459 } |
2460 | 2460 |
2461 compiler.reporter.reportErrorMessage(astAdapter.getNode(invocation), | 2461 reporter.reportErrorMessage(astAdapter.getNode(invocation), |
2462 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | 2462 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); |
2463 stack.add(graph.addConstantNull(closedWorld)); | 2463 stack.add(graph.addConstantNull(closedWorld)); |
2464 } | 2464 } |
2465 | 2465 |
2466 void handleForeignJs(ir.StaticInvocation invocation) { | 2466 void handleForeignJs(ir.StaticInvocation invocation) { |
2467 if (_unexpectedForeignArguments(invocation, 2)) { | 2467 if (_unexpectedForeignArguments(invocation, 2)) { |
2468 // Result expected on stack. | 2468 // Result expected on stack. |
2469 stack.add(graph.addConstantNull(closedWorld)); | 2469 stack.add(graph.addConstantNull(closedWorld)); |
2470 return; | 2470 return; |
2471 } | 2471 } |
2472 | 2472 |
2473 native.NativeBehavior nativeBehavior = | 2473 native.NativeBehavior nativeBehavior = |
2474 astAdapter.getNativeBehaviorForJsCall(invocation); | 2474 astAdapter.getNativeBehaviorForJsCall(invocation); |
2475 assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null, | 2475 assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null, |
2476 message: "No NativeBehavior for $invocation")); | 2476 message: "No NativeBehavior for $invocation")); |
2477 | 2477 |
2478 List<HInstruction> inputs = <HInstruction>[]; | 2478 List<HInstruction> inputs = <HInstruction>[]; |
2479 for (ir.Expression argument in invocation.arguments.positional.skip(2)) { | 2479 for (ir.Expression argument in invocation.arguments.positional.skip(2)) { |
2480 argument.accept(this); | 2480 argument.accept(this); |
2481 inputs.add(pop()); | 2481 inputs.add(pop()); |
2482 } | 2482 } |
2483 | 2483 |
2484 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) { | 2484 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) { |
2485 compiler.reporter.reportErrorMessage( | 2485 reporter.reportErrorMessage( |
2486 astAdapter.getNode(invocation), MessageKind.GENERIC, { | 2486 astAdapter.getNode(invocation), MessageKind.GENERIC, { |
2487 'text': 'Mismatch between number of placeholders' | 2487 'text': 'Mismatch between number of placeholders' |
2488 ' and number of arguments.' | 2488 ' and number of arguments.' |
2489 }); | 2489 }); |
2490 // Result expected on stack. | 2490 // Result expected on stack. |
2491 stack.add(graph.addConstantNull(closedWorld)); | 2491 stack.add(graph.addConstantNull(closedWorld)); |
2492 return; | 2492 return; |
2493 } | 2493 } |
2494 | 2494 |
2495 if (native.HasCapturedPlaceholders.check(nativeBehavior.codeTemplate.ast)) { | 2495 if (native.HasCapturedPlaceholders.check(nativeBehavior.codeTemplate.ast)) { |
2496 compiler.reporter.reportErrorMessage( | 2496 reporter.reportErrorMessage( |
2497 astAdapter.getNode(invocation), MessageKind.JS_PLACEHOLDER_CAPTURE); | 2497 astAdapter.getNode(invocation), MessageKind.JS_PLACEHOLDER_CAPTURE); |
2498 } | 2498 } |
2499 | 2499 |
2500 TypeMask ssaType = | 2500 TypeMask ssaType = |
2501 astAdapter.typeFromNativeBehavior(nativeBehavior, closedWorld); | 2501 astAdapter.typeFromNativeBehavior(nativeBehavior, closedWorld); |
2502 | 2502 |
2503 SourceInformation sourceInformation = null; | 2503 SourceInformation sourceInformation = null; |
2504 push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs, | 2504 push(new HForeignCode(nativeBehavior.codeTemplate, ssaType, inputs, |
2505 isStatement: !nativeBehavior.codeTemplate.isExpression, | 2505 isStatement: !nativeBehavior.codeTemplate.isExpression, |
2506 effects: nativeBehavior.sideEffects, | 2506 effects: nativeBehavior.sideEffects, |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2931 HInstruction awaited = pop(); | 2931 HInstruction awaited = pop(); |
2932 // TODO(herhut): Improve this type. | 2932 // TODO(herhut): Improve this type. |
2933 push(new HAwait(awaited, astAdapter.makeSubtypeOfObject(closedWorld))); | 2933 push(new HAwait(awaited, astAdapter.makeSubtypeOfObject(closedWorld))); |
2934 } | 2934 } |
2935 | 2935 |
2936 @override | 2936 @override |
2937 void visitRethrow(ir.Rethrow rethrowNode) { | 2937 void visitRethrow(ir.Rethrow rethrowNode) { |
2938 HInstruction exception = rethrowableException; | 2938 HInstruction exception = rethrowableException; |
2939 if (exception == null) { | 2939 if (exception == null) { |
2940 exception = graph.addConstantNull(closedWorld); | 2940 exception = graph.addConstantNull(closedWorld); |
2941 compiler.reporter.internalError(astAdapter.getNode(rethrowNode), | 2941 reporter.internalError(astAdapter.getNode(rethrowNode), |
2942 'rethrowableException should not be null.'); | 2942 'rethrowableException should not be null.'); |
2943 } | 2943 } |
2944 handleInTryStatement(); | 2944 handleInTryStatement(); |
2945 SourceInformation sourceInformation = null; | 2945 SourceInformation sourceInformation = null; |
2946 closeAndGotoExit(new HThrow(exception, sourceInformation, isRethrow: true)); | 2946 closeAndGotoExit(new HThrow(exception, sourceInformation, isRethrow: true)); |
2947 // ir.Rethrow is an expression so we need to push a value - a constant with | 2947 // ir.Rethrow is an expression so we need to push a value - a constant with |
2948 // no type. | 2948 // no type. |
2949 stack.add(graph.addConstantUnreachable(closedWorld)); | 2949 stack.add(graph.addConstantUnreachable(closedWorld)); |
2950 } | 2950 } |
2951 | 2951 |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3226 enterBlock.setBlockFlow( | 3226 enterBlock.setBlockFlow( |
3227 new HTryBlockInformation( | 3227 new HTryBlockInformation( |
3228 kernelBuilder.wrapStatementGraph(bodyGraph), | 3228 kernelBuilder.wrapStatementGraph(bodyGraph), |
3229 exception, | 3229 exception, |
3230 kernelBuilder.wrapStatementGraph(catchGraph), | 3230 kernelBuilder.wrapStatementGraph(catchGraph), |
3231 kernelBuilder.wrapStatementGraph(finallyGraph)), | 3231 kernelBuilder.wrapStatementGraph(finallyGraph)), |
3232 exitBlock); | 3232 exitBlock); |
3233 kernelBuilder.inTryStatement = previouslyInTryStatement; | 3233 kernelBuilder.inTryStatement = previouslyInTryStatement; |
3234 } | 3234 } |
3235 } | 3235 } |
OLD | NEW |