OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library dart2js.type_mask_system; | 5 library dart2js.type_mask_system; |
6 | 6 |
7 import '../common/names.dart' show Selectors, Identifiers; | 7 import '../common/names.dart' show Selectors, Identifiers; |
8 import '../compiler.dart' as dart2js show Compiler; | 8 import '../compiler.dart' as dart2js show Compiler; |
9 import '../constants/values.dart'; | 9 import '../constants/values.dart'; |
10 import '../dart_types.dart' as types; | 10 import '../dart_types.dart' as types; |
11 import '../elements/elements.dart'; | 11 import '../elements/elements.dart'; |
12 import '../js_backend/backend_helpers.dart' show BackendHelpers; | 12 import '../js_backend/backend_helpers.dart' show BackendHelpers; |
13 import '../js_backend/js_backend.dart' show JavaScriptBackend; | 13 import '../js_backend/js_backend.dart' show JavaScriptBackend; |
14 import '../types/types.dart'; | 14 import '../types/types.dart'; |
15 import '../types/constants.dart' show computeTypeMask; | 15 import '../types/constants.dart' show computeTypeMask; |
16 import '../universe/selector.dart' show Selector; | 16 import '../universe/selector.dart' show Selector; |
17 import '../world.dart' show World; | 17 import '../world.dart' show World; |
18 | 18 |
19 enum AbstractBool { | 19 enum AbstractBool { |
20 True, False, Maybe, Nothing | 20 True, False, Maybe, Nothing |
21 } | 21 } |
22 | 22 |
23 class TypeMaskSystem { | 23 class TypeMaskSystem { |
24 final TypesTask inferrer; | 24 final TypesTask inferrer; |
25 final World classWorld; | 25 final World classWorld; |
26 final JavaScriptBackend backend; | 26 final JavaScriptBackend backend; |
27 | 27 |
| 28 TypeMask _numStringBoolType; |
| 29 TypeMask _fixedLengthType; |
| 30 TypeMask _interceptorType; |
| 31 TypeMask _interceptedTypes; // Does not include null. |
| 32 |
| 33 TypeMask __indexableTypeTest; |
| 34 |
28 TypeMask get dynamicType => inferrer.dynamicType; | 35 TypeMask get dynamicType => inferrer.dynamicType; |
29 TypeMask get typeType => inferrer.typeType; | 36 TypeMask get typeType => inferrer.typeType; |
30 TypeMask get functionType => inferrer.functionType; | 37 TypeMask get functionType => inferrer.functionType; |
31 TypeMask get boolType => inferrer.boolType; | 38 TypeMask get boolType => inferrer.boolType; |
32 TypeMask get intType => inferrer.intType; | 39 TypeMask get intType => inferrer.intType; |
33 TypeMask get doubleType => inferrer.doubleType; | 40 TypeMask get doubleType => inferrer.doubleType; |
34 TypeMask get numType => inferrer.numType; | 41 TypeMask get numType => inferrer.numType; |
35 TypeMask get stringType => inferrer.stringType; | 42 TypeMask get stringType => inferrer.stringType; |
36 TypeMask get listType => inferrer.listType; | 43 TypeMask get listType => inferrer.listType; |
37 TypeMask get mapType => inferrer.mapType; | 44 TypeMask get mapType => inferrer.mapType; |
38 TypeMask get nonNullType => inferrer.nonNullType; | 45 TypeMask get nonNullType => inferrer.nonNullType; |
39 TypeMask get nullType => inferrer.nullType; | 46 TypeMask get nullType => inferrer.nullType; |
40 TypeMask get extendableNativeListType => backend.extendableArrayType; | 47 TypeMask get extendableNativeListType => backend.extendableArrayType; |
41 | 48 |
42 TypeMask get uint31Type => inferrer.uint31Type; | 49 TypeMask get uint31Type => inferrer.uint31Type; |
43 TypeMask get uint32Type => inferrer.uint32Type; | 50 TypeMask get uint32Type => inferrer.uint32Type; |
44 TypeMask get uintType => inferrer.positiveIntType; | 51 TypeMask get uintType => inferrer.positiveIntType; |
45 | 52 |
46 TypeMask numStringBoolType; | 53 TypeMask get numStringBoolType { |
47 TypeMask fixedLengthType; | 54 if (_numStringBoolType == null) { |
48 TypeMask interceptorType; | 55 // Build the number+string+bool type. To make containment tests more |
49 TypeMask interceptedTypes; // Does not include null. | 56 // inclusive, we use the num, String, bool types for this, not |
| 57 // the JSNumber, JSString, JSBool subclasses. |
| 58 TypeMask anyNum = |
| 59 new TypeMask.nonNullSubtype(classWorld.numClass, classWorld); |
| 60 TypeMask anyString = |
| 61 new TypeMask.nonNullSubtype(classWorld.stringClass, classWorld); |
| 62 TypeMask anyBool = |
| 63 new TypeMask.nonNullSubtype(classWorld.boolClass, classWorld); |
| 64 _numStringBoolType = |
| 65 new TypeMask.unionOf(<TypeMask>[anyNum, anyString, anyBool], |
| 66 classWorld); |
| 67 } |
| 68 return _numStringBoolType; |
| 69 } |
50 | 70 |
51 TypeMask _indexableTypeTest; | 71 TypeMask get fixedLengthType { |
| 72 if (_fixedLengthType == null) { |
| 73 List<TypeMask> fixedLengthTypes = |
| 74 <TypeMask>[stringType, backend.fixedArrayType]; |
| 75 if (classWorld.isInstantiated(helpers.typedArrayClass)) { |
| 76 fixedLengthTypes.add(nonNullSubclass(helpers.typedArrayClass)); |
| 77 } |
| 78 _fixedLengthType = new TypeMask.unionOf(fixedLengthTypes, classWorld); |
| 79 } |
| 80 return _fixedLengthType; |
| 81 } |
| 82 |
| 83 TypeMask get interceptorType { |
| 84 if (_interceptorType == null) { |
| 85 _interceptorType = |
| 86 new TypeMask.nonNullSubtype(helpers.jsInterceptorClass, classWorld); |
| 87 } |
| 88 return _interceptorType; |
| 89 } |
| 90 |
| 91 TypeMask get interceptedTypes { // Does not include null. |
| 92 if (_interceptedTypes == null) { |
| 93 // We redundantly include subtypes of num/string/bool as intercepted |
| 94 // types, because the type system does not infer that their |
| 95 // implementations are all subclasses of Interceptor. |
| 96 _interceptedTypes = new TypeMask.unionOf( |
| 97 <TypeMask>[interceptorType, numStringBoolType], classWorld); |
| 98 } |
| 99 return _interceptedTypes; |
| 100 } |
| 101 |
| 102 TypeMask get _indexableTypeTest { |
| 103 if (__indexableTypeTest == null) { |
| 104 // Make a TypeMask containing Indexable and (redundantly) subtypes of |
| 105 // string because the type inference does not infer that all strings are |
| 106 // indexables. |
| 107 TypeMask indexable = |
| 108 new TypeMask.nonNullSubtype(helpers.jsIndexableClass, classWorld); |
| 109 TypeMask anyString = |
| 110 new TypeMask.nonNullSubtype(classWorld.stringClass, classWorld); |
| 111 __indexableTypeTest = new TypeMask.unionOf( |
| 112 <TypeMask>[indexable, anyString], |
| 113 classWorld); |
| 114 } |
| 115 return __indexableTypeTest; |
| 116 } |
52 | 117 |
53 ClassElement get jsNullClass => helpers.jsNullClass; | 118 ClassElement get jsNullClass => helpers.jsNullClass; |
54 | 119 |
55 BackendHelpers get helpers => backend.helpers; | 120 BackendHelpers get helpers => backend.helpers; |
56 | 121 |
57 // TODO(karlklose): remove compiler here. | 122 // TODO(karlklose): remove compiler here. |
58 TypeMaskSystem(dart2js.Compiler compiler) | 123 TypeMaskSystem(dart2js.Compiler compiler) |
59 : inferrer = compiler.typesTask, | 124 : inferrer = compiler.typesTask, |
60 classWorld = compiler.world, | 125 classWorld = compiler.world, |
61 backend = compiler.backend { | 126 backend = compiler.backend { |
62 | |
63 // Build the number+string+bool type. To make containment tests more | |
64 // inclusive, we use the num, String, bool types for this, not | |
65 // the JSNumber, JSString, JSBool subclasses. | |
66 TypeMask anyNum = | |
67 new TypeMask.nonNullSubtype(classWorld.numClass, classWorld); | |
68 TypeMask anyString = | |
69 new TypeMask.nonNullSubtype(classWorld.stringClass, classWorld); | |
70 TypeMask anyBool = | |
71 new TypeMask.nonNullSubtype(classWorld.boolClass, classWorld); | |
72 numStringBoolType = | |
73 new TypeMask.unionOf(<TypeMask>[anyNum, anyString, anyBool], | |
74 classWorld); | |
75 interceptorType = | |
76 new TypeMask.nonNullSubtype(helpers.jsInterceptorClass, classWorld); | |
77 | |
78 // We redundantly include subtypes of num/string/bool as intercepted types, | |
79 // because the type system does not infer that their implementations are | |
80 // all subclasses of Interceptor. | |
81 interceptedTypes = new TypeMask.unionOf( | |
82 <TypeMask>[interceptorType, numStringBoolType], classWorld); | |
83 | |
84 TypeMask typedArray = nonNullSubclass(helpers.typedArrayClass); | |
85 fixedLengthType = new TypeMask.unionOf( | |
86 <TypeMask>[stringType, backend.fixedArrayType, typedArray], | |
87 classWorld); | |
88 | |
89 // Make a TypeMask containing Indexable and (redundantly) subtypes of | |
90 // string because the type inference does not infer that all strings are | |
91 // indexables. | |
92 TypeMask indexable = | |
93 new TypeMask.nonNullSubtype(helpers.jsIndexableClass, classWorld); | |
94 _indexableTypeTest = new TypeMask.unionOf( | |
95 <TypeMask>[indexable, anyString], | |
96 classWorld); | |
97 } | 127 } |
98 | 128 |
99 bool methodUsesReceiverArgument(FunctionElement function) { | 129 bool methodUsesReceiverArgument(FunctionElement function) { |
100 assert(backend.isInterceptedMethod(function)); | 130 assert(backend.isInterceptedMethod(function)); |
101 ClassElement clazz = function.enclosingClass.declaration; | 131 ClassElement clazz = function.enclosingClass.declaration; |
102 return clazz.isSubclassOf(helpers.jsInterceptorClass) || | 132 return clazz.isSubclassOf(helpers.jsInterceptorClass) || |
103 classWorld.isUsedAsMixin(clazz); | 133 classWorld.isUsedAsMixin(clazz); |
104 } | 134 } |
105 | 135 |
106 Element locateSingleElement(TypeMask mask, Selector selector) { | 136 Element locateSingleElement(TypeMask mask, Selector selector) { |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 | 452 |
423 /// The length of something of [type], or `null` if unknown. | 453 /// The length of something of [type], or `null` if unknown. |
424 int getContainerLength(TypeMask type) { | 454 int getContainerLength(TypeMask type) { |
425 if (type is ContainerTypeMask) { | 455 if (type is ContainerTypeMask) { |
426 return type.length; | 456 return type.length; |
427 } else { | 457 } else { |
428 return null; | 458 return null; |
429 } | 459 } |
430 } | 460 } |
431 } | 461 } |
OLD | NEW |