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