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 |