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 |