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 |