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); |
(...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
708 stack.add(graph.addConstant( | 709 stack.add(graph.addConstant( |
709 astAdapter.getConstantForSymbol(symbolLiteral), compiler)); | 710 astAdapter.getConstantForSymbol(symbolLiteral), compiler)); |
710 registry?.registerConstSymbol(symbolLiteral.value); | 711 registry?.registerConstSymbol(symbolLiteral.value); |
711 } | 712 } |
712 | 713 |
713 @override | 714 @override |
714 void visitNullLiteral(ir.NullLiteral nullLiteral) { | 715 void visitNullLiteral(ir.NullLiteral nullLiteral) { |
715 stack.add(graph.addConstantNull(compiler)); | 716 stack.add(graph.addConstantNull(compiler)); |
716 } | 717 } |
717 | 718 |
718 HInstruction setRtiIfNeeded(HInstruction object, ir.ListLiteral listLiteral) { | 719 /// Set the runtime type information if necessary. Cases where this is needed |
720 /// are for classes that are: | |
721 /// (1) used in a is check with type variables, | |
722 /// (2) dependencies of classes in (1), | |
723 /// (3) subclasses of (2) and (3). | |
sra1
2016/11/17 23:51:41
The code is now a little bit too general, since it
Emily Fortuna
2016/11/18 01:30:35
Done.
| |
724 HInstruction setRuntimeTypeInfoIfNeeded( | |
725 HInstruction object, ir.ListLiteral listLiteral) { | |
719 InterfaceType type = localsHandler | 726 InterfaceType type = localsHandler |
720 .substInContext(elements.getType(astAdapter.getNode(listLiteral))); | 727 .substInContext(elements.getType(astAdapter.getNode(listLiteral))); |
721 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { | 728 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { |
722 return object; | 729 return object; |
723 } | 730 } |
724 List<HInstruction> arguments = <HInstruction>[]; | 731 List<HInstruction> arguments = <HInstruction>[]; |
725 for (DartType argument in type.typeArguments) { | 732 for (DartType argument in type.typeArguments) { |
726 arguments.add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); | 733 arguments.add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); |
727 } | 734 } |
728 // TODO(15489): Register at codegen. | 735 // TODO(15489): Register at codegen. |
729 registry?.registerInstantiation(type); | 736 registry?.registerInstantiation(type); |
730 return callSetRuntimeTypeInfoWithTypeArguments(type, arguments, object); | 737 return callSetRuntimeTypeInfoWithTypeArguments(type, arguments, object); |
731 } | 738 } |
732 | 739 |
733 @override | 740 @override |
734 void visitListLiteral(ir.ListLiteral listLiteral) { | 741 void visitListLiteral(ir.ListLiteral listLiteral) { |
735 HInstruction listInstruction; | 742 HInstruction listInstruction; |
736 if (listLiteral.isConst) { | 743 if (listLiteral.isConst) { |
737 listInstruction = | 744 listInstruction = |
738 graph.addConstant(astAdapter.getConstantFor(listLiteral), compiler); | 745 graph.addConstant(astAdapter.getConstantFor(listLiteral), compiler); |
739 } else { | 746 } else { |
740 List<HInstruction> elements = <HInstruction>[]; | 747 List<HInstruction> elements = <HInstruction>[]; |
741 for (ir.Expression element in listLiteral.expressions) { | 748 for (ir.Expression element in listLiteral.expressions) { |
742 element.accept(this); | 749 element.accept(this); |
743 elements.add(pop()); | 750 elements.add(pop()); |
744 } | 751 } |
745 listInstruction = new HLiteralList(elements, backend.extendableArrayType); | 752 listInstruction = new HLiteralList(elements, backend.extendableArrayType); |
746 add(listInstruction); | 753 add(listInstruction); |
747 listInstruction = setRtiIfNeeded(listInstruction, listLiteral); | 754 listInstruction = |
755 setRuntimeTypeInfoIfNeeded(listInstruction, listLiteral); | |
748 } | 756 } |
749 | 757 |
750 TypeMask type = astAdapter.typeOfNewList(targetElement, listLiteral); | 758 TypeMask type = astAdapter.typeOfNewList(targetElement, listLiteral); |
751 if (!type.containsAll(compiler.closedWorld)) { | 759 if (!type.containsAll(compiler.closedWorld)) { |
752 listInstruction.instructionType = type; | 760 listInstruction.instructionType = type; |
753 } | 761 } |
754 stack.add(listInstruction); | 762 stack.add(listInstruction); |
755 } | 763 } |
756 | 764 |
757 @override | 765 @override |
(...skipping 18 matching lines...) Expand all Loading... | |
776 if (constructorArgs.isEmpty) { | 784 if (constructorArgs.isEmpty) { |
777 constructor = astAdapter.mapLiteralConstructorEmpty; | 785 constructor = astAdapter.mapLiteralConstructorEmpty; |
778 } else { | 786 } else { |
779 constructor = astAdapter.mapLiteralConstructor; | 787 constructor = astAdapter.mapLiteralConstructor; |
780 HLiteralList argList = | 788 HLiteralList argList = |
781 new HLiteralList(constructorArgs, backend.extendableArrayType); | 789 new HLiteralList(constructorArgs, backend.extendableArrayType); |
782 add(argList); | 790 add(argList); |
783 inputs.add(argList); | 791 inputs.add(argList); |
784 } | 792 } |
785 | 793 |
786 // TODO(het): Add type information | 794 assert(constructor.kind == ir.ProcedureKind.Factory); |
787 _pushStaticInvocation(constructor, inputs, backend.dynamicType); | 795 |
796 InterfaceType type = localsHandler | |
797 .substInContext(elements.getType(astAdapter.getNode(mapLiteral))); | |
798 | |
799 ir.Class cls = constructor.enclosingClass; | |
800 | |
801 if (backend.classNeedsRti(astAdapter.getElement(cls))) { | |
802 List<HInstruction> typeInputs = <HInstruction>[]; | |
803 type.typeArguments.forEach((DartType argument) { | |
804 typeInputs | |
805 .add(typeBuilder.analyzeTypeArgument(argument, sourceElement)); | |
806 }); | |
807 | |
808 // We lift this common call pattern into a helper function to save space | |
809 // in the output. | |
810 if (typeInputs.every((HInstruction input) => input.isNull())) { | |
811 if (constructorArgs.isEmpty) { | |
812 constructor = astAdapter.mapLiteralUntypedEmptyMaker; | |
813 } else { | |
814 constructor = astAdapter.mapLiteralUntypedMaker; | |
815 } | |
816 } else { | |
817 inputs.addAll(typeInputs); | |
818 } | |
819 } | |
820 | |
821 // If runtime type information is needed and the map literal has no type | |
822 // parameters, 'constructor' is a static function that forwards the call to | |
823 // the factory constructor without type parameters. | |
824 assert(constructor.kind == ir.ProcedureKind.Factory); | |
825 | |
826 // The instruction type will always be a subtype of the mapLiteralClass, but | |
827 // type inference might discover a more specific type, or find nothing (in | |
828 // dart2js unit tests). | |
829 TypeMask mapType = new TypeMask.nonNullSubtype( | |
830 astAdapter.getElement(astAdapter.mapLiteralClass), | |
831 compiler.closedWorld); | |
832 TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement( | |
833 astAdapter.getElement(constructor), compiler); | |
834 TypeMask instructionType = | |
835 mapType.intersection(returnTypeMask, compiler.closedWorld); | |
836 | |
837 // TODO(efortuna): Inlining. | |
Siggi Cherem (dart-lang)
2016/11/17 23:56:53
Let's change the TODO to explicitly say this is fo
Emily Fortuna
2016/11/18 01:30:35
hmmmm. I added them, but I'm not certain that this
Siggi Cherem (dart-lang)
2016/11/18 15:47:06
Stephen/Johnni - please confirm, but I believe we
| |
838 _pushStaticInvocation(constructor, inputs, instructionType); | |
788 } | 839 } |
789 | 840 |
790 @override | 841 @override |
791 void visitMapEntry(ir.MapEntry mapEntry) { | 842 void visitMapEntry(ir.MapEntry mapEntry) { |
792 // Visit value before the key because each will push an expression to the | 843 // 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. | 844 // stack, so when we pop them off, the key is popped first, then the value. |
794 mapEntry.value.accept(this); | 845 mapEntry.value.accept(this); |
795 mapEntry.key.accept(this); | 846 mapEntry.key.accept(this); |
796 } | 847 } |
797 | 848 |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1051 push(new HNot(popBoolified(), backend.boolType)); | 1102 push(new HNot(popBoolified(), backend.boolType)); |
1052 } | 1103 } |
1053 | 1104 |
1054 @override | 1105 @override |
1055 void visitStringConcatenation(ir.StringConcatenation stringConcat) { | 1106 void visitStringConcatenation(ir.StringConcatenation stringConcat) { |
1056 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); | 1107 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); |
1057 stringConcat.accept(stringBuilder); | 1108 stringConcat.accept(stringBuilder); |
1058 stack.add(stringBuilder.result); | 1109 stack.add(stringBuilder.result); |
1059 } | 1110 } |
1060 } | 1111 } |
OLD | NEW |