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 | |
35 TypeMask get dynamicType => inferrer.dynamicType; | 28 TypeMask get dynamicType => inferrer.dynamicType; |
36 TypeMask get typeType => inferrer.typeType; | 29 TypeMask get typeType => inferrer.typeType; |
37 TypeMask get functionType => inferrer.functionType; | 30 TypeMask get functionType => inferrer.functionType; |
38 TypeMask get boolType => inferrer.boolType; | 31 TypeMask get boolType => inferrer.boolType; |
39 TypeMask get intType => inferrer.intType; | 32 TypeMask get intType => inferrer.intType; |
40 TypeMask get doubleType => inferrer.doubleType; | 33 TypeMask get doubleType => inferrer.doubleType; |
41 TypeMask get numType => inferrer.numType; | 34 TypeMask get numType => inferrer.numType; |
42 TypeMask get stringType => inferrer.stringType; | 35 TypeMask get stringType => inferrer.stringType; |
43 TypeMask get listType => inferrer.listType; | 36 TypeMask get listType => inferrer.listType; |
44 TypeMask get mapType => inferrer.mapType; | 37 TypeMask get mapType => inferrer.mapType; |
45 TypeMask get nonNullType => inferrer.nonNullType; | 38 TypeMask get nonNullType => inferrer.nonNullType; |
46 TypeMask get nullType => inferrer.nullType; | 39 TypeMask get nullType => inferrer.nullType; |
47 TypeMask get extendableNativeListType => backend.extendableArrayType; | 40 TypeMask get extendableNativeListType => backend.extendableArrayType; |
48 | 41 |
49 TypeMask get uint31Type => inferrer.uint31Type; | 42 TypeMask get uint31Type => inferrer.uint31Type; |
50 TypeMask get uint32Type => inferrer.uint32Type; | 43 TypeMask get uint32Type => inferrer.uint32Type; |
51 TypeMask get uintType => inferrer.positiveIntType; | 44 TypeMask get uintType => inferrer.positiveIntType; |
52 | 45 |
53 TypeMask get numStringBoolType { | 46 TypeMask numStringBoolType; |
54 if (_numStringBoolType == null) { | 47 TypeMask fixedLengthType; |
55 // Build the number+string+bool type. To make containment tests more | 48 TypeMask interceptorType; |
56 // inclusive, we use the num, String, bool types for this, not | 49 TypeMask interceptedTypes; // Does not include null. |
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 } | |
70 | 50 |
71 TypeMask get fixedLengthType { | 51 TypeMask _indexableTypeTest; |
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 } | |
117 | 52 |
118 ClassElement get jsNullClass => helpers.jsNullClass; | 53 ClassElement get jsNullClass => helpers.jsNullClass; |
119 | 54 |
120 BackendHelpers get helpers => backend.helpers; | 55 BackendHelpers get helpers => backend.helpers; |
121 | 56 |
122 // TODO(karlklose): remove compiler here. | 57 // TODO(karlklose): remove compiler here. |
123 TypeMaskSystem(dart2js.Compiler compiler) | 58 TypeMaskSystem(dart2js.Compiler compiler) |
124 : inferrer = compiler.typesTask, | 59 : inferrer = compiler.typesTask, |
125 classWorld = compiler.world, | 60 classWorld = compiler.world, |
126 backend = compiler.backend { | 61 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); |
127 } | 97 } |
128 | 98 |
129 bool methodUsesReceiverArgument(FunctionElement function) { | 99 bool methodUsesReceiverArgument(FunctionElement function) { |
130 assert(backend.isInterceptedMethod(function)); | 100 assert(backend.isInterceptedMethod(function)); |
131 ClassElement clazz = function.enclosingClass.declaration; | 101 ClassElement clazz = function.enclosingClass.declaration; |
132 return clazz.isSubclassOf(helpers.jsInterceptorClass) || | 102 return clazz.isSubclassOf(helpers.jsInterceptorClass) || |
133 classWorld.isUsedAsMixin(clazz); | 103 classWorld.isUsedAsMixin(clazz); |
134 } | 104 } |
135 | 105 |
136 Element locateSingleElement(TypeMask mask, Selector selector) { | 106 Element locateSingleElement(TypeMask mask, Selector selector) { |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 | 422 |
453 /// The length of something of [type], or `null` if unknown. | 423 /// The length of something of [type], or `null` if unknown. |
454 int getContainerLength(TypeMask type) { | 424 int getContainerLength(TypeMask type) { |
455 if (type is ContainerTypeMask) { | 425 if (type is ContainerTypeMask) { |
456 return type.length; | 426 return type.length; |
457 } else { | 427 } else { |
458 return null; | 428 return null; |
459 } | 429 } |
460 } | 430 } |
461 } | 431 } |
OLD | NEW |