OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "types.h" | 5 #include "types.h" |
6 | 6 |
7 #include "string-stream.h" | 7 #include "string-stream.h" |
8 #include "types-inl.h" | 8 #include "types-inl.h" |
9 | 9 |
10 namespace v8 { | 10 namespace v8 { |
11 namespace internal { | 11 namespace internal { |
12 | 12 |
13 template<class Config> | 13 template<class Config> |
14 int TypeImpl<Config>::NumClasses() { | 14 int TypeImpl<Config>::NumClasses() { |
15 if (this->IsClass()) { | 15 if (this->IsClass()) { |
16 return 1; | 16 return 1; |
17 } else if (this->IsUnion()) { | 17 } else if (this->IsUnion()) { |
18 UnionHandle unioned = handle(this->AsUnion()); | 18 StructHandle unioned = this->AsUnion(); |
19 int result = 0; | 19 int result = 0; |
20 for (int i = 0; i < unioned->Length(); ++i) { | 20 for (int i = 0; i < Config::struct_length(unioned); ++i) { |
21 if (unioned->Get(i)->IsClass()) ++result; | 21 if (Config::struct_get(unioned, i)->IsClass()) ++result; |
22 } | 22 } |
23 return result; | 23 return result; |
24 } else { | 24 } else { |
25 return 0; | 25 return 0; |
26 } | 26 } |
27 } | 27 } |
28 | 28 |
29 | 29 |
30 template<class Config> | 30 template<class Config> |
31 int TypeImpl<Config>::NumConstants() { | 31 int TypeImpl<Config>::NumConstants() { |
32 if (this->IsConstant()) { | 32 if (this->IsConstant()) { |
33 return 1; | 33 return 1; |
34 } else if (this->IsUnion()) { | 34 } else if (this->IsUnion()) { |
35 UnionHandle unioned = handle(this->AsUnion()); | 35 StructHandle unioned = this->AsUnion(); |
36 int result = 0; | 36 int result = 0; |
37 for (int i = 0; i < unioned->Length(); ++i) { | 37 for (int i = 0; i < Config::struct_length(unioned); ++i) { |
38 if (unioned->Get(i)->IsConstant()) ++result; | 38 if (Config::struct_get(unioned, i)->IsConstant()) ++result; |
39 } | 39 } |
40 return result; | 40 return result; |
41 } else { | 41 } else { |
42 return 0; | 42 return 0; |
43 } | 43 } |
44 } | 44 } |
45 | 45 |
46 | 46 |
47 template<class Config> template<class T> | 47 template<class Config> template<class T> |
48 typename TypeImpl<Config>::TypeHandle | 48 typename TypeImpl<Config>::TypeHandle |
49 TypeImpl<Config>::Iterator<T>::get_type() { | 49 TypeImpl<Config>::Iterator<T>::get_type() { |
50 ASSERT(!Done()); | 50 ASSERT(!Done()); |
51 return type_->IsUnion() ? type_->AsUnion()->Get(index_) : type_; | 51 return type_->IsUnion() |
| 52 ? Config::struct_get(type_->AsUnion(), index_) : type_; |
52 } | 53 } |
53 | 54 |
54 | 55 |
55 // C++ cannot specialise nested templates, so we have to go through this | 56 // C++ cannot specialise nested templates, so we have to go through this |
56 // contortion with an auxiliary template to simulate it. | 57 // contortion with an auxiliary template to simulate it. |
57 template<class Config, class T> | 58 template<class Config, class T> |
58 struct TypeImplIteratorAux { | 59 struct TypeImplIteratorAux { |
59 static bool matches(typename TypeImpl<Config>::TypeHandle type); | 60 static bool matches(typename TypeImpl<Config>::TypeHandle type); |
60 static i::Handle<T> current(typename TypeImpl<Config>::TypeHandle type); | 61 static i::Handle<T> current(typename TypeImpl<Config>::TypeHandle type); |
61 }; | 62 }; |
62 | 63 |
63 template<class Config> | 64 template<class Config> |
64 struct TypeImplIteratorAux<Config, i::Map> { | 65 struct TypeImplIteratorAux<Config, i::Map> { |
65 static bool matches(typename TypeImpl<Config>::TypeHandle type) { | 66 static bool matches(typename TypeImpl<Config>::TypeHandle type) { |
66 return type->IsClass(); | 67 return type->IsClass(); |
67 } | 68 } |
68 static i::Handle<i::Map> current(typename TypeImpl<Config>::TypeHandle type) { | 69 static i::Handle<i::Map> current(typename TypeImpl<Config>::TypeHandle type) { |
69 return type->AsClass()->Map(); | 70 return type->AsClass(); |
70 } | 71 } |
71 }; | 72 }; |
72 | 73 |
73 template<class Config> | 74 template<class Config> |
74 struct TypeImplIteratorAux<Config, i::Object> { | 75 struct TypeImplIteratorAux<Config, i::Object> { |
75 static bool matches(typename TypeImpl<Config>::TypeHandle type) { | 76 static bool matches(typename TypeImpl<Config>::TypeHandle type) { |
76 return type->IsConstant(); | 77 return type->IsConstant(); |
77 } | 78 } |
78 static i::Handle<i::Object> current( | 79 static i::Handle<i::Object> current( |
79 typename TypeImpl<Config>::TypeHandle type) { | 80 typename TypeImpl<Config>::TypeHandle type) { |
80 return type->AsConstant()->Value(); | 81 return type->AsConstant(); |
81 } | 82 } |
82 }; | 83 }; |
83 | 84 |
84 template<class Config> template<class T> | 85 template<class Config> template<class T> |
85 bool TypeImpl<Config>::Iterator<T>::matches(TypeHandle type) { | 86 bool TypeImpl<Config>::Iterator<T>::matches(TypeHandle type) { |
86 return TypeImplIteratorAux<Config, T>::matches(type); | 87 return TypeImplIteratorAux<Config, T>::matches(type); |
87 } | 88 } |
88 | 89 |
89 template<class Config> template<class T> | 90 template<class Config> template<class T> |
90 i::Handle<T> TypeImpl<Config>::Iterator<T>::Current() { | 91 i::Handle<T> TypeImpl<Config>::Iterator<T>::Current() { |
91 return TypeImplIteratorAux<Config, T>::current(get_type()); | 92 return TypeImplIteratorAux<Config, T>::current(get_type()); |
92 } | 93 } |
93 | 94 |
94 | 95 |
95 template<class Config> template<class T> | 96 template<class Config> template<class T> |
96 void TypeImpl<Config>::Iterator<T>::Advance() { | 97 void TypeImpl<Config>::Iterator<T>::Advance() { |
97 ++index_; | 98 ++index_; |
98 if (type_->IsUnion()) { | 99 if (type_->IsUnion()) { |
99 UnionHandle unioned = handle(type_->AsUnion()); | 100 StructHandle unioned = type_->AsUnion(); |
100 for (; index_ < unioned->Length(); ++index_) { | 101 for (; index_ < Config::struct_length(unioned); ++index_) { |
101 if (matches(unioned->Get(index_))) return; | 102 if (matches(Config::struct_get(unioned, index_))) return; |
102 } | 103 } |
103 } else if (index_ == 0 && matches(type_)) { | 104 } else if (index_ == 0 && matches(type_)) { |
104 return; | 105 return; |
105 } | 106 } |
106 index_ = -1; | 107 index_ = -1; |
107 } | 108 } |
108 | 109 |
109 | 110 |
110 // Get the largest bitset subsumed by this type. | |
111 template<class Config> | |
112 int TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) { | |
113 if (type->IsBitset()) { | |
114 return type->AsBitset(); | |
115 } else if (type->IsUnion()) { | |
116 // All but the first are non-bitsets and thus would yield kNone anyway. | |
117 return type->AsUnion()->Get(0)->BitsetGlb(); | |
118 } else { | |
119 return kNone; | |
120 } | |
121 } | |
122 | |
123 | |
124 // Get the smallest bitset subsuming this type. | 111 // Get the smallest bitset subsuming this type. |
125 template<class Config> | 112 template<class Config> |
126 int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { | 113 int TypeImpl<Config>::LubBitset() { |
127 if (type->IsBitset()) { | 114 if (this->IsBitset()) { |
128 return type->AsBitset(); | 115 return this->AsBitset(); |
129 } else if (type->IsUnion()) { | 116 } else if (this->IsUnion()) { |
130 UnionHandle unioned = handle(type->AsUnion()); | 117 StructHandle unioned = this->AsUnion(); |
131 int bitset = kNone; | 118 int bitset = kNone; |
132 for (int i = 0; i < unioned->Length(); ++i) { | 119 for (int i = 0; i < Config::struct_length(unioned); ++i) { |
133 bitset |= unioned->Get(i)->BitsetLub(); | 120 bitset |= Config::struct_get(unioned, i)->LubBitset(); |
134 } | 121 } |
135 return bitset; | 122 return bitset; |
136 } else if (type->IsClass()) { | 123 } else if (this->IsClass()) { |
137 int bitset = Config::lub_bitset(type); | 124 int bitset = Config::lub_bitset(this); |
138 return bitset ? bitset : Lub(*type->AsClass()->Map()); | 125 return bitset ? bitset : LubBitset(*this->AsClass()); |
139 } else if (type->IsConstant()) { | |
140 int bitset = Config::lub_bitset(type); | |
141 return bitset ? bitset : Lub(*type->AsConstant()->Value()); | |
142 } else if (type->IsArray()) { | |
143 return kArray; | |
144 } else if (type->IsFunction()) { | |
145 return kFunction; | |
146 } else { | 126 } else { |
147 UNREACHABLE(); | 127 int bitset = Config::lub_bitset(this); |
148 return kNone; | 128 return bitset ? bitset : LubBitset(*this->AsConstant()); |
149 } | 129 } |
150 } | 130 } |
151 | 131 |
152 | 132 |
153 template<class Config> | 133 template<class Config> |
154 int TypeImpl<Config>::BitsetType::Lub(i::Object* value) { | 134 int TypeImpl<Config>::LubBitset(i::Object* value) { |
155 if (value->IsSmi()) return kSignedSmall & kTaggedInt; | 135 if (value->IsSmi()) return kSignedSmall & kTaggedInt; |
156 i::Map* map = i::HeapObject::cast(value)->map(); | 136 i::Map* map = i::HeapObject::cast(value)->map(); |
157 if (map->instance_type() == HEAP_NUMBER_TYPE) { | 137 if (map->instance_type() == HEAP_NUMBER_TYPE) { |
158 int32_t i; | 138 int32_t i; |
159 uint32_t u; | 139 uint32_t u; |
160 return kTaggedPtr & ( | 140 return kTaggedPtr & ( |
161 value->ToInt32(&i) ? (Smi::IsValid(i) ? kSignedSmall : kOtherSigned32) : | 141 value->ToInt32(&i) ? (Smi::IsValid(i) ? kSignedSmall : kOtherSigned32) : |
162 value->ToUint32(&u) ? kUnsigned32 : kFloat); | 142 value->ToUint32(&u) ? kUnsigned32 : kFloat); |
163 } | 143 } |
164 return Lub(map); | 144 return LubBitset(map); |
165 } | 145 } |
166 | 146 |
167 | 147 |
168 template<class Config> | 148 template<class Config> |
169 int TypeImpl<Config>::BitsetType::Lub(i::Map* map) { | 149 int TypeImpl<Config>::LubBitset(i::Map* map) { |
170 switch (map->instance_type()) { | 150 switch (map->instance_type()) { |
171 case STRING_TYPE: | 151 case STRING_TYPE: |
172 case ASCII_STRING_TYPE: | 152 case ASCII_STRING_TYPE: |
173 case CONS_STRING_TYPE: | 153 case CONS_STRING_TYPE: |
174 case CONS_ASCII_STRING_TYPE: | 154 case CONS_ASCII_STRING_TYPE: |
175 case SLICED_STRING_TYPE: | 155 case SLICED_STRING_TYPE: |
176 case SLICED_ASCII_STRING_TYPE: | 156 case SLICED_ASCII_STRING_TYPE: |
177 case EXTERNAL_STRING_TYPE: | 157 case EXTERNAL_STRING_TYPE: |
178 case EXTERNAL_ASCII_STRING_TYPE: | 158 case EXTERNAL_ASCII_STRING_TYPE: |
179 case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: | 159 case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 case ACCESSOR_PAIR_TYPE: | 228 case ACCESSOR_PAIR_TYPE: |
249 case FIXED_ARRAY_TYPE: | 229 case FIXED_ARRAY_TYPE: |
250 return kInternal & kTaggedPtr; | 230 return kInternal & kTaggedPtr; |
251 default: | 231 default: |
252 UNREACHABLE(); | 232 UNREACHABLE(); |
253 return kNone; | 233 return kNone; |
254 } | 234 } |
255 } | 235 } |
256 | 236 |
257 | 237 |
| 238 // Get the largest bitset subsumed by this type. |
| 239 template<class Config> |
| 240 int TypeImpl<Config>::GlbBitset() { |
| 241 if (this->IsBitset()) { |
| 242 return this->AsBitset(); |
| 243 } else if (this->IsUnion()) { |
| 244 // All but the first are non-bitsets and thus would yield kNone anyway. |
| 245 return Config::struct_get(this->AsUnion(), 0)->GlbBitset(); |
| 246 } else { |
| 247 return kNone; |
| 248 } |
| 249 } |
| 250 |
| 251 |
258 // Most precise _current_ type of a value (usually its class). | 252 // Most precise _current_ type of a value (usually its class). |
259 template<class Config> | 253 template<class Config> |
260 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NowOf( | 254 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NowOf( |
261 i::Object* value, Region* region) { | 255 i::Object* value, Region* region) { |
262 if (value->IsSmi() || | 256 if (value->IsSmi() || |
263 i::HeapObject::cast(value)->map()->instance_type() == HEAP_NUMBER_TYPE) { | 257 i::HeapObject::cast(value)->map()->instance_type() == HEAP_NUMBER_TYPE) { |
264 return Of(value, region); | 258 return Of(value, region); |
265 } | 259 } |
266 return Class(i::handle(i::HeapObject::cast(value)->map()), region); | 260 return Class(i::handle(i::HeapObject::cast(value)->map()), region); |
267 } | 261 } |
268 | 262 |
269 | 263 |
270 // Check this <= that. | 264 // Check this <= that. |
271 template<class Config> | 265 template<class Config> |
272 bool TypeImpl<Config>::SlowIs(TypeImpl* that) { | 266 bool TypeImpl<Config>::SlowIs(TypeImpl* that) { |
273 // Fast path for bitsets. | 267 // Fast path for bitsets. |
274 if (this->IsNone()) return true; | 268 if (this->IsNone()) return true; |
275 if (that->IsBitset()) { | 269 if (that->IsBitset()) { |
276 return (BitsetType::Lub(this) | that->AsBitset()) == that->AsBitset(); | 270 return (this->LubBitset() | that->AsBitset()) == that->AsBitset(); |
277 } | 271 } |
278 | 272 |
279 if (that->IsClass()) { | 273 if (that->IsClass()) { |
280 return this->IsClass() | 274 return this->IsClass() && *this->AsClass() == *that->AsClass(); |
281 && *this->AsClass()->Map() == *that->AsClass()->Map(); | |
282 } | 275 } |
283 if (that->IsConstant()) { | 276 if (that->IsConstant()) { |
284 return this->IsConstant() | 277 return this->IsConstant() && *this->AsConstant() == *that->AsConstant(); |
285 && *this->AsConstant()->Value() == *that->AsConstant()->Value(); | |
286 } | |
287 if (that->IsArray()) { | |
288 return this->IsArray() | |
289 && this->AsArray()->Element()->Equals(that->AsArray()->Element()); | |
290 } | |
291 if (that->IsFunction()) { | |
292 // We currently do not allow for any variance here, in order to keep | |
293 // Union and Intersect operations simple. | |
294 if (!this->IsFunction()) return false; | |
295 FunctionType* this_fun = this->AsFunction(); | |
296 FunctionType* that_fun = that->AsFunction(); | |
297 if (this_fun->Arity() != that_fun->Arity() || | |
298 !this_fun->Result()->Equals(that_fun->Result()) || | |
299 !that_fun->Receiver()->Equals(this_fun->Receiver())) { | |
300 return false; | |
301 } | |
302 for (int i = 0; i < this_fun->Arity(); ++i) { | |
303 if (!that_fun->Parameter(i)->Equals(this_fun->Parameter(i))) return false; | |
304 } | |
305 return true; | |
306 } | 278 } |
307 | 279 |
308 // (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T) | 280 // (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T) |
309 if (this->IsUnion()) { | 281 if (this->IsUnion()) { |
310 UnionHandle unioned = handle(this->AsUnion()); | 282 StructHandle unioned = this->AsUnion(); |
311 for (int i = 0; i < unioned->Length(); ++i) { | 283 for (int i = 0; i < Config::struct_length(unioned); ++i) { |
312 if (!unioned->Get(i)->Is(that)) return false; | 284 TypeHandle this_i = Config::struct_get(unioned, i); |
| 285 if (!this_i->Is(that)) return false; |
313 } | 286 } |
314 return true; | 287 return true; |
315 } | 288 } |
316 | 289 |
317 // T <= (T1 \/ ... \/ Tn) <=> (T <= T1) \/ ... \/ (T <= Tn) | 290 // T <= (T1 \/ ... \/ Tn) <=> (T <= T1) \/ ... \/ (T <= Tn) |
318 // (iff T is not a union) | 291 // (iff T is not a union) |
319 ASSERT(!this->IsUnion()); | 292 ASSERT(!this->IsUnion()); |
320 if (that->IsUnion()) { | 293 if (that->IsUnion()) { |
321 UnionHandle unioned = handle(that->AsUnion()); | 294 StructHandle unioned = that->AsUnion(); |
322 for (int i = 0; i < unioned->Length(); ++i) { | 295 for (int i = 0; i < Config::struct_length(unioned); ++i) { |
323 if (this->Is(unioned->Get(i))) return true; | 296 TypeHandle that_i = Config::struct_get(unioned, i); |
| 297 if (this->Is(that_i)) return true; |
324 if (this->IsBitset()) break; // Fast fail, only first field is a bitset. | 298 if (this->IsBitset()) break; // Fast fail, only first field is a bitset. |
325 } | 299 } |
326 return false; | 300 return false; |
327 } | 301 } |
328 | 302 |
329 return false; | 303 return false; |
330 } | 304 } |
331 | 305 |
332 | 306 |
333 template<class Config> | 307 template<class Config> |
334 bool TypeImpl<Config>::NowIs(TypeImpl* that) { | 308 bool TypeImpl<Config>::NowIs(TypeImpl* that) { |
335 // TODO(rossberg): this is incorrect for | 309 // TODO(rossberg): this is incorrect for |
336 // Union(Constant(V), T)->NowIs(Class(M)) | 310 // Union(Constant(V), T)->NowIs(Class(M)) |
337 // but fuzzing does not cover that! | 311 // but fuzzing does not cover that! |
338 DisallowHeapAllocation no_allocation; | 312 DisallowHeapAllocation no_allocation; |
339 if (this->IsConstant()) { | 313 if (this->IsConstant()) { |
340 i::Object* object = *this->AsConstant()->Value(); | 314 i::Object* object = *this->AsConstant(); |
341 if (object->IsHeapObject()) { | 315 if (object->IsHeapObject()) { |
342 i::Map* map = i::HeapObject::cast(object)->map(); | 316 i::Map* map = i::HeapObject::cast(object)->map(); |
343 for (Iterator<i::Map> it = that->Classes(); !it.Done(); it.Advance()) { | 317 for (Iterator<i::Map> it = that->Classes(); !it.Done(); it.Advance()) { |
344 if (*it.Current() == map) return true; | 318 if (*it.Current() == map) return true; |
345 } | 319 } |
346 } | 320 } |
347 } | 321 } |
348 return this->Is(that); | 322 return this->Is(that); |
349 } | 323 } |
350 | 324 |
351 | 325 |
352 // Check this overlaps that. | 326 // Check this overlaps that. |
353 template<class Config> | 327 template<class Config> |
354 bool TypeImpl<Config>::Maybe(TypeImpl* that) { | 328 bool TypeImpl<Config>::Maybe(TypeImpl* that) { |
355 // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T) | 329 // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T) |
356 if (this->IsUnion()) { | 330 if (this->IsUnion()) { |
357 UnionHandle unioned = handle(this->AsUnion()); | 331 StructHandle unioned = this->AsUnion(); |
358 for (int i = 0; i < unioned->Length(); ++i) { | 332 for (int i = 0; i < Config::struct_length(unioned); ++i) { |
359 if (unioned->Get(i)->Maybe(that)) return true; | 333 TypeHandle this_i = Config::struct_get(unioned, i); |
| 334 if (this_i->Maybe(that)) return true; |
360 } | 335 } |
361 return false; | 336 return false; |
362 } | 337 } |
363 | 338 |
364 // T overlaps (T1 \/ ... \/ Tn) <=> (T overlaps T1) \/ ... \/ (T overlaps Tn) | 339 // T overlaps (T1 \/ ... \/ Tn) <=> (T overlaps T1) \/ ... \/ (T overlaps Tn) |
365 if (that->IsUnion()) { | 340 if (that->IsUnion()) { |
366 UnionHandle unioned = handle(that->AsUnion()); | 341 StructHandle unioned = that->AsUnion(); |
367 for (int i = 0; i < unioned->Length(); ++i) { | 342 for (int i = 0; i < Config::struct_length(unioned); ++i) { |
368 if (this->Maybe(unioned->Get(i))) return true; | 343 TypeHandle that_i = Config::struct_get(unioned, i); |
| 344 if (this->Maybe(that_i)) return true; |
369 } | 345 } |
370 return false; | 346 return false; |
371 } | 347 } |
372 | 348 |
373 ASSERT(!this->IsUnion() && !that->IsUnion()); | 349 ASSERT(!this->IsUnion() && !that->IsUnion()); |
374 if (this->IsBitset()) { | 350 if (this->IsBitset()) { |
375 return BitsetType::IsInhabited(this->AsBitset() & that->BitsetLub()); | 351 return IsInhabited(this->AsBitset() & that->LubBitset()); |
376 } | 352 } |
377 if (that->IsBitset()) { | 353 if (that->IsBitset()) { |
378 return BitsetType::IsInhabited(this->BitsetLub() & that->AsBitset()); | 354 return IsInhabited(this->LubBitset() & that->AsBitset()); |
379 } | 355 } |
| 356 |
380 if (this->IsClass()) { | 357 if (this->IsClass()) { |
381 return that->IsClass() | 358 return that->IsClass() && *this->AsClass() == *that->AsClass(); |
382 && *this->AsClass()->Map() == *that->AsClass()->Map(); | |
383 } | 359 } |
384 if (this->IsConstant()) { | 360 if (this->IsConstant()) { |
385 return that->IsConstant() | 361 return that->IsConstant() && *this->AsConstant() == *that->AsConstant(); |
386 && *this->AsConstant()->Value() == *that->AsConstant()->Value(); | |
387 } | |
388 if (this->IsArray()) { | |
389 // There is no variance! | |
390 return this->Equals(that); | |
391 } | |
392 if (this->IsFunction()) { | |
393 // There is no variance! | |
394 return this->Equals(that); | |
395 } | 362 } |
396 | 363 |
397 return false; | 364 return false; |
398 } | 365 } |
399 | 366 |
400 | 367 |
401 template<class Config> | 368 template<class Config> |
402 bool TypeImpl<Config>::Contains(i::Object* value) { | 369 bool TypeImpl<Config>::Contains(i::Object* value) { |
403 for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) { | 370 for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) { |
404 if (*it.Current() == value) return true; | 371 if (*it.Current() == value) return true; |
405 } | 372 } |
406 return BitsetType::New(BitsetType::Lub(value))->Is(this); | 373 return Config::from_bitset(LubBitset(value))->Is(this); |
407 } | 374 } |
408 | 375 |
409 | 376 |
410 template<class Config> | 377 template<class Config> |
411 bool TypeImpl<Config>::InUnion(UnionHandle unioned, int current_size) { | 378 bool TypeImpl<Config>::InUnion(StructHandle unioned, int current_size) { |
412 ASSERT(!this->IsUnion()); | 379 ASSERT(!this->IsUnion()); |
413 for (int i = 0; i < current_size; ++i) { | 380 for (int i = 0; i < current_size; ++i) { |
414 if (this->Is(unioned->Get(i))) return true; | 381 TypeHandle type = Config::struct_get(unioned, i); |
| 382 if (this->Is(type)) return true; |
415 } | 383 } |
416 return false; | 384 return false; |
417 } | 385 } |
418 | 386 |
419 | 387 |
420 // Get non-bitsets from this which are not subsumed by union, store at result, | 388 // Get non-bitsets from this which are not subsumed by union, store at result, |
421 // starting at index. Returns updated index. | 389 // starting at index. Returns updated index. |
422 template<class Config> | 390 template<class Config> |
423 int TypeImpl<Config>::ExtendUnion( | 391 int TypeImpl<Config>::ExtendUnion( |
424 UnionHandle result, TypeHandle type, int current_size) { | 392 StructHandle result, TypeHandle type, int current_size) { |
425 int old_size = current_size; | 393 int old_size = current_size; |
426 if (type->IsUnion()) { | 394 if (type->IsClass() || type->IsConstant()) { |
427 UnionHandle unioned = handle(type->AsUnion()); | 395 if (!type->InUnion(result, old_size)) { |
428 for (int i = 0; i < unioned->Length(); ++i) { | 396 Config::struct_set(result, current_size++, type); |
429 TypeHandle type = unioned->Get(i); | 397 } |
430 ASSERT(i == 0 || !(type->IsBitset() || type->Is(unioned->Get(0)))); | 398 } else if (type->IsUnion()) { |
| 399 StructHandle unioned = type->AsUnion(); |
| 400 for (int i = 0; i < Config::struct_length(unioned); ++i) { |
| 401 TypeHandle type = Config::struct_get(unioned, i); |
| 402 ASSERT(i == 0 || |
| 403 !(type->IsBitset() || type->Is(Config::struct_get(unioned, 0)))); |
431 if (!type->IsBitset() && !type->InUnion(result, old_size)) { | 404 if (!type->IsBitset() && !type->InUnion(result, old_size)) { |
432 result->Set(current_size++, type); | 405 Config::struct_set(result, current_size++, type); |
433 } | 406 } |
434 } | 407 } |
435 } else if (!type->IsBitset()) { | |
436 // For all structural types, subtyping implies equivalence. | |
437 ASSERT(type->IsClass() || type->IsConstant() || | |
438 type->IsArray() || type->IsFunction()); | |
439 if (!type->InUnion(result, old_size)) { | |
440 result->Set(current_size++, type); | |
441 } | |
442 } | 408 } |
443 return current_size; | 409 return current_size; |
444 } | 410 } |
445 | 411 |
446 | 412 |
447 // Union is O(1) on simple bit unions, but O(n*m) on structured unions. | 413 // Union is O(1) on simple bit unions, but O(n*m) on structured unions. |
448 template<class Config> | 414 template<class Config> |
449 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union( | 415 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union( |
450 TypeHandle type1, TypeHandle type2, Region* region) { | 416 TypeHandle type1, TypeHandle type2, Region* region) { |
451 // Fast case: bit sets. | 417 // Fast case: bit sets. |
452 if (type1->IsBitset() && type2->IsBitset()) { | 418 if (type1->IsBitset() && type2->IsBitset()) { |
453 return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region); | 419 return Config::from_bitset(type1->AsBitset() | type2->AsBitset(), region); |
454 } | 420 } |
455 | 421 |
456 // Fast case: top or bottom types. | 422 // Fast case: top or bottom types. |
457 if (type1->IsAny() || type2->IsNone()) return type1; | 423 if (type1->IsAny() || type2->IsNone()) return type1; |
458 if (type2->IsAny() || type1->IsNone()) return type2; | 424 if (type2->IsAny() || type1->IsNone()) return type2; |
459 | 425 |
460 // Semi-fast case: Unioned objects are neither involved nor produced. | 426 // Semi-fast case: Unioned objects are neither involved nor produced. |
461 if (!(type1->IsUnion() || type2->IsUnion())) { | 427 if (!(type1->IsUnion() || type2->IsUnion())) { |
462 if (type1->Is(type2)) return type2; | 428 if (type1->Is(type2)) return type2; |
463 if (type2->Is(type1)) return type1; | 429 if (type2->Is(type1)) return type1; |
464 } | 430 } |
465 | 431 |
466 // Slow case: may need to produce a Unioned object. | 432 // Slow case: may need to produce a Unioned object. |
467 int size = 0; | 433 int size = 0; |
468 if (!type1->IsBitset()) { | 434 if (!type1->IsBitset()) { |
469 size += (type1->IsUnion() ? type1->AsUnion()->Length() : 1); | 435 size += (type1->IsUnion() ? Config::struct_length(type1->AsUnion()) : 1); |
470 } | 436 } |
471 if (!type2->IsBitset()) { | 437 if (!type2->IsBitset()) { |
472 size += (type2->IsUnion() ? type2->AsUnion()->Length() : 1); | 438 size += (type2->IsUnion() ? Config::struct_length(type2->AsUnion()) : 1); |
473 } | 439 } |
474 int bitset = type1->BitsetGlb() | type2->BitsetGlb(); | 440 int bitset = type1->GlbBitset() | type2->GlbBitset(); |
475 if (bitset != BitsetType::kNone) ++size; | 441 if (bitset != kNone) ++size; |
476 ASSERT(size >= 1); | 442 ASSERT(size >= 1); |
| 443 StructHandle unioned = Config::struct_create(kUnionTag, size, region); |
477 | 444 |
478 UnionHandle unioned = UnionType::New(size, region); | |
479 size = 0; | 445 size = 0; |
480 if (bitset != BitsetType::kNone) { | 446 if (bitset != kNone) { |
481 unioned->Set(size++, BitsetType::New(bitset, region)); | 447 Config::struct_set(unioned, size++, Config::from_bitset(bitset, region)); |
482 } | 448 } |
483 size = ExtendUnion(unioned, type1, size); | 449 size = ExtendUnion(unioned, type1, size); |
484 size = ExtendUnion(unioned, type2, size); | 450 size = ExtendUnion(unioned, type2, size); |
485 | 451 |
486 if (size == 1) { | 452 if (size == 1) { |
487 return unioned->Get(0); | 453 return Config::struct_get(unioned, 0); |
488 } else { | 454 } else { |
489 unioned->Shrink(size); | 455 Config::struct_shrink(unioned, size); |
490 return unioned; | 456 return Config::from_struct(unioned); |
491 } | 457 } |
492 } | 458 } |
493 | 459 |
494 | 460 |
495 // Get non-bitsets from type which are also in other, store at result, | 461 // Get non-bitsets from type which are also in other, store at result, |
496 // starting at index. Returns updated index. | 462 // starting at index. Returns updated index. |
497 template<class Config> | 463 template<class Config> |
498 int TypeImpl<Config>::ExtendIntersection( | 464 int TypeImpl<Config>::ExtendIntersection( |
499 UnionHandle result, TypeHandle type, TypeHandle other, int current_size) { | 465 StructHandle result, TypeHandle type, TypeHandle other, int current_size) { |
500 int old_size = current_size; | 466 int old_size = current_size; |
501 if (type->IsUnion()) { | 467 if (type->IsClass() || type->IsConstant()) { |
502 UnionHandle unioned = handle(type->AsUnion()); | 468 if (type->Is(other) && !type->InUnion(result, old_size)) { |
503 for (int i = 0; i < unioned->Length(); ++i) { | 469 Config::struct_set(result, current_size++, type); |
504 TypeHandle type = unioned->Get(i); | 470 } |
505 ASSERT(i == 0 || !(type->IsBitset() || type->Is(unioned->Get(0)))); | 471 } else if (type->IsUnion()) { |
| 472 StructHandle unioned = type->AsUnion(); |
| 473 for (int i = 0; i < Config::struct_length(unioned); ++i) { |
| 474 TypeHandle type = Config::struct_get(unioned, i); |
| 475 ASSERT(i == 0 || |
| 476 !(type->IsBitset() || type->Is(Config::struct_get(unioned, 0)))); |
506 if (!type->IsBitset() && type->Is(other) && | 477 if (!type->IsBitset() && type->Is(other) && |
507 !type->InUnion(result, old_size)) { | 478 !type->InUnion(result, old_size)) { |
508 result->Set(current_size++, type); | 479 Config::struct_set(result, current_size++, type); |
509 } | 480 } |
510 } | 481 } |
511 } else if (!type->IsBitset()) { | |
512 // For all structural types, subtyping implies equivalence. | |
513 ASSERT(type->IsClass() || type->IsConstant() || | |
514 type->IsArray() || type->IsFunction()); | |
515 if (type->Is(other) && !type->InUnion(result, old_size)) { | |
516 result->Set(current_size++, type); | |
517 } | |
518 } | 482 } |
519 return current_size; | 483 return current_size; |
520 } | 484 } |
521 | 485 |
522 | 486 |
523 // Intersection is O(1) on simple bit unions, but O(n*m) on structured unions. | 487 // Intersection is O(1) on simple bit unions, but O(n*m) on structured unions. |
| 488 // TODO(rossberg): Should we use object sets somehow? Is it worth it? |
524 template<class Config> | 489 template<class Config> |
525 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect( | 490 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect( |
526 TypeHandle type1, TypeHandle type2, Region* region) { | 491 TypeHandle type1, TypeHandle type2, Region* region) { |
527 // Fast case: bit sets. | 492 // Fast case: bit sets. |
528 if (type1->IsBitset() && type2->IsBitset()) { | 493 if (type1->IsBitset() && type2->IsBitset()) { |
529 return BitsetType::New(type1->AsBitset() & type2->AsBitset(), region); | 494 return Config::from_bitset(type1->AsBitset() & type2->AsBitset(), region); |
530 } | 495 } |
531 | 496 |
532 // Fast case: top or bottom types. | 497 // Fast case: top or bottom types. |
533 if (type1->IsNone() || type2->IsAny()) return type1; | 498 if (type1->IsNone() || type2->IsAny()) return type1; |
534 if (type2->IsNone() || type1->IsAny()) return type2; | 499 if (type2->IsNone() || type1->IsAny()) return type2; |
535 | 500 |
536 // Semi-fast case: Unioned objects are neither involved nor produced. | 501 // Semi-fast case: Unioned objects are neither involved nor produced. |
537 if (!(type1->IsUnion() || type2->IsUnion())) { | 502 if (!(type1->IsUnion() || type2->IsUnion())) { |
538 if (type1->Is(type2)) return type1; | 503 if (type1->Is(type2)) return type1; |
539 if (type2->Is(type1)) return type2; | 504 if (type2->Is(type1)) return type2; |
540 } | 505 } |
541 | 506 |
542 // Slow case: may need to produce a Unioned object. | 507 // Slow case: may need to produce a Unioned object. |
543 int size = 0; | 508 int size = 0; |
544 if (!type1->IsBitset()) { | 509 if (!type1->IsBitset()) { |
545 size += (type1->IsUnion() ? type1->AsUnion()->Length() : 1); | 510 size += (type1->IsUnion() ? Config::struct_length(type1->AsUnion()) : 1); |
546 } | 511 } |
547 if (!type2->IsBitset()) { | 512 if (!type2->IsBitset()) { |
548 size += (type2->IsUnion() ? type2->AsUnion()->Length() : 1); | 513 size += (type2->IsUnion() ? Config::struct_length(type2->AsUnion()) : 1); |
549 } | 514 } |
550 int bitset = type1->BitsetGlb() & type2->BitsetGlb(); | 515 int bitset = type1->GlbBitset() & type2->GlbBitset(); |
551 if (bitset != BitsetType::kNone) ++size; | 516 if (bitset != kNone) ++size; |
552 ASSERT(size >= 1); | 517 ASSERT(size >= 1); |
| 518 StructHandle unioned = Config::struct_create(kUnionTag, size, region); |
553 | 519 |
554 UnionHandle unioned = UnionType::New(size, region); | |
555 size = 0; | 520 size = 0; |
556 if (bitset != BitsetType::kNone) { | 521 if (bitset != kNone) { |
557 unioned->Set(size++, BitsetType::New(bitset, region)); | 522 Config::struct_set(unioned, size++, Config::from_bitset(bitset, region)); |
558 } | 523 } |
559 size = ExtendIntersection(unioned, type1, type2, size); | 524 size = ExtendIntersection(unioned, type1, type2, size); |
560 size = ExtendIntersection(unioned, type2, type1, size); | 525 size = ExtendIntersection(unioned, type2, type1, size); |
561 | 526 |
562 if (size == 0) { | 527 if (size == 0) { |
563 return None(region); | 528 return None(region); |
564 } else if (size == 1) { | 529 } else if (size == 1) { |
565 return unioned->Get(0); | 530 return Config::struct_get(unioned, 0); |
566 } else { | 531 } else { |
567 unioned->Shrink(size); | 532 Config::struct_shrink(unioned, size); |
568 return unioned; | 533 return Config::from_struct(unioned); |
569 } | 534 } |
570 } | 535 } |
571 | 536 |
572 | 537 |
573 template<class Config> | 538 template<class Config> |
574 template<class OtherType> | 539 template<class OtherType> |
575 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert( | 540 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert( |
576 typename OtherType::TypeHandle type, Region* region) { | 541 typename OtherType::TypeHandle type, Region* region) { |
577 if (type->IsBitset()) { | 542 if (type->IsBitset()) { |
578 return BitsetType::New(type->AsBitset(), region); | 543 return Config::from_bitset(type->AsBitset(), region); |
579 } else if (type->IsClass()) { | 544 } else if (type->IsClass()) { |
580 return ClassType::New(type->AsClass()->Map(), region); | 545 return Config::from_class(type->AsClass(), type->LubBitset(), region); |
581 } else if (type->IsConstant()) { | 546 } else if (type->IsConstant()) { |
582 return ConstantType::New(type->AsConstant()->Value(), region); | 547 return Config::from_constant(type->AsConstant(), type->LubBitset(), region); |
583 } else if (type->IsUnion()) { | 548 } else { |
584 int length = type->AsUnion()->Length(); | 549 ASSERT(type->IsUnion()); |
585 UnionHandle unioned = UnionType::New(length, region); | 550 typename OtherType::StructHandle unioned = type->AsUnion(); |
| 551 int length = OtherType::StructLength(unioned); |
| 552 StructHandle new_unioned = Config::struct_create(kUnionTag, length, region); |
586 for (int i = 0; i < length; ++i) { | 553 for (int i = 0; i < length; ++i) { |
587 unioned->Set(i, Convert<OtherType>(type->AsUnion()->Get(i), region)); | 554 Config::struct_set(new_unioned, i, |
| 555 Convert<OtherType>(OtherType::StructGet(unioned, i), region)); |
588 } | 556 } |
589 return unioned; | 557 return Config::from_struct(new_unioned); |
590 } else if (type->IsArray()) { | |
591 return ArrayType::New( | |
592 Convert<OtherType>(type->AsArray()->Element(), region), region); | |
593 } else if (type->IsFunction()) { | |
594 FunctionHandle function = FunctionType::New( | |
595 Convert<OtherType>(type->AsFunction()->Result(), region), | |
596 Convert<OtherType>(type->AsFunction()->Receiver(), region), | |
597 type->AsFunction()->Arity(), region); | |
598 for (int i = 0; i < function->Arity(); ++i) { | |
599 function->InitParameter(i, | |
600 Convert<OtherType>(type->AsFunction()->Parameter(i), region)); | |
601 } | |
602 return function; | |
603 } else { | |
604 UNREACHABLE(); | |
605 return None(region); | |
606 } | 558 } |
607 } | 559 } |
608 | 560 |
609 | 561 |
610 // TODO(rossberg): this does not belong here. | 562 // TODO(rossberg): this does not belong here. |
611 Representation Representation::FromType(Type* type) { | 563 Representation Representation::FromType(Type* type) { |
612 if (type->Is(Type::None())) return Representation::None(); | 564 if (type->Is(Type::None())) return Representation::None(); |
613 if (type->Is(Type::SignedSmall())) return Representation::Smi(); | 565 if (type->Is(Type::SignedSmall())) return Representation::Smi(); |
614 if (type->Is(Type::Signed32())) return Representation::Integer32(); | 566 if (type->Is(Type::Signed32())) return Representation::Integer32(); |
615 if (type->Is(Type::Number())) return Representation::Double(); | 567 if (type->Is(Type::Number())) return Representation::Double(); |
616 return Representation::Tagged(); | 568 return Representation::Tagged(); |
617 } | 569 } |
618 | 570 |
619 | 571 |
620 template<class Config> | 572 template<class Config> |
621 void TypeImpl<Config>::TypePrint(PrintDimension dim) { | 573 void TypeImpl<Config>::TypePrint(PrintDimension dim) { |
622 TypePrint(stdout, dim); | 574 TypePrint(stdout, dim); |
623 PrintF(stdout, "\n"); | 575 PrintF(stdout, "\n"); |
624 Flush(stdout); | 576 Flush(stdout); |
625 } | 577 } |
626 | 578 |
627 | 579 |
628 template<class Config> | 580 template<class Config> |
629 const char* TypeImpl<Config>::BitsetType::Name(int bitset) { | 581 const char* TypeImpl<Config>::bitset_name(int bitset) { |
630 switch (bitset) { | 582 switch (bitset) { |
631 case kAny & kRepresentation: return "Any"; | 583 case kAny & kRepresentation: return "Any"; |
632 #define PRINT_COMPOSED_TYPE(type, value) \ | 584 #define PRINT_COMPOSED_TYPE(type, value) \ |
633 case k##type & kRepresentation: return #type; | 585 case k##type & kRepresentation: return #type; |
634 REPRESENTATION_BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE) | 586 REPRESENTATION_BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE) |
635 #undef PRINT_COMPOSED_TYPE | 587 #undef PRINT_COMPOSED_TYPE |
636 | 588 |
637 #define PRINT_COMPOSED_TYPE(type, value) \ | 589 #define PRINT_COMPOSED_TYPE(type, value) \ |
638 case k##type & kSemantic: return #type; | 590 case k##type & kSemantic: return #type; |
639 SEMANTIC_BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE) | 591 SEMANTIC_BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE) |
640 #undef PRINT_COMPOSED_TYPE | 592 #undef PRINT_COMPOSED_TYPE |
641 | 593 |
642 default: | 594 default: |
643 return NULL; | 595 return NULL; |
644 } | 596 } |
645 } | 597 } |
646 | 598 |
647 | 599 |
648 template<class Config> | 600 template<class Config> |
649 void TypeImpl<Config>::BitsetType::BitsetTypePrint(FILE* out, int bitset) { | 601 void TypeImpl<Config>::BitsetTypePrint(FILE* out, int bitset) { |
650 const char* name = Name(bitset); | 602 const char* name = bitset_name(bitset); |
651 if (name != NULL) { | 603 if (name != NULL) { |
652 PrintF(out, "%s", name); | 604 PrintF(out, "%s", name); |
653 } else { | 605 } else { |
654 static const int named_bitsets[] = { | 606 static const int named_bitsets[] = { |
655 #define BITSET_CONSTANT(type, value) k##type & kRepresentation, | 607 #define BITSET_CONSTANT(type, value) k##type & kRepresentation, |
656 REPRESENTATION_BITSET_TYPE_LIST(BITSET_CONSTANT) | 608 REPRESENTATION_BITSET_TYPE_LIST(BITSET_CONSTANT) |
657 #undef BITSET_CONSTANT | 609 #undef BITSET_CONSTANT |
658 | 610 |
659 #define BITSET_CONSTANT(type, value) k##type & kSemantic, | 611 #define BITSET_CONSTANT(type, value) k##type & kSemantic, |
660 SEMANTIC_BITSET_TYPE_LIST(BITSET_CONSTANT) | 612 SEMANTIC_BITSET_TYPE_LIST(BITSET_CONSTANT) |
661 #undef BITSET_CONSTANT | 613 #undef BITSET_CONSTANT |
662 }; | 614 }; |
663 | 615 |
664 bool is_first = true; | 616 bool is_first = true; |
665 PrintF(out, "("); | 617 PrintF(out, "("); |
666 for (int i(ARRAY_SIZE(named_bitsets) - 1); bitset != 0 && i >= 0; --i) { | 618 for (int i(ARRAY_SIZE(named_bitsets) - 1); bitset != 0 && i >= 0; --i) { |
667 int subset = named_bitsets[i]; | 619 int subset = named_bitsets[i]; |
668 if ((bitset & subset) == subset) { | 620 if ((bitset & subset) == subset) { |
669 if (!is_first) PrintF(out, " | "); | 621 if (!is_first) PrintF(out, " | "); |
670 is_first = false; | 622 is_first = false; |
671 PrintF(out, "%s", Name(subset)); | 623 PrintF(out, "%s", bitset_name(subset)); |
672 bitset -= subset; | 624 bitset -= subset; |
673 } | 625 } |
674 } | 626 } |
675 ASSERT(bitset == 0); | 627 ASSERT(bitset == 0); |
676 PrintF(out, ")"); | 628 PrintF(out, ")"); |
677 } | 629 } |
678 } | 630 } |
679 | 631 |
680 | 632 |
681 template<class Config> | 633 template<class Config> |
682 void TypeImpl<Config>::TypePrint(FILE* out, PrintDimension dim) { | 634 void TypeImpl<Config>::TypePrint(FILE* out, PrintDimension dim) { |
683 if (this->IsBitset()) { | 635 if (this->IsBitset()) { |
684 int bitset = this->AsBitset(); | 636 int bitset = this->AsBitset(); |
685 switch (dim) { | 637 switch (dim) { |
686 case BOTH_DIMS: | 638 case BOTH_DIMS: |
687 BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic); | 639 BitsetTypePrint(out, bitset & kSemantic); |
688 PrintF(out, "/"); | 640 PrintF(out, "/"); |
689 BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation); | 641 BitsetTypePrint(out, bitset & kRepresentation); |
690 break; | 642 break; |
691 case SEMANTIC_DIM: | 643 case SEMANTIC_DIM: |
692 BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic); | 644 BitsetTypePrint(out, bitset & kSemantic); |
693 break; | 645 break; |
694 case REPRESENTATION_DIM: | 646 case REPRESENTATION_DIM: |
695 BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation); | 647 BitsetTypePrint(out, bitset & kRepresentation); |
696 break; | 648 break; |
697 } | 649 } |
698 } else if (this->IsConstant()) { | 650 } else if (this->IsConstant()) { |
699 PrintF(out, "Constant(%p : ", | 651 PrintF(out, "Constant(%p : ", static_cast<void*>(*this->AsConstant())); |
700 static_cast<void*>(*this->AsConstant()->Value())); | 652 Config::from_bitset(this->LubBitset())->TypePrint(out, dim); |
701 BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim); | |
702 PrintF(out, ")"); | 653 PrintF(out, ")"); |
703 } else if (this->IsClass()) { | 654 } else if (this->IsClass()) { |
704 PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()->Map())); | 655 PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass())); |
705 BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim); | 656 Config::from_bitset(this->LubBitset())->TypePrint(out, dim); |
706 PrintF(out, ")"); | 657 PrintF(out, ")"); |
707 } else if (this->IsUnion()) { | 658 } else if (this->IsUnion()) { |
708 PrintF(out, "("); | 659 PrintF(out, "("); |
709 UnionHandle unioned = handle(this->AsUnion()); | 660 StructHandle unioned = this->AsUnion(); |
710 for (int i = 0; i < unioned->Length(); ++i) { | 661 for (int i = 0; i < Config::struct_length(unioned); ++i) { |
711 TypeHandle type_i = unioned->Get(i); | 662 TypeHandle type_i = Config::struct_get(unioned, i); |
712 if (i > 0) PrintF(out, " | "); | 663 if (i > 0) PrintF(out, " | "); |
713 type_i->TypePrint(out, dim); | 664 type_i->TypePrint(out, dim); |
714 } | 665 } |
715 PrintF(out, ")"); | 666 PrintF(out, ")"); |
716 } else if (this->IsArray()) { | |
717 PrintF(out, "["); | |
718 AsArray()->Element()->TypePrint(out, dim); | |
719 PrintF(out, "]"); | |
720 } else if (this->IsFunction()) { | |
721 if (!this->AsFunction()->Receiver()->IsAny()) { | |
722 this->AsFunction()->Receiver()->TypePrint(out, dim); | |
723 PrintF(out, "."); | |
724 } | |
725 PrintF(out, "("); | |
726 for (int i = 0; i < this->AsFunction()->Arity(); ++i) { | |
727 if (i > 0) PrintF(out, ", "); | |
728 this->AsFunction()->Parameter(i)->TypePrint(out, dim); | |
729 } | |
730 PrintF(out, ")->"); | |
731 this->AsFunction()->Result()->TypePrint(out, dim); | |
732 } else { | |
733 UNREACHABLE(); | |
734 } | 667 } |
735 } | 668 } |
736 | 669 |
737 | 670 |
738 template class TypeImpl<ZoneTypeConfig>; | 671 template class TypeImpl<ZoneTypeConfig>; |
739 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Map>; | 672 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Map>; |
740 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Object>; | 673 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Object>; |
741 | 674 |
742 template class TypeImpl<HeapTypeConfig>; | 675 template class TypeImpl<HeapTypeConfig>; |
743 template class TypeImpl<HeapTypeConfig>::Iterator<i::Map>; | 676 template class TypeImpl<HeapTypeConfig>::Iterator<i::Map>; |
744 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; | 677 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; |
745 | 678 |
746 template TypeImpl<ZoneTypeConfig>::TypeHandle | 679 template TypeImpl<ZoneTypeConfig>::TypeHandle |
747 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( | 680 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( |
748 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); | 681 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); |
749 template TypeImpl<HeapTypeConfig>::TypeHandle | 682 template TypeImpl<HeapTypeConfig>::TypeHandle |
750 TypeImpl<HeapTypeConfig>::Convert<Type>( | 683 TypeImpl<HeapTypeConfig>::Convert<Type>( |
751 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); | 684 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); |
752 | 685 |
753 } } // namespace v8::internal | 686 } } // namespace v8::internal |
OLD | NEW |