| 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 typedef void Recompile(Element element); | 7 typedef void Recompile(Element element); |
| 8 | 8 |
| 9 class ReturnInfo { | 9 class ReturnInfo { |
| 10 HType returnType; | 10 HType returnType; |
| 11 List<Element> compiledFunctions; | 11 List<Element> compiledFunctions; |
| 12 | 12 |
| 13 ReturnInfo(HType this.returnType) | 13 ReturnInfo(HType this.returnType) |
| 14 : compiledFunctions = new List<Element>(); | 14 : compiledFunctions = new List<Element>(); |
| 15 | 15 |
| 16 ReturnInfo.unknownType() | 16 ReturnInfo.unknownType() |
| 17 : this.returnType = null, | 17 : this.returnType = HType.UNKNOWN, |
| 18 compiledFunctions = new List<Element>(); | 18 compiledFunctions = new List<Element>(); |
| 19 | 19 |
| 20 void update(HType type, Recompile recompile, Compiler compiler) { | 20 void update(HType type, Recompile recompile, Compiler compiler) { |
| 21 HType newType = | 21 HType newType = |
| 22 returnType != null ? returnType.union(type, compiler) : type; | 22 returnType != null ? returnType.union(type, compiler) : type; |
| 23 if (newType != returnType) { | 23 if (newType != returnType) { |
| 24 if (returnType == null && identical(newType, HType.UNKNOWN)) { | 24 if (returnType == null && identical(newType, HType.UNKNOWN)) { |
| 25 // If the first actual piece of information is not providing any type | 25 // If the first actual piece of information is not providing any type |
| 26 // information there is no need to recompile callers. | 26 // information there is no need to recompile callers. |
| 27 compiledFunctions.clear(); | 27 compiledFunctions.clear(); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 } | 121 } |
| 122 return result; | 122 return result; |
| 123 } | 123 } |
| 124 | 124 |
| 125 static const HTypeList ALL_UNKNOWN = const HTypeList.withAllUnknown(); | 125 static const HTypeList ALL_UNKNOWN = const HTypeList.withAllUnknown(); |
| 126 | 126 |
| 127 bool get allUnknown => types == null; | 127 bool get allUnknown => types == null; |
| 128 bool get hasNamedArguments => namedArguments != null; | 128 bool get hasNamedArguments => namedArguments != null; |
| 129 int get length => types.length; | 129 int get length => types.length; |
| 130 HType operator[](int index) => types[index]; | 130 HType operator[](int index) => types[index]; |
| 131 void operator[]=(int index, HType type) { types[index] = type; } |
| 131 | 132 |
| 132 HTypeList union(HTypeList other, Compiler compiler) { | 133 HTypeList union(HTypeList other, Compiler compiler) { |
| 133 if (allUnknown) return this; | 134 if (allUnknown) return this; |
| 134 if (other.allUnknown) return other; | 135 if (other.allUnknown) return other; |
| 135 if (length != other.length) return HTypeList.ALL_UNKNOWN; | 136 if (length != other.length) return HTypeList.ALL_UNKNOWN; |
| 136 bool onlyUnknown = true; | 137 bool onlyUnknown = true; |
| 137 HTypeList result = this; | 138 HTypeList result = this; |
| 138 for (int i = 0; i < length; i++) { | 139 for (int i = 0; i < length; i++) { |
| 139 HType newType = this[i].union(other[i], compiler); | 140 HType newType = this[i].union(other[i], compiler); |
| 140 if (result == this && newType != this[i]) { | 141 if (result == this && newType != this[i]) { |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 // When a static is used for anything else than a call target we cannot | 476 // When a static is used for anything else than a call target we cannot |
| 476 // infer anything about its parameter types. | 477 // infer anything about its parameter types. |
| 477 Element element = node.element; | 478 Element element = node.element; |
| 478 assert(invariant(node, element.isDeclaration)); | 479 assert(invariant(node, element.isDeclaration)); |
| 479 if (optimizedStaticFunctions.contains(element)) { | 480 if (optimizedStaticFunctions.contains(element)) { |
| 480 backend.scheduleForRecompilation(element); | 481 backend.scheduleForRecompilation(element); |
| 481 } | 482 } |
| 482 staticTypeMap[element] = HTypeList.ALL_UNKNOWN; | 483 staticTypeMap[element] = HTypeList.ALL_UNKNOWN; |
| 483 } | 484 } |
| 484 | 485 |
| 485 void registerDynamicInvocation(HInvokeDynamic node, | 486 void registerDynamicInvocation(HTypeList providedTypes, Selector selector) { |
| 486 Selector selector, | |
| 487 HTypeMap types) { | |
| 488 if (selector.isClosureCall()) { | 487 if (selector.isClosureCall()) { |
| 489 // We cannot use the current framework to do optimizations based | 488 // We cannot use the current framework to do optimizations based |
| 490 // on the 'call' selector because we are also generating closure | 489 // on the 'call' selector because we are also generating closure |
| 491 // calls during the emitter phase, which at this point, does not | 490 // calls during the emitter phase, which at this point, does not |
| 492 // track parameter types, nor invalidates optimized methods. | 491 // track parameter types, nor invalidates optimized methods. |
| 493 return; | 492 return; |
| 494 } | 493 } |
| 495 HTypeList providedTypes = | |
| 496 new HTypeList.fromDynamicInvocation(node, selector, types); | |
| 497 if (!selectorTypeMap.containsKey(selector)) { | 494 if (!selectorTypeMap.containsKey(selector)) { |
| 498 selectorTypeMap[selector] = providedTypes; | 495 selectorTypeMap[selector] = providedTypes; |
| 499 } else { | 496 } else { |
| 500 HTypeList oldTypes = selectorTypeMap[selector]; | 497 HTypeList oldTypes = selectorTypeMap[selector]; |
| 501 updateTypes(oldTypes, providedTypes, selector, selectorTypeMap); | 498 updateTypes(oldTypes, providedTypes, selector, selectorTypeMap); |
| 502 } | 499 } |
| 503 | 500 |
| 504 // If we're not compiling, we don't have to do anything. | 501 // If we're not compiling, we don't have to do anything. |
| 505 if (compiler.phase != Compiler.PHASE_COMPILING) return; | 502 if (compiler.phase != Compiler.PHASE_COMPILING) return; |
| 506 | 503 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 ClassElement jsBoolClass; | 633 ClassElement jsBoolClass; |
| 637 ClassElement objectInterceptorClass; | 634 ClassElement objectInterceptorClass; |
| 638 Element jsArrayLength; | 635 Element jsArrayLength; |
| 639 Element jsStringLength; | 636 Element jsStringLength; |
| 640 Element jsArrayRemoveLast; | 637 Element jsArrayRemoveLast; |
| 641 Element jsArrayAdd; | 638 Element jsArrayAdd; |
| 642 Element jsStringSplit; | 639 Element jsStringSplit; |
| 643 Element jsStringConcat; | 640 Element jsStringConcat; |
| 644 Element getInterceptorMethod; | 641 Element getInterceptorMethod; |
| 645 Element fixedLengthListConstructor; | 642 Element fixedLengthListConstructor; |
| 646 bool _interceptorsAreInitialized = false; | 643 bool seenAnyClass = false; |
| 647 | 644 |
| 648 final Namer namer; | 645 final Namer namer; |
| 649 | 646 |
| 650 /** | 647 /** |
| 651 * Interface used to determine if an object has the JavaScript | 648 * Interface used to determine if an object has the JavaScript |
| 652 * indexing behavior. The interface is only visible to specific | 649 * indexing behavior. The interface is only visible to specific |
| 653 * libraries. | 650 * libraries. |
| 654 */ | 651 */ |
| 655 ClassElement jsIndexingBehaviorInterface; | 652 ClassElement jsIndexingBehaviorInterface; |
| 656 | 653 |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 return keys; | 833 return keys; |
| 837 }); | 834 }); |
| 838 return namer.isolateAccess(getInterceptorMethod); | 835 return namer.isolateAccess(getInterceptorMethod); |
| 839 } else { | 836 } else { |
| 840 String name = namer.getSpecializedName(getInterceptorMethod, classes); | 837 String name = namer.getSpecializedName(getInterceptorMethod, classes); |
| 841 specializedGetInterceptors[name] = classes; | 838 specializedGetInterceptors[name] = classes; |
| 842 return '${namer.CURRENT_ISOLATE}.$name'; | 839 return '${namer.CURRENT_ISOLATE}.$name'; |
| 843 } | 840 } |
| 844 } | 841 } |
| 845 | 842 |
| 843 void initializeNoSuchMethod() { |
| 844 // In case the emitter generates noSuchMethod calls, we need to |
| 845 // make sure all [noSuchMethod] methods know they might take a |
| 846 // [JsInvocationMirror] as parameter. |
| 847 HTypeList types = new HTypeList(1); |
| 848 types[0] = new HType.fromBoundedType( |
| 849 compiler.jsInvocationMirrorClass.computeType(compiler), |
| 850 compiler, |
| 851 false); |
| 852 argumentTypes.registerDynamicInvocation(types, new Selector.noSuchMethod()); |
| 853 } |
| 854 |
| 846 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) { | 855 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) { |
| 856 if (!seenAnyClass) { |
| 857 initializeInterceptorElements(); |
| 858 initializeNoSuchMethod(); |
| 859 seenAnyClass = true; |
| 860 } |
| 847 ClassElement result = null; | 861 ClassElement result = null; |
| 848 if (!_interceptorsAreInitialized) { | |
| 849 initializeInterceptorElements(); | |
| 850 _interceptorsAreInitialized = true; | |
| 851 } | |
| 852 if (cls == compiler.stringClass) { | 862 if (cls == compiler.stringClass) { |
| 853 addInterceptors(jsStringClass, enqueuer); | 863 addInterceptors(jsStringClass, enqueuer); |
| 854 } else if (cls == compiler.listClass) { | 864 } else if (cls == compiler.listClass) { |
| 855 addInterceptors(jsArrayClass, enqueuer); | 865 addInterceptors(jsArrayClass, enqueuer); |
| 856 // The backend will try to optimize array access and use the | 866 // The backend will try to optimize array access and use the |
| 857 // `ioore` and `iae` helpers directly. | 867 // `ioore` and `iae` helpers directly. |
| 858 enqueuer.registerStaticUse( | 868 enqueuer.registerStaticUse( |
| 859 compiler.findHelper(const SourceString('ioore'))); | 869 compiler.findHelper(const SourceString('ioore'))); |
| 860 enqueuer.registerStaticUse( | 870 enqueuer.registerStaticUse( |
| 861 compiler.findHelper(const SourceString('iae'))); | 871 compiler.findHelper(const SourceString('iae'))); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 957 } | 967 } |
| 958 } | 968 } |
| 959 | 969 |
| 960 /** | 970 /** |
| 961 * Register a dynamic invocation and collect the provided types for the | 971 * Register a dynamic invocation and collect the provided types for the |
| 962 * named selector. | 972 * named selector. |
| 963 */ | 973 */ |
| 964 void registerDynamicInvocation(HInvokeDynamic node, | 974 void registerDynamicInvocation(HInvokeDynamic node, |
| 965 Selector selector, | 975 Selector selector, |
| 966 HTypeMap types) { | 976 HTypeMap types) { |
| 967 argumentTypes.registerDynamicInvocation(node, selector, types); | 977 HTypeList providedTypes = |
| 978 new HTypeList.fromDynamicInvocation(node, selector, types); |
| 979 argumentTypes.registerDynamicInvocation(providedTypes, selector); |
| 968 } | 980 } |
| 969 | 981 |
| 970 /** | 982 /** |
| 971 * Register a static invocation and collect the provided types for the | 983 * Register a static invocation and collect the provided types for the |
| 972 * named selector. | 984 * named selector. |
| 973 */ | 985 */ |
| 974 void registerStaticInvocation(HInvokeStatic node, HTypeMap types) { | 986 void registerStaticInvocation(HInvokeStatic node, HTypeMap types) { |
| 975 argumentTypes.registerStaticInvocation(node, types); | 987 argumentTypes.registerStaticInvocation(node, types); |
| 976 } | 988 } |
| 977 | 989 |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1142 print("Inferred return types:"); | 1154 print("Inferred return types:"); |
| 1143 print("----------------------"); | 1155 print("----------------------"); |
| 1144 dumpReturnTypes(); | 1156 dumpReturnTypes(); |
| 1145 print(""); | 1157 print(""); |
| 1146 print("Inferred field types:"); | 1158 print("Inferred field types:"); |
| 1147 print("------------------------"); | 1159 print("------------------------"); |
| 1148 fieldTypes.dump(); | 1160 fieldTypes.dump(); |
| 1149 print(""); | 1161 print(""); |
| 1150 } | 1162 } |
| 1151 } | 1163 } |
| OLD | NEW |