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 { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 } | 110 } |
111 | 111 |
112 | 112 |
113 // Get the largest bitset subsumed by this type. | 113 // Get the largest bitset subsumed by this type. |
114 template<class Config> | 114 template<class Config> |
115 int TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) { | 115 int TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) { |
116 DisallowHeapAllocation no_allocation; | 116 DisallowHeapAllocation no_allocation; |
117 if (type->IsBitset()) { | 117 if (type->IsBitset()) { |
118 return type->AsBitset(); | 118 return type->AsBitset(); |
119 } else if (type->IsUnion()) { | 119 } else if (type->IsUnion()) { |
120 // All but the first are non-bitsets and thus would yield kNone anyway. | 120 UnionHandle unioned = handle(type->AsUnion()); |
121 return type->AsUnion()->Get(0)->BitsetGlb(); | 121 int bitset = kNone; |
| 122 for (int i = 0; i < unioned->Length(); ++i) { |
| 123 bitset |= unioned->Get(i)->BitsetGlb(); |
| 124 } |
| 125 return bitset; |
| 126 } else if (type->IsClass()) { |
| 127 // Little hack to avoid the need for a region for handlification here... |
| 128 return REPRESENTATION(Config::is_class(type) |
| 129 ? Lub(*Config::as_class(type)) |
| 130 : type->AsClass()->Bound(NULL)->AsBitset()); |
| 131 } else if (type->IsConstant()) { |
| 132 return REPRESENTATION(type->AsConstant()->Bound()->AsBitset()); |
| 133 } else if (type->IsArray()) { |
| 134 return REPRESENTATION(type->AsArray()->Bound()->AsBitset()); |
| 135 } else if (type->IsFunction()) { |
| 136 return REPRESENTATION(type->AsFunction()->Bound()->AsBitset()); |
122 } else { | 137 } else { |
| 138 UNREACHABLE(); |
123 return kNone; | 139 return kNone; |
124 } | 140 } |
125 } | 141 } |
126 | 142 |
127 | 143 |
128 // Get the smallest bitset subsuming this type. | 144 // Get the smallest bitset subsuming this type. |
129 template<class Config> | 145 template<class Config> |
130 int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { | 146 int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { |
131 DisallowHeapAllocation no_allocation; | 147 DisallowHeapAllocation no_allocation; |
132 if (type->IsBitset()) { | 148 if (type->IsBitset()) { |
133 return type->AsBitset(); | 149 return type->AsBitset(); |
134 } else if (type->IsUnion()) { | 150 } else if (type->IsUnion()) { |
135 UnionHandle unioned = handle(type->AsUnion()); | 151 UnionHandle unioned = handle(type->AsUnion()); |
136 int bitset = kNone; | 152 int bitset = kNone; |
137 for (int i = 0; i < unioned->Length(); ++i) { | 153 for (int i = 0; i < unioned->Length(); ++i) { |
138 bitset |= unioned->Get(i)->BitsetLub(); | 154 bitset |= unioned->Get(i)->BitsetLub(); |
139 } | 155 } |
140 return bitset; | 156 return bitset; |
141 } else if (type->IsClass()) { | 157 } else if (type->IsClass()) { |
142 int bitset = Config::lub_bitset(type); | 158 // Little hack to avoid the need for a region for handlification here... |
143 return bitset ? bitset : Lub(*type->AsClass()->Map()); | 159 return Config::is_class(type) ? Lub(*Config::as_class(type)) : |
| 160 type->AsClass()->Bound(NULL)->AsBitset(); |
144 } else if (type->IsConstant()) { | 161 } else if (type->IsConstant()) { |
145 int bitset = Config::lub_bitset(type); | 162 return type->AsConstant()->Bound()->AsBitset(); |
146 return bitset ? bitset : Lub(*type->AsConstant()->Value()); | 163 } else if (type->IsArray()) { |
| 164 return type->AsArray()->Bound()->AsBitset(); |
| 165 } else if (type->IsFunction()) { |
| 166 return type->AsFunction()->Bound()->AsBitset(); |
| 167 } else { |
| 168 UNREACHABLE(); |
| 169 return kNone; |
| 170 } |
| 171 } |
| 172 |
| 173 |
| 174 // Get the smallest bitset subsuming this type, ignoring current bounds. |
| 175 template<class Config> |
| 176 int TypeImpl<Config>::BitsetType::InherentLub(TypeImpl* type) { |
| 177 DisallowHeapAllocation no_allocation; |
| 178 if (type->IsBitset()) { |
| 179 return type->AsBitset(); |
| 180 } else if (type->IsUnion()) { |
| 181 UnionHandle unioned = handle(type->AsUnion()); |
| 182 int bitset = kNone; |
| 183 for (int i = 0; i < unioned->Length(); ++i) { |
| 184 bitset |= unioned->Get(i)->InherentBitsetLub(); |
| 185 } |
| 186 return bitset; |
| 187 } else if (type->IsClass()) { |
| 188 return Lub(*type->AsClass()->Map()); |
| 189 } else if (type->IsConstant()) { |
| 190 return Lub(*type->AsConstant()->Value()); |
147 } else if (type->IsArray()) { | 191 } else if (type->IsArray()) { |
148 return kArray; | 192 return kArray; |
149 } else if (type->IsFunction()) { | 193 } else if (type->IsFunction()) { |
150 return kFunction; | 194 return kFunction; |
151 } else { | 195 } else { |
152 UNREACHABLE(); | 196 UNREACHABLE(); |
153 return kNone; | 197 return kNone; |
154 } | 198 } |
155 } | 199 } |
156 | 200 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 // Check this <= that. | 321 // Check this <= that. |
278 template<class Config> | 322 template<class Config> |
279 bool TypeImpl<Config>::SlowIs(TypeImpl* that) { | 323 bool TypeImpl<Config>::SlowIs(TypeImpl* that) { |
280 DisallowHeapAllocation no_allocation; | 324 DisallowHeapAllocation no_allocation; |
281 | 325 |
282 // Fast path for bitsets. | 326 // Fast path for bitsets. |
283 if (this->IsNone()) return true; | 327 if (this->IsNone()) return true; |
284 if (that->IsBitset()) { | 328 if (that->IsBitset()) { |
285 return (BitsetType::Lub(this) | that->AsBitset()) == that->AsBitset(); | 329 return (BitsetType::Lub(this) | that->AsBitset()) == that->AsBitset(); |
286 } | 330 } |
| 331 if (this->IsBitset() && SEMANTIC(this->AsBitset()) == BitsetType::kNone) { |
| 332 // Bitsets only have non-bitset supertypes along the representation axis. |
| 333 int that_bitset = that->BitsetGlb(); |
| 334 return (this->AsBitset() | that_bitset) == that_bitset; |
| 335 } |
287 | 336 |
288 if (that->IsClass()) { | 337 if (that->IsClass()) { |
289 return this->IsClass() | 338 return this->IsClass() |
290 && *this->AsClass()->Map() == *that->AsClass()->Map(); | 339 && *this->AsClass()->Map() == *that->AsClass()->Map() |
| 340 && ((Config::is_class(that) && Config::is_class(this)) || |
| 341 BitsetType::New(this->BitsetLub())->Is( |
| 342 BitsetType::New(that->BitsetLub()))); |
291 } | 343 } |
292 if (that->IsConstant()) { | 344 if (that->IsConstant()) { |
293 return this->IsConstant() | 345 return this->IsConstant() |
294 && *this->AsConstant()->Value() == *that->AsConstant()->Value(); | 346 && *this->AsConstant()->Value() == *that->AsConstant()->Value() |
| 347 && this->AsConstant()->Bound()->Is(that->AsConstant()->Bound()); |
295 } | 348 } |
296 if (that->IsArray()) { | 349 if (that->IsArray()) { |
297 return this->IsArray() | 350 return this->IsArray() |
298 && this->AsArray()->Element()->Equals(that->AsArray()->Element()); | 351 && this->AsArray()->Element()->Equals(that->AsArray()->Element()); |
299 } | 352 } |
300 if (that->IsFunction()) { | 353 if (that->IsFunction()) { |
301 // We currently do not allow for any variance here, in order to keep | 354 // We currently do not allow for any variance here, in order to keep |
302 // Union and Intersect operations simple. | 355 // Union and Intersect operations simple. |
303 if (!this->IsFunction()) return false; | 356 if (!this->IsFunction()) return false; |
304 FunctionType* this_fun = this->AsFunction(); | 357 FunctionType* this_fun = this->AsFunction(); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 return this->Equals(that); | 470 return this->Equals(that); |
418 } | 471 } |
419 | 472 |
420 return false; | 473 return false; |
421 } | 474 } |
422 | 475 |
423 | 476 |
424 template<class Config> | 477 template<class Config> |
425 bool TypeImpl<Config>::Contains(i::Object* value) { | 478 bool TypeImpl<Config>::Contains(i::Object* value) { |
426 DisallowHeapAllocation no_allocation; | 479 DisallowHeapAllocation no_allocation; |
427 | |
428 for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) { | 480 for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) { |
429 if (*it.Current() == value) return true; | 481 if (*it.Current() == value) return true; |
430 } | 482 } |
431 return BitsetType::New(BitsetType::Lub(value))->Is(this); | 483 return BitsetType::New(BitsetType::Lub(value))->Is(this); |
432 } | 484 } |
433 | 485 |
434 | 486 |
435 template<class Config> | 487 template<class Config> |
436 bool TypeImpl<Config>::InUnion(UnionHandle unioned, int current_size) { | 488 bool TypeImpl<Config>::UnionType::Wellformed() { |
437 ASSERT(!this->IsUnion()); | 489 ASSERT(this->Length() >= 2); |
438 for (int i = 0; i < current_size; ++i) { | 490 for (int i = 0; i < this->Length(); ++i) { |
439 if (this->Is(unioned->Get(i))) return true; | 491 ASSERT(!this->Get(i)->IsUnion()); |
| 492 if (i > 0) ASSERT(!this->Get(i)->IsBitset()); |
| 493 for (int j = 0; j < this->Length(); ++j) { |
| 494 if (i != j) ASSERT(!this->Get(i)->Is(this->Get(j))); |
| 495 } |
440 } | 496 } |
441 return false; | 497 return true; |
442 } | 498 } |
443 | 499 |
444 | 500 |
445 // Get non-bitsets from this which are not subsumed by union, store at result, | 501 template<class Config> |
446 // starting at index. Returns updated index. | 502 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Narrow( |
| 503 int bitset, Region* region) { |
| 504 TypeHandle bound = BitsetType::New(bitset, region); |
| 505 if (this->IsClass()) { |
| 506 return ClassType::New(this->AsClass()->Map(), bound, region); |
| 507 } else if (this->IsConstant()) { |
| 508 return ConstantType::New(this->AsConstant()->Value(), bound, region); |
| 509 } else if (this->IsArray()) { |
| 510 return ArrayType::New(this->AsArray()->Element(), bound, region); |
| 511 } else if (this->IsFunction()) { |
| 512 FunctionType* function = this->AsFunction(); |
| 513 int arity = function->Arity(); |
| 514 FunctionHandle type = FunctionType::New( |
| 515 function->Result(), function->Receiver(), bound, arity, region); |
| 516 for (int i = 0; i < arity; ++i) { |
| 517 type->InitParameter(i, function->Parameter(i)); |
| 518 } |
| 519 return type; |
| 520 } |
| 521 UNREACHABLE(); |
| 522 return TypeHandle(); |
| 523 } |
| 524 |
| 525 |
| 526 template<class Config> |
| 527 int TypeImpl<Config>::BoundBy(TypeImpl* that) { |
| 528 ASSERT(!this->IsUnion()); |
| 529 if (that->IsUnion()) { |
| 530 UnionType* unioned = that->AsUnion(); |
| 531 int length = unioned->Length(); |
| 532 int bitset = BitsetType::kNone; |
| 533 for (int i = 0; i < length; ++i) { |
| 534 bitset |= BoundBy(unioned->Get(i)->unhandle()); |
| 535 } |
| 536 return bitset; |
| 537 } else if (that->IsClass() && this->IsClass() && |
| 538 *this->AsClass()->Map() == *that->AsClass()->Map()) { |
| 539 return that->BitsetLub(); |
| 540 } else if (that->IsConstant() && this->IsConstant() && |
| 541 *this->AsConstant()->Value() == *that->AsConstant()->Value()) { |
| 542 return that->AsConstant()->Bound()->AsBitset(); |
| 543 } else if (that->IsArray() && this->IsArray() && this->Is(that)) { |
| 544 return that->AsArray()->Bound()->AsBitset(); |
| 545 } else if (that->IsFunction() && this->IsFunction() && this->Is(that)) { |
| 546 return that->AsFunction()->Bound()->AsBitset(); |
| 547 } |
| 548 return that->BitsetGlb(); |
| 549 } |
| 550 |
| 551 |
| 552 template<class Config> |
| 553 int TypeImpl<Config>::IndexInUnion( |
| 554 int bound, UnionHandle unioned, int current_size) { |
| 555 ASSERT(!this->IsUnion()); |
| 556 for (int i = 0; i < current_size; ++i) { |
| 557 TypeHandle that = unioned->Get(i); |
| 558 if (that->IsBitset()) { |
| 559 if ((bound | that->AsBitset()) == that->AsBitset()) return i; |
| 560 } else if (that->IsClass() && this->IsClass()) { |
| 561 if (*this->AsClass()->Map() == *that->AsClass()->Map()) return i; |
| 562 } else if (that->IsConstant() && this->IsConstant()) { |
| 563 if (*this->AsConstant()->Value() == *that->AsConstant()->Value()) |
| 564 return i; |
| 565 } else if (that->IsArray() && this->IsArray()) { |
| 566 if (this->Is(that)) return i; |
| 567 } else if (that->IsFunction() && this->IsFunction()) { |
| 568 if (this->Is(that)) return i; |
| 569 } |
| 570 } |
| 571 return -1; |
| 572 } |
| 573 |
| 574 |
| 575 // Get non-bitsets from type, bounded by upper. |
| 576 // Store at result starting at index. Returns updated index. |
447 template<class Config> | 577 template<class Config> |
448 int TypeImpl<Config>::ExtendUnion( | 578 int TypeImpl<Config>::ExtendUnion( |
449 UnionHandle result, TypeHandle type, int current_size) { | 579 UnionHandle result, int size, TypeHandle type, |
450 int old_size = current_size; | 580 TypeHandle other, bool is_intersect, Region* region) { |
| 581 int old_size = size; |
451 if (type->IsUnion()) { | 582 if (type->IsUnion()) { |
452 UnionHandle unioned = handle(type->AsUnion()); | 583 UnionHandle unioned = handle(type->AsUnion()); |
453 for (int i = 0; i < unioned->Length(); ++i) { | 584 for (int i = 0; i < unioned->Length(); ++i) { |
454 TypeHandle type = unioned->Get(i); | 585 TypeHandle type_i = unioned->Get(i); |
455 ASSERT(i == 0 || !(type->IsBitset() || type->Is(unioned->Get(0)))); | 586 ASSERT(i == 0 || !(type_i->IsBitset() || type_i->Is(unioned->Get(0)))); |
456 if (!type->IsBitset() && !type->InUnion(result, old_size)) { | 587 if (!type_i->IsBitset()) { |
457 result->Set(current_size++, type); | 588 size = ExtendUnion(result, size, type_i, other, is_intersect, region); |
458 } | 589 } |
459 } | 590 } |
460 } else if (!type->IsBitset()) { | 591 } else if (!type->IsBitset()) { |
461 // For all structural types, subtyping implies equivalence. | |
462 ASSERT(type->IsClass() || type->IsConstant() || | 592 ASSERT(type->IsClass() || type->IsConstant() || |
463 type->IsArray() || type->IsFunction()); | 593 type->IsArray() || type->IsFunction()); |
464 if (!type->InUnion(result, old_size)) { | 594 int inherent_bound = type->InherentBitsetLub(); |
465 result->Set(current_size++, type); | 595 int old_bound = type->BitsetLub(); |
| 596 int other_bound = type->BoundBy(other->unhandle()) & inherent_bound; |
| 597 int new_bound = |
| 598 is_intersect ? (old_bound & other_bound) : (old_bound | other_bound); |
| 599 if (new_bound != BitsetType::kNone) { |
| 600 int i = type->IndexInUnion(new_bound, result, old_size); |
| 601 if (i == -1) { |
| 602 i = size++; |
| 603 } else if (result->Get(i)->IsBitset()) { |
| 604 return size; // Already fully subsumed. |
| 605 } else { |
| 606 int type_i_bound = result->Get(i)->BitsetLub(); |
| 607 new_bound |= type_i_bound; |
| 608 if (new_bound == type_i_bound) return size; |
| 609 } |
| 610 if (new_bound != old_bound) type = type->Narrow(new_bound, region); |
| 611 result->Set(i, type); |
466 } | 612 } |
467 } | 613 } |
468 return current_size; | 614 return size; |
469 } | 615 } |
470 | 616 |
471 | 617 |
472 // Union is O(1) on simple bit unions, but O(n*m) on structured unions. | 618 // If bitset is subsumed by another entry in the result, remove it. |
| 619 // (Only bitsets with empty semantic axis can be subtypes of non-bitsets.) |
| 620 template<class Config> |
| 621 int TypeImpl<Config>::NormalizeUnion(UnionHandle result, int size, int bitset) { |
| 622 if (bitset != BitsetType::kNone && SEMANTIC(bitset) == BitsetType::kNone) { |
| 623 for (int i = 1; i < size; ++i) { |
| 624 int glb = result->Get(i)->BitsetGlb(); |
| 625 if ((bitset | glb) == glb) { |
| 626 for (int j = 1; j < size; ++j) { |
| 627 result->Set(j - 1, result->Get(j)); |
| 628 } |
| 629 --size; |
| 630 break; |
| 631 } |
| 632 } |
| 633 } |
| 634 return size; |
| 635 } |
| 636 |
| 637 |
| 638 // Union is O(1) on simple bitsets, but O(n*m) on structured unions. |
473 template<class Config> | 639 template<class Config> |
474 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union( | 640 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union( |
475 TypeHandle type1, TypeHandle type2, Region* region) { | 641 TypeHandle type1, TypeHandle type2, Region* region) { |
476 // Fast case: bit sets. | 642 // Fast case: bit sets. |
477 if (type1->IsBitset() && type2->IsBitset()) { | 643 if (type1->IsBitset() && type2->IsBitset()) { |
478 return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region); | 644 return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region); |
479 } | 645 } |
480 | 646 |
481 // Fast case: top or bottom types. | 647 // Fast case: top or bottom types. |
482 if (type1->IsAny() || type2->IsNone()) return type1; | 648 if (type1->IsAny() || type2->IsNone()) return type1; |
(...skipping 15 matching lines...) Expand all Loading... |
498 } | 664 } |
499 int bitset = type1->BitsetGlb() | type2->BitsetGlb(); | 665 int bitset = type1->BitsetGlb() | type2->BitsetGlb(); |
500 if (bitset != BitsetType::kNone) ++size; | 666 if (bitset != BitsetType::kNone) ++size; |
501 ASSERT(size >= 1); | 667 ASSERT(size >= 1); |
502 | 668 |
503 UnionHandle unioned = UnionType::New(size, region); | 669 UnionHandle unioned = UnionType::New(size, region); |
504 size = 0; | 670 size = 0; |
505 if (bitset != BitsetType::kNone) { | 671 if (bitset != BitsetType::kNone) { |
506 unioned->Set(size++, BitsetType::New(bitset, region)); | 672 unioned->Set(size++, BitsetType::New(bitset, region)); |
507 } | 673 } |
508 size = ExtendUnion(unioned, type1, size); | 674 size = ExtendUnion(unioned, size, type1, type2, false, region); |
509 size = ExtendUnion(unioned, type2, size); | 675 size = ExtendUnion(unioned, size, type2, type1, false, region); |
| 676 size = NormalizeUnion(unioned, size, bitset); |
510 | 677 |
511 if (size == 1) { | 678 if (size == 1) { |
512 return unioned->Get(0); | 679 return unioned->Get(0); |
513 } else { | 680 } else { |
514 unioned->Shrink(size); | 681 unioned->Shrink(size); |
| 682 ASSERT(unioned->Wellformed()); |
515 return unioned; | 683 return unioned; |
516 } | 684 } |
517 } | 685 } |
518 | 686 |
519 | 687 |
520 // Get non-bitsets from type which are also in other, store at result, | 688 // Intersection is O(1) on simple bitsets, but O(n*m) on structured unions. |
521 // starting at index. Returns updated index. | |
522 template<class Config> | |
523 int TypeImpl<Config>::ExtendIntersection( | |
524 UnionHandle result, TypeHandle type, TypeHandle other, int current_size) { | |
525 int old_size = current_size; | |
526 if (type->IsUnion()) { | |
527 UnionHandle unioned = handle(type->AsUnion()); | |
528 for (int i = 0; i < unioned->Length(); ++i) { | |
529 TypeHandle type = unioned->Get(i); | |
530 ASSERT(i == 0 || !(type->IsBitset() || type->Is(unioned->Get(0)))); | |
531 if (!type->IsBitset() && type->Is(other) && | |
532 !type->InUnion(result, old_size)) { | |
533 result->Set(current_size++, type); | |
534 } | |
535 } | |
536 } else if (!type->IsBitset()) { | |
537 // For all structural types, subtyping implies equivalence. | |
538 ASSERT(type->IsClass() || type->IsConstant() || | |
539 type->IsArray() || type->IsFunction()); | |
540 if (type->Is(other) && !type->InUnion(result, old_size)) { | |
541 result->Set(current_size++, type); | |
542 } | |
543 } | |
544 return current_size; | |
545 } | |
546 | |
547 | |
548 // Intersection is O(1) on simple bit unions, but O(n*m) on structured unions. | |
549 template<class Config> | 689 template<class Config> |
550 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect( | 690 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect( |
551 TypeHandle type1, TypeHandle type2, Region* region) { | 691 TypeHandle type1, TypeHandle type2, Region* region) { |
552 // Fast case: bit sets. | 692 // Fast case: bit sets. |
553 if (type1->IsBitset() && type2->IsBitset()) { | 693 if (type1->IsBitset() && type2->IsBitset()) { |
554 return BitsetType::New(type1->AsBitset() & type2->AsBitset(), region); | 694 return BitsetType::New(type1->AsBitset() & type2->AsBitset(), region); |
555 } | 695 } |
556 | 696 |
557 // Fast case: top or bottom types. | 697 // Fast case: top or bottom types. |
558 if (type1->IsNone() || type2->IsAny()) return type1; | 698 if (type1->IsNone() || type2->IsAny()) return type1; |
(...skipping 15 matching lines...) Expand all Loading... |
574 } | 714 } |
575 int bitset = type1->BitsetGlb() & type2->BitsetGlb(); | 715 int bitset = type1->BitsetGlb() & type2->BitsetGlb(); |
576 if (bitset != BitsetType::kNone) ++size; | 716 if (bitset != BitsetType::kNone) ++size; |
577 ASSERT(size >= 1); | 717 ASSERT(size >= 1); |
578 | 718 |
579 UnionHandle unioned = UnionType::New(size, region); | 719 UnionHandle unioned = UnionType::New(size, region); |
580 size = 0; | 720 size = 0; |
581 if (bitset != BitsetType::kNone) { | 721 if (bitset != BitsetType::kNone) { |
582 unioned->Set(size++, BitsetType::New(bitset, region)); | 722 unioned->Set(size++, BitsetType::New(bitset, region)); |
583 } | 723 } |
584 size = ExtendIntersection(unioned, type1, type2, size); | 724 size = ExtendUnion(unioned, size, type1, type2, true, region); |
585 size = ExtendIntersection(unioned, type2, type1, size); | 725 size = ExtendUnion(unioned, size, type2, type1, true, region); |
| 726 size = NormalizeUnion(unioned, size, bitset); |
586 | 727 |
587 if (size == 0) { | 728 if (size == 0) { |
588 return None(region); | 729 return None(region); |
589 } else if (size == 1) { | 730 } else if (size == 1) { |
590 return unioned->Get(0); | 731 return unioned->Get(0); |
591 } else { | 732 } else { |
592 unioned->Shrink(size); | 733 unioned->Shrink(size); |
| 734 ASSERT(unioned->Wellformed()); |
593 return unioned; | 735 return unioned; |
594 } | 736 } |
595 } | 737 } |
596 | 738 |
597 | 739 |
598 template<class Config> | 740 template<class Config> |
599 template<class OtherType> | 741 template<class OtherType> |
600 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert( | 742 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert( |
601 typename OtherType::TypeHandle type, Region* region) { | 743 typename OtherType::TypeHandle type, Region* region) { |
602 if (type->IsBitset()) { | 744 if (type->IsBitset()) { |
603 return BitsetType::New(type->AsBitset(), region); | 745 return BitsetType::New(type->AsBitset(), region); |
604 } else if (type->IsClass()) { | 746 } else if (type->IsClass()) { |
605 return ClassType::New(type->AsClass()->Map(), region); | 747 return ClassType::New( |
| 748 type->AsClass()->Map(), |
| 749 BitsetType::New(type->BitsetLub(), region), region); |
606 } else if (type->IsConstant()) { | 750 } else if (type->IsConstant()) { |
607 return ConstantType::New(type->AsConstant()->Value(), region); | 751 return ConstantType::New( |
| 752 type->AsConstant()->Value(), |
| 753 Convert<OtherType>(type->AsConstant()->Bound(), region), region); |
608 } else if (type->IsUnion()) { | 754 } else if (type->IsUnion()) { |
609 int length = type->AsUnion()->Length(); | 755 int length = type->AsUnion()->Length(); |
610 UnionHandle unioned = UnionType::New(length, region); | 756 UnionHandle unioned = UnionType::New(length, region); |
611 for (int i = 0; i < length; ++i) { | 757 for (int i = 0; i < length; ++i) { |
612 unioned->Set(i, Convert<OtherType>(type->AsUnion()->Get(i), region)); | 758 unioned->Set(i, Convert<OtherType>(type->AsUnion()->Get(i), region)); |
613 } | 759 } |
614 return unioned; | 760 return unioned; |
615 } else if (type->IsArray()) { | 761 } else if (type->IsArray()) { |
616 return ArrayType::New( | 762 return ArrayType::New( |
617 Convert<OtherType>(type->AsArray()->Element(), region), region); | 763 Convert<OtherType>(type->AsArray()->Element(), region), |
| 764 Convert<OtherType>(type->AsArray()->Bound(), region), region); |
618 } else if (type->IsFunction()) { | 765 } else if (type->IsFunction()) { |
619 FunctionHandle function = FunctionType::New( | 766 FunctionHandle function = FunctionType::New( |
620 Convert<OtherType>(type->AsFunction()->Result(), region), | 767 Convert<OtherType>(type->AsFunction()->Result(), region), |
621 Convert<OtherType>(type->AsFunction()->Receiver(), region), | 768 Convert<OtherType>(type->AsFunction()->Receiver(), region), |
| 769 Convert<OtherType>(type->AsFunction()->Bound(), region), |
622 type->AsFunction()->Arity(), region); | 770 type->AsFunction()->Arity(), region); |
623 for (int i = 0; i < function->Arity(); ++i) { | 771 for (int i = 0; i < function->Arity(); ++i) { |
624 function->InitParameter(i, | 772 function->InitParameter(i, |
625 Convert<OtherType>(type->AsFunction()->Parameter(i), region)); | 773 Convert<OtherType>(type->AsFunction()->Parameter(i), region)); |
626 } | 774 } |
627 return function; | 775 return function; |
628 } else { | 776 } else { |
629 UNREACHABLE(); | 777 UNREACHABLE(); |
630 return None(region); | 778 return None(region); |
631 } | 779 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
701 } | 849 } |
702 ASSERT(bitset == 0); | 850 ASSERT(bitset == 0); |
703 PrintF(out, ")"); | 851 PrintF(out, ")"); |
704 } | 852 } |
705 } | 853 } |
706 | 854 |
707 | 855 |
708 template<class Config> | 856 template<class Config> |
709 void TypeImpl<Config>::TypePrint(FILE* out, PrintDimension dim) { | 857 void TypeImpl<Config>::TypePrint(FILE* out, PrintDimension dim) { |
710 DisallowHeapAllocation no_allocation; | 858 DisallowHeapAllocation no_allocation; |
711 if (this->IsBitset()) { | 859 if (dim != REPRESENTATION_DIM) { |
712 int bitset = this->AsBitset(); | 860 if (this->IsBitset()) { |
713 switch (dim) { | 861 BitsetType::BitsetTypePrint(out, SEMANTIC(this->AsBitset())); |
714 case BOTH_DIMS: | 862 } else if (this->IsConstant()) { |
715 BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic); | 863 PrintF(out, "Constant(%p : ", |
716 PrintF(out, "/"); | 864 static_cast<void*>(*this->AsConstant()->Value())); |
717 BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation); | 865 BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim); |
718 break; | 866 PrintF(out, ")"); |
719 case SEMANTIC_DIM: | 867 return; |
720 BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic); | 868 } else if (this->IsClass()) { |
721 break; | 869 PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()->Map())); |
722 case REPRESENTATION_DIM: | 870 BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim); |
723 BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation); | 871 PrintF(out, ")"); |
724 break; | 872 return; |
| 873 } else if (this->IsUnion()) { |
| 874 PrintF(out, "("); |
| 875 UnionHandle unioned = handle(this->AsUnion()); |
| 876 for (int i = 0; i < unioned->Length(); ++i) { |
| 877 TypeHandle type_i = unioned->Get(i); |
| 878 if (i > 0) PrintF(out, " | "); |
| 879 type_i->TypePrint(out, dim); |
| 880 } |
| 881 PrintF(out, ")"); |
| 882 return; |
| 883 } else if (this->IsArray()) { |
| 884 PrintF(out, "Array("); |
| 885 AsArray()->Element()->TypePrint(out, dim); |
| 886 PrintF(out, ")"); |
| 887 } else if (this->IsFunction()) { |
| 888 if (!this->AsFunction()->Receiver()->IsAny()) { |
| 889 this->AsFunction()->Receiver()->TypePrint(out, dim); |
| 890 PrintF(out, "."); |
| 891 } |
| 892 PrintF(out, "("); |
| 893 for (int i = 0; i < this->AsFunction()->Arity(); ++i) { |
| 894 if (i > 0) PrintF(out, ", "); |
| 895 this->AsFunction()->Parameter(i)->TypePrint(out, dim); |
| 896 } |
| 897 PrintF(out, ")->"); |
| 898 this->AsFunction()->Result()->TypePrint(out, dim); |
| 899 } else { |
| 900 UNREACHABLE(); |
725 } | 901 } |
726 } else if (this->IsConstant()) { | 902 } |
727 PrintF(out, "Constant(%p : ", | 903 if (dim == BOTH_DIMS) { |
728 static_cast<void*>(*this->AsConstant()->Value())); | 904 PrintF(out, "/"); |
729 BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim); | 905 } |
730 PrintF(out, ")"); | 906 if (dim != SEMANTIC_DIM) { |
731 } else if (this->IsClass()) { | 907 BitsetType::BitsetTypePrint(out, REPRESENTATION(this->BitsetLub())); |
732 PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()->Map())); | |
733 BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim); | |
734 PrintF(out, ")"); | |
735 } else if (this->IsUnion()) { | |
736 PrintF(out, "("); | |
737 UnionHandle unioned = handle(this->AsUnion()); | |
738 for (int i = 0; i < unioned->Length(); ++i) { | |
739 TypeHandle type_i = unioned->Get(i); | |
740 if (i > 0) PrintF(out, " | "); | |
741 type_i->TypePrint(out, dim); | |
742 } | |
743 PrintF(out, ")"); | |
744 } else if (this->IsArray()) { | |
745 PrintF(out, "["); | |
746 AsArray()->Element()->TypePrint(out, dim); | |
747 PrintF(out, "]"); | |
748 } else if (this->IsFunction()) { | |
749 if (!this->AsFunction()->Receiver()->IsAny()) { | |
750 this->AsFunction()->Receiver()->TypePrint(out, dim); | |
751 PrintF(out, "."); | |
752 } | |
753 PrintF(out, "("); | |
754 for (int i = 0; i < this->AsFunction()->Arity(); ++i) { | |
755 if (i > 0) PrintF(out, ", "); | |
756 this->AsFunction()->Parameter(i)->TypePrint(out, dim); | |
757 } | |
758 PrintF(out, ")->"); | |
759 this->AsFunction()->Result()->TypePrint(out, dim); | |
760 } else { | |
761 UNREACHABLE(); | |
762 } | 908 } |
763 } | 909 } |
764 | 910 |
765 | 911 |
766 template class TypeImpl<ZoneTypeConfig>; | 912 template class TypeImpl<ZoneTypeConfig>; |
767 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Map>; | 913 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Map>; |
768 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Object>; | 914 template class TypeImpl<ZoneTypeConfig>::Iterator<i::Object>; |
769 | 915 |
770 template class TypeImpl<HeapTypeConfig>; | 916 template class TypeImpl<HeapTypeConfig>; |
771 template class TypeImpl<HeapTypeConfig>::Iterator<i::Map>; | 917 template class TypeImpl<HeapTypeConfig>::Iterator<i::Map>; |
772 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; | 918 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>; |
773 | 919 |
774 template TypeImpl<ZoneTypeConfig>::TypeHandle | 920 template TypeImpl<ZoneTypeConfig>::TypeHandle |
775 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( | 921 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( |
776 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); | 922 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); |
777 template TypeImpl<HeapTypeConfig>::TypeHandle | 923 template TypeImpl<HeapTypeConfig>::TypeHandle |
778 TypeImpl<HeapTypeConfig>::Convert<Type>( | 924 TypeImpl<HeapTypeConfig>::Convert<Type>( |
779 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); | 925 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); |
780 | 926 |
781 } } // namespace v8::internal | 927 } } // namespace v8::internal |
OLD | NEW |