| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 class JavaScriptItemCompilationContext extends ItemCompilationContext { | 7 class JavaScriptItemCompilationContext extends ItemCompilationContext { |
| 8 final Set<HInstruction> boundsChecked; | 8 final Set<HInstruction> boundsChecked; |
| 9 | 9 |
| 10 JavaScriptItemCompilationContext() | 10 JavaScriptItemCompilationContext() |
| 11 : boundsChecked = new Set<HInstruction>(); | 11 : boundsChecked = new Set<HInstruction>(); |
| 12 } | 12 } |
| 13 | 13 |
| 14 |
| 15 class CheckedModeHelper { |
| 16 final SourceString name; |
| 17 |
| 18 const CheckedModeHelper(SourceString this.name); |
| 19 |
| 20 Element getElement(Compiler compiler) => compiler.findHelper(name); |
| 21 |
| 22 jsAst.Expression generateCall(SsaCodeGenerator codegen, |
| 23 HTypeConversion node) { |
| 24 Element helperElement = getElement(codegen.compiler); |
| 25 codegen.world.registerStaticUse(helperElement); |
| 26 List<jsAst.Expression> arguments = <jsAst.Expression>[]; |
| 27 codegen.use(node.checkedInput); |
| 28 arguments.add(codegen.pop()); |
| 29 generateAdditionalArguments(codegen, node, arguments); |
| 30 String helperName = codegen.backend.namer.isolateAccess(helperElement); |
| 31 return new jsAst.Call(new jsAst.VariableUse(helperName), arguments); |
| 32 } |
| 33 |
| 34 void generateAdditionalArguments(SsaCodeGenerator codegen, |
| 35 HTypeConversion node, |
| 36 List<jsAst.Expression> arguments) { |
| 37 assert(!node.typeExpression.isMalformed); |
| 38 // No additional arguments needed. |
| 39 } |
| 40 } |
| 41 |
| 42 class PropertyCheckedModeHelper extends CheckedModeHelper { |
| 43 const PropertyCheckedModeHelper(SourceString name) : super(name); |
| 44 |
| 45 void generateAdditionalArguments(SsaCodeGenerator codegen, |
| 46 HTypeConversion node, |
| 47 List<jsAst.Expression> arguments) { |
| 48 DartType type = node.typeExpression; |
| 49 assert(!type.isMalformed); |
| 50 String additionalArgument = codegen.backend.namer.operatorIsType(type); |
| 51 arguments.add(js.string(additionalArgument)); |
| 52 } |
| 53 } |
| 54 |
| 55 class TypeVariableCheckedModeHelper extends CheckedModeHelper { |
| 56 const TypeVariableCheckedModeHelper(SourceString name) : super(name); |
| 57 |
| 58 void generateAdditionalArguments(SsaCodeGenerator codegen, |
| 59 HTypeConversion node, |
| 60 List<jsAst.Expression> arguments) { |
| 61 assert(node.typeExpression.kind == TypeKind.TYPE_VARIABLE); |
| 62 codegen.use(node.typeRepresentation); |
| 63 arguments.add(codegen.pop()); |
| 64 } |
| 65 } |
| 66 |
| 67 class SubtypeCheckedModeHelper extends CheckedModeHelper { |
| 68 const SubtypeCheckedModeHelper(SourceString name) : super(name); |
| 69 |
| 70 void generateAdditionalArguments(SsaCodeGenerator codegen, |
| 71 HTypeConversion node, |
| 72 List<jsAst.Expression> arguments) { |
| 73 DartType type = node.typeExpression; |
| 74 Element element = type.element; |
| 75 String isField = codegen.backend.namer.operatorIs(element); |
| 76 arguments.add(js.string(isField)); |
| 77 codegen.use(node.typeRepresentation); |
| 78 arguments.add(codegen.pop()); |
| 79 String asField = codegen.backend.namer.substitutionName(element); |
| 80 arguments.add(js.string(asField)); |
| 81 } |
| 82 } |
| 83 |
| 84 class FunctionTypeCheckedModeHelper extends CheckedModeHelper { |
| 85 const FunctionTypeCheckedModeHelper(SourceString name) : super(name); |
| 86 |
| 87 void generateAdditionalArguments(SsaCodeGenerator codegen, |
| 88 HTypeConversion node, |
| 89 List<jsAst.Expression> arguments) { |
| 90 DartType type = node.typeExpression; |
| 91 String signatureName = codegen.backend.namer.getFunctionTypeName(type); |
| 92 arguments.add(js.string(signatureName)); |
| 93 |
| 94 if (type.containsTypeVariables) { |
| 95 ClassElement contextClass = Types.getClassContext(type); |
| 96 String contextName = codegen.backend.namer.getName(contextClass); |
| 97 arguments.add(js.string(contextName)); |
| 98 |
| 99 if (node.contextIsTypeArguments) { |
| 100 arguments.add(new jsAst.LiteralNull()); |
| 101 codegen.use(node.context); |
| 102 arguments.add(codegen.pop()); |
| 103 } else { |
| 104 codegen.use(node.context); |
| 105 arguments.add(codegen.pop()); |
| 106 } |
| 107 } |
| 108 } |
| 109 } |
| 110 |
| 111 class MalformedCheckedModeHelper extends CheckedModeHelper { |
| 112 const MalformedCheckedModeHelper(SourceString name) : super(name); |
| 113 |
| 114 void generateAdditionalArguments(SsaCodeGenerator codegen, |
| 115 HTypeConversion node, |
| 116 List<jsAst.Expression> arguments) { |
| 117 DartType type = node.typeExpression; |
| 118 assert(type.isMalformed); |
| 119 String reasons = Types.fetchReasonsFromMalformedType(type); |
| 120 arguments.add(js.string('$type')); |
| 121 // TODO(johnniwinther): Handle escaping correctly. |
| 122 arguments.add(js.string(reasons)); |
| 123 } |
| 124 } |
| 125 |
| 126 |
| 14 class JavaScriptBackend extends Backend { | 127 class JavaScriptBackend extends Backend { |
| 15 SsaBuilderTask builder; | 128 SsaBuilderTask builder; |
| 16 SsaOptimizerTask optimizer; | 129 SsaOptimizerTask optimizer; |
| 17 SsaCodeGeneratorTask generator; | 130 SsaCodeGeneratorTask generator; |
| 18 CodeEmitterTask emitter; | 131 CodeEmitterTask emitter; |
| 19 | 132 |
| 20 /** | 133 /** |
| 21 * The generated code as a js AST for compiled methods. | 134 * The generated code as a js AST for compiled methods. |
| 22 */ | 135 */ |
| 23 Map<Element, jsAst.Expression> get generatedCode { | 136 Map<Element, jsAst.Expression> get generatedCode { |
| (...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 606 } | 719 } |
| 607 | 720 |
| 608 void registerSetRuntimeType(TreeElements elements) { | 721 void registerSetRuntimeType(TreeElements elements) { |
| 609 enqueueInResolution(getSetRuntimeTypeInfo(), elements); | 722 enqueueInResolution(getSetRuntimeTypeInfo(), elements); |
| 610 } | 723 } |
| 611 | 724 |
| 612 void registerGetRuntimeTypeArgument(TreeElements elements) { | 725 void registerGetRuntimeTypeArgument(TreeElements elements) { |
| 613 enqueueInResolution(getGetRuntimeTypeArgument(), elements); | 726 enqueueInResolution(getGetRuntimeTypeArgument(), elements); |
| 614 } | 727 } |
| 615 | 728 |
| 616 void registerRuntimeType(TreeElements elements) { | 729 void registerGenericCallMethod(Element callMethod, |
| 730 Enqueuer enqueuer, TreeElements elements) { |
| 731 if (enqueuer.isResolutionQueue || methodNeedsRti(callMethod)) { |
| 732 registerComputeSignature(enqueuer, elements); |
| 733 } |
| 734 } |
| 735 |
| 736 void registerGenericClosure(Element closure, |
| 737 Enqueuer enqueuer, TreeElements elements) { |
| 738 if (enqueuer.isResolutionQueue || methodNeedsRti(closure)) { |
| 739 registerComputeSignature(enqueuer, elements); |
| 740 } |
| 741 } |
| 742 |
| 743 void registerComputeSignature(Enqueuer enqueuer, TreeElements elements) { |
| 744 // Calls to [:computeSignature:] are generated by the emitter and we |
| 745 // therefore need to enqueue the used elements in the codegen enqueuer as |
| 746 // well as in the resolution enqueuer. |
| 747 enqueue(enqueuer, getSetRuntimeTypeInfo(), elements); |
| 748 enqueue(enqueuer, getGetRuntimeTypeInfo(), elements); |
| 749 enqueue(enqueuer, getComputeSignature(), elements); |
| 750 enqueue(enqueuer, getGetRuntimeTypeArguments(), elements); |
| 751 enqueuer.registerInstantiatedClass(compiler.listClass, elements); |
| 752 } |
| 753 |
| 754 void registerRuntimeType(Enqueuer enqueuer, TreeElements elements) { |
| 755 registerComputeSignature(enqueuer, elements); |
| 617 enqueueInResolution(getSetRuntimeTypeInfo(), elements); | 756 enqueueInResolution(getSetRuntimeTypeInfo(), elements); |
| 618 enqueueInResolution(getGetRuntimeTypeInfo(), elements); | 757 enqueueInResolution(getGetRuntimeTypeInfo(), elements); |
| 619 enqueueInResolution(getGetRuntimeTypeArgument(), elements); | 758 registerGetRuntimeTypeArgument(elements); |
| 620 compiler.enqueuer.resolution.registerInstantiatedClass( | 759 compiler.enqueuer.resolution.registerInstantiatedClass( |
| 621 compiler.listClass, elements); | 760 compiler.listClass, elements); |
| 622 } | 761 } |
| 623 | 762 |
| 624 void registerTypeVariableExpression(TreeElements elements) { | 763 void registerTypeVariableExpression(TreeElements elements) { |
| 625 registerRuntimeType(elements); | 764 enqueueInResolution(getSetRuntimeTypeInfo(), elements); |
| 765 enqueueInResolution(getGetRuntimeTypeInfo(), elements); |
| 766 registerGetRuntimeTypeArgument(elements); |
| 767 compiler.enqueuer.resolution.registerInstantiatedClass( |
| 768 compiler.listClass, elements); |
| 626 enqueueInResolution(getRuntimeTypeToString(), elements); | 769 enqueueInResolution(getRuntimeTypeToString(), elements); |
| 627 enqueueInResolution(getCreateRuntimeType(), elements); | 770 enqueueInResolution(getCreateRuntimeType(), elements); |
| 628 } | 771 } |
| 629 | 772 |
| 630 void registerIsCheck(DartType type, Enqueuer world, TreeElements elements) { | 773 void registerIsCheck(DartType type, Enqueuer world, TreeElements elements) { |
| 774 type = type.unalias(compiler); |
| 631 world.registerInstantiatedClass(compiler.boolClass, elements); | 775 world.registerInstantiatedClass(compiler.boolClass, elements); |
| 776 bool inCheckedMode = compiler.enableTypeAssertions; |
| 777 // [registerIsCheck] is also called for checked mode checks, so we |
| 778 // need to register checked mode helpers. |
| 779 if (inCheckedMode) { |
| 780 CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: false); |
| 781 if (helper != null) world.addToWorkList(helper.getElement(compiler)); |
| 782 // We also need the native variant of the check (for DOM types). |
| 783 helper = getNativeCheckedModeHelper(type, typeCast: false); |
| 784 if (helper != null) world.addToWorkList(helper.getElement(compiler)); |
| 785 if (type.isMalformed) { |
| 786 enqueueInResolution(getThrowMalformedSubtypeError(), elements); |
| 787 return; |
| 788 } |
| 789 } else if (type.isMalformed) { |
| 790 registerThrowRuntimeError(elements); |
| 791 return; |
| 792 } |
| 632 bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE; | 793 bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE; |
| 633 bool inCheckedMode = compiler.enableTypeAssertions; | 794 if (!type.isRaw || type.containsTypeVariables) { |
| 634 if (!type.isRaw || isTypeVariable) { | |
| 635 enqueueInResolution(getSetRuntimeTypeInfo(), elements); | 795 enqueueInResolution(getSetRuntimeTypeInfo(), elements); |
| 636 enqueueInResolution(getGetRuntimeTypeInfo(), elements); | 796 enqueueInResolution(getGetRuntimeTypeInfo(), elements); |
| 637 enqueueInResolution(getGetRuntimeTypeArgument(), elements); | 797 enqueueInResolution(getGetRuntimeTypeArgument(), elements); |
| 638 if (inCheckedMode) { | 798 if (inCheckedMode) { |
| 639 enqueueInResolution(getAssertSubtype(), elements); | 799 enqueueInResolution(getAssertSubtype(), elements); |
| 640 } | 800 } |
| 641 enqueueInResolution(getCheckSubtype(), elements); | 801 enqueueInResolution(getCheckSubtype(), elements); |
| 642 if (isTypeVariable) { | 802 if (isTypeVariable) { |
| 643 enqueueInResolution(getCheckSubtypeOfRuntimeType(), elements); | 803 enqueueInResolution(getCheckSubtypeOfRuntimeType(), elements); |
| 644 if (inCheckedMode) { | 804 if (inCheckedMode) { |
| 645 enqueueInResolution(getAssertSubtypeOfRuntimeType(), elements); | 805 enqueueInResolution(getAssertSubtypeOfRuntimeType(), elements); |
| 646 } | 806 } |
| 647 } | 807 } |
| 648 world.registerInstantiatedClass(compiler.listClass, elements); | 808 world.registerInstantiatedClass(compiler.listClass, elements); |
| 649 } | 809 } |
| 650 // [registerIsCheck] is also called for checked mode checks, so we | 810 if (type is FunctionType) { |
| 651 // need to register checked mode helpers. | 811 enqueueInResolution(getCheckFunctionSubtype(), elements); |
| 652 if (inCheckedMode) { | |
| 653 Element e = getCheckedModeHelper(type, typeCast: false); | |
| 654 if (e != null) world.addToWorkList(e); | |
| 655 // We also need the native variant of the check (for DOM types). | |
| 656 e = getNativeCheckedModeHelper(type, typeCast: false); | |
| 657 if (e != null) world.addToWorkList(e); | |
| 658 } | 812 } |
| 659 if (type.element.isNative()) { | 813 if (type.element.isNative()) { |
| 660 // We will neeed to add the "$is" and "$as" properties on the | 814 // We will neeed to add the "$is" and "$as" properties on the |
| 661 // JavaScript object prototype, so we make sure | 815 // JavaScript object prototype, so we make sure |
| 662 // [:defineProperty:] is compiled. | 816 // [:defineProperty:] is compiled. |
| 663 world.addToWorkList( | 817 world.addToWorkList( |
| 664 compiler.findHelper(const SourceString('defineProperty'))); | 818 compiler.findHelper(const SourceString('defineProperty'))); |
| 665 } | 819 } |
| 666 } | 820 } |
| 667 | 821 |
| 668 void registerAsCheck(DartType type, TreeElements elements) { | 822 void registerAsCheck(DartType type, TreeElements elements) { |
| 669 Element e = getCheckedModeHelper(type, typeCast: true); | 823 type = type.unalias(compiler); |
| 670 enqueueInResolution(e, elements); | 824 CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: true); |
| 825 enqueueInResolution(helper.getElement(compiler), elements); |
| 671 // We also need the native variant of the check (for DOM types). | 826 // We also need the native variant of the check (for DOM types). |
| 672 e = getNativeCheckedModeHelper(type, typeCast: true); | 827 helper = getNativeCheckedModeHelper(type, typeCast: true); |
| 673 enqueueInResolution(e, elements); | 828 if (helper != null) { |
| 829 enqueueInResolution(helper.getElement(compiler), elements); |
| 830 } |
| 674 } | 831 } |
| 675 | 832 |
| 676 void registerThrowNoSuchMethod(TreeElements elements) { | 833 void registerThrowNoSuchMethod(TreeElements elements) { |
| 677 enqueueInResolution(getThrowNoSuchMethod(), elements); | 834 enqueueInResolution(getThrowNoSuchMethod(), elements); |
| 678 } | 835 } |
| 679 | 836 |
| 680 void registerThrowRuntimeError(TreeElements elements) { | 837 void registerThrowRuntimeError(TreeElements elements) { |
| 681 enqueueInResolution(getThrowRuntimeError(), elements); | 838 enqueueInResolution(getThrowRuntimeError(), elements); |
| 682 } | 839 } |
| 683 | 840 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 analyzeTypeArgument(type, argument); | 884 analyzeTypeArgument(type, argument); |
| 728 }); | 885 }); |
| 729 } | 886 } |
| 730 // TODO(ngeoffray): Also handle T a (in checked mode). | 887 // TODO(ngeoffray): Also handle T a (in checked mode). |
| 731 } | 888 } |
| 732 | 889 |
| 733 void registerClassUsingVariableExpression(ClassElement cls) { | 890 void registerClassUsingVariableExpression(ClassElement cls) { |
| 734 rti.classesUsingTypeVariableExpression.add(cls); | 891 rti.classesUsingTypeVariableExpression.add(cls); |
| 735 } | 892 } |
| 736 | 893 |
| 737 bool needsRti(ClassElement cls) { | 894 bool classNeedsRti(ClassElement cls) { |
| 738 return rti.classesNeedingRti.contains(cls.declaration) || | 895 return rti.classesNeedingRti.contains(cls.declaration) || |
| 739 compiler.enabledRuntimeType; | 896 compiler.enabledRuntimeType; |
| 740 } | 897 } |
| 741 | 898 |
| 742 bool isDefaultNoSuchMethodImplementation(Element element) { | 899 bool isDefaultNoSuchMethodImplementation(Element element) { |
| 743 assert(element.name == Compiler.NO_SUCH_METHOD); | 900 assert(element.name == Compiler.NO_SUCH_METHOD); |
| 744 ClassElement classElement = element.getEnclosingClass(); | 901 ClassElement classElement = element.getEnclosingClass(); |
| 745 return classElement == compiler.objectClass | 902 return classElement == compiler.objectClass |
| 746 || classElement == jsInterceptorClass; | 903 || classElement == jsInterceptorClass; |
| 747 } | 904 } |
| 748 | 905 |
| 749 bool isDefaultEqualityImplementation(Element element) { | 906 bool isDefaultEqualityImplementation(Element element) { |
| 750 assert(element.name == const SourceString('==')); | 907 assert(element.name == const SourceString('==')); |
| 751 ClassElement classElement = element.getEnclosingClass(); | 908 ClassElement classElement = element.getEnclosingClass(); |
| 752 return classElement == compiler.objectClass | 909 return classElement == compiler.objectClass |
| 753 || classElement == jsInterceptorClass | 910 || classElement == jsInterceptorClass |
| 754 || classElement == jsNullClass; | 911 || classElement == jsNullClass; |
| 755 } | 912 } |
| 756 | 913 |
| 914 bool methodNeedsRti(FunctionElement function) { |
| 915 return rti.methodsNeedingRti.contains(function) || |
| 916 compiler.enabledRuntimeType; |
| 917 } |
| 918 |
| 919 void enqueue(Enqueuer enqueuer, Element e, TreeElements elements) { |
| 920 enqueuer.addToWorkList(e); |
| 921 elements.registerDependency(e); |
| 922 } |
| 923 |
| 757 void enqueueInResolution(Element e, TreeElements elements) { | 924 void enqueueInResolution(Element e, TreeElements elements) { |
| 758 if (e == null) return; | 925 if (e == null) return; |
| 759 ResolutionEnqueuer enqueuer = compiler.enqueuer.resolution; | 926 ResolutionEnqueuer enqueuer = compiler.enqueuer.resolution; |
| 760 enqueuer.addToWorkList(e); | 927 enqueue(enqueuer, e, elements); |
| 761 elements.registerDependency(e); | |
| 762 } | 928 } |
| 763 | 929 |
| 764 void registerConstantMap(TreeElements elements) { | 930 void registerConstantMap(TreeElements elements) { |
| 765 Element e = compiler.findHelper(const SourceString('ConstantMap')); | 931 Element e = compiler.findHelper(const SourceString('ConstantMap')); |
| 766 if (e != null) { | 932 if (e != null) { |
| 767 compiler.enqueuer.resolution.registerInstantiatedClass(e, elements); | 933 compiler.enqueuer.resolution.registerInstantiatedClass(e, elements); |
| 768 } | 934 } |
| 769 e = compiler.findHelper(const SourceString('ConstantProtoMap')); | 935 e = compiler.findHelper(const SourceString('ConstantProtoMap')); |
| 770 if (e != null) { | 936 if (e != null) { |
| 771 compiler.enqueuer.resolution.registerInstantiatedClass(e, elements); | 937 compiler.enqueuer.resolution.registerInstantiatedClass(e, elements); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 return element; | 1016 return element; |
| 851 } | 1017 } |
| 852 } | 1018 } |
| 853 | 1019 |
| 854 /** | 1020 /** |
| 855 * Returns the checked mode helper that will be needed to do a type check/type | 1021 * Returns the checked mode helper that will be needed to do a type check/type |
| 856 * cast on [type] at runtime. Note that this method is being called both by | 1022 * cast on [type] at runtime. Note that this method is being called both by |
| 857 * the resolver with interface types (int, String, ...), and by the SSA | 1023 * the resolver with interface types (int, String, ...), and by the SSA |
| 858 * backend with implementation types (JSInt, JSString, ...). | 1024 * backend with implementation types (JSInt, JSString, ...). |
| 859 */ | 1025 */ |
| 860 Element getCheckedModeHelper(DartType type, {bool typeCast}) { | 1026 CheckedModeHelper getCheckedModeHelper(DartType type, {bool typeCast}) { |
| 861 SourceString name = getCheckedModeHelperName( | 1027 return getCheckedModeHelperInternal( |
| 862 type, typeCast: typeCast, nativeCheckOnly: false); | 1028 type, typeCast: typeCast, nativeCheckOnly: false); |
| 863 return compiler.findHelper(name); | |
| 864 } | 1029 } |
| 865 | 1030 |
| 866 /** | 1031 /** |
| 867 * Returns the native checked mode helper that will be needed to do a type | 1032 * Returns the native checked mode helper that will be needed to do a type |
| 868 * check/type cast on [type] at runtime. If no native helper exists for | 1033 * check/type cast on [type] at runtime. If no native helper exists for |
| 869 * [type], [:null:] is returned. | 1034 * [type], [:null:] is returned. |
| 870 */ | 1035 */ |
| 871 Element getNativeCheckedModeHelper(DartType type, {bool typeCast}) { | 1036 CheckedModeHelper getNativeCheckedModeHelper(DartType type, {bool typeCast}) { |
| 872 SourceString sourceName = getCheckedModeHelperName( | 1037 return getCheckedModeHelperInternal( |
| 873 type, typeCast: typeCast, nativeCheckOnly: true); | 1038 type, typeCast: typeCast, nativeCheckOnly: true); |
| 874 if (sourceName == null) return null; | |
| 875 return compiler.findHelper(sourceName); | |
| 876 } | 1039 } |
| 877 | 1040 |
| 878 /** | 1041 /** |
| 879 * Returns the name of the type check/type cast helper method for [type]. If | 1042 * Returns the checked mode helper for the type check/type cast for [type]. If |
| 880 * [nativeCheckOnly] is [:true:], only names for native helpers are returned. | 1043 * [nativeCheckOnly] is [:true:], only names for native helpers are returned. |
| 881 */ | 1044 */ |
| 882 SourceString getCheckedModeHelperName(DartType type, | 1045 CheckedModeHelper getCheckedModeHelperInternal(DartType type, |
| 883 {bool typeCast, | 1046 {bool typeCast, |
| 884 bool nativeCheckOnly}) { | 1047 bool nativeCheckOnly}) { |
| 1048 assert(type.kind != TypeKind.TYPEDEF); |
| 885 Element element = type.element; | 1049 Element element = type.element; |
| 886 bool nativeCheck = nativeCheckOnly || | 1050 bool nativeCheck = nativeCheckOnly || |
| 887 emitter.nativeEmitter.requiresNativeIsCheck(element); | 1051 emitter.nativeEmitter.requiresNativeIsCheck(element); |
| 888 if (type.isMalformed) { | 1052 if (type.isMalformed) { |
| 889 // Check for malformed types first, because the type may be a list type | 1053 // Check for malformed types first, because the type may be a list type |
| 890 // with a malformed argument type. | 1054 // with a malformed argument type. |
| 891 if (nativeCheckOnly) return null; | 1055 if (nativeCheckOnly) return null; |
| 892 return typeCast | 1056 return typeCast |
| 893 ? const SourceString('malformedTypeCast') | 1057 ? const MalformedCheckedModeHelper( |
| 894 : const SourceString('malformedTypeCheck'); | 1058 const SourceString('malformedTypeCast')) |
| 1059 : const MalformedCheckedModeHelper( |
| 1060 const SourceString('malformedTypeCheck')); |
| 895 } else if (type == compiler.types.voidType) { | 1061 } else if (type == compiler.types.voidType) { |
| 896 assert(!typeCast); // Cannot cast to void. | 1062 assert(!typeCast); // Cannot cast to void. |
| 897 if (nativeCheckOnly) return null; | 1063 if (nativeCheckOnly) return null; |
| 898 return const SourceString('voidTypeCheck'); | 1064 return const CheckedModeHelper(const SourceString('voidTypeCheck')); |
| 899 } else if (element == jsStringClass || element == compiler.stringClass) { | 1065 } else if (element == jsStringClass || element == compiler.stringClass) { |
| 900 if (nativeCheckOnly) return null; | 1066 if (nativeCheckOnly) return null; |
| 901 return typeCast | 1067 return typeCast |
| 902 ? const SourceString("stringTypeCast") | 1068 ? const CheckedModeHelper(const SourceString("stringTypeCast")) |
| 903 : const SourceString('stringTypeCheck'); | 1069 : const CheckedModeHelper(const SourceString('stringTypeCheck')); |
| 904 } else if (element == jsDoubleClass || element == compiler.doubleClass) { | 1070 } else if (element == jsDoubleClass || element == compiler.doubleClass) { |
| 905 if (nativeCheckOnly) return null; | 1071 if (nativeCheckOnly) return null; |
| 906 return typeCast | 1072 return typeCast |
| 907 ? const SourceString("doubleTypeCast") | 1073 ? const CheckedModeHelper(const SourceString("doubleTypeCast")) |
| 908 : const SourceString('doubleTypeCheck'); | 1074 : const CheckedModeHelper(const SourceString('doubleTypeCheck')); |
| 909 } else if (element == jsNumberClass || element == compiler.numClass) { | 1075 } else if (element == jsNumberClass || element == compiler.numClass) { |
| 910 if (nativeCheckOnly) return null; | 1076 if (nativeCheckOnly) return null; |
| 911 return typeCast | 1077 return typeCast |
| 912 ? const SourceString("numTypeCast") | 1078 ? const CheckedModeHelper(const SourceString("numTypeCast")) |
| 913 : const SourceString('numTypeCheck'); | 1079 : const CheckedModeHelper(const SourceString('numTypeCheck')); |
| 914 } else if (element == jsBoolClass || element == compiler.boolClass) { | 1080 } else if (element == jsBoolClass || element == compiler.boolClass) { |
| 915 if (nativeCheckOnly) return null; | 1081 if (nativeCheckOnly) return null; |
| 916 return typeCast | 1082 return typeCast |
| 917 ? const SourceString("boolTypeCast") | 1083 ? const CheckedModeHelper(const SourceString("boolTypeCast")) |
| 918 : const SourceString('boolTypeCheck'); | 1084 : const CheckedModeHelper(const SourceString('boolTypeCheck')); |
| 919 } else if (element == jsIntClass || element == compiler.intClass) { | 1085 } else if (element == jsIntClass || element == compiler.intClass) { |
| 920 if (nativeCheckOnly) return null; | 1086 if (nativeCheckOnly) return null; |
| 921 return typeCast ? | 1087 return typeCast |
| 922 const SourceString("intTypeCast") : | 1088 ? const CheckedModeHelper(const SourceString("intTypeCast")) |
| 923 const SourceString('intTypeCheck'); | 1089 : const CheckedModeHelper(const SourceString('intTypeCheck')); |
| 924 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { | 1090 } else if (Elements.isNumberOrStringSupertype(element, compiler)) { |
| 925 if (nativeCheck) { | 1091 if (nativeCheck) { |
| 926 return typeCast | 1092 return typeCast |
| 927 ? const SourceString("numberOrStringSuperNativeTypeCast") | 1093 ? const PropertyCheckedModeHelper( |
| 928 : const SourceString('numberOrStringSuperNativeTypeCheck'); | 1094 const SourceString("numberOrStringSuperNativeTypeCast")) |
| 1095 : const PropertyCheckedModeHelper( |
| 1096 const SourceString('numberOrStringSuperNativeTypeCheck')); |
| 929 } else { | 1097 } else { |
| 930 return typeCast | 1098 return typeCast |
| 931 ? const SourceString("numberOrStringSuperTypeCast") | 1099 ? const PropertyCheckedModeHelper( |
| 932 : const SourceString('numberOrStringSuperTypeCheck'); | 1100 const SourceString("numberOrStringSuperTypeCast")) |
| 1101 : const PropertyCheckedModeHelper( |
| 1102 const SourceString('numberOrStringSuperTypeCheck')); |
| 933 } | 1103 } |
| 934 } else if (Elements.isStringOnlySupertype(element, compiler)) { | 1104 } else if (Elements.isStringOnlySupertype(element, compiler)) { |
| 935 if (nativeCheck) { | 1105 if (nativeCheck) { |
| 936 return typeCast | 1106 return typeCast |
| 937 ? const SourceString("stringSuperNativeTypeCast") | 1107 ? const PropertyCheckedModeHelper( |
| 938 : const SourceString('stringSuperNativeTypeCheck'); | 1108 const SourceString("stringSuperNativeTypeCast")) |
| 1109 : const PropertyCheckedModeHelper( |
| 1110 const SourceString('stringSuperNativeTypeCheck')); |
| 939 } else { | 1111 } else { |
| 940 return typeCast | 1112 return typeCast |
| 941 ? const SourceString("stringSuperTypeCast") | 1113 ? const PropertyCheckedModeHelper( |
| 942 : const SourceString('stringSuperTypeCheck'); | 1114 const SourceString("stringSuperTypeCast")) |
| 1115 : const PropertyCheckedModeHelper( |
| 1116 const SourceString('stringSuperTypeCheck')); |
| 943 } | 1117 } |
| 944 } else if ((element == compiler.listClass || element == jsArrayClass) && | 1118 } else if ((element == compiler.listClass || element == jsArrayClass) && |
| 945 type.isRaw) { | 1119 type.isRaw) { |
| 946 if (nativeCheckOnly) return null; | 1120 if (nativeCheckOnly) return null; |
| 947 return typeCast | 1121 return typeCast |
| 948 ? const SourceString("listTypeCast") | 1122 ? const CheckedModeHelper(const SourceString("listTypeCast")) |
| 949 : const SourceString('listTypeCheck'); | 1123 : const CheckedModeHelper(const SourceString('listTypeCheck')); |
| 950 } else { | 1124 } else { |
| 951 if (Elements.isListSupertype(element, compiler)) { | 1125 if (Elements.isListSupertype(element, compiler)) { |
| 952 if (nativeCheck) { | 1126 if (nativeCheck) { |
| 953 return typeCast | 1127 return typeCast |
| 954 ? const SourceString("listSuperNativeTypeCast") | 1128 ? const PropertyCheckedModeHelper( |
| 955 : const SourceString('listSuperNativeTypeCheck'); | 1129 const SourceString("listSuperNativeTypeCast")) |
| 1130 : const PropertyCheckedModeHelper( |
| 1131 const SourceString('listSuperNativeTypeCheck')); |
| 956 } else { | 1132 } else { |
| 957 return typeCast | 1133 return typeCast |
| 958 ? const SourceString("listSuperTypeCast") | 1134 ? const PropertyCheckedModeHelper( |
| 959 : const SourceString('listSuperTypeCheck'); | 1135 const SourceString("listSuperTypeCast")) |
| 1136 : const PropertyCheckedModeHelper( |
| 1137 const SourceString('listSuperTypeCheck')); |
| 960 } | 1138 } |
| 961 } else { | 1139 } else { |
| 962 if (nativeCheck) { | 1140 if (nativeCheck) { |
| 963 // TODO(karlklose): can we get rid of this branch when we use | 1141 // TODO(karlklose): can we get rid of this branch when we use |
| 964 // interceptors? | 1142 // interceptors? |
| 965 return typeCast | 1143 return typeCast |
| 966 ? const SourceString("interceptedTypeCast") | 1144 ? const PropertyCheckedModeHelper( |
| 967 : const SourceString('interceptedTypeCheck'); | 1145 const SourceString("interceptedTypeCast")) |
| 1146 : const PropertyCheckedModeHelper( |
| 1147 const SourceString('interceptedTypeCheck')); |
| 968 } else { | 1148 } else { |
| 969 if (type.kind == TypeKind.INTERFACE && !type.isRaw) { | 1149 if (type.kind == TypeKind.INTERFACE && !type.isRaw) { |
| 970 return typeCast | 1150 return typeCast |
| 971 ? const SourceString('subtypeCast') | 1151 ? const SubtypeCheckedModeHelper( |
| 972 : const SourceString('assertSubtype'); | 1152 const SourceString('subtypeCast')) |
| 1153 : const SubtypeCheckedModeHelper( |
| 1154 const SourceString('assertSubtype')); |
| 973 } else if (type.kind == TypeKind.TYPE_VARIABLE) { | 1155 } else if (type.kind == TypeKind.TYPE_VARIABLE) { |
| 974 return typeCast | 1156 return typeCast |
| 975 ? const SourceString('subtypeOfRuntimeTypeCast') | 1157 ? const TypeVariableCheckedModeHelper( |
| 976 : const SourceString('assertSubtypeOfRuntimeType'); | 1158 const SourceString('subtypeOfRuntimeTypeCast')) |
| 1159 : const TypeVariableCheckedModeHelper( |
| 1160 const SourceString('assertSubtypeOfRuntimeType')); |
| 1161 } else if (type.kind == TypeKind.FUNCTION) { |
| 1162 return typeCast |
| 1163 ? const FunctionTypeCheckedModeHelper( |
| 1164 const SourceString('functionSubtypeCast')) |
| 1165 : const FunctionTypeCheckedModeHelper( |
| 1166 const SourceString('assertFunctionSubtype')); |
| 977 } else { | 1167 } else { |
| 978 return typeCast | 1168 return typeCast |
| 979 ? const SourceString('propertyTypeCast') | 1169 ? const PropertyCheckedModeHelper( |
| 980 : const SourceString('propertyTypeCheck'); | 1170 const SourceString('propertyTypeCast')) |
| 1171 : const PropertyCheckedModeHelper( |
| 1172 const SourceString('propertyTypeCheck')); |
| 981 } | 1173 } |
| 982 } | 1174 } |
| 983 } | 1175 } |
| 984 } | 1176 } |
| 985 } | 1177 } |
| 986 | 1178 |
| 987 Element getExceptionUnwrapper() { | 1179 Element getExceptionUnwrapper() { |
| 988 return compiler.findHelper(const SourceString('unwrapException')); | 1180 return compiler.findHelper(const SourceString('unwrapException')); |
| 989 } | 1181 } |
| 990 | 1182 |
| 991 Element getThrowRuntimeError() { | 1183 Element getThrowRuntimeError() { |
| 992 return compiler.findHelper(const SourceString('throwRuntimeError')); | 1184 return compiler.findHelper(const SourceString('throwRuntimeError')); |
| 993 } | 1185 } |
| 994 | 1186 |
| 1187 Element getMalformedTypeCheck() { |
| 1188 return compiler.findHelper(const SourceString('malformedTypeCheck')); |
| 1189 } |
| 1190 |
| 995 Element getThrowMalformedSubtypeError() { | 1191 Element getThrowMalformedSubtypeError() { |
| 996 return compiler.findHelper( | 1192 return compiler.findHelper( |
| 997 const SourceString('throwMalformedSubtypeError')); | 1193 const SourceString('throwMalformedSubtypeError')); |
| 998 } | 1194 } |
| 999 | 1195 |
| 1000 Element getThrowAbstractClassInstantiationError() { | 1196 Element getThrowAbstractClassInstantiationError() { |
| 1001 return compiler.findHelper( | 1197 return compiler.findHelper( |
| 1002 const SourceString('throwAbstractClassInstantiationError')); | 1198 const SourceString('throwAbstractClassInstantiationError')); |
| 1003 } | 1199 } |
| 1004 | 1200 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1027 } | 1223 } |
| 1028 | 1224 |
| 1029 Element getSetRuntimeTypeInfo() { | 1225 Element getSetRuntimeTypeInfo() { |
| 1030 return compiler.findHelper(const SourceString('setRuntimeTypeInfo')); | 1226 return compiler.findHelper(const SourceString('setRuntimeTypeInfo')); |
| 1031 } | 1227 } |
| 1032 | 1228 |
| 1033 Element getGetRuntimeTypeInfo() { | 1229 Element getGetRuntimeTypeInfo() { |
| 1034 return compiler.findHelper(const SourceString('getRuntimeTypeInfo')); | 1230 return compiler.findHelper(const SourceString('getRuntimeTypeInfo')); |
| 1035 } | 1231 } |
| 1036 | 1232 |
| 1233 Element getComputeSignature() { |
| 1234 return compiler.findHelper(const SourceString('computeSignature')); |
| 1235 } |
| 1236 |
| 1237 Element getGetRuntimeTypeArguments() { |
| 1238 return compiler.findHelper(const SourceString('getRuntimeTypeArguments')); |
| 1239 } |
| 1240 |
| 1037 Element getGetRuntimeTypeArgument() { | 1241 Element getGetRuntimeTypeArgument() { |
| 1038 return compiler.findHelper(const SourceString('getRuntimeTypeArgument')); | 1242 return compiler.findHelper(const SourceString('getRuntimeTypeArgument')); |
| 1039 } | 1243 } |
| 1040 | 1244 |
| 1041 Element getRuntimeTypeToString() { | 1245 Element getRuntimeTypeToString() { |
| 1042 return compiler.findHelper(const SourceString('runtimeTypeToString')); | 1246 return compiler.findHelper(const SourceString('runtimeTypeToString')); |
| 1043 } | 1247 } |
| 1044 | 1248 |
| 1045 Element getCheckSubtype() { | 1249 Element getCheckSubtype() { |
| 1046 return compiler.findHelper(const SourceString('checkSubtype')); | 1250 return compiler.findHelper(const SourceString('checkSubtype')); |
| 1047 } | 1251 } |
| 1048 | 1252 |
| 1049 Element getAssertSubtype() { | 1253 Element getAssertSubtype() { |
| 1050 return compiler.findHelper(const SourceString('assertSubtype')); | 1254 return compiler.findHelper(const SourceString('assertSubtype')); |
| 1051 } | 1255 } |
| 1052 | 1256 |
| 1053 Element getCheckSubtypeOfRuntimeType() { | 1257 Element getCheckSubtypeOfRuntimeType() { |
| 1054 return compiler.findHelper(const SourceString('checkSubtypeOfRuntimeType')); | 1258 return compiler.findHelper(const SourceString('checkSubtypeOfRuntimeType')); |
| 1055 } | 1259 } |
| 1056 | 1260 |
| 1057 Element getAssertSubtypeOfRuntimeType() { | 1261 Element getAssertSubtypeOfRuntimeType() { |
| 1058 return compiler.findHelper( | 1262 return compiler.findHelper( |
| 1059 const SourceString('assertSubtypeOfRuntimeType')); | 1263 const SourceString('assertSubtypeOfRuntimeType')); |
| 1060 } | 1264 } |
| 1061 | 1265 |
| 1266 Element getCheckFunctionSubtype() { |
| 1267 return compiler.findHelper(const SourceString('checkFunctionSubtype')); |
| 1268 } |
| 1269 |
| 1062 Element getThrowNoSuchMethod() { | 1270 Element getThrowNoSuchMethod() { |
| 1063 return compiler.findHelper(const SourceString('throwNoSuchMethod')); | 1271 return compiler.findHelper(const SourceString('throwNoSuchMethod')); |
| 1064 } | 1272 } |
| 1065 | 1273 |
| 1066 Element getCreateRuntimeType() { | 1274 Element getCreateRuntimeType() { |
| 1067 return compiler.findHelper(const SourceString('createRuntimeType')); | 1275 return compiler.findHelper(const SourceString('createRuntimeType')); |
| 1068 } | 1276 } |
| 1069 | 1277 |
| 1070 Element getFallThroughError() { | 1278 Element getFallThroughError() { |
| 1071 return compiler.findHelper(const SourceString("getFallThroughError")); | 1279 return compiler.findHelper(const SourceString("getFallThroughError")); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1119 } | 1327 } |
| 1120 | 1328 |
| 1121 void registerStaticUse(Element element, Enqueuer enqueuer) { | 1329 void registerStaticUse(Element element, Enqueuer enqueuer) { |
| 1122 if (element == disableTreeShakingMarker) { | 1330 if (element == disableTreeShakingMarker) { |
| 1123 enqueuer.enqueueEverything(); | 1331 enqueuer.enqueueEverything(); |
| 1124 compiler.disableTypeInferenceForMirrors = true; | 1332 compiler.disableTypeInferenceForMirrors = true; |
| 1125 } else if (element == preserveNamesMarker) { | 1333 } else if (element == preserveNamesMarker) { |
| 1126 } | 1334 } |
| 1127 } | 1335 } |
| 1128 } | 1336 } |
| OLD | NEW |