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 '../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 |