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