| 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 |