| 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 '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
| 9 import '../common/names.dart'; | 9 import '../common/names.dart'; |
| 10 import '../common/tasks.dart' show CompilerTask; | 10 import '../common/tasks.dart' show CompilerTask; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 import '../universe/selector.dart'; | 22 import '../universe/selector.dart'; |
| 23 import '../universe/use.dart' show TypeUse; | 23 import '../universe/use.dart' show TypeUse; |
| 24 import 'graph_builder.dart'; | 24 import 'graph_builder.dart'; |
| 25 import 'kernel_ast_adapter.dart'; | 25 import 'kernel_ast_adapter.dart'; |
| 26 import 'kernel_string_builder.dart'; | 26 import 'kernel_string_builder.dart'; |
| 27 import 'locals_handler.dart'; | 27 import 'locals_handler.dart'; |
| 28 import 'loop_handler.dart'; | 28 import 'loop_handler.dart'; |
| 29 import 'nodes.dart'; | 29 import 'nodes.dart'; |
| 30 import 'ssa_branch_builder.dart'; | 30 import 'ssa_branch_builder.dart'; |
| 31 import 'type_builder.dart'; | 31 import 'type_builder.dart'; |
| 32 import 'types.dart' show TypeMaskFactory; |
| 32 | 33 |
| 33 class SsaKernelBuilderTask extends CompilerTask { | 34 class SsaKernelBuilderTask extends CompilerTask { |
| 34 final JavaScriptBackend backend; | 35 final JavaScriptBackend backend; |
| 35 final SourceInformationStrategy sourceInformationFactory; | 36 final SourceInformationStrategy sourceInformationFactory; |
| 36 | 37 |
| 37 String get name => 'SSA kernel builder'; | 38 String get name => 'SSA kernel builder'; |
| 38 | 39 |
| 39 SsaKernelBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory) | 40 SsaKernelBuilderTask(JavaScriptBackend backend, this.sourceInformationFactory) |
| 40 : backend = backend, | 41 : backend = backend, |
| 41 super(backend.compiler.measurer); | 42 super(backend.compiler.measurer); |
| 42 | 43 |
| 43 HGraph build(CodegenWorkItem work) { | 44 HGraph build(CodegenWorkItem work) { |
| 44 return measure(() { | 45 return measure(() { |
| 45 AstElement element = work.element.implementation; | 46 AstElement element = work.element.implementation; |
| 46 Kernel kernel = backend.kernelTask.kernel; | 47 Kernel kernel = backend.kernelTask.kernel; |
| 47 KernelSsaBuilder builder = new KernelSsaBuilder(element, work.resolvedAst, | 48 KernelSsaBuilder builder = new KernelSsaBuilder(element, work.resolvedAst, |
| 48 backend.compiler, work.registry, sourceInformationFactory, kernel); | 49 backend.compiler, work.registry, sourceInformationFactory, kernel); |
| 49 return builder.build(); | 50 return builder.build(); |
| 50 }); | 51 }); |
| 51 } | 52 } |
| 52 } | 53 } |
| 53 | 54 |
| 54 class KernelSsaBuilder extends ir.Visitor with GraphBuilder { | 55 class KernelSsaBuilder extends ir.Visitor with GraphBuilder { |
| 55 ir.Node target; | 56 ir.Node target; |
| 56 final AstElement targetElement; | 57 final AstElement targetElement; |
| 57 final ResolvedAst resolvedAst; | 58 final ResolvedAst resolvedAst; |
| 58 final CodegenRegistry registry; | 59 final CodegenRegistry registry; |
| 59 | 60 |
| 61 /// A stack of [DartType]s that have been seen during inlining of factory |
| 62 /// constructors. These types are preserved in [HInvokeStatic]s and |
| 63 /// [HCreate]s inside the inline code and registered during code generation |
| 64 /// for these nodes. |
| 65 // TODO(karlklose): consider removing this and keeping the (substituted) types |
| 66 // of the type variables in an environment (like the [LocalsHandler]). |
| 67 final List<DartType> currentImplicitInstantiations = <DartType>[]; |
| 68 |
| 60 @override | 69 @override |
| 61 JavaScriptBackend get backend => compiler.backend; | 70 JavaScriptBackend get backend => compiler.backend; |
| 62 | 71 |
| 63 @override | 72 @override |
| 64 TreeElements get elements => resolvedAst.elements; | 73 TreeElements get elements => resolvedAst.elements; |
| 65 | 74 |
| 66 SourceInformationBuilder sourceInformationBuilder; | 75 SourceInformationBuilder sourceInformationBuilder; |
| 67 KernelAstAdapter astAdapter; | 76 KernelAstAdapter astAdapter; |
| 68 LoopHandler<ir.Node> loopHandler; | 77 LoopHandler<ir.Node> loopHandler; |
| 69 TypeBuilder typeBuilder; | 78 TypeBuilder typeBuilder; |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 type, kind, original.instructionType, reifiedType, original); | 322 type, kind, original.instructionType, reifiedType, original); |
| 314 } | 323 } |
| 315 | 324 |
| 316 /// Builds a SSA graph for [procedure]. | 325 /// Builds a SSA graph for [procedure]. |
| 317 void buildProcedure(ir.Procedure procedure) { | 326 void buildProcedure(ir.Procedure procedure) { |
| 318 openFunction(); | 327 openFunction(); |
| 319 procedure.function.body.accept(this); | 328 procedure.function.body.accept(this); |
| 320 closeFunction(); | 329 closeFunction(); |
| 321 } | 330 } |
| 322 | 331 |
| 332 void addImplicitInstantiation(DartType type) { |
| 333 if (type != null) { |
| 334 currentImplicitInstantiations.add(type); |
| 335 } |
| 336 } |
| 337 |
| 338 void removeImplicitInstantiation(DartType type) { |
| 339 if (type != null) { |
| 340 currentImplicitInstantiations.removeLast(); |
| 341 } |
| 342 } |
| 343 |
| 323 void openFunction() { | 344 void openFunction() { |
| 324 HBasicBlock block = graph.addNewBlock(); | 345 HBasicBlock block = graph.addNewBlock(); |
| 325 open(graph.entry); | 346 open(graph.entry); |
| 326 | 347 |
| 327 Node function; | 348 Node function; |
| 328 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 349 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
| 329 function = resolvedAst.node; | 350 function = resolvedAst.node; |
| 330 } | 351 } |
| 331 localsHandler.startFunction(targetElement, function); | 352 localsHandler.startFunction(targetElement, function); |
| 332 close(new HGoto()).addSuccessor(block); | 353 close(new HGoto()).addSuccessor(block); |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 stack.add(graph.addConstant( | 729 stack.add(graph.addConstant( |
| 709 astAdapter.getConstantForSymbol(symbolLiteral), compiler)); | 730 astAdapter.getConstantForSymbol(symbolLiteral), compiler)); |
| 710 registry?.registerConstSymbol(symbolLiteral.value); | 731 registry?.registerConstSymbol(symbolLiteral.value); |
| 711 } | 732 } |
| 712 | 733 |
| 713 @override | 734 @override |
| 714 void visitNullLiteral(ir.NullLiteral nullLiteral) { | 735 void visitNullLiteral(ir.NullLiteral nullLiteral) { |
| 715 stack.add(graph.addConstantNull(compiler)); | 736 stack.add(graph.addConstantNull(compiler)); |
| 716 } | 737 } |
| 717 | 738 |
| 718 HInstruction setRtiIfNeeded(HInstruction object, ir.ListLiteral listLiteral) { | 739 /// Set the runtime type information if necessary. |
| 740 HInstruction setListRuntimeTypeInfoIfNeeded( |
| 741 HInstruction object, ir.ListLiteral listLiteral) { |
| 719 InterfaceType type = localsHandler | 742 InterfaceType type = localsHandler |
| 720 .substInContext(elements.getType(astAdapter.getNode(listLiteral))); | 743 .substInContext(elements.getType(astAdapter.getNode(listLiteral))); |
| 721 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { | 744 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { |
| 722 return object; | 745 return object; |
| 723 } | 746 } |
| 724 List<HInstruction> arguments = <HInstruction>[]; | 747 List<HInstruction> arguments = <HInstruction>[]; |
| 725 for (DartType argument in type.typeArguments) { | 748 for (DartType argument in type.typeArguments) { |
| 726 arguments.add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); | 749 arguments.add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); |
| 727 } | 750 } |
| 728 // TODO(15489): Register at codegen. | 751 // TODO(15489): Register at codegen. |
| 729 registry?.registerInstantiation(type); | 752 registry?.registerInstantiation(type); |
| 730 return callSetRuntimeTypeInfoWithTypeArguments(type, arguments, object); | 753 return callSetRuntimeTypeInfoWithTypeArguments(type, arguments, object); |
| 731 } | 754 } |
| 732 | 755 |
| 733 @override | 756 @override |
| 734 void visitListLiteral(ir.ListLiteral listLiteral) { | 757 void visitListLiteral(ir.ListLiteral listLiteral) { |
| 735 HInstruction listInstruction; | 758 HInstruction listInstruction; |
| 736 if (listLiteral.isConst) { | 759 if (listLiteral.isConst) { |
| 737 listInstruction = | 760 listInstruction = |
| 738 graph.addConstant(astAdapter.getConstantFor(listLiteral), compiler); | 761 graph.addConstant(astAdapter.getConstantFor(listLiteral), compiler); |
| 739 } else { | 762 } else { |
| 740 List<HInstruction> elements = <HInstruction>[]; | 763 List<HInstruction> elements = <HInstruction>[]; |
| 741 for (ir.Expression element in listLiteral.expressions) { | 764 for (ir.Expression element in listLiteral.expressions) { |
| 742 element.accept(this); | 765 element.accept(this); |
| 743 elements.add(pop()); | 766 elements.add(pop()); |
| 744 } | 767 } |
| 745 listInstruction = new HLiteralList(elements, backend.extendableArrayType); | 768 listInstruction = new HLiteralList(elements, backend.extendableArrayType); |
| 746 add(listInstruction); | 769 add(listInstruction); |
| 747 listInstruction = setRtiIfNeeded(listInstruction, listLiteral); | 770 listInstruction = |
| 771 setListRuntimeTypeInfoIfNeeded(listInstruction, listLiteral); |
| 748 } | 772 } |
| 749 | 773 |
| 750 TypeMask type = astAdapter.typeOfNewList(targetElement, listLiteral); | 774 TypeMask type = astAdapter.typeOfNewList(targetElement, listLiteral); |
| 751 if (!type.containsAll(compiler.closedWorld)) { | 775 if (!type.containsAll(compiler.closedWorld)) { |
| 752 listInstruction.instructionType = type; | 776 listInstruction.instructionType = type; |
| 753 } | 777 } |
| 754 stack.add(listInstruction); | 778 stack.add(listInstruction); |
| 755 } | 779 } |
| 756 | 780 |
| 757 @override | 781 @override |
| (...skipping 18 matching lines...) Expand all Loading... |
| 776 if (constructorArgs.isEmpty) { | 800 if (constructorArgs.isEmpty) { |
| 777 constructor = astAdapter.mapLiteralConstructorEmpty; | 801 constructor = astAdapter.mapLiteralConstructorEmpty; |
| 778 } else { | 802 } else { |
| 779 constructor = astAdapter.mapLiteralConstructor; | 803 constructor = astAdapter.mapLiteralConstructor; |
| 780 HLiteralList argList = | 804 HLiteralList argList = |
| 781 new HLiteralList(constructorArgs, backend.extendableArrayType); | 805 new HLiteralList(constructorArgs, backend.extendableArrayType); |
| 782 add(argList); | 806 add(argList); |
| 783 inputs.add(argList); | 807 inputs.add(argList); |
| 784 } | 808 } |
| 785 | 809 |
| 786 // TODO(het): Add type information | 810 assert(constructor.kind == ir.ProcedureKind.Factory); |
| 787 _pushStaticInvocation(constructor, inputs, backend.dynamicType); | 811 |
| 812 InterfaceType type = localsHandler |
| 813 .substInContext(elements.getType(astAdapter.getNode(mapLiteral))); |
| 814 |
| 815 ir.Class cls = constructor.enclosingClass; |
| 816 |
| 817 if (backend.classNeedsRti(astAdapter.getElement(cls))) { |
| 818 List<HInstruction> typeInputs = <HInstruction>[]; |
| 819 type.typeArguments.forEach((DartType argument) { |
| 820 typeInputs |
| 821 .add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); |
| 822 }); |
| 823 |
| 824 // We lift this common call pattern into a helper function to save space |
| 825 // in the output. |
| 826 if (typeInputs.every((HInstruction input) => input.isNull())) { |
| 827 if (constructorArgs.isEmpty) { |
| 828 constructor = astAdapter.mapLiteralUntypedEmptyMaker; |
| 829 } else { |
| 830 constructor = astAdapter.mapLiteralUntypedMaker; |
| 831 } |
| 832 } else { |
| 833 inputs.addAll(typeInputs); |
| 834 } |
| 835 } |
| 836 |
| 837 // If runtime type information is needed and the map literal has no type |
| 838 // parameters, 'constructor' is a static function that forwards the call to |
| 839 // the factory constructor without type parameters. |
| 840 assert(constructor.kind == ir.ProcedureKind.Factory); |
| 841 |
| 842 // The instruction type will always be a subtype of the mapLiteralClass, but |
| 843 // type inference might discover a more specific type, or find nothing (in |
| 844 // dart2js unit tests). |
| 845 TypeMask mapType = new TypeMask.nonNullSubtype( |
| 846 astAdapter.getElement(astAdapter.mapLiteralClass), |
| 847 compiler.closedWorld); |
| 848 TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement( |
| 849 astAdapter.getElement(constructor), compiler); |
| 850 TypeMask instructionType = |
| 851 mapType.intersection(returnTypeMask, compiler.closedWorld); |
| 852 |
| 853 addImplicitInstantiation(type); |
| 854 _pushStaticInvocation(constructor, inputs, instructionType); |
| 855 removeImplicitInstantiation(type); |
| 788 } | 856 } |
| 789 | 857 |
| 790 @override | 858 @override |
| 791 void visitMapEntry(ir.MapEntry mapEntry) { | 859 void visitMapEntry(ir.MapEntry mapEntry) { |
| 792 // Visit value before the key because each will push an expression to the | 860 // Visit value before the key because each will push an expression to the |
| 793 // stack, so when we pop them off, the key is popped first, then the value. | 861 // stack, so when we pop them off, the key is popped first, then the value. |
| 794 mapEntry.value.accept(this); | 862 mapEntry.value.accept(this); |
| 795 mapEntry.key.accept(this); | 863 mapEntry.key.accept(this); |
| 796 } | 864 } |
| 797 | 865 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 910 List<HInstruction> arguments = _visitArguments(invocation.arguments); | 978 List<HInstruction> arguments = _visitArguments(invocation.arguments); |
| 911 | 979 |
| 912 _pushStaticInvocation(target, arguments, typeMask); | 980 _pushStaticInvocation(target, arguments, typeMask); |
| 913 } | 981 } |
| 914 | 982 |
| 915 void _pushStaticInvocation( | 983 void _pushStaticInvocation( |
| 916 ir.Node target, List<HInstruction> arguments, TypeMask typeMask) { | 984 ir.Node target, List<HInstruction> arguments, TypeMask typeMask) { |
| 917 HInstruction instruction = new HInvokeStatic( | 985 HInstruction instruction = new HInvokeStatic( |
| 918 astAdapter.getMember(target), arguments, typeMask, | 986 astAdapter.getMember(target), arguments, typeMask, |
| 919 targetCanThrow: astAdapter.getCanThrow(target)); | 987 targetCanThrow: astAdapter.getCanThrow(target)); |
| 988 if (currentImplicitInstantiations.isNotEmpty) { |
| 989 instruction.instantiatedTypes = |
| 990 new List<DartType>.from(currentImplicitInstantiations); |
| 991 } |
| 920 instruction.sideEffects = astAdapter.getSideEffects(target); | 992 instruction.sideEffects = astAdapter.getSideEffects(target); |
| 921 | 993 |
| 922 push(instruction); | 994 push(instruction); |
| 923 } | 995 } |
| 924 | 996 |
| 925 void _pushDynamicInvocation( | 997 void _pushDynamicInvocation( |
| 926 ir.Node node, TypeMask mask, List<HInstruction> arguments, | 998 ir.Node node, TypeMask mask, List<HInstruction> arguments, |
| 927 {Selector selector}) { | 999 {Selector selector}) { |
| 928 HInstruction receiver = arguments.first; | 1000 HInstruction receiver = arguments.first; |
| 929 List<HInstruction> inputs = <HInstruction>[]; | 1001 List<HInstruction> inputs = <HInstruction>[]; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1051 push(new HNot(popBoolified(), backend.boolType)); | 1123 push(new HNot(popBoolified(), backend.boolType)); |
| 1052 } | 1124 } |
| 1053 | 1125 |
| 1054 @override | 1126 @override |
| 1055 void visitStringConcatenation(ir.StringConcatenation stringConcat) { | 1127 void visitStringConcatenation(ir.StringConcatenation stringConcat) { |
| 1056 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); | 1128 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); |
| 1057 stringConcat.accept(stringBuilder); | 1129 stringConcat.accept(stringBuilder); |
| 1058 stack.add(stringBuilder.result); | 1130 stack.add(stringBuilder.result); |
| 1059 } | 1131 } |
| 1060 } | 1132 } |
| OLD | NEW |