| 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; | 9 import '../common/codegen.dart' show CodegenRegistry; |
| 10 import '../common/names.dart'; | 10 import '../common/names.dart'; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 import '../universe/use.dart' show DynamicUse; | 34 import '../universe/use.dart' show DynamicUse; |
| 35 import '../universe/world_builder.dart' show CodegenWorldBuilder; | 35 import '../universe/world_builder.dart' show CodegenWorldBuilder; |
| 36 import '../world.dart'; | 36 import '../world.dart'; |
| 37 import 'graph_builder.dart'; | 37 import 'graph_builder.dart'; |
| 38 import 'jump_handler.dart'; | 38 import 'jump_handler.dart'; |
| 39 import 'kernel_ast_adapter.dart'; | 39 import 'kernel_ast_adapter.dart'; |
| 40 import 'kernel_string_builder.dart'; | 40 import 'kernel_string_builder.dart'; |
| 41 import 'locals_handler.dart'; | 41 import 'locals_handler.dart'; |
| 42 import 'loop_handler.dart'; | 42 import 'loop_handler.dart'; |
| 43 import 'nodes.dart'; | 43 import 'nodes.dart'; |
| 44 import 'ssa.dart'; | |
| 45 import 'ssa_branch_builder.dart'; | 44 import 'ssa_branch_builder.dart'; |
| 46 import 'switch_continue_analysis.dart'; | 45 import 'switch_continue_analysis.dart'; |
| 47 import 'type_builder.dart'; | 46 import 'type_builder.dart'; |
| 48 | 47 |
| 49 class KernelSsaBuilder extends ir.Visitor | 48 class KernelSsaBuilder extends ir.Visitor with GraphBuilder { |
| 50 with GraphBuilder, SsaBuilderFieldMixin { | |
| 51 final ir.Node target; | 49 final ir.Node target; |
| 52 final bool _targetIsConstructorBody; | 50 final bool _targetIsConstructorBody; |
| 53 final MemberEntity targetElement; | 51 final MemberEntity targetElement; |
| 54 | 52 |
| 55 /// The root node of [targetElement]. This is used as the key into the | 53 /// The root node of [targetElement]. This is used as the key into the |
| 56 /// [startFunction] of the locals handler. | 54 /// [startFunction] of the locals handler. |
| 57 // TODO(johnniwinther,efortuna): Avoid the need for AST nodes in the locals | 55 // TODO(johnniwinther,efortuna): Avoid the need for AST nodes in the locals |
| 58 // handler. | 56 // handler. |
| 59 final Node functionNode; | 57 final Node functionNode; |
| 60 final ClosedWorld closedWorld; | 58 final ClosedWorld closedWorld; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 CommonElements get _commonElements => _elementMap.commonElements; | 131 CommonElements get _commonElements => _elementMap.commonElements; |
| 134 | 132 |
| 135 HGraph build() { | 133 HGraph build() { |
| 136 return reporter.withCurrentElement(localsMap.currentMember, () { | 134 return reporter.withCurrentElement(localsMap.currentMember, () { |
| 137 // TODO(het): no reason to do this here... | 135 // TODO(het): no reason to do this here... |
| 138 HInstruction.idCounter = 0; | 136 HInstruction.idCounter = 0; |
| 139 if (target is ir.Procedure) { | 137 if (target is ir.Procedure) { |
| 140 _targetFunction = (target as ir.Procedure).function; | 138 _targetFunction = (target as ir.Procedure).function; |
| 141 buildFunctionNode(_targetFunction); | 139 buildFunctionNode(_targetFunction); |
| 142 } else if (target is ir.Field) { | 140 } else if (target is ir.Field) { |
| 143 if (handleConstantField(targetElement, registry, closedWorld)) { | |
| 144 // No code is generated for `targetElement`: All references inline the | |
| 145 // constant value. | |
| 146 return null; | |
| 147 } else if (targetElement.isStatic || targetElement.isTopLevel) { | |
| 148 backend.constants.registerLazyStatic(targetElement); | |
| 149 } | |
| 150 buildField(target); | 141 buildField(target); |
| 151 } else if (target is ir.Constructor) { | 142 } else if (target is ir.Constructor) { |
| 152 if (_targetIsConstructorBody) { | 143 if (_targetIsConstructorBody) { |
| 153 buildConstructorBody(target); | 144 buildConstructorBody(target); |
| 154 } else { | 145 } else { |
| 155 buildConstructor(target); | 146 buildConstructor(target); |
| 156 } | 147 } |
| 157 } else if (target is ir.FunctionExpression) { | 148 } else if (target is ir.FunctionExpression) { |
| 158 _targetFunction = (target as ir.FunctionExpression).function; | 149 _targetFunction = (target as ir.FunctionExpression).function; |
| 159 buildFunctionNode(_targetFunction); | 150 buildFunctionNode(_targetFunction); |
| 160 } else if (target is ir.FunctionDeclaration) { | 151 } else if (target is ir.FunctionDeclaration) { |
| 161 _targetFunction = (target as ir.FunctionDeclaration).function; | 152 _targetFunction = (target as ir.FunctionDeclaration).function; |
| 162 buildFunctionNode(_targetFunction); | 153 buildFunctionNode(_targetFunction); |
| 163 } else { | 154 } else { |
| 164 throw 'No case implemented to handle target: ' | 155 throw 'No case implemented to handle target: ' |
| 165 '$target for $targetElement'; | 156 '$target for $targetElement'; |
| 166 } | 157 } |
| 167 assert(graph.isValid()); | 158 assert(graph.isValid()); |
| 168 return graph; | 159 return graph; |
| 169 }); | 160 }); |
| 170 } | 161 } |
| 171 | 162 |
| 172 @override | |
| 173 ConstantValue getFieldInitialConstantValue(FieldEntity field) { | |
| 174 assert(field == targetElement); | |
| 175 return _elementMap.getFieldConstantValue(target); | |
| 176 } | |
| 177 | |
| 178 void buildField(ir.Field field) { | 163 void buildField(ir.Field field) { |
| 179 openFunction(); | 164 openFunction(); |
| 180 if (field.initializer != null) { | 165 if (field.initializer != null) { |
| 181 field.initializer.accept(this); | 166 field.initializer.accept(this); |
| 182 HInstruction fieldValue = pop(); | 167 HInstruction fieldValue = pop(); |
| 183 HInstruction checkInstruction = typeBuilder.potentiallyCheckOrTrustType( | 168 HInstruction checkInstruction = typeBuilder.potentiallyCheckOrTrustType( |
| 184 fieldValue, _getDartTypeIfValid(field.type)); | 169 fieldValue, _getDartTypeIfValid(field.type)); |
| 185 stack.add(checkInstruction); | 170 stack.add(checkInstruction); |
| 186 } else { | 171 } else { |
| 187 stack.add(graph.addConstantNull(closedWorld)); | 172 stack.add(graph.addConstantNull(closedWorld)); |
| (...skipping 1114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1302 loopEntryBlock.postProcessLoopHeader(); | 1287 loopEntryBlock.postProcessLoopHeader(); |
| 1303 SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock); | 1288 SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock); |
| 1304 HLoopBlockInformation loopBlockInfo = new HLoopBlockInformation( | 1289 HLoopBlockInformation loopBlockInfo = new HLoopBlockInformation( |
| 1305 HLoopBlockInformation.DO_WHILE_LOOP, | 1290 HLoopBlockInformation.DO_WHILE_LOOP, |
| 1306 null, | 1291 null, |
| 1307 wrapExpressionGraph(conditionExpression), | 1292 wrapExpressionGraph(conditionExpression), |
| 1308 wrapStatementGraph(bodyGraph), | 1293 wrapStatementGraph(bodyGraph), |
| 1309 null, | 1294 null, |
| 1310 loopEntryBlock.loopInformation.target, | 1295 loopEntryBlock.loopInformation.target, |
| 1311 loopEntryBlock.loopInformation.labels, | 1296 loopEntryBlock.loopInformation.labels, |
| 1312 // TODO(johnniwinther): Provide source information like: | 1297 sourceInformationBuilder.buildLoop(astAdapter.getNode(doStatement))); |
| 1313 // sourceInformationBuilder.buildLoop(astAdapter.getNode(doStatement)) | |
| 1314 null); | |
| 1315 loopEntryBlock.setBlockFlow(loopBlockInfo, current); | 1298 loopEntryBlock.setBlockFlow(loopBlockInfo, current); |
| 1316 loopInfo.loopBlockInformation = loopBlockInfo; | 1299 loopInfo.loopBlockInformation = loopBlockInfo; |
| 1317 } else { | 1300 } else { |
| 1318 // Since the loop has no back edge, we remove the loop information on the | 1301 // Since the loop has no back edge, we remove the loop information on the |
| 1319 // header. | 1302 // header. |
| 1320 loopEntryBlock.loopInformation = null; | 1303 loopEntryBlock.loopInformation = null; |
| 1321 | 1304 |
| 1322 if (jumpHandler.hasAnyBreak()) { | 1305 if (jumpHandler.hasAnyBreak()) { |
| 1323 // Null branchBlock because the body of the do-while loop always aborts, | 1306 // Null branchBlock because the body of the do-while loop always aborts, |
| 1324 // so we never get to the condition. | 1307 // so we never get to the condition. |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1446 | 1429 |
| 1447 /// Creates a [JumpHandler] for a statement. The node must be a jump | 1430 /// Creates a [JumpHandler] for a statement. The node must be a jump |
| 1448 /// target. If there are no breaks or continues targeting the statement, | 1431 /// target. If there are no breaks or continues targeting the statement, |
| 1449 /// a special "null handler" is returned. | 1432 /// a special "null handler" is returned. |
| 1450 /// | 1433 /// |
| 1451 /// [isLoopJump] is true when the jump handler is for a loop. This is used | 1434 /// [isLoopJump] is true when the jump handler is for a loop. This is used |
| 1452 /// to distinguish the synthesized loop created for a switch statement with | 1435 /// to distinguish the synthesized loop created for a switch statement with |
| 1453 /// continue statements from simple switch statements. | 1436 /// continue statements from simple switch statements. |
| 1454 JumpHandler createJumpHandler(ir.TreeNode node, {bool isLoopJump: false}) { | 1437 JumpHandler createJumpHandler(ir.TreeNode node, {bool isLoopJump: false}) { |
| 1455 JumpTarget target = localsMap.getJumpTarget(node); | 1438 JumpTarget target = localsMap.getJumpTarget(node); |
| 1439 assert(target is KernelJumpTarget); |
| 1456 if (target == null) { | 1440 if (target == null) { |
| 1457 // No breaks or continues to this node. | 1441 // No breaks or continues to this node. |
| 1458 return new NullJumpHandler(reporter); | 1442 return new NullJumpHandler(reporter); |
| 1459 } | 1443 } |
| 1460 if (isLoopJump && node is ir.SwitchStatement) { | 1444 if (isLoopJump && node is ir.SwitchStatement) { |
| 1461 return new KernelSwitchCaseJumpHandler(this, target, node, localsMap); | 1445 return new KernelSwitchCaseJumpHandler(this, target, node, localsMap); |
| 1462 } | 1446 } |
| 1463 | 1447 |
| 1464 return new JumpHandler(this, target); | 1448 return new JumpHandler(this, target); |
| 1465 } | 1449 } |
| (...skipping 1141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2607 stack.add(graph.addConstantNull(closedWorld)); | 2591 stack.add(graph.addConstantNull(closedWorld)); |
| 2608 return; | 2592 return; |
| 2609 } | 2593 } |
| 2610 | 2594 |
| 2611 ir.Node argument = invocation.arguments.positional.first; | 2595 ir.Node argument = invocation.arguments.positional.first; |
| 2612 argument.accept(this); | 2596 argument.accept(this); |
| 2613 HInstruction instruction = pop(); | 2597 HInstruction instruction = pop(); |
| 2614 | 2598 |
| 2615 if (instruction is HConstant) { | 2599 if (instruction is HConstant) { |
| 2616 js.Name name = | 2600 js.Name name = |
| 2617 _elementMap.getNameForJsGetName(instruction.constant, namer); | 2601 astAdapter.getNameForJsGetName(argument, instruction.constant); |
| 2618 stack.add(graph.addConstantStringFromName(name, closedWorld)); | 2602 stack.add(graph.addConstantStringFromName(name, closedWorld)); |
| 2619 return; | 2603 return; |
| 2620 } | 2604 } |
| 2621 | 2605 |
| 2622 reporter.reportErrorMessage( | 2606 reporter.reportErrorMessage( |
| 2623 _elementMap.getSpannable(targetElement, argument), | 2607 _elementMap.getSpannable(targetElement, argument), |
| 2624 MessageKind.GENERIC, | 2608 MessageKind.GENERIC, |
| 2625 {'text': 'Error: Expected a JsGetName enum value.'}); | 2609 {'text': 'Error: Expected a JsGetName enum value.'}); |
| 2626 // Result expected on stack. | 2610 // Result expected on stack. |
| 2627 stack.add(graph.addConstantNull(closedWorld)); | 2611 stack.add(graph.addConstantNull(closedWorld)); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2659 } | 2643 } |
| 2660 | 2644 |
| 2661 List<ir.Expression> arguments = invocation.arguments.positional; | 2645 List<ir.Expression> arguments = invocation.arguments.positional; |
| 2662 ir.Expression nameArgument = arguments[1]; | 2646 ir.Expression nameArgument = arguments[1]; |
| 2663 | 2647 |
| 2664 nameArgument.accept(this); | 2648 nameArgument.accept(this); |
| 2665 HInstruction instruction = pop(); | 2649 HInstruction instruction = pop(); |
| 2666 | 2650 |
| 2667 js.Template template; | 2651 js.Template template; |
| 2668 if (instruction is HConstant) { | 2652 if (instruction is HConstant) { |
| 2669 template = | 2653 template = astAdapter.getJsBuiltinTemplate(instruction.constant); |
| 2670 _elementMap.getJsBuiltinTemplate(instruction.constant, emitter); | |
| 2671 } | 2654 } |
| 2672 if (template == null) { | 2655 if (template == null) { |
| 2673 reporter.reportErrorMessage( | 2656 reporter.reportErrorMessage( |
| 2674 _elementMap.getSpannable(targetElement, nameArgument), | 2657 _elementMap.getSpannable(targetElement, nameArgument), |
| 2675 MessageKind.GENERIC, | 2658 MessageKind.GENERIC, |
| 2676 {'text': 'Error: Expected a JsBuiltin enum value.'}); | 2659 {'text': 'Error: Expected a JsBuiltin enum value.'}); |
| 2677 // Result expected on stack. | 2660 // Result expected on stack. |
| 2678 stack.add(graph.addConstantNull(closedWorld)); | 2661 stack.add(graph.addConstantNull(closedWorld)); |
| 2679 return; | 2662 return; |
| 2680 } | 2663 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2724 // Result expected on stack. | 2707 // Result expected on stack. |
| 2725 stack.add(graph.addConstantNull(closedWorld)); | 2708 stack.add(graph.addConstantNull(closedWorld)); |
| 2726 return; | 2709 return; |
| 2727 } | 2710 } |
| 2728 ir.Expression argument = invocation.arguments.positional.single; | 2711 ir.Expression argument = invocation.arguments.positional.single; |
| 2729 argument.accept(this); | 2712 argument.accept(this); |
| 2730 HInstruction argumentInstruction = pop(); | 2713 HInstruction argumentInstruction = pop(); |
| 2731 if (argumentInstruction is HConstant) { | 2714 if (argumentInstruction is HConstant) { |
| 2732 ConstantValue argumentConstant = argumentInstruction.constant; | 2715 ConstantValue argumentConstant = argumentInstruction.constant; |
| 2733 if (argumentConstant is TypeConstantValue && | 2716 if (argumentConstant is TypeConstantValue && |
| 2734 argumentConstant.representedType is InterfaceType) { | 2717 argumentConstant.representedType is ResolutionInterfaceType) { |
| 2735 InterfaceType type = argumentConstant.representedType; | 2718 ResolutionInterfaceType type = argumentConstant.representedType; |
| 2736 // TODO(sra): Check that type is a subclass of [Interceptor]. | 2719 // TODO(sra): Check that type is a subclass of [Interceptor]. |
| 2737 ConstantValue constant = new InterceptorConstantValue(type.element); | 2720 ConstantValue constant = new InterceptorConstantValue(type.element); |
| 2738 HInstruction instruction = graph.addConstant(constant, closedWorld); | 2721 HInstruction instruction = graph.addConstant(constant, closedWorld); |
| 2739 stack.add(instruction); | 2722 stack.add(instruction); |
| 2740 return; | 2723 return; |
| 2741 } | 2724 } |
| 2742 } | 2725 } |
| 2743 | 2726 |
| 2744 reporter.reportErrorMessage( | 2727 reporter.reportErrorMessage( |
| 2745 _elementMap.getSpannable(targetElement, invocation), | 2728 _elementMap.getSpannable(targetElement, invocation), |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3048 | 3031 |
| 3049 // TODO(sra): For JS-interop targets, process arguments differently. | 3032 // TODO(sra): For JS-interop targets, process arguments differently. |
| 3050 List<HInstruction> arguments = | 3033 List<HInstruction> arguments = |
| 3051 _visitArgumentsForStaticTarget(target.function, invocation.arguments); | 3034 _visitArgumentsForStaticTarget(target.function, invocation.arguments); |
| 3052 ConstructorEntity constructor = _elementMap.getConstructor(target); | 3035 ConstructorEntity constructor = _elementMap.getConstructor(target); |
| 3053 ClassEntity cls = constructor.enclosingClass; | 3036 ClassEntity cls = constructor.enclosingClass; |
| 3054 if (backend.rtiNeed.classNeedsRti(cls)) { | 3037 if (backend.rtiNeed.classNeedsRti(cls)) { |
| 3055 _addTypeArguments(arguments, invocation.arguments); | 3038 _addTypeArguments(arguments, invocation.arguments); |
| 3056 } | 3039 } |
| 3057 TypeMask typeMask = new TypeMask.nonNullExact(cls, closedWorld); | 3040 TypeMask typeMask = new TypeMask.nonNullExact(cls, closedWorld); |
| 3058 InterfaceType type = _elementMap.createInterfaceType( | |
| 3059 target.enclosingClass, invocation.arguments.types); | |
| 3060 addImplicitInstantiation(type); | |
| 3061 _pushStaticInvocation(constructor, arguments, typeMask); | 3041 _pushStaticInvocation(constructor, arguments, typeMask); |
| 3062 removeImplicitInstantiation(type); | |
| 3063 } | 3042 } |
| 3064 | 3043 |
| 3065 @override | 3044 @override |
| 3066 void visitIsExpression(ir.IsExpression isExpression) { | 3045 void visitIsExpression(ir.IsExpression isExpression) { |
| 3067 isExpression.operand.accept(this); | 3046 isExpression.operand.accept(this); |
| 3068 HInstruction expression = pop(); | 3047 HInstruction expression = pop(); |
| 3069 pushIsTest(isExpression, isExpression.type, expression); | 3048 pushIsTest(isExpression, isExpression.type, expression); |
| 3070 } | 3049 } |
| 3071 | 3050 |
| 3072 void pushIsTest(ir.Node node, ir.DartType type, HInstruction expression) { | 3051 void pushIsTest(ir.Node node, ir.DartType type, HInstruction expression) { |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3492 enterBlock.setBlockFlow( | 3471 enterBlock.setBlockFlow( |
| 3493 new HTryBlockInformation( | 3472 new HTryBlockInformation( |
| 3494 kernelBuilder.wrapStatementGraph(bodyGraph), | 3473 kernelBuilder.wrapStatementGraph(bodyGraph), |
| 3495 exception, | 3474 exception, |
| 3496 kernelBuilder.wrapStatementGraph(catchGraph), | 3475 kernelBuilder.wrapStatementGraph(catchGraph), |
| 3497 kernelBuilder.wrapStatementGraph(finallyGraph)), | 3476 kernelBuilder.wrapStatementGraph(finallyGraph)), |
| 3498 exitBlock); | 3477 exitBlock); |
| 3499 kernelBuilder.inTryStatement = previouslyInTryStatement; | 3478 kernelBuilder.inTryStatement = previouslyInTryStatement; |
| 3500 } | 3479 } |
| 3501 } | 3480 } |
| OLD | NEW |