OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 12 matching lines...) Expand all Loading... |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "types.h" | 28 #include "types.h" |
29 | 29 |
30 namespace v8 { | 30 namespace v8 { |
31 namespace internal { | 31 namespace internal { |
32 | 32 |
| 33 int Type::NumClasses() { |
| 34 if (is_class()) { |
| 35 return 1; |
| 36 } else if (is_union()) { |
| 37 Handle<Unioned> unioned = as_union(); |
| 38 int result = 0; |
| 39 for (int i = 0; i < unioned->length(); ++i) { |
| 40 if (union_get(unioned, i)->is_class()) ++result; |
| 41 } |
| 42 return result; |
| 43 } else { |
| 44 return 0; |
| 45 } |
| 46 } |
| 47 |
| 48 |
| 49 int Type::NumConstants() { |
| 50 if (is_constant()) { |
| 51 return 1; |
| 52 } else if (is_union()) { |
| 53 Handle<Unioned> unioned = as_union(); |
| 54 int result = 0; |
| 55 for (int i = 0; i < unioned->length(); ++i) { |
| 56 if (union_get(unioned, i)->is_constant()) ++result; |
| 57 } |
| 58 return result; |
| 59 } else { |
| 60 return 0; |
| 61 } |
| 62 } |
| 63 |
| 64 |
| 65 template<class T> |
| 66 Handle<Type> Type::Iterator<T>::get_type() { |
| 67 ASSERT(!Done()); |
| 68 return type_->is_union() ? union_get(type_->as_union(), index_) : type_; |
| 69 } |
| 70 |
| 71 template<> |
| 72 Handle<Map> Type::Iterator<Map>::Current() { |
| 73 return get_type()->as_class(); |
| 74 } |
| 75 |
| 76 template<> |
| 77 Handle<v8::internal::Object> Type::Iterator<v8::internal::Object>::Current() { |
| 78 return get_type()->as_constant(); |
| 79 } |
| 80 |
| 81 |
| 82 template<> |
| 83 bool Type::Iterator<Map>::matches(Handle<Type> type) { |
| 84 return type->is_class(); |
| 85 } |
| 86 |
| 87 template<> |
| 88 bool Type::Iterator<v8::internal::Object>::matches(Handle<Type> type) { |
| 89 return type->is_constant(); |
| 90 } |
| 91 |
| 92 |
| 93 template<class T> |
| 94 void Type::Iterator<T>::Advance() { |
| 95 ++index_; |
| 96 if (type_->is_union()) { |
| 97 Handle<Unioned> unioned = type_->as_union(); |
| 98 for (; index_ < unioned->length(); ++index_) { |
| 99 if (matches(union_get(unioned, index_))) return; |
| 100 } |
| 101 } else if (index_ == 0 && matches(type_)) { |
| 102 return; |
| 103 } |
| 104 index_ = -1; |
| 105 } |
| 106 |
| 107 template class Type::Iterator<Map>; |
| 108 template class Type::Iterator<v8::internal::Object>; |
| 109 |
| 110 |
33 // Get the smallest bitset subsuming this type. | 111 // Get the smallest bitset subsuming this type. |
34 int Type::LubBitset() { | 112 int Type::LubBitset() { |
35 if (this->is_bitset()) { | 113 if (this->is_bitset()) { |
36 return this->as_bitset(); | 114 return this->as_bitset(); |
37 } else if (this->is_union()) { | 115 } else if (this->is_union()) { |
38 Handle<Unioned> unioned = this->as_union(); | 116 Handle<Unioned> unioned = this->as_union(); |
39 int bitset = kNone; | 117 int bitset = kNone; |
40 for (int i = 0; i < unioned->length(); ++i) { | 118 for (int i = 0; i < unioned->length(); ++i) { |
41 bitset |= union_get(unioned, i)->LubBitset(); | 119 bitset |= union_get(unioned, i)->LubBitset(); |
42 } | 120 } |
43 return bitset; | 121 return bitset; |
44 } else { | 122 } else { |
45 Map* map = NULL; | 123 Map* map = NULL; |
46 if (this->is_class()) { | 124 if (this->is_class()) { |
47 map = *this->as_class(); | 125 map = *this->as_class(); |
48 } else { | 126 } else { |
49 v8::internal::Object* value = this->as_constant()->value(); | 127 Handle<v8::internal::Object> value = this->as_constant(); |
50 if (value->IsSmi()) return kSmi; | 128 if (value->IsSmi()) return kInteger31; |
51 map = HeapObject::cast(value)->map(); | 129 map = HeapObject::cast(*value)->map(); |
| 130 if (map->instance_type() == ODDBALL_TYPE) { |
| 131 if (value->IsUndefined()) return kUndefined; |
| 132 if (value->IsNull()) return kNull; |
| 133 if (value->IsTrue() || value->IsFalse()) return kBoolean; |
| 134 } |
52 } | 135 } |
53 switch (map->instance_type()) { | 136 switch (map->instance_type()) { |
54 case STRING_TYPE: | 137 case STRING_TYPE: |
55 case ASCII_STRING_TYPE: | 138 case ASCII_STRING_TYPE: |
56 case CONS_STRING_TYPE: | 139 case CONS_STRING_TYPE: |
57 case CONS_ASCII_STRING_TYPE: | 140 case CONS_ASCII_STRING_TYPE: |
58 case SLICED_STRING_TYPE: | 141 case SLICED_STRING_TYPE: |
| 142 case SLICED_ASCII_STRING_TYPE: |
59 case EXTERNAL_STRING_TYPE: | 143 case EXTERNAL_STRING_TYPE: |
60 case EXTERNAL_ASCII_STRING_TYPE: | 144 case EXTERNAL_ASCII_STRING_TYPE: |
61 case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: | 145 case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: |
62 case SHORT_EXTERNAL_STRING_TYPE: | 146 case SHORT_EXTERNAL_STRING_TYPE: |
63 case SHORT_EXTERNAL_ASCII_STRING_TYPE: | 147 case SHORT_EXTERNAL_ASCII_STRING_TYPE: |
64 case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: | 148 case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: |
65 case INTERNALIZED_STRING_TYPE: | 149 case INTERNALIZED_STRING_TYPE: |
66 case ASCII_INTERNALIZED_STRING_TYPE: | 150 case ASCII_INTERNALIZED_STRING_TYPE: |
67 case CONS_INTERNALIZED_STRING_TYPE: | 151 case CONS_INTERNALIZED_STRING_TYPE: |
68 case CONS_ASCII_INTERNALIZED_STRING_TYPE: | 152 case CONS_ASCII_INTERNALIZED_STRING_TYPE: |
(...skipping 16 matching lines...) Expand all Loading... |
85 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | 169 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
86 case JS_GENERATOR_OBJECT_TYPE: | 170 case JS_GENERATOR_OBJECT_TYPE: |
87 case JS_MODULE_TYPE: | 171 case JS_MODULE_TYPE: |
88 case JS_GLOBAL_OBJECT_TYPE: | 172 case JS_GLOBAL_OBJECT_TYPE: |
89 case JS_BUILTINS_OBJECT_TYPE: | 173 case JS_BUILTINS_OBJECT_TYPE: |
90 case JS_GLOBAL_PROXY_TYPE: | 174 case JS_GLOBAL_PROXY_TYPE: |
91 case JS_ARRAY_BUFFER_TYPE: | 175 case JS_ARRAY_BUFFER_TYPE: |
92 case JS_TYPED_ARRAY_TYPE: | 176 case JS_TYPED_ARRAY_TYPE: |
93 case JS_WEAK_MAP_TYPE: | 177 case JS_WEAK_MAP_TYPE: |
94 case JS_REGEXP_TYPE: | 178 case JS_REGEXP_TYPE: |
| 179 if (map->is_undetectable()) return kUndetectable; |
95 return kOtherObject; | 180 return kOtherObject; |
96 case JS_ARRAY_TYPE: | 181 case JS_ARRAY_TYPE: |
97 return kArray; | 182 return kArray; |
98 case JS_FUNCTION_TYPE: | 183 case JS_FUNCTION_TYPE: |
99 return kFunction; | 184 return kFunction; |
100 case JS_PROXY_TYPE: | 185 case JS_PROXY_TYPE: |
101 case JS_FUNCTION_PROXY_TYPE: | 186 case JS_FUNCTION_PROXY_TYPE: |
102 return kProxy; | 187 return kProxy; |
| 188 case MAP_TYPE: |
| 189 // When compiling stub templates, the meta map is used as a place holder |
| 190 // for the actual map with which the template is later instantiated. |
| 191 // We treat it as a kind of type variable whose upper bound is Any. |
| 192 // TODO(rossberg): for caching of CompareNilIC stubs to work correctly, |
| 193 // we must exclude Undetectable here. This makes no sense, really, |
| 194 // because it means that the template isn't actually parametric. |
| 195 // Also, it doesn't apply elsewhere. 8-( |
| 196 // We ought to find a cleaner solution for compiling stubs parameterised |
| 197 // over type or class variables, esp ones with bounds... |
| 198 return kDetectable; |
103 default: | 199 default: |
104 UNREACHABLE(); | 200 UNREACHABLE(); |
105 return kNone; | 201 return kNone; |
106 } | 202 } |
107 } | 203 } |
108 } | 204 } |
109 | 205 |
110 | 206 |
111 // Get the largest bitset subsumed by this type. | 207 // Get the largest bitset subsumed by this type. |
112 int Type::GlbBitset() { | 208 int Type::GlbBitset() { |
113 if (this->is_bitset()) { | 209 if (this->is_bitset()) { |
114 return this->as_bitset(); | 210 return this->as_bitset(); |
115 } else if (this->is_union()) { | 211 } else if (this->is_union()) { |
116 // All but the first are non-bitsets and thus would yield kNone anyway. | 212 // All but the first are non-bitsets and thus would yield kNone anyway. |
117 return union_get(this->as_union(), 0)->GlbBitset(); | 213 return union_get(this->as_union(), 0)->GlbBitset(); |
118 } else { | 214 } else { |
119 return kNone; | 215 return kNone; |
120 } | 216 } |
121 } | 217 } |
122 | 218 |
123 | 219 |
124 // Check this <= that. | 220 // Check this <= that. |
125 bool Type::Is(Handle<Type> that) { | 221 bool Type::Is(Type* that) { |
126 // Fast path for bitsets. | 222 // Fast path for bitsets. |
127 if (that->is_bitset()) { | 223 if (that->is_bitset()) { |
128 return (this->LubBitset() | that->as_bitset()) == that->as_bitset(); | 224 return (this->LubBitset() | that->as_bitset()) == that->as_bitset(); |
129 } | 225 } |
130 | 226 |
131 if (that->is_class()) { | 227 if (that->is_class()) { |
132 return this->is_class() && *this->as_class() == *that->as_class(); | 228 return this->is_class() && *this->as_class() == *that->as_class(); |
133 } | 229 } |
134 if (that->is_constant()) { | 230 if (that->is_constant()) { |
135 return this->is_constant() && | 231 return this->is_constant() && *this->as_constant() == *that->as_constant(); |
136 this->as_constant()->value() == that->as_constant()->value(); | |
137 } | 232 } |
138 | 233 |
139 // (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T) | 234 // (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T) |
140 if (this->is_union()) { | 235 if (this->is_union()) { |
141 Handle<Unioned> unioned = this->as_union(); | 236 Handle<Unioned> unioned = this->as_union(); |
142 for (int i = 0; i < unioned->length(); ++i) { | 237 for (int i = 0; i < unioned->length(); ++i) { |
143 Handle<Type> this_i = union_get(unioned, i); | 238 Handle<Type> this_i = union_get(unioned, i); |
144 if (!this_i->Is(that)) return false; | 239 if (!this_i->Is(that)) return false; |
145 } | 240 } |
146 return true; | 241 return true; |
147 } | 242 } |
148 | 243 |
149 // T <= (T1 \/ ... \/ Tn) <=> (T <= T1) \/ ... \/ (T <= Tn) | 244 // T <= (T1 \/ ... \/ Tn) <=> (T <= T1) \/ ... \/ (T <= Tn) |
150 // (iff T is not a union) | 245 // (iff T is not a union) |
151 if (that->is_union()) { | 246 if (that->is_union()) { |
152 Handle<Unioned> unioned = that->as_union(); | 247 Handle<Unioned> unioned = that->as_union(); |
153 for (int i = 0; i < unioned->length(); ++i) { | 248 for (int i = 0; i < unioned->length(); ++i) { |
154 Handle<Type> that_i = union_get(unioned, i); | 249 Handle<Type> that_i = union_get(unioned, i); |
155 if (this->Is(that_i)) return true; | 250 if (this->Is(that_i)) return true; |
156 if (this->is_bitset()) break; // Fast fail, no other field is a bitset. | 251 if (this->is_bitset()) break; // Fast fail, no other field is a bitset. |
157 } | 252 } |
158 return false; | 253 return false; |
159 } | 254 } |
160 | 255 |
161 return false; | 256 return false; |
162 } | 257 } |
163 | 258 |
164 | 259 |
165 // Check this overlaps that. | 260 // Check this overlaps that. |
166 bool Type::Maybe(Handle<Type> that) { | 261 bool Type::Maybe(Type* that) { |
167 // Fast path for bitsets. | 262 // Fast path for bitsets. |
168 if (this->is_bitset()) { | 263 if (this->is_bitset()) { |
169 return (this->as_bitset() & that->LubBitset()) != 0; | 264 return (this->as_bitset() & that->LubBitset()) != 0; |
170 } | 265 } |
171 if (that->is_bitset()) { | 266 if (that->is_bitset()) { |
172 return (this->LubBitset() & that->as_bitset()) != 0; | 267 return (this->LubBitset() & that->as_bitset()) != 0; |
173 } | 268 } |
174 | 269 |
175 if (this->is_class()) { | 270 if (this->is_class()) { |
176 return that->is_class() && *this->as_class() == *that->as_class(); | 271 return that->is_class() && *this->as_class() == *that->as_class(); |
177 } | 272 } |
178 if (this->is_constant()) { | 273 if (this->is_constant()) { |
179 return that->is_constant() && | 274 return that->is_constant() && *this->as_constant() == *that->as_constant(); |
180 this->as_constant()->value() == that->as_constant()->value(); | |
181 } | 275 } |
182 | 276 |
183 // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T) | 277 // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T) |
184 if (this->is_union()) { | 278 if (this->is_union()) { |
185 Handle<Unioned> unioned = this->as_union(); | 279 Handle<Unioned> unioned = this->as_union(); |
186 for (int i = 0; i < unioned->length(); ++i) { | 280 for (int i = 0; i < unioned->length(); ++i) { |
187 Handle<Type> this_i = union_get(unioned, i); | 281 Handle<Type> this_i = union_get(unioned, i); |
188 if (this_i->Maybe(that)) return true; | 282 if (this_i->Maybe(that)) return true; |
189 } | 283 } |
190 return false; | 284 return false; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 } | 374 } |
281 | 375 |
282 | 376 |
283 Type* Type::Optional(Handle<Type> type) { | 377 Type* Type::Optional(Handle<Type> type) { |
284 return type->is_bitset() | 378 return type->is_bitset() |
285 ? from_bitset(type->as_bitset() | kUndefined) | 379 ? from_bitset(type->as_bitset() | kUndefined) |
286 : Union(type, Undefined()->handle_via_isolate_of(*type)); | 380 : Union(type, Undefined()->handle_via_isolate_of(*type)); |
287 } | 381 } |
288 | 382 |
289 } } // namespace v8::internal | 383 } } // namespace v8::internal |
OLD | NEW |