Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(421)

Side by Side Diff: src/types.cc

Issue 107933005: Templatise type representation (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 13 matching lines...) Expand all
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 #include "string-stream.h" 29 #include "string-stream.h"
30 30
31 namespace v8 { 31 namespace v8 {
32 namespace internal { 32 namespace internal {
33 33
34 int Type::NumClasses() { 34 template<class Config>
35 if (is_class()) { 35 int TypeImpl<Config>::NumClasses() {
36 if (this->IsClass()) {
36 return 1; 37 return 1;
37 } else if (is_union()) { 38 } else if (this->IsUnion()) {
38 Handle<Unioned> unioned = as_union(); 39 UnionedHandle unioned = this->AsUnion();
39 int result = 0; 40 int result = 0;
40 for (int i = 0; i < unioned->length(); ++i) { 41 for (int i = 0; i < unioned->length(); ++i) {
41 if (union_get(unioned, i)->is_class()) ++result; 42 if (Config::union_get(unioned, i)->IsClass()) ++result;
42 } 43 }
43 return result; 44 return result;
44 } else { 45 } else {
45 return 0; 46 return 0;
46 } 47 }
47 } 48 }
48 49
49 50
50 int Type::NumConstants() { 51 template<class Config>
51 if (is_constant()) { 52 int TypeImpl<Config>::NumConstants() {
53 if (this->IsConstant()) {
52 return 1; 54 return 1;
53 } else if (is_union()) { 55 } else if (this->IsUnion()) {
54 Handle<Unioned> unioned = as_union(); 56 UnionedHandle unioned = this->AsUnion();
55 int result = 0; 57 int result = 0;
56 for (int i = 0; i < unioned->length(); ++i) { 58 for (int i = 0; i < unioned->length(); ++i) {
57 if (union_get(unioned, i)->is_constant()) ++result; 59 if (Config::union_get(unioned, i)->IsConstant()) ++result;
58 } 60 }
59 return result; 61 return result;
60 } else { 62 } else {
61 return 0; 63 return 0;
62 } 64 }
63 } 65 }
64 66
65 67
66 template<class T> 68 template<class Config> template<class T>
67 Handle<Type> Type::Iterator<T>::get_type() { 69 typename TypeImpl<Config>::TypeHandle
70 TypeImpl<Config>::Iterator<T>::get_type() {
68 ASSERT(!Done()); 71 ASSERT(!Done());
69 return type_->is_union() ? union_get(type_->as_union(), index_) : type_; 72 return type_->IsUnion() ? Config::union_get(type_->AsUnion(), index_) : type_;
70 }
71
72 template<>
73 Handle<i::Map> Type::Iterator<i::Map>::Current() {
74 return get_type()->as_class();
75 }
76
77 template<>
78 Handle<i::Object> Type::Iterator<i::Object>::Current() {
79 return get_type()->as_constant();
80 } 73 }
81 74
82 75
83 template<> 76 // C++ cannot specialise nested templates, so we have to go through this
84 bool Type::Iterator<i::Map>::matches(Handle<Type> type) { 77 // contortion with an auxiliary template to simulate it.
85 return type->is_class(); 78 template<class Config, class T>
79 struct TypeImplIteratorAux {
80 static bool matches(typename TypeImpl<Config>::TypeHandle type);
81 static i::Handle<T> current(typename TypeImpl<Config>::TypeHandle type);
82 };
83
84 template<class Config>
85 struct TypeImplIteratorAux<Config, i::Map> {
86 static bool matches(typename TypeImpl<Config>::TypeHandle type) {
87 return type->IsClass();
88 }
89 static i::Handle<i::Map> current(typename TypeImpl<Config>::TypeHandle type) {
90 return type->AsClass();
91 }
92 };
93
94 template<class Config>
95 struct TypeImplIteratorAux<Config, i::Object> {
96 static bool matches(typename TypeImpl<Config>::TypeHandle type) {
97 return type->IsConstant();
98 }
99 static i::Handle<i::Object> current(
100 typename TypeImpl<Config>::TypeHandle type) {
101 return type->AsConstant();
102 }
103 };
104
105 template<class Config> template<class T>
106 bool TypeImpl<Config>::Iterator<T>::matches(TypeHandle type) {
107 return TypeImplIteratorAux<Config, T>::matches(type);
86 } 108 }
87 109
88 template<> 110 template<class Config> template<class T>
89 bool Type::Iterator<i::Object>::matches(Handle<Type> type) { 111 i::Handle<T> TypeImpl<Config>::Iterator<T>::Current() {
90 return type->is_constant(); 112 return TypeImplIteratorAux<Config, T>::current(get_type());
91 } 113 }
92 114
93 115
94 template<class T> 116 template<class Config> template<class T>
95 void Type::Iterator<T>::Advance() { 117 void TypeImpl<Config>::Iterator<T>::Advance() {
96 ++index_; 118 ++index_;
97 if (type_->is_union()) { 119 if (type_->IsUnion()) {
98 Handle<Unioned> unioned = type_->as_union(); 120 UnionedHandle unioned = type_->AsUnion();
99 for (; index_ < unioned->length(); ++index_) { 121 for (; index_ < unioned->length(); ++index_) {
100 if (matches(union_get(unioned, index_))) return; 122 if (matches(Config::union_get(unioned, index_))) return;
101 } 123 }
102 } else if (index_ == 0 && matches(type_)) { 124 } else if (index_ == 0 && matches(type_)) {
103 return; 125 return;
104 } 126 }
105 index_ = -1; 127 index_ = -1;
106 } 128 }
107 129
108 template class Type::Iterator<i::Map>;
109 template class Type::Iterator<i::Object>;
110
111 130
112 // Get the smallest bitset subsuming this type. 131 // Get the smallest bitset subsuming this type.
113 int Type::LubBitset() { 132 template<class Config>
114 if (this->is_bitset()) { 133 int TypeImpl<Config>::LubBitset() {
115 return this->as_bitset(); 134 if (this->IsBitset()) {
116 } else if (this->is_union()) { 135 return this->AsBitset();
117 Handle<Unioned> unioned = this->as_union(); 136 } else if (this->IsUnion()) {
137 UnionedHandle unioned = this->AsUnion();
118 int bitset = kNone; 138 int bitset = kNone;
119 for (int i = 0; i < unioned->length(); ++i) { 139 for (int i = 0; i < unioned->length(); ++i) {
120 bitset |= union_get(unioned, i)->LubBitset(); 140 bitset |= Config::union_get(unioned, i)->LubBitset();
121 } 141 }
122 return bitset; 142 return bitset;
123 } else if (this->is_class()) { 143 } else if (this->IsClass()) {
124 return LubBitset(*this->as_class()); 144 return LubBitset(*this->AsClass());
125 } else { 145 } else {
126 return LubBitset(*this->as_constant()); 146 return LubBitset(*this->AsConstant());
127 } 147 }
128 } 148 }
129 149
130 150
131 int Type::LubBitset(i::Object* value) { 151 template<class Config>
152 int TypeImpl<Config>::LubBitset(i::Object* value) {
132 if (value->IsSmi()) return kSmi; 153 if (value->IsSmi()) return kSmi;
133 i::Map* map = i::HeapObject::cast(value)->map(); 154 i::Map* map = i::HeapObject::cast(value)->map();
134 if (map->instance_type() == HEAP_NUMBER_TYPE) { 155 if (map->instance_type() == HEAP_NUMBER_TYPE) {
135 int32_t i; 156 int32_t i;
136 uint32_t u; 157 uint32_t u;
137 if (value->ToInt32(&i)) return Smi::IsValid(i) ? kSmi : kOtherSigned32; 158 if (value->ToInt32(&i)) return Smi::IsValid(i) ? kSmi : kOtherSigned32;
138 if (value->ToUint32(&u)) return kUnsigned32; 159 if (value->ToUint32(&u)) return kUnsigned32;
139 return kDouble; 160 return kDouble;
140 } 161 }
141 if (map->instance_type() == ODDBALL_TYPE) { 162 if (map->instance_type() == ODDBALL_TYPE) {
142 if (value->IsUndefined()) return kUndefined; 163 if (value->IsUndefined()) return kUndefined;
143 if (value->IsNull()) return kNull; 164 if (value->IsNull()) return kNull;
144 if (value->IsBoolean()) return kBoolean; 165 if (value->IsBoolean()) return kBoolean;
145 if (value->IsTheHole()) return kAny; // TODO(rossberg): kNone? 166 if (value->IsTheHole()) return kAny; // TODO(rossberg): kNone?
146 UNREACHABLE(); 167 UNREACHABLE();
147 } 168 }
148 return Type::LubBitset(map); 169 return LubBitset(map);
149 } 170 }
150 171
151 172
152 int Type::LubBitset(i::Map* map) { 173 template<class Config>
174 int TypeImpl<Config>::LubBitset(i::Map* map) {
153 switch (map->instance_type()) { 175 switch (map->instance_type()) {
154 case STRING_TYPE: 176 case STRING_TYPE:
155 case ASCII_STRING_TYPE: 177 case ASCII_STRING_TYPE:
156 case CONS_STRING_TYPE: 178 case CONS_STRING_TYPE:
157 case CONS_ASCII_STRING_TYPE: 179 case CONS_ASCII_STRING_TYPE:
158 case SLICED_STRING_TYPE: 180 case SLICED_STRING_TYPE:
159 case SLICED_ASCII_STRING_TYPE: 181 case SLICED_ASCII_STRING_TYPE:
160 case EXTERNAL_STRING_TYPE: 182 case EXTERNAL_STRING_TYPE:
161 case EXTERNAL_ASCII_STRING_TYPE: 183 case EXTERNAL_ASCII_STRING_TYPE:
162 case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE: 184 case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 case FIXED_ARRAY_TYPE: 246 case FIXED_ARRAY_TYPE:
225 return kInternal; 247 return kInternal;
226 default: 248 default:
227 UNREACHABLE(); 249 UNREACHABLE();
228 return kNone; 250 return kNone;
229 } 251 }
230 } 252 }
231 253
232 254
233 // Get the largest bitset subsumed by this type. 255 // Get the largest bitset subsumed by this type.
234 int Type::GlbBitset() { 256 template<class Config>
235 if (this->is_bitset()) { 257 int TypeImpl<Config>::GlbBitset() {
236 return this->as_bitset(); 258 if (this->IsBitset()) {
237 } else if (this->is_union()) { 259 return this->AsBitset();
260 } else if (this->IsUnion()) {
238 // All but the first are non-bitsets and thus would yield kNone anyway. 261 // All but the first are non-bitsets and thus would yield kNone anyway.
239 return union_get(this->as_union(), 0)->GlbBitset(); 262 return Config::union_get(this->AsUnion(), 0)->GlbBitset();
240 } else { 263 } else {
241 return kNone; 264 return kNone;
242 } 265 }
243 } 266 }
244 267
245 268
246 // Most precise _current_ type of a value (usually its class). 269 // Most precise _current_ type of a value (usually its class).
247 Type* Type::OfCurrently(Handle<i::Object> value) { 270 template<class Config>
248 if (value->IsSmi()) return Smi(); 271 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::OfCurrently(
272 i::Handle<i::Object> value, Region* region) {
273 if (value->IsSmi()) return Smi(region);
249 i::Map* map = i::HeapObject::cast(*value)->map(); 274 i::Map* map = i::HeapObject::cast(*value)->map();
250 if (map->instance_type() == HEAP_NUMBER_TYPE || 275 if (map->instance_type() == HEAP_NUMBER_TYPE ||
251 map->instance_type() == ODDBALL_TYPE) { 276 map->instance_type() == ODDBALL_TYPE) {
252 return Type::Of(value); 277 return Of(value, region);
253 } 278 }
254 return Class(i::handle(map)); 279 return Class(i::handle(map), region);
255 } 280 }
256 281
257 282
258 // Check this <= that. 283 // Check this <= that.
259 bool Type::SlowIs(Type* that) { 284 template<class Config>
285 bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
260 // Fast path for bitsets. 286 // Fast path for bitsets.
261 if (this->is_none()) return true; 287 if (this->IsNone()) return true;
262 if (that->is_bitset()) { 288 if (that->IsBitset()) {
263 return (this->LubBitset() | that->as_bitset()) == that->as_bitset(); 289 return (this->LubBitset() | that->AsBitset()) == that->AsBitset();
264 } 290 }
265 291
266 if (that->is_class()) { 292 if (that->IsClass()) {
267 return this->is_class() && *this->as_class() == *that->as_class(); 293 return this->IsClass() && *this->AsClass() == *that->AsClass();
268 } 294 }
269 if (that->is_constant()) { 295 if (that->IsConstant()) {
270 return this->is_constant() && *this->as_constant() == *that->as_constant(); 296 return this->IsConstant() && *this->AsConstant() == *that->AsConstant();
271 } 297 }
272 298
273 // (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T) 299 // (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T)
274 if (this->is_union()) { 300 if (this->IsUnion()) {
275 Handle<Unioned> unioned = this->as_union(); 301 UnionedHandle unioned = this->AsUnion();
276 for (int i = 0; i < unioned->length(); ++i) { 302 for (int i = 0; i < unioned->length(); ++i) {
277 Handle<Type> this_i = union_get(unioned, i); 303 TypeHandle this_i = Config::union_get(unioned, i);
278 if (!this_i->Is(that)) return false; 304 if (!this_i->Is(that)) return false;
279 } 305 }
280 return true; 306 return true;
281 } 307 }
282 308
283 // T <= (T1 \/ ... \/ Tn) <=> (T <= T1) \/ ... \/ (T <= Tn) 309 // T <= (T1 \/ ... \/ Tn) <=> (T <= T1) \/ ... \/ (T <= Tn)
284 // (iff T is not a union) 310 // (iff T is not a union)
285 ASSERT(!this->is_union()); 311 ASSERT(!this->IsUnion());
286 if (that->is_union()) { 312 if (that->IsUnion()) {
287 Handle<Unioned> unioned = that->as_union(); 313 UnionedHandle unioned = that->AsUnion();
288 for (int i = 0; i < unioned->length(); ++i) { 314 for (int i = 0; i < unioned->length(); ++i) {
289 Handle<Type> that_i = union_get(unioned, i); 315 TypeHandle that_i = Config::union_get(unioned, i);
290 if (this->Is(that_i)) return true; 316 if (this->Is(that_i)) return true;
291 if (this->is_bitset()) break; // Fast fail, no other field is a bitset. 317 if (this->IsBitset()) break; // Fast fail, only first field is a bitset.
292 } 318 }
293 return false; 319 return false;
294 } 320 }
295 321
296 return false; 322 return false;
297 } 323 }
298 324
299 325
300 bool Type::IsCurrently(Type* that) { 326 template<class Config>
327 bool TypeImpl<Config>::IsCurrently(TypeImpl* that) {
301 return this->Is(that) || 328 return this->Is(that) ||
302 (this->is_constant() && that->is_class() && 329 (this->IsConstant() && that->IsClass() &&
303 this->as_constant()->IsHeapObject() && 330 this->AsConstant()->IsHeapObject() &&
304 i::HeapObject::cast(*this->as_constant())->map() == *that->as_class()); 331 i::HeapObject::cast(*this->AsConstant())->map() == *that->AsClass());
305 } 332 }
306 333
307 334
308 // Check this overlaps that. 335 // Check this overlaps that.
309 bool Type::Maybe(Type* that) { 336 template<class Config>
337 bool TypeImpl<Config>::Maybe(TypeImpl* that) {
310 // Fast path for bitsets. 338 // Fast path for bitsets.
311 if (this->is_bitset()) { 339 if (this->IsBitset()) {
312 return (this->as_bitset() & that->LubBitset()) != 0; 340 return (this->AsBitset() & that->LubBitset()) != 0;
313 } 341 }
314 if (that->is_bitset()) { 342 if (that->IsBitset()) {
315 return (this->LubBitset() & that->as_bitset()) != 0; 343 return (this->LubBitset() & that->AsBitset()) != 0;
316 } 344 }
317 345
318 // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T) 346 // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T)
319 if (this->is_union()) { 347 if (this->IsUnion()) {
320 Handle<Unioned> unioned = this->as_union(); 348 UnionedHandle unioned = this->AsUnion();
321 for (int i = 0; i < unioned->length(); ++i) { 349 for (int i = 0; i < unioned->length(); ++i) {
322 Handle<Type> this_i = union_get(unioned, i); 350 TypeHandle this_i = Config::union_get(unioned, i);
323 if (this_i->Maybe(that)) return true; 351 if (this_i->Maybe(that)) return true;
324 } 352 }
325 return false; 353 return false;
326 } 354 }
327 355
328 // T overlaps (T1 \/ ... \/ Tn) <=> (T overlaps T1) \/ ... \/ (T overlaps Tn) 356 // T overlaps (T1 \/ ... \/ Tn) <=> (T overlaps T1) \/ ... \/ (T overlaps Tn)
329 if (that->is_union()) { 357 if (that->IsUnion()) {
330 Handle<Unioned> unioned = that->as_union(); 358 UnionedHandle unioned = that->AsUnion();
331 for (int i = 0; i < unioned->length(); ++i) { 359 for (int i = 0; i < unioned->length(); ++i) {
332 Handle<Type> that_i = union_get(unioned, i); 360 TypeHandle that_i = Config::union_get(unioned, i);
333 if (this->Maybe(that_i)) return true; 361 if (this->Maybe(that_i)) return true;
334 } 362 }
335 return false; 363 return false;
336 } 364 }
337 365
338 ASSERT(!that->is_union()); 366 ASSERT(!this->IsUnion() && !that->IsUnion());
339 if (this->is_class()) { 367 if (this->IsClass()) {
340 return that->is_class() && *this->as_class() == *that->as_class(); 368 return that->IsClass() && *this->AsClass() == *that->AsClass();
341 } 369 }
342 if (this->is_constant()) { 370 if (this->IsConstant()) {
343 return that->is_constant() && *this->as_constant() == *that->as_constant(); 371 return that->IsConstant() && *this->AsConstant() == *that->AsConstant();
344 } 372 }
345 373
346 return false; 374 return false;
347 } 375 }
348 376
349 377
350 bool Type::InUnion(Handle<Unioned> unioned, int current_size) { 378 template<class Config>
351 ASSERT(!this->is_union()); 379 bool TypeImpl<Config>::InUnion(UnionedHandle unioned, int current_size) {
380 ASSERT(!this->IsUnion());
352 for (int i = 0; i < current_size; ++i) { 381 for (int i = 0; i < current_size; ++i) {
353 Handle<Type> type = union_get(unioned, i); 382 TypeHandle type = Config::union_get(unioned, i);
354 if (this->Is(type)) return true; 383 if (this->Is(type)) return true;
355 } 384 }
356 return false; 385 return false;
357 } 386 }
358 387
359 388
360 // Get non-bitsets from this which are not subsumed by union, store at unioned, 389 // Get non-bitsets from this which are not subsumed by union, store at unioned,
361 // starting at index. Returns updated index. 390 // starting at index. Returns updated index.
362 int Type::ExtendUnion(Handle<Unioned> result, int current_size) { 391 template<class Config>
392 int TypeImpl<Config>::ExtendUnion(UnionedHandle result, int current_size) {
363 int old_size = current_size; 393 int old_size = current_size;
364 if (this->is_class() || this->is_constant()) { 394 if (this->IsClass() || this->IsConstant()) {
365 if (!this->InUnion(result, old_size)) result->set(current_size++, this); 395 if (!this->InUnion(result, old_size)) result->set(current_size++, this);
366 } else if (this->is_union()) { 396 } else if (this->IsUnion()) {
367 Handle<Unioned> unioned = this->as_union(); 397 UnionedHandle unioned = this->AsUnion();
368 for (int i = 0; i < unioned->length(); ++i) { 398 for (int i = 0; i < unioned->length(); ++i) {
369 Handle<Type> type = union_get(unioned, i); 399 TypeHandle type = Config::union_get(unioned, i);
370 ASSERT(i == 0 || !(type->is_bitset() || type->Is(union_get(unioned, 0)))); 400 ASSERT(i == 0 ||
371 if (type->is_bitset()) continue; 401 !(type->IsBitset() || type->Is(Config::union_get(unioned, 0))));
372 if (!type->InUnion(result, old_size)) result->set(current_size++, *type); 402 if (!type->IsBitset() && !type->InUnion(result, old_size)) {
403 result->set(current_size++, *type);
404 }
373 } 405 }
374 } 406 }
375 return current_size; 407 return current_size;
376 } 408 }
377 409
378 410
379 // Union is O(1) on simple bit unions, but O(n*m) on structured unions. 411 // Union is O(1) on simple bit unions, but O(n*m) on structured unions.
380 // TODO(rossberg): Should we use object sets somehow? Is it worth it? 412 // TODO(rossberg): Should we use object sets somehow? Is it worth it?
381 Type* Type::Union(Handle<Type> type1, Handle<Type> type2) { 413 template<class Config>
414 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union(
415 TypeHandle type1, TypeHandle type2, Region* region) {
382 // Fast case: bit sets. 416 // Fast case: bit sets.
383 if (type1->is_bitset() && type2->is_bitset()) { 417 if (type1->IsBitset() && type2->IsBitset()) {
384 return from_bitset(type1->as_bitset() | type2->as_bitset()); 418 return Config::from_bitset(type1->AsBitset() | type2->AsBitset(), region);
385 } 419 }
386 420
387 // Fast case: top or bottom types. 421 // Fast case: top or bottom types.
388 if (type1->SameValue(Type::Any())) return *type1; 422 if (type1->IsAny()) return type1;
389 if (type2->SameValue(Type::Any())) return *type2; 423 if (type2->IsAny()) return type2;
390 if (type1->SameValue(Type::None())) return *type2; 424 if (type1->IsNone()) return type2;
391 if (type2->SameValue(Type::None())) return *type1; 425 if (type2->IsNone()) return type1;
392 426
393 // Semi-fast case: Unioned objects are neither involved nor produced. 427 // Semi-fast case: Unioned objects are neither involved nor produced.
394 if (!(type1->is_union() || type2->is_union())) { 428 if (!(type1->IsUnion() || type2->IsUnion())) {
395 if (type1->Is(type2)) return *type2; 429 if (type1->Is(type2)) return type2;
396 if (type2->Is(type1)) return *type1; 430 if (type2->Is(type1)) return type1;
397 } 431 }
398 432
399 // Slow case: may need to produce a Unioned object. 433 // Slow case: may need to produce a Unioned object.
400 Isolate* isolate = NULL; 434 int size = type1->IsBitset() || type2->IsBitset() ? 1 : 0;
401 int size = type1->is_bitset() || type2->is_bitset() ? 1 : 0; 435 if (!type1->IsBitset()) {
402 if (!type1->is_bitset()) { 436 size += (type1->IsUnion() ? type1->AsUnion()->length() : 1);
403 isolate = i::HeapObject::cast(*type1)->GetIsolate();
404 size += (type1->is_union() ? type1->as_union()->length() : 1);
405 } 437 }
406 if (!type2->is_bitset()) { 438 if (!type2->IsBitset()) {
407 isolate = i::HeapObject::cast(*type2)->GetIsolate(); 439 size += (type2->IsUnion() ? type2->AsUnion()->length() : 1);
408 size += (type2->is_union() ? type2->as_union()->length() : 1);
409 } 440 }
410 ASSERT(isolate != NULL);
411 ASSERT(size >= 2); 441 ASSERT(size >= 2);
412 Handle<Unioned> unioned = isolate->factory()->NewFixedArray(size); 442 UnionedHandle unioned = Config::union_create(size, region);
413 size = 0; 443 size = 0;
414 444
415 int bitset = type1->GlbBitset() | type2->GlbBitset(); 445 int bitset = type1->GlbBitset() | type2->GlbBitset();
416 if (bitset != kNone) unioned->set(size++, from_bitset(bitset)); 446 if (bitset != kNone) unioned->set(size++, Config::from_bitset(bitset));
417 size = type1->ExtendUnion(unioned, size); 447 size = type1->ExtendUnion(unioned, size);
418 size = type2->ExtendUnion(unioned, size); 448 size = type2->ExtendUnion(unioned, size);
419 449
420 if (size == 1) { 450 if (size == 1) {
421 return *union_get(unioned, 0); 451 return Config::union_get(unioned, 0);
422 } else if (size == unioned->length()) { 452 } else if (size == unioned->length()) {
423 return from_handle(unioned); 453 return Config::from_union(unioned);
424 } 454 }
425 455
426 // There was an overlap. Copy to smaller union. 456 // There was an overlap. Copy to smaller union.
427 Handle<Unioned> result = isolate->factory()->NewFixedArray(size); 457 UnionedHandle result = Config::union_create(size, region);
428 for (int i = 0; i < size; ++i) result->set(i, unioned->get(i)); 458 for (int i = 0; i < size; ++i) result->set(i, unioned->get(i));
429 return from_handle(result); 459 return Config::from_union(result);
430 } 460 }
431 461
432 462
433 // Get non-bitsets from this which are also in that, store at unioned, 463 // Get non-bitsets from this which are also in that, store at unioned,
434 // starting at index. Returns updated index. 464 // starting at index. Returns updated index.
435 int Type::ExtendIntersection( 465 template<class Config>
436 Handle<Unioned> result, Handle<Type> that, int current_size) { 466 int TypeImpl<Config>::ExtendIntersection(
467 UnionedHandle result, TypeHandle that, int current_size) {
437 int old_size = current_size; 468 int old_size = current_size;
438 if (this->is_class() || this->is_constant()) { 469 if (this->IsClass() || this->IsConstant()) {
439 if (this->Is(that) && !this->InUnion(result, old_size)) 470 if (this->Is(that) && !this->InUnion(result, old_size))
440 result->set(current_size++, this); 471 result->set(current_size++, this);
441 } else if (this->is_union()) { 472 } else if (this->IsUnion()) {
442 Handle<Unioned> unioned = this->as_union(); 473 UnionedHandle unioned = this->AsUnion();
443 for (int i = 0; i < unioned->length(); ++i) { 474 for (int i = 0; i < unioned->length(); ++i) {
444 Handle<Type> type = union_get(unioned, i); 475 TypeHandle type = Config::union_get(unioned, i);
445 ASSERT(i == 0 || !(type->is_bitset() || type->Is(union_get(unioned, 0)))); 476 ASSERT(i == 0 ||
446 if (type->is_bitset()) continue; 477 !(type->IsBitset() || type->Is(Config::union_get(unioned, 0))));
447 if (type->Is(that) && !type->InUnion(result, old_size)) 478 if (!type->IsBitset() && type->Is(that) &&
479 !type->InUnion(result, old_size)) {
448 result->set(current_size++, *type); 480 result->set(current_size++, *type);
481 }
449 } 482 }
450 } 483 }
451 return current_size; 484 return current_size;
452 } 485 }
453 486
454 487
455 // Intersection is O(1) on simple bit unions, but O(n*m) on structured unions. 488 // Intersection is O(1) on simple bit unions, but O(n*m) on structured unions.
456 // TODO(rossberg): Should we use object sets somehow? Is it worth it? 489 // TODO(rossberg): Should we use object sets somehow? Is it worth it?
457 Type* Type::Intersect(Handle<Type> type1, Handle<Type> type2) { 490 template<class Config>
491 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect(
492 TypeHandle type1, TypeHandle type2, Region* region) {
458 // Fast case: bit sets. 493 // Fast case: bit sets.
459 if (type1->is_bitset() && type2->is_bitset()) { 494 if (type1->IsBitset() && type2->IsBitset()) {
460 return from_bitset(type1->as_bitset() & type2->as_bitset()); 495 return Config::from_bitset(type1->AsBitset() & type2->AsBitset(), region);
461 } 496 }
462 497
463 // Fast case: top or bottom types. 498 // Fast case: top or bottom types.
464 if (type1->SameValue(Type::None())) return *type1; 499 if (type1->IsNone()) return type1;
465 if (type2->SameValue(Type::None())) return *type2; 500 if (type2->IsNone()) return type2;
466 if (type1->SameValue(Type::Any())) return *type2; 501 if (type1->IsAny()) return type2;
467 if (type2->SameValue(Type::Any())) return *type1; 502 if (type2->IsAny()) return type1;
468 503
469 // Semi-fast case: Unioned objects are neither involved nor produced. 504 // Semi-fast case: Unioned objects are neither involved nor produced.
470 if (!(type1->is_union() || type2->is_union())) { 505 if (!(type1->IsUnion() || type2->IsUnion())) {
471 if (type1->Is(type2)) return *type1; 506 if (type1->Is(type2)) return type1;
472 if (type2->Is(type1)) return *type2; 507 if (type2->Is(type1)) return type2;
473 } 508 }
474 509
475 // Slow case: may need to produce a Unioned object. 510 // Slow case: may need to produce a Unioned object.
476 Isolate* isolate = NULL;
477 int size = 0; 511 int size = 0;
478 if (!type1->is_bitset()) { 512 if (!type1->IsBitset()) {
479 isolate = i::HeapObject::cast(*type1)->GetIsolate(); 513 size = (type1->IsUnion() ? type1->AsUnion()->length() : 2);
480 size = (type1->is_union() ? type1->as_union()->length() : 2);
481 } 514 }
482 if (!type2->is_bitset()) { 515 if (!type2->IsBitset()) {
483 isolate = i::HeapObject::cast(*type2)->GetIsolate(); 516 int size2 = (type2->IsUnion() ? type2->AsUnion()->length() : 2);
484 int size2 = (type2->is_union() ? type2->as_union()->length() : 2);
485 size = (size == 0 ? size2 : Min(size, size2)); 517 size = (size == 0 ? size2 : Min(size, size2));
486 } 518 }
487 ASSERT(isolate != NULL);
488 ASSERT(size >= 2); 519 ASSERT(size >= 2);
489 Handle<Unioned> unioned = isolate->factory()->NewFixedArray(size); 520 UnionedHandle unioned = Config::union_create(size, region);
490 size = 0; 521 size = 0;
491 522
492 int bitset = type1->GlbBitset() & type2->GlbBitset(); 523 int bitset = type1->GlbBitset() & type2->GlbBitset();
493 if (bitset != kNone) unioned->set(size++, from_bitset(bitset)); 524 if (bitset != kNone) unioned->set(size++, Config::from_bitset(bitset));
494 size = type1->ExtendIntersection(unioned, type2, size); 525 size = type1->ExtendIntersection(unioned, type2, size);
495 size = type2->ExtendIntersection(unioned, type1, size); 526 size = type2->ExtendIntersection(unioned, type1, size);
496 527
497 if (size == 0) { 528 if (size == 0) {
498 return None(); 529 return None(region);
499 } else if (size == 1) { 530 } else if (size == 1) {
500 return *union_get(unioned, 0); 531 return Config::union_get(unioned, 0);
501 } else if (size == unioned->length()) { 532 } else if (size == unioned->length()) {
502 return from_handle(unioned); 533 return Config::from_union(unioned);
503 } 534 }
504 535
505 // There were dropped cases. Copy to smaller union. 536 // There were dropped cases. Copy to smaller union.
506 Handle<Unioned> result = isolate->factory()->NewFixedArray(size); 537 UnionedHandle result = Config::union_create(size, region);
507 for (int i = 0; i < size; ++i) result->set(i, unioned->get(i)); 538 for (int i = 0; i < size; ++i) result->set(i, unioned->get(i));
508 return from_handle(result); 539 return Config::from_union(result);
509 } 540 }
510 541
511 542
512 Type* Type::Optional(Handle<Type> type) { 543 // TODO(rossberg): this does not belong here.
513 return type->is_bitset()
514 ? from_bitset(type->as_bitset() | kUndefined)
515 : Union(type, Undefined()->handle_via_isolate_of(*type));
516 }
517
518
519 Representation Representation::FromType(Handle<Type> type) { 544 Representation Representation::FromType(Handle<Type> type) {
520 if (type->Is(Type::None())) return Representation::None(); 545 if (type->Is(Type::None())) return Representation::None();
521 if (type->Is(Type::Smi())) return Representation::Smi(); 546 if (type->Is(Type::Smi())) return Representation::Smi();
522 if (type->Is(Type::Signed32())) return Representation::Integer32(); 547 if (type->Is(Type::Signed32())) return Representation::Integer32();
523 if (type->Is(Type::Number())) return Representation::Double(); 548 if (type->Is(Type::Number())) return Representation::Double();
524 return Representation::Tagged(); 549 return Representation::Tagged();
525 } 550 }
526 551
527 552
528 #ifdef OBJECT_PRINT 553 #ifdef OBJECT_PRINT
529 void Type::TypePrint() { 554 template<class Config>
555 void TypeImpl<Config>::TypePrint() {
530 TypePrint(stdout); 556 TypePrint(stdout);
531 PrintF(stdout, "\n"); 557 PrintF(stdout, "\n");
532 Flush(stdout); 558 Flush(stdout);
533 } 559 }
534 560
535 561
536 const char* Type::bitset_name(int bitset) { 562 template<class Config>
563 const char* TypeImpl<Config>::bitset_name(int bitset) {
537 switch (bitset) { 564 switch (bitset) {
538 #define PRINT_COMPOSED_TYPE(type, value) case k##type: return #type; 565 #define PRINT_COMPOSED_TYPE(type, value) case k##type: return #type;
539 BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE) 566 BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE)
540 #undef PRINT_COMPOSED_TYPE 567 #undef PRINT_COMPOSED_TYPE
541 default: 568 default:
542 return NULL; 569 return NULL;
543 } 570 }
544 } 571 }
545 572
546 573
547 void Type::TypePrint(FILE* out) { 574 template<class Config>
548 if (is_bitset()) { 575 void TypeImpl<Config>::TypePrint(FILE* out) {
549 int bitset = as_bitset(); 576 if (this->IsBitset()) {
577 int bitset = this->AsBitset();
550 const char* name = bitset_name(bitset); 578 const char* name = bitset_name(bitset);
551 if (name != NULL) { 579 if (name != NULL) {
552 PrintF(out, "%s", name); 580 PrintF(out, "%s", name);
553 } else { 581 } else {
554 bool is_first = true; 582 bool is_first = true;
555 PrintF(out, "("); 583 PrintF(out, "(");
556 for (int mask = 1; mask != 0; mask = mask << 1) { 584 for (int mask = 1; mask != 0; mask = mask << 1) {
557 if ((bitset & mask) != 0) { 585 if ((bitset & mask) != 0) {
558 if (!is_first) PrintF(out, " | "); 586 if (!is_first) PrintF(out, " | ");
559 is_first = false; 587 is_first = false;
560 PrintF(out, "%s", bitset_name(mask)); 588 PrintF(out, "%s", bitset_name(mask));
561 } 589 }
562 } 590 }
563 PrintF(out, ")"); 591 PrintF(out, ")");
564 } 592 }
565 } else if (is_constant()) { 593 } else if (this->IsConstant()) {
566 PrintF(out, "Constant(%p : ", static_cast<void*>(*as_constant())); 594 PrintF(out, "Constant(%p : ", static_cast<void*>(*this->AsConstant()));
567 from_bitset(LubBitset())->TypePrint(out); 595 Config::from_bitset(this->LubBitset())->TypePrint(out);
568 PrintF(")"); 596 PrintF(")");
569 } else if (is_class()) { 597 } else if (this->IsClass()) {
570 PrintF(out, "Class(%p < ", static_cast<void*>(*as_class())); 598 PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()));
571 from_bitset(LubBitset())->TypePrint(out); 599 Config::from_bitset(this->LubBitset())->TypePrint(out);
572 PrintF(")"); 600 PrintF(")");
573 } else if (is_union()) { 601 } else if (this->IsUnion()) {
574 PrintF(out, "("); 602 PrintF(out, "(");
575 Handle<Unioned> unioned = as_union(); 603 UnionedHandle unioned = this->AsUnion();
576 for (int i = 0; i < unioned->length(); ++i) { 604 for (int i = 0; i < unioned->length(); ++i) {
577 Handle<Type> type_i = union_get(unioned, i); 605 TypeHandle type_i = Config::union_get(unioned, i);
578 if (i > 0) PrintF(out, " | "); 606 if (i > 0) PrintF(out, " | ");
579 type_i->TypePrint(out); 607 type_i->TypePrint(out);
580 } 608 }
581 PrintF(out, ")"); 609 PrintF(out, ")");
582 } 610 }
583 } 611 }
584 #endif 612 #endif
585 613
586 614
615 template class TypeImpl<HeapTypeConfig>;
616 template class TypeImpl<HeapTypeConfig>::Iterator<i::Map>;
617 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>;
618
619
587 } } // namespace v8::internal 620 } } // namespace v8::internal
OLDNEW
« src/property-details.h ('K') | « src/types.h ('k') | src/typing.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698