Chromium Code Reviews| 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 |