| 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 27 matching lines...) Expand all Loading... |
| 38 import 'kernel_string_builder.dart'; | 38 import 'kernel_string_builder.dart'; |
| 39 import 'locals_handler.dart'; | 39 import 'locals_handler.dart'; |
| 40 import 'loop_handler.dart'; | 40 import 'loop_handler.dart'; |
| 41 import 'nodes.dart'; | 41 import 'nodes.dart'; |
| 42 import 'ssa_branch_builder.dart'; | 42 import 'ssa_branch_builder.dart'; |
| 43 import 'switch_continue_analysis.dart'; | 43 import 'switch_continue_analysis.dart'; |
| 44 import 'type_builder.dart'; | 44 import 'type_builder.dart'; |
| 45 import 'types.dart' show TypeMaskFactory; | 45 import 'types.dart' show TypeMaskFactory; |
| 46 | 46 |
| 47 class KernelSsaBuilder extends ir.Visitor with GraphBuilder { | 47 class KernelSsaBuilder extends ir.Visitor with GraphBuilder { |
| 48 ir.Node target; | 48 final ir.Node target; |
| 49 bool _targetIsConstructorBody = false; | 49 final bool _targetIsConstructorBody; |
| 50 final MemberEntity targetElement; | 50 final MemberEntity targetElement; |
| 51 | 51 |
| 52 /// The root node of [targetElement]. This is used as the key into the | 52 /// The root node of [targetElement]. This is used as the key into the |
| 53 /// [startFunction] of the locals handler. | 53 /// [startFunction] of the locals handler. |
| 54 // TODO(johnniwinther,efortuna): Avoid the need for AST nodes in the locals | 54 // TODO(johnniwinther,efortuna): Avoid the need for AST nodes in the locals |
| 55 // handler. | 55 // handler. |
| 56 final Node functionNode; | 56 final Node functionNode; |
| 57 final ClosedWorld closedWorld; | 57 final ClosedWorld closedWorld; |
| 58 final CodegenRegistry registry; | 58 final CodegenRegistry registry; |
| 59 final ClosureClassMaps closureToClassMapper; |
| 59 | 60 |
| 60 /// Helper accessor for all kernel function-like targets (Procedure, | 61 /// Helper accessor for all kernel function-like targets (Procedure, |
| 61 /// FunctionExpression, FunctionDeclaration) of the inner FunctionNode itself. | 62 /// FunctionExpression, FunctionDeclaration) of the inner FunctionNode itself. |
| 62 /// If the current target is not a function-like target, _targetFunction will | 63 /// If the current target is not a function-like target, _targetFunction will |
| 63 /// be null. | 64 /// be null. |
| 64 ir.FunctionNode _targetFunction; | 65 ir.FunctionNode _targetFunction; |
| 65 | 66 |
| 66 /// A stack of [ResolutionDartType]s that have been seen during inlining of | 67 /// A stack of [ResolutionDartType]s that have been seen during inlining of |
| 67 /// factory constructors. These types are preserved in [HInvokeStatic]s and | 68 /// factory constructors. These types are preserved in [HInvokeStatic]s and |
| 68 /// [HCreate]s inside the inline code and registered during code generation | 69 /// [HCreate]s inside the inline code and registered during code generation |
| (...skipping 21 matching lines...) Expand all Loading... |
| 90 | 91 |
| 91 final Map<ir.VariableDeclaration, HInstruction> letBindings = | 92 final Map<ir.VariableDeclaration, HInstruction> letBindings = |
| 92 <ir.VariableDeclaration, HInstruction>{}; | 93 <ir.VariableDeclaration, HInstruction>{}; |
| 93 | 94 |
| 94 /// True if we are visiting the expression of a throw statement; we assume | 95 /// True if we are visiting the expression of a throw statement; we assume |
| 95 /// this is a slow path. | 96 /// this is a slow path. |
| 96 bool _inExpressionOfThrow = false; | 97 bool _inExpressionOfThrow = false; |
| 97 | 98 |
| 98 KernelSsaBuilder( | 99 KernelSsaBuilder( |
| 99 this.targetElement, | 100 this.targetElement, |
| 101 this.target, |
| 100 this.compiler, | 102 this.compiler, |
| 101 this._elementMap, | 103 this._elementMap, |
| 102 this._typeInferenceMap, | 104 this._typeInferenceMap, |
| 103 this.closedWorld, | 105 this.closedWorld, |
| 104 this.registry, | 106 this.registry, |
| 107 this.closureToClassMapper, |
| 105 // TODO(het): Should sourceInformationBuilder be in GraphBuilder? | 108 // TODO(het): Should sourceInformationBuilder be in GraphBuilder? |
| 106 this.sourceInformationBuilder, | 109 this.sourceInformationBuilder, |
| 107 this.functionNode) { | 110 this.functionNode, |
| 111 {bool targetIsConstructorBody: false}) |
| 112 : this._targetIsConstructorBody = targetIsConstructorBody { |
| 108 this.loopHandler = new KernelLoopHandler(this); | 113 this.loopHandler = new KernelLoopHandler(this); |
| 109 typeBuilder = new TypeBuilder(this); | 114 typeBuilder = new TypeBuilder(this); |
| 110 graph.element = targetElement; | 115 graph.element = targetElement; |
| 111 graph.sourceInformation = | 116 graph.sourceInformation = |
| 112 sourceInformationBuilder.buildVariableDeclaration(); | 117 sourceInformationBuilder.buildVariableDeclaration(); |
| 113 this.localsHandler = new LocalsHandler(this, targetElement, targetElement, | 118 this.localsHandler = new LocalsHandler(this, targetElement, targetElement, |
| 114 targetElement.enclosingClass, null, nativeData, interceptorData); | 119 targetElement.enclosingClass, null, nativeData, interceptorData); |
| 115 target = astAdapter.getInitialKernelNode(targetElement); | |
| 116 if (targetElement is ConstructorBodyElement) { | |
| 117 _targetIsConstructorBody = true; | |
| 118 } | |
| 119 _targetStack.add(target); | 120 _targetStack.add(target); |
| 120 } | 121 } |
| 121 | 122 |
| 122 @deprecated // Use [_elementMap] instead. | 123 @deprecated // Use [_elementMap] instead. |
| 123 KernelAstAdapter get astAdapter => _elementMap; | 124 KernelAstAdapter get astAdapter => _elementMap; |
| 124 | 125 |
| 125 CommonElements get _commonElements => _elementMap.commonElements; | 126 CommonElements get _commonElements => _elementMap.commonElements; |
| 126 | 127 |
| 127 HGraph build() { | 128 HGraph build() { |
| 128 // TODO(het): no reason to do this here... | 129 // TODO(het): no reason to do this here... |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 for (ir.Constructor body in constructorChain.reversed) { | 308 for (ir.Constructor body in constructorChain.reversed) { |
| 308 if (_isEmptyStatement(body.function.body)) continue; | 309 if (_isEmptyStatement(body.function.body)) continue; |
| 309 | 310 |
| 310 List<HInstruction> bodyCallInputs = <HInstruction>[]; | 311 List<HInstruction> bodyCallInputs = <HInstruction>[]; |
| 311 bodyCallInputs.add(newObject); | 312 bodyCallInputs.add(newObject); |
| 312 | 313 |
| 313 // Pass uncaptured arguments first, captured arguments in a box, then type | 314 // Pass uncaptured arguments first, captured arguments in a box, then type |
| 314 // arguments. | 315 // arguments. |
| 315 | 316 |
| 316 ConstructorElement constructorElement = astAdapter.getElement(body); | 317 ConstructorElement constructorElement = astAdapter.getElement(body); |
| 317 ClosureClassMap parameterClosureData = closureToClassMapper | 318 ClosureClassMap parameterClosureData = |
| 318 .getClosureToClassMapping(constructorElement.resolvedAst); | 319 closureToClassMapper.getMemberMap(constructorElement); |
| 319 | 320 |
| 320 var functionSignature = astAdapter.getFunctionSignature(body.function); | 321 var functionSignature = astAdapter.getFunctionSignature(body.function); |
| 321 // Provide the parameters to the generative constructor body. | 322 // Provide the parameters to the generative constructor body. |
| 322 functionSignature.orderedForEachParameter((ParameterElement parameter) { | 323 functionSignature.orderedForEachParameter((ParameterElement parameter) { |
| 323 // If [parameter] is boxed, it will be a field in the box passed as the | 324 // If [parameter] is boxed, it will be a field in the box passed as the |
| 324 // last parameter. So no need to directly pass it. | 325 // last parameter. So no need to directly pass it. |
| 325 if (!localsHandler.isBoxed(parameter)) { | 326 if (!localsHandler.isBoxed(parameter)) { |
| 326 bodyCallInputs.add(localsHandler.readLocal(parameter)); | 327 bodyCallInputs.add(localsHandler.readLocal(parameter)); |
| 327 } | 328 } |
| 328 }); | 329 }); |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 HInstruction argument = arguments[index++]; | 577 HInstruction argument = arguments[index++]; |
| 577 // Because we are inlining the initializer, we must update | 578 // Because we are inlining the initializer, we must update |
| 578 // what was given as parameter. This will be used in case | 579 // what was given as parameter. This will be used in case |
| 579 // there is a parameter check expression in the initializer. | 580 // there is a parameter check expression in the initializer. |
| 580 parameters[parameter] = argument; | 581 parameters[parameter] = argument; |
| 581 localsHandler.updateLocal(parameter, argument); | 582 localsHandler.updateLocal(parameter, argument); |
| 582 }); | 583 }); |
| 583 | 584 |
| 584 // Set the locals handler state as if we were inlining the constructor. | 585 // Set the locals handler state as if we were inlining the constructor. |
| 585 astAdapter.pushResolvedAst(constructor); | 586 astAdapter.pushResolvedAst(constructor); |
| 586 AstElement astElement = astAdapter.getElement(constructor); | 587 ConstructorElement astElement = astAdapter.getElement(constructor); |
| 587 ResolvedAst resolvedAst = astElement.resolvedAst; | 588 ResolvedAst resolvedAst = astElement.resolvedAst; |
| 588 ClosureClassMap oldClosureData = localsHandler.closureData; | 589 ClosureClassMap oldClosureData = localsHandler.closureData; |
| 589 ClosureClassMap newClosureData = | 590 ClosureClassMap newClosureData = |
| 590 compiler.closureToClassMapper.getClosureToClassMapping(resolvedAst); | 591 closureToClassMapper.getMemberMap(astElement); |
| 591 localsHandler.closureData = newClosureData; | 592 localsHandler.closureData = newClosureData; |
| 592 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 593 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
| 593 localsHandler.enterScope( | 594 localsHandler.enterScope(resolvedAst.node, |
| 594 resolvedAst.node, astAdapter.getElement(constructor)); | 595 forGenerativeConstructorBody: astElement.isGenerativeConstructorBody); |
| 595 } | 596 } |
| 596 inlinedFrom(constructor, () { | 597 inlinedFrom(constructor, () { |
| 597 _buildInitializers(constructor, constructorChain, fieldValues); | 598 _buildInitializers(constructor, constructorChain, fieldValues); |
| 598 }); | 599 }); |
| 599 localsHandler.closureData = oldClosureData; | 600 localsHandler.closureData = oldClosureData; |
| 600 astAdapter.popResolvedAstStack(); | 601 astAdapter.popResolvedAstStack(); |
| 601 } | 602 } |
| 602 | 603 |
| 603 /// Builds generative constructor body. | 604 /// Builds generative constructor body. |
| 604 void buildConstructorBody(ir.Constructor constructor) { | 605 void buildConstructorBody(ir.Constructor constructor) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 void removeImplicitInstantiation(ResolutionDartType type) { | 657 void removeImplicitInstantiation(ResolutionDartType type) { |
| 657 if (type != null) { | 658 if (type != null) { |
| 658 currentImplicitInstantiations.removeLast(); | 659 currentImplicitInstantiations.removeLast(); |
| 659 } | 660 } |
| 660 } | 661 } |
| 661 | 662 |
| 662 void openFunction() { | 663 void openFunction() { |
| 663 HBasicBlock block = graph.addNewBlock(); | 664 HBasicBlock block = graph.addNewBlock(); |
| 664 open(graph.entry); | 665 open(graph.entry); |
| 665 | 666 |
| 666 localsHandler.startFunction(targetElement, functionNode); | 667 localsHandler.startFunction(targetElement, functionNode, |
| 668 isGenerativeConstructorBody: _targetIsConstructorBody); |
| 667 close(new HGoto()).addSuccessor(block); | 669 close(new HGoto()).addSuccessor(block); |
| 668 | 670 |
| 669 open(block); | 671 open(block); |
| 670 } | 672 } |
| 671 | 673 |
| 672 void closeFunction() { | 674 void closeFunction() { |
| 673 if (!isAborted()) closeAndGotoExit(new HGoto()); | 675 if (!isAborted()) closeAndGotoExit(new HGoto()); |
| 674 graph.finalize(); | 676 graph.finalize(); |
| 675 } | 677 } |
| 676 | 678 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 Element get sourceElement => _sourceElementForTarget(_targetStack.last); | 715 Element get sourceElement => _sourceElementForTarget(_targetStack.last); |
| 714 | 716 |
| 715 List<ir.Node> _targetStack = <ir.Node>[]; | 717 List<ir.Node> _targetStack = <ir.Node>[]; |
| 716 | 718 |
| 717 Element _sourceElementForTarget(ir.Node target) { | 719 Element _sourceElementForTarget(ir.Node target) { |
| 718 // For closure-converted (i.e. local functions) the source element is the | 720 // For closure-converted (i.e. local functions) the source element is the |
| 719 // 'call' method of the class that represents the closure. | 721 // 'call' method of the class that represents the closure. |
| 720 Element callMethodOfClosureClass() { | 722 Element callMethodOfClosureClass() { |
| 721 LocalFunctionElement element = astAdapter.getElement(target); | 723 LocalFunctionElement element = astAdapter.getElement(target); |
| 722 ClosureClassMap classMap = | 724 ClosureClassMap classMap = |
| 723 closureToClassMapper.getClosureToClassMapping(element.resolvedAst); | 725 closureToClassMapper.getLocalFunctionMap(element); |
| 724 return classMap.callElement; | 726 return classMap.callElement; |
| 725 } | 727 } |
| 726 | 728 |
| 727 if (target is ir.FunctionExpression) { | 729 if (target is ir.FunctionExpression) { |
| 728 return callMethodOfClosureClass(); | 730 return callMethodOfClosureClass(); |
| 729 } | 731 } |
| 730 if (target is ir.FunctionDeclaration) { | 732 if (target is ir.FunctionDeclaration) { |
| 731 return callMethodOfClosureClass(); | 733 return callMethodOfClosureClass(); |
| 732 } | 734 } |
| 733 Element element = astAdapter.getElement(target); | 735 Element element = astAdapter.getElement(target); |
| (...skipping 1502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2236 // TODO(sra): Evaluate constant in ir.Node domain. | 2238 // TODO(sra): Evaluate constant in ir.Node domain. |
| 2237 ConstantValue constant = | 2239 ConstantValue constant = |
| 2238 astAdapter.getConstantForParameterDefaultValue(initializer); | 2240 astAdapter.getConstantForParameterDefaultValue(initializer); |
| 2239 if (constant == null) return graph.addConstantNull(closedWorld); | 2241 if (constant == null) return graph.addConstantNull(closedWorld); |
| 2240 return graph.addConstant(constant, closedWorld); | 2242 return graph.addConstant(constant, closedWorld); |
| 2241 } | 2243 } |
| 2242 | 2244 |
| 2243 @override | 2245 @override |
| 2244 void visitStaticInvocation(ir.StaticInvocation invocation) { | 2246 void visitStaticInvocation(ir.StaticInvocation invocation) { |
| 2245 ir.Procedure target = invocation.target; | 2247 ir.Procedure target = invocation.target; |
| 2246 if (astAdapter.isForeignLibrary(target.enclosingLibrary)) { | 2248 if (_elementMap.isForeignLibrary(target.enclosingLibrary)) { |
| 2247 handleInvokeStaticForeign(invocation, target); | 2249 handleInvokeStaticForeign(invocation, target); |
| 2248 return; | 2250 return; |
| 2249 } | 2251 } |
| 2250 FunctionEntity function = _elementMap.getMember(target); | 2252 FunctionEntity function = _elementMap.getMember(target); |
| 2251 TypeMask typeMask = _typeInferenceMap.getReturnTypeOf(function); | 2253 TypeMask typeMask = _typeInferenceMap.getReturnTypeOf(function); |
| 2252 | 2254 |
| 2253 // TODO(sra): For JS interop external functions, use a different function to | 2255 // TODO(sra): For JS interop external functions, use a different function to |
| 2254 // build arguments. | 2256 // build arguments. |
| 2255 List<HInstruction> arguments = | 2257 List<HInstruction> arguments = |
| 2256 _visitArgumentsForStaticTarget(target.function, invocation.arguments); | 2258 _visitArgumentsForStaticTarget(target.function, invocation.arguments); |
| (...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2748 push(new HInvokeDynamicSetter(selector, mask, null, inputs, type)); | 2750 push(new HInvokeDynamicSetter(selector, mask, null, inputs, type)); |
| 2749 } else { | 2751 } else { |
| 2750 push(new HInvokeDynamicMethod( | 2752 push(new HInvokeDynamicMethod( |
| 2751 selector, mask, inputs, type, isIntercepted)); | 2753 selector, mask, inputs, type, isIntercepted)); |
| 2752 } | 2754 } |
| 2753 } | 2755 } |
| 2754 | 2756 |
| 2755 @override | 2757 @override |
| 2756 visitFunctionNode(ir.FunctionNode node) { | 2758 visitFunctionNode(ir.FunctionNode node) { |
| 2757 LocalFunctionElement methodElement = astAdapter.getElement(node); | 2759 LocalFunctionElement methodElement = astAdapter.getElement(node); |
| 2758 ClosureClassMap nestedClosureData = closureToClassMapper | 2760 ClosureClassMap nestedClosureData = |
| 2759 .getClosureToClassMapping(methodElement.resolvedAst); | 2761 closureToClassMapper.getLocalFunctionMap(methodElement); |
| 2760 assert(nestedClosureData != null); | 2762 assert(nestedClosureData != null); |
| 2761 assert(nestedClosureData.closureClassElement != null); | 2763 assert(nestedClosureData.closureClassElement != null); |
| 2762 ClosureClassElement closureClassElement = | 2764 ClosureClassElement closureClassElement = |
| 2763 nestedClosureData.closureClassElement; | 2765 nestedClosureData.closureClassElement; |
| 2764 MethodElement callElement = nestedClosureData.callElement; | 2766 MethodElement callElement = nestedClosureData.callElement; |
| 2765 | 2767 |
| 2766 List<HInstruction> capturedVariables = <HInstruction>[]; | 2768 List<HInstruction> capturedVariables = <HInstruction>[]; |
| 2767 closureClassElement.closureFields.forEach((ClosureFieldElement field) { | 2769 closureClassElement.closureFields.forEach((ClosureFieldElement field) { |
| 2768 Local capturedLocal = | 2770 Local capturedLocal = |
| 2769 nestedClosureData.getLocalVariableForClosureField(field); | 2771 nestedClosureData.getLocalVariableForClosureField(field); |
| (...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3399 enterBlock.setBlockFlow( | 3401 enterBlock.setBlockFlow( |
| 3400 new HTryBlockInformation( | 3402 new HTryBlockInformation( |
| 3401 kernelBuilder.wrapStatementGraph(bodyGraph), | 3403 kernelBuilder.wrapStatementGraph(bodyGraph), |
| 3402 exception, | 3404 exception, |
| 3403 kernelBuilder.wrapStatementGraph(catchGraph), | 3405 kernelBuilder.wrapStatementGraph(catchGraph), |
| 3404 kernelBuilder.wrapStatementGraph(finallyGraph)), | 3406 kernelBuilder.wrapStatementGraph(finallyGraph)), |
| 3405 exitBlock); | 3407 exitBlock); |
| 3406 kernelBuilder.inTryStatement = previouslyInTryStatement; | 3408 kernelBuilder.inTryStatement = previouslyInTryStatement; |
| 3407 } | 3409 } |
| 3408 } | 3410 } |
| OLD | NEW |