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