| 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 |