| 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 <iomanip> | 5 #include <iomanip> |
| 6 | 6 |
| 7 #include "src/compiler/types.h" | 7 #include "src/compiler/types.h" |
| 8 | 8 |
| 9 #include "src/handles-inl.h" | 9 #include "src/handles-inl.h" |
| 10 #include "src/ostreams.h" | 10 #include "src/ostreams.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 bool Type::Contains(RangeType* range, i::Object* val) { | 65 bool Type::Contains(RangeType* range, i::Object* val) { |
| 66 DisallowHeapAllocation no_allocation; | 66 DisallowHeapAllocation no_allocation; |
| 67 return IsInteger(val) && range->Min() <= val->Number() && | 67 return IsInteger(val) && range->Min() <= val->Number() && |
| 68 val->Number() <= range->Max(); | 68 val->Number() <= range->Max(); |
| 69 } | 69 } |
| 70 | 70 |
| 71 // ----------------------------------------------------------------------------- | 71 // ----------------------------------------------------------------------------- |
| 72 // Min and Max computation. | 72 // Min and Max computation. |
| 73 | 73 |
| 74 double Type::Min() { | 74 double Type::Min() { |
| 75 DCHECK(this->SemanticIs(Number())); | 75 DCHECK(this->Is(Number())); |
| 76 if (this->IsBitset()) return BitsetType::Min(this->AsBitset()); | 76 if (this->IsBitset()) return BitsetType::Min(this->AsBitset()); |
| 77 if (this->IsUnion()) { | 77 if (this->IsUnion()) { |
| 78 double min = +V8_INFINITY; | 78 double min = +V8_INFINITY; |
| 79 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 79 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { |
| 80 min = std::min(min, this->AsUnion()->Get(i)->Min()); | 80 min = std::min(min, this->AsUnion()->Get(i)->Min()); |
| 81 } | 81 } |
| 82 return min; | 82 return min; |
| 83 } | 83 } |
| 84 if (this->IsRange()) return this->AsRange()->Min(); | 84 if (this->IsRange()) return this->AsRange()->Min(); |
| 85 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); | 85 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); |
| 86 UNREACHABLE(); | 86 UNREACHABLE(); |
| 87 return 0; | 87 return 0; |
| 88 } | 88 } |
| 89 | 89 |
| 90 double Type::Max() { | 90 double Type::Max() { |
| 91 DCHECK(this->SemanticIs(Number())); | 91 DCHECK(this->Is(Number())); |
| 92 if (this->IsBitset()) return BitsetType::Max(this->AsBitset()); | 92 if (this->IsBitset()) return BitsetType::Max(this->AsBitset()); |
| 93 if (this->IsUnion()) { | 93 if (this->IsUnion()) { |
| 94 double max = -V8_INFINITY; | 94 double max = -V8_INFINITY; |
| 95 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 95 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { |
| 96 max = std::max(max, this->AsUnion()->Get(i)->Max()); | 96 max = std::max(max, this->AsUnion()->Get(i)->Max()); |
| 97 } | 97 } |
| 98 return max; | 98 return max; |
| 99 } | 99 } |
| 100 if (this->IsRange()) return this->AsRange()->Max(); | 100 if (this->IsRange()) return this->AsRange()->Max(); |
| 101 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); | 101 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); |
| 102 UNREACHABLE(); | 102 UNREACHABLE(); |
| 103 return 0; | 103 return 0; |
| 104 } | 104 } |
| 105 | 105 |
| 106 // ----------------------------------------------------------------------------- | 106 // ----------------------------------------------------------------------------- |
| 107 // Glb and lub computation. | 107 // Glb and lub computation. |
| 108 | 108 |
| 109 // The largest bitset subsumed by this type. | 109 // The largest bitset subsumed by this type. |
| 110 Type::bitset BitsetType::Glb(Type* type) { | 110 Type::bitset BitsetType::Glb(Type* type) { |
| 111 DisallowHeapAllocation no_allocation; | 111 DisallowHeapAllocation no_allocation; |
| 112 // Fast case. | 112 // Fast case. |
| 113 if (IsBitset(type)) { | 113 if (IsBitset(type)) { |
| 114 return type->AsBitset(); | 114 return type->AsBitset(); |
| 115 } else if (type->IsUnion()) { | 115 } else if (type->IsUnion()) { |
| 116 SLOW_DCHECK(type->AsUnion()->Wellformed()); | 116 SLOW_DCHECK(type->AsUnion()->Wellformed()); |
| 117 return type->AsUnion()->Get(0)->BitsetGlb() | | 117 return type->AsUnion()->Get(0)->BitsetGlb() | |
| 118 SEMANTIC(type->AsUnion()->Get(1)->BitsetGlb()); // Shortcut. | 118 type->AsUnion()->Get(1)->BitsetGlb(); // Shortcut. |
| 119 } else if (type->IsRange()) { | 119 } else if (type->IsRange()) { |
| 120 bitset glb = SEMANTIC( | 120 bitset glb = |
| 121 BitsetType::Glb(type->AsRange()->Min(), type->AsRange()->Max())); | 121 BitsetType::Glb(type->AsRange()->Min(), type->AsRange()->Max()); |
| 122 return glb; | 122 return glb; |
| 123 } else { | 123 } else { |
| 124 return kNone; | 124 return kNone; |
| 125 } | 125 } |
| 126 } | 126 } |
| 127 | 127 |
| 128 // The smallest bitset subsuming this type, possibly not a proper one. | 128 // The smallest bitset subsuming this type, possibly not a proper one. |
| 129 Type::bitset BitsetType::Lub(Type* type) { | 129 Type::bitset BitsetType::Lub(Type* type) { |
| 130 DisallowHeapAllocation no_allocation; | 130 DisallowHeapAllocation no_allocation; |
| 131 if (IsBitset(type)) return type->AsBitset(); | 131 if (IsBitset(type)) return type->AsBitset(); |
| 132 if (type->IsUnion()) { | 132 if (type->IsUnion()) { |
| 133 // Take the representation from the first element, which is always | 133 // Take the representation from the first element, which is always |
| 134 // a bitset. | 134 // a bitset. |
| 135 int bitset = type->AsUnion()->Get(0)->BitsetLub(); | 135 int bitset = type->AsUnion()->Get(0)->BitsetLub(); |
| 136 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { | 136 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { |
| 137 // Other elements only contribute their semantic part. | 137 // Other elements only contribute their semantic part. |
| 138 bitset |= SEMANTIC(type->AsUnion()->Get(i)->BitsetLub()); | 138 bitset |= type->AsUnion()->Get(i)->BitsetLub(); |
| 139 } | 139 } |
| 140 return bitset; | 140 return bitset; |
| 141 } | 141 } |
| 142 if (type->IsConstant()) return type->AsConstant()->Lub(); | 142 if (type->IsConstant()) return type->AsConstant()->Lub(); |
| 143 if (type->IsRange()) return type->AsRange()->Lub(); | 143 if (type->IsRange()) return type->AsRange()->Lub(); |
| 144 if (type->IsTuple()) return kOtherInternal; | 144 if (type->IsTuple()) return kOtherInternal; |
| 145 UNREACHABLE(); | 145 UNREACHABLE(); |
| 146 return kNone; | 146 return kNone; |
| 147 } | 147 } |
| 148 | 148 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 const BitsetType::Boundary* BitsetType::Boundaries() { return BoundariesArray; } | 308 const BitsetType::Boundary* BitsetType::Boundaries() { return BoundariesArray; } |
| 309 | 309 |
| 310 size_t BitsetType::BoundariesSize() { | 310 size_t BitsetType::BoundariesSize() { |
| 311 // Windows doesn't like arraysize here. | 311 // Windows doesn't like arraysize here. |
| 312 // return arraysize(BoundariesArray); | 312 // return arraysize(BoundariesArray); |
| 313 return 7; | 313 return 7; |
| 314 } | 314 } |
| 315 | 315 |
| 316 Type::bitset BitsetType::ExpandInternals(Type::bitset bits) { | 316 Type::bitset BitsetType::ExpandInternals(Type::bitset bits) { |
| 317 DisallowHeapAllocation no_allocation; | 317 DisallowHeapAllocation no_allocation; |
| 318 if (!(bits & SEMANTIC(kPlainNumber))) return bits; // Shortcut. | 318 if (!(bits & kPlainNumber)) return bits; // Shortcut. |
| 319 const Boundary* boundaries = Boundaries(); | 319 const Boundary* boundaries = Boundaries(); |
| 320 for (size_t i = 0; i < BoundariesSize(); ++i) { | 320 for (size_t i = 0; i < BoundariesSize(); ++i) { |
| 321 DCHECK(BitsetType::Is(boundaries[i].internal, boundaries[i].external)); | 321 DCHECK(BitsetType::Is(boundaries[i].internal, boundaries[i].external)); |
| 322 if (bits & SEMANTIC(boundaries[i].internal)) | 322 if (bits & boundaries[i].internal) bits |= boundaries[i].external; |
| 323 bits |= SEMANTIC(boundaries[i].external); | |
| 324 } | 323 } |
| 325 return bits; | 324 return bits; |
| 326 } | 325 } |
| 327 | 326 |
| 328 Type::bitset BitsetType::Lub(double min, double max) { | 327 Type::bitset BitsetType::Lub(double min, double max) { |
| 329 DisallowHeapAllocation no_allocation; | 328 DisallowHeapAllocation no_allocation; |
| 330 int lub = kNone; | 329 int lub = kNone; |
| 331 const Boundary* mins = Boundaries(); | 330 const Boundary* mins = Boundaries(); |
| 332 | 331 |
| 333 for (size_t i = 1; i < BoundariesSize(); ++i) { | 332 for (size_t i = 1; i < BoundariesSize(); ++i) { |
| 334 if (min < mins[i].min) { | 333 if (min < mins[i].min) { |
| 335 lub |= mins[i - 1].internal; | 334 lub |= mins[i - 1].internal; |
| 336 if (max < mins[i].min) return lub; | 335 if (max < mins[i].min) return lub; |
| 337 } | 336 } |
| 338 } | 337 } |
| 339 return lub | mins[BoundariesSize() - 1].internal; | 338 return lub | mins[BoundariesSize() - 1].internal; |
| 340 } | 339 } |
| 341 | 340 |
| 342 Type::bitset BitsetType::NumberBits(bitset bits) { | 341 Type::bitset BitsetType::NumberBits(bitset bits) { return bits & kPlainNumber; } |
| 343 return SEMANTIC(bits & kPlainNumber); | |
| 344 } | |
| 345 | 342 |
| 346 Type::bitset BitsetType::Glb(double min, double max) { | 343 Type::bitset BitsetType::Glb(double min, double max) { |
| 347 DisallowHeapAllocation no_allocation; | 344 DisallowHeapAllocation no_allocation; |
| 348 int glb = kNone; | 345 int glb = kNone; |
| 349 const Boundary* mins = Boundaries(); | 346 const Boundary* mins = Boundaries(); |
| 350 | 347 |
| 351 // If the range does not touch 0, the bound is empty. | 348 // If the range does not touch 0, the bound is empty. |
| 352 if (max < -1 || min > 0) return glb; | 349 if (max < -1 || min > 0) return glb; |
| 353 | 350 |
| 354 for (size_t i = 1; i + 1 < BoundariesSize(); ++i) { | 351 for (size_t i = 1; i + 1 < BoundariesSize(); ++i) { |
| 355 if (min <= mins[i].min) { | 352 if (min <= mins[i].min) { |
| 356 if (max + 1 < mins[i + 1].min) break; | 353 if (max + 1 < mins[i + 1].min) break; |
| 357 glb |= mins[i].external; | 354 glb |= mins[i].external; |
| 358 } | 355 } |
| 359 } | 356 } |
| 360 // OtherNumber also contains float numbers, so it can never be | 357 // OtherNumber also contains float numbers, so it can never be |
| 361 // in the greatest lower bound. | 358 // in the greatest lower bound. |
| 362 return glb & ~(SEMANTIC(kOtherNumber)); | 359 return glb & ~(kOtherNumber); |
| 363 } | 360 } |
| 364 | 361 |
| 365 double BitsetType::Min(bitset bits) { | 362 double BitsetType::Min(bitset bits) { |
| 366 DisallowHeapAllocation no_allocation; | 363 DisallowHeapAllocation no_allocation; |
| 367 DCHECK(Is(SEMANTIC(bits), kNumber)); | 364 DCHECK(Is(bits, kNumber)); |
| 368 const Boundary* mins = Boundaries(); | 365 const Boundary* mins = Boundaries(); |
| 369 bool mz = SEMANTIC(bits & kMinusZero); | 366 bool mz = bits & kMinusZero; |
| 370 for (size_t i = 0; i < BoundariesSize(); ++i) { | 367 for (size_t i = 0; i < BoundariesSize(); ++i) { |
| 371 if (Is(SEMANTIC(mins[i].internal), bits)) { | 368 if (Is(mins[i].internal, bits)) { |
| 372 return mz ? std::min(0.0, mins[i].min) : mins[i].min; | 369 return mz ? std::min(0.0, mins[i].min) : mins[i].min; |
| 373 } | 370 } |
| 374 } | 371 } |
| 375 if (mz) return 0; | 372 if (mz) return 0; |
| 376 return std::numeric_limits<double>::quiet_NaN(); | 373 return std::numeric_limits<double>::quiet_NaN(); |
| 377 } | 374 } |
| 378 | 375 |
| 379 double BitsetType::Max(bitset bits) { | 376 double BitsetType::Max(bitset bits) { |
| 380 DisallowHeapAllocation no_allocation; | 377 DisallowHeapAllocation no_allocation; |
| 381 DCHECK(Is(SEMANTIC(bits), kNumber)); | 378 DCHECK(Is(bits, kNumber)); |
| 382 const Boundary* mins = Boundaries(); | 379 const Boundary* mins = Boundaries(); |
| 383 bool mz = SEMANTIC(bits & kMinusZero); | 380 bool mz = bits & kMinusZero; |
| 384 if (BitsetType::Is(SEMANTIC(mins[BoundariesSize() - 1].internal), bits)) { | 381 if (BitsetType::Is(mins[BoundariesSize() - 1].internal, bits)) { |
| 385 return +V8_INFINITY; | 382 return +V8_INFINITY; |
| 386 } | 383 } |
| 387 for (size_t i = BoundariesSize() - 1; i-- > 0;) { | 384 for (size_t i = BoundariesSize() - 1; i-- > 0;) { |
| 388 if (Is(SEMANTIC(mins[i].internal), bits)) { | 385 if (Is(mins[i].internal, bits)) { |
| 389 return mz ? std::max(0.0, mins[i + 1].min - 1) : mins[i + 1].min - 1; | 386 return mz ? std::max(0.0, mins[i + 1].min - 1) : mins[i + 1].min - 1; |
| 390 } | 387 } |
| 391 } | 388 } |
| 392 if (mz) return 0; | 389 if (mz) return 0; |
| 393 return std::numeric_limits<double>::quiet_NaN(); | 390 return std::numeric_limits<double>::quiet_NaN(); |
| 394 } | 391 } |
| 395 | 392 |
| 396 // ----------------------------------------------------------------------------- | 393 // ----------------------------------------------------------------------------- |
| 397 // Predicates. | 394 // Predicates. |
| 398 | 395 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 424 | 421 |
| 425 // Fast bitset cases | 422 // Fast bitset cases |
| 426 if (that->IsBitset()) { | 423 if (that->IsBitset()) { |
| 427 return BitsetType::Is(this->BitsetLub(), that->AsBitset()); | 424 return BitsetType::Is(this->BitsetLub(), that->AsBitset()); |
| 428 } | 425 } |
| 429 | 426 |
| 430 if (this->IsBitset()) { | 427 if (this->IsBitset()) { |
| 431 return BitsetType::Is(this->AsBitset(), that->BitsetGlb()); | 428 return BitsetType::Is(this->AsBitset(), that->BitsetGlb()); |
| 432 } | 429 } |
| 433 | 430 |
| 434 // Check the semantic part. | |
| 435 return SemanticIs(that); | |
| 436 } | |
| 437 | |
| 438 // Check if SEMANTIC([this]) <= SEMANTIC([that]). The result of the method | |
| 439 // should be independent of the representation axis of the types. | |
| 440 bool Type::SemanticIs(Type* that) { | |
| 441 DisallowHeapAllocation no_allocation; | |
| 442 | |
| 443 if (this == that) return true; | |
| 444 | |
| 445 if (that->IsBitset()) { | |
| 446 return BitsetType::Is(SEMANTIC(this->BitsetLub()), that->AsBitset()); | |
| 447 } | |
| 448 if (this->IsBitset()) { | |
| 449 return BitsetType::Is(SEMANTIC(this->AsBitset()), that->BitsetGlb()); | |
| 450 } | |
| 451 | |
| 452 // (T1 \/ ... \/ Tn) <= T if (T1 <= T) /\ ... /\ (Tn <= T) | 431 // (T1 \/ ... \/ Tn) <= T if (T1 <= T) /\ ... /\ (Tn <= T) |
| 453 if (this->IsUnion()) { | 432 if (this->IsUnion()) { |
| 454 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 433 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { |
| 455 if (!this->AsUnion()->Get(i)->SemanticIs(that)) return false; | 434 if (!this->AsUnion()->Get(i)->Is(that)) return false; |
| 456 } | 435 } |
| 457 return true; | 436 return true; |
| 458 } | 437 } |
| 459 | 438 |
| 460 // T <= (T1 \/ ... \/ Tn) if (T <= T1) \/ ... \/ (T <= Tn) | 439 // T <= (T1 \/ ... \/ Tn) if (T <= T1) \/ ... \/ (T <= Tn) |
| 461 if (that->IsUnion()) { | 440 if (that->IsUnion()) { |
| 462 for (int i = 0, n = that->AsUnion()->Length(); i < n; ++i) { | 441 for (int i = 0, n = that->AsUnion()->Length(); i < n; ++i) { |
| 463 if (this->SemanticIs(that->AsUnion()->Get(i))) return true; | 442 if (this->Is(that->AsUnion()->Get(i))) return true; |
| 464 if (i > 1 && this->IsRange()) return false; // Shortcut. | 443 if (i > 1 && this->IsRange()) return false; // Shortcut. |
| 465 } | 444 } |
| 466 return false; | 445 return false; |
| 467 } | 446 } |
| 468 | 447 |
| 469 if (that->IsRange()) { | 448 if (that->IsRange()) { |
| 470 return (this->IsRange() && Contains(that->AsRange(), this->AsRange())) || | 449 return (this->IsRange() && Contains(that->AsRange(), this->AsRange())) || |
| 471 (this->IsConstant() && | 450 (this->IsConstant() && |
| 472 Contains(that->AsRange(), this->AsConstant())); | 451 Contains(that->AsRange(), this->AsConstant())); |
| 473 } | 452 } |
| 474 if (this->IsRange()) return false; | 453 if (this->IsRange()) return false; |
| 475 | 454 |
| 476 return this->SimplyEquals(that); | 455 return this->SimplyEquals(that); |
| 477 } | 456 } |
| 478 | 457 |
| 479 // Check if [this] and [that] overlap. | 458 // Check if [this] and [that] overlap. |
| 480 bool Type::Maybe(Type* that) { | 459 bool Type::Maybe(Type* that) { |
| 481 DisallowHeapAllocation no_allocation; | 460 DisallowHeapAllocation no_allocation; |
| 482 | 461 |
| 483 // Take care of the representation part (and also approximate | |
| 484 // the semantic part). | |
| 485 if (!BitsetType::IsInhabited(this->BitsetLub() & that->BitsetLub())) | 462 if (!BitsetType::IsInhabited(this->BitsetLub() & that->BitsetLub())) |
| 486 return false; | 463 return false; |
| 487 | 464 |
| 488 return SemanticMaybe(that); | |
| 489 } | |
| 490 | |
| 491 bool Type::SemanticMaybe(Type* that) { | |
| 492 DisallowHeapAllocation no_allocation; | |
| 493 | |
| 494 // (T1 \/ ... \/ Tn) overlaps T if (T1 overlaps T) \/ ... \/ (Tn overlaps T) | 465 // (T1 \/ ... \/ Tn) overlaps T if (T1 overlaps T) \/ ... \/ (Tn overlaps T) |
| 495 if (this->IsUnion()) { | 466 if (this->IsUnion()) { |
| 496 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 467 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { |
| 497 if (this->AsUnion()->Get(i)->SemanticMaybe(that)) return true; | 468 if (this->AsUnion()->Get(i)->Maybe(that)) return true; |
| 498 } | 469 } |
| 499 return false; | 470 return false; |
| 500 } | 471 } |
| 501 | 472 |
| 502 // T overlaps (T1 \/ ... \/ Tn) if (T overlaps T1) \/ ... \/ (T overlaps Tn) | 473 // T overlaps (T1 \/ ... \/ Tn) if (T overlaps T1) \/ ... \/ (T overlaps Tn) |
| 503 if (that->IsUnion()) { | 474 if (that->IsUnion()) { |
| 504 for (int i = 0, n = that->AsUnion()->Length(); i < n; ++i) { | 475 for (int i = 0, n = that->AsUnion()->Length(); i < n; ++i) { |
| 505 if (this->SemanticMaybe(that->AsUnion()->Get(i))) return true; | 476 if (this->Maybe(that->AsUnion()->Get(i))) return true; |
| 506 } | 477 } |
| 507 return false; | 478 return false; |
| 508 } | 479 } |
| 509 | 480 |
| 510 if (!BitsetType::SemanticIsInhabited(this->BitsetLub() & that->BitsetLub())) | |
| 511 return false; | |
| 512 | |
| 513 if (this->IsBitset() && that->IsBitset()) return true; | 481 if (this->IsBitset() && that->IsBitset()) return true; |
| 514 | 482 |
| 515 if (this->IsRange()) { | 483 if (this->IsRange()) { |
| 516 if (that->IsConstant()) { | 484 if (that->IsConstant()) { |
| 517 return Contains(this->AsRange(), that->AsConstant()); | 485 return Contains(this->AsRange(), that->AsConstant()); |
| 518 } | 486 } |
| 519 if (that->IsRange()) { | 487 if (that->IsRange()) { |
| 520 return Overlap(this->AsRange(), that->AsRange()); | 488 return Overlap(this->AsRange(), that->AsRange()); |
| 521 } | 489 } |
| 522 if (that->IsBitset()) { | 490 if (that->IsBitset()) { |
| 523 bitset number_bits = BitsetType::NumberBits(that->AsBitset()); | 491 bitset number_bits = BitsetType::NumberBits(that->AsBitset()); |
| 524 if (number_bits == BitsetType::kNone) { | 492 if (number_bits == BitsetType::kNone) { |
| 525 return false; | 493 return false; |
| 526 } | 494 } |
| 527 double min = std::max(BitsetType::Min(number_bits), this->Min()); | 495 double min = std::max(BitsetType::Min(number_bits), this->Min()); |
| 528 double max = std::min(BitsetType::Max(number_bits), this->Max()); | 496 double max = std::min(BitsetType::Max(number_bits), this->Max()); |
| 529 return min <= max; | 497 return min <= max; |
| 530 } | 498 } |
| 531 } | 499 } |
| 532 if (that->IsRange()) { | 500 if (that->IsRange()) { |
| 533 return that->SemanticMaybe(this); // This case is handled above. | 501 return that->Maybe(this); // This case is handled above. |
| 534 } | 502 } |
| 535 | 503 |
| 536 if (this->IsBitset() || that->IsBitset()) return true; | 504 if (this->IsBitset() || that->IsBitset()) return true; |
| 537 | 505 |
| 538 return this->SimplyEquals(that); | 506 return this->SimplyEquals(that); |
| 539 } | 507 } |
| 540 | 508 |
| 541 // Return the range in [this], or [NULL]. | 509 // Return the range in [this], or [NULL]. |
| 542 Type* Type::GetRange() { | 510 Type* Type::GetRange() { |
| 543 DisallowHeapAllocation no_allocation; | 511 DisallowHeapAllocation no_allocation; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 571 // 6. If there is a range, then the bitset type does not contain | 539 // 6. If there is a range, then the bitset type does not contain |
| 572 // plain number bits. | 540 // plain number bits. |
| 573 DCHECK(this->Length() >= 2); // (1) | 541 DCHECK(this->Length() >= 2); // (1) |
| 574 DCHECK(this->Get(0)->IsBitset()); // (2a) | 542 DCHECK(this->Get(0)->IsBitset()); // (2a) |
| 575 | 543 |
| 576 for (int i = 0; i < this->Length(); ++i) { | 544 for (int i = 0; i < this->Length(); ++i) { |
| 577 if (i != 0) DCHECK(!this->Get(i)->IsBitset()); // (2b) | 545 if (i != 0) DCHECK(!this->Get(i)->IsBitset()); // (2b) |
| 578 if (i != 1) DCHECK(!this->Get(i)->IsRange()); // (3) | 546 if (i != 1) DCHECK(!this->Get(i)->IsRange()); // (3) |
| 579 DCHECK(!this->Get(i)->IsUnion()); // (4) | 547 DCHECK(!this->Get(i)->IsUnion()); // (4) |
| 580 for (int j = 0; j < this->Length(); ++j) { | 548 for (int j = 0; j < this->Length(); ++j) { |
| 581 if (i != j && i != 0) | 549 if (i != j && i != 0) DCHECK(!this->Get(i)->Is(this->Get(j))); // (5) |
| 582 DCHECK(!this->Get(i)->SemanticIs(this->Get(j))); // (5) | |
| 583 } | 550 } |
| 584 } | 551 } |
| 585 DCHECK(!this->Get(1)->IsRange() || | 552 DCHECK(!this->Get(1)->IsRange() || |
| 586 (BitsetType::NumberBits(this->Get(0)->AsBitset()) == | 553 (BitsetType::NumberBits(this->Get(0)->AsBitset()) == |
| 587 BitsetType::kNone)); // (6) | 554 BitsetType::kNone)); // (6) |
| 588 return true; | 555 return true; |
| 589 } | 556 } |
| 590 | 557 |
| 591 // ----------------------------------------------------------------------------- | 558 // ----------------------------------------------------------------------------- |
| 592 // Union and intersection | 559 // Union and intersection |
| (...skipping 14 matching lines...) Expand all Loading... |
| 607 if (type2->IsNone() || type1->IsAny()) return type2; // Shortcut. | 574 if (type2->IsNone() || type1->IsAny()) return type2; // Shortcut. |
| 608 | 575 |
| 609 // Semi-fast case. | 576 // Semi-fast case. |
| 610 if (type1->Is(type2)) return type1; | 577 if (type1->Is(type2)) return type1; |
| 611 if (type2->Is(type1)) return type2; | 578 if (type2->Is(type1)) return type2; |
| 612 | 579 |
| 613 // Slow case: create union. | 580 // Slow case: create union. |
| 614 | 581 |
| 615 // Semantic subtyping check - this is needed for consistency with the | 582 // Semantic subtyping check - this is needed for consistency with the |
| 616 // semi-fast case above. | 583 // semi-fast case above. |
| 617 if (type1->SemanticIs(type2)) { | 584 if (type1->Is(type2)) { |
| 618 type2 = Any(); | 585 type2 = Any(); |
| 619 } else if (type2->SemanticIs(type1)) { | 586 } else if (type2->Is(type1)) { |
| 620 type1 = Any(); | 587 type1 = Any(); |
| 621 } | 588 } |
| 622 | 589 |
| 623 bitset bits = SEMANTIC(type1->BitsetGlb() & type2->BitsetGlb()); | 590 bitset bits = type1->BitsetGlb() & type2->BitsetGlb(); |
| 624 int size1 = type1->IsUnion() ? type1->AsUnion()->Length() : 1; | 591 int size1 = type1->IsUnion() ? type1->AsUnion()->Length() : 1; |
| 625 int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1; | 592 int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1; |
| 626 if (!AddIsSafe(size1, size2)) return Any(); | 593 if (!AddIsSafe(size1, size2)) return Any(); |
| 627 int size = size1 + size2; | 594 int size = size1 + size2; |
| 628 if (!AddIsSafe(size, 2)) return Any(); | 595 if (!AddIsSafe(size, 2)) return Any(); |
| 629 size += 2; | 596 size += 2; |
| 630 Type* result_type = UnionType::New(size, zone); | 597 Type* result_type = UnionType::New(size, zone); |
| 631 UnionType* result = result_type->AsUnion(); | 598 UnionType* result = result_type->AsUnion(); |
| 632 size = 0; | 599 size = 0; |
| 633 | 600 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 654 if (size == 1) { | 621 if (size == 1) { |
| 655 result->Set(size++, range); | 622 result->Set(size++, range); |
| 656 } else { | 623 } else { |
| 657 // Make space for the range. | 624 // Make space for the range. |
| 658 result->Set(size++, result->Get(1)); | 625 result->Set(size++, result->Get(1)); |
| 659 result->Set(1, range); | 626 result->Set(1, range); |
| 660 } | 627 } |
| 661 | 628 |
| 662 // Remove any components that just got subsumed. | 629 // Remove any components that just got subsumed. |
| 663 for (int i = 2; i < size;) { | 630 for (int i = 2; i < size;) { |
| 664 if (result->Get(i)->SemanticIs(range)) { | 631 if (result->Get(i)->Is(range)) { |
| 665 result->Set(i, result->Get(--size)); | 632 result->Set(i, result->Get(--size)); |
| 666 } else { | 633 } else { |
| 667 ++i; | 634 ++i; |
| 668 } | 635 } |
| 669 } | 636 } |
| 670 return size; | 637 return size; |
| 671 } | 638 } |
| 672 | 639 |
| 673 RangeType::Limits Type::ToLimits(bitset bits, Zone* zone) { | 640 RangeType::Limits Type::ToLimits(bitset bits, Zone* zone) { |
| 674 bitset number_bits = BitsetType::NumberBits(bits); | 641 bitset number_bits = BitsetType::NumberBits(bits); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 698 return size; | 665 return size; |
| 699 } | 666 } |
| 700 if (rhs->IsUnion()) { | 667 if (rhs->IsUnion()) { |
| 701 for (int i = 0, n = rhs->AsUnion()->Length(); i < n; ++i) { | 668 for (int i = 0, n = rhs->AsUnion()->Length(); i < n; ++i) { |
| 702 size = | 669 size = |
| 703 IntersectAux(lhs, rhs->AsUnion()->Get(i), result, size, lims, zone); | 670 IntersectAux(lhs, rhs->AsUnion()->Get(i), result, size, lims, zone); |
| 704 } | 671 } |
| 705 return size; | 672 return size; |
| 706 } | 673 } |
| 707 | 674 |
| 708 if (!BitsetType::SemanticIsInhabited(lhs->BitsetLub() & rhs->BitsetLub())) { | 675 if (!BitsetType::IsInhabited(lhs->BitsetLub() & rhs->BitsetLub())) { |
| 709 return size; | 676 return size; |
| 710 } | 677 } |
| 711 | 678 |
| 712 if (lhs->IsRange()) { | 679 if (lhs->IsRange()) { |
| 713 if (rhs->IsBitset()) { | 680 if (rhs->IsBitset()) { |
| 714 RangeType::Limits lim = IntersectRangeAndBitset(lhs, rhs, zone); | 681 RangeType::Limits lim = IntersectRangeAndBitset(lhs, rhs, zone); |
| 715 | 682 |
| 716 if (!lim.IsEmpty()) { | 683 if (!lim.IsEmpty()) { |
| 717 *lims = RangeType::Limits::Union(lim, *lims); | 684 *lims = RangeType::Limits::Union(lim, *lims); |
| 718 } | 685 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 Type* Type::NormalizeRangeAndBitset(Type* range, bitset* bits, Zone* zone) { | 717 Type* Type::NormalizeRangeAndBitset(Type* range, bitset* bits, Zone* zone) { |
| 751 // Fast path: If the bitset does not mention numbers, we can just keep the | 718 // Fast path: If the bitset does not mention numbers, we can just keep the |
| 752 // range. | 719 // range. |
| 753 bitset number_bits = BitsetType::NumberBits(*bits); | 720 bitset number_bits = BitsetType::NumberBits(*bits); |
| 754 if (number_bits == 0) { | 721 if (number_bits == 0) { |
| 755 return range; | 722 return range; |
| 756 } | 723 } |
| 757 | 724 |
| 758 // If the range is semantically contained within the bitset, return None and | 725 // If the range is semantically contained within the bitset, return None and |
| 759 // leave the bitset untouched. | 726 // leave the bitset untouched. |
| 760 bitset range_lub = SEMANTIC(range->BitsetLub()); | 727 bitset range_lub = range->BitsetLub(); |
| 761 if (BitsetType::Is(range_lub, *bits)) { | 728 if (BitsetType::Is(range_lub, *bits)) { |
| 762 return None(); | 729 return None(); |
| 763 } | 730 } |
| 764 | 731 |
| 765 // Slow path: reconcile the bitset range and the range. | 732 // Slow path: reconcile the bitset range and the range. |
| 766 double bitset_min = BitsetType::Min(number_bits); | 733 double bitset_min = BitsetType::Min(number_bits); |
| 767 double bitset_max = BitsetType::Max(number_bits); | 734 double bitset_max = BitsetType::Max(number_bits); |
| 768 | 735 |
| 769 double range_min = range->Min(); | 736 double range_min = range->Min(); |
| 770 double range_max = range->Max(); | 737 double range_max = range->Max(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 807 int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1; | 774 int size2 = type2->IsUnion() ? type2->AsUnion()->Length() : 1; |
| 808 if (!AddIsSafe(size1, size2)) return Any(); | 775 if (!AddIsSafe(size1, size2)) return Any(); |
| 809 int size = size1 + size2; | 776 int size = size1 + size2; |
| 810 if (!AddIsSafe(size, 2)) return Any(); | 777 if (!AddIsSafe(size, 2)) return Any(); |
| 811 size += 2; | 778 size += 2; |
| 812 Type* result_type = UnionType::New(size, zone); | 779 Type* result_type = UnionType::New(size, zone); |
| 813 UnionType* result = result_type->AsUnion(); | 780 UnionType* result = result_type->AsUnion(); |
| 814 size = 0; | 781 size = 0; |
| 815 | 782 |
| 816 // Compute the new bitset. | 783 // Compute the new bitset. |
| 817 bitset new_bitset = SEMANTIC(type1->BitsetGlb() | type2->BitsetGlb()); | 784 bitset new_bitset = type1->BitsetGlb() | type2->BitsetGlb(); |
| 818 | 785 |
| 819 // Deal with ranges. | 786 // Deal with ranges. |
| 820 Type* range = None(); | 787 Type* range = None(); |
| 821 Type* range1 = type1->GetRange(); | 788 Type* range1 = type1->GetRange(); |
| 822 Type* range2 = type2->GetRange(); | 789 Type* range2 = type2->GetRange(); |
| 823 if (range1 != NULL && range2 != NULL) { | 790 if (range1 != NULL && range2 != NULL) { |
| 824 RangeType::Limits lims = | 791 RangeType::Limits lims = |
| 825 RangeType::Limits::Union(RangeType::Limits(range1->AsRange()), | 792 RangeType::Limits::Union(RangeType::Limits(range1->AsRange()), |
| 826 RangeType::Limits(range2->AsRange())); | 793 RangeType::Limits(range2->AsRange())); |
| 827 Type* union_range = RangeType::New(lims, zone); | 794 Type* union_range = RangeType::New(lims, zone); |
| 828 range = NormalizeRangeAndBitset(union_range, &new_bitset, zone); | 795 range = NormalizeRangeAndBitset(union_range, &new_bitset, zone); |
| 829 } else if (range1 != NULL) { | 796 } else if (range1 != NULL) { |
| 830 range = NormalizeRangeAndBitset(range1, &new_bitset, zone); | 797 range = NormalizeRangeAndBitset(range1, &new_bitset, zone); |
| 831 } else if (range2 != NULL) { | 798 } else if (range2 != NULL) { |
| 832 range = NormalizeRangeAndBitset(range2, &new_bitset, zone); | 799 range = NormalizeRangeAndBitset(range2, &new_bitset, zone); |
| 833 } | 800 } |
| 834 new_bitset = SEMANTIC(new_bitset); | |
| 835 Type* bits = BitsetType::New(new_bitset); | 801 Type* bits = BitsetType::New(new_bitset); |
| 836 result->Set(size++, bits); | 802 result->Set(size++, bits); |
| 837 if (!range->IsNone()) result->Set(size++, range); | 803 if (!range->IsNone()) result->Set(size++, range); |
| 838 | 804 |
| 839 size = AddToUnion(type1, result, size, zone); | 805 size = AddToUnion(type1, result, size, zone); |
| 840 size = AddToUnion(type2, result, size, zone); | 806 size = AddToUnion(type2, result, size, zone); |
| 841 return NormalizeUnion(result_type, size, zone); | 807 return NormalizeUnion(result_type, size, zone); |
| 842 } | 808 } |
| 843 | 809 |
| 844 // Add [type] to [result] unless [type] is bitset, range, or already subsumed. | 810 // Add [type] to [result] unless [type] is bitset, range, or already subsumed. |
| 845 // Return new size of [result]. | 811 // Return new size of [result]. |
| 846 int Type::AddToUnion(Type* type, UnionType* result, int size, Zone* zone) { | 812 int Type::AddToUnion(Type* type, UnionType* result, int size, Zone* zone) { |
| 847 if (type->IsBitset() || type->IsRange()) return size; | 813 if (type->IsBitset() || type->IsRange()) return size; |
| 848 if (type->IsUnion()) { | 814 if (type->IsUnion()) { |
| 849 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { | 815 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { |
| 850 size = AddToUnion(type->AsUnion()->Get(i), result, size, zone); | 816 size = AddToUnion(type->AsUnion()->Get(i), result, size, zone); |
| 851 } | 817 } |
| 852 return size; | 818 return size; |
| 853 } | 819 } |
| 854 for (int i = 0; i < size; ++i) { | 820 for (int i = 0; i < size; ++i) { |
| 855 if (type->SemanticIs(result->Get(i))) return size; | 821 if (type->Is(result->Get(i))) return size; |
| 856 } | 822 } |
| 857 result->Set(size++, type); | 823 result->Set(size++, type); |
| 858 return size; | 824 return size; |
| 859 } | 825 } |
| 860 | 826 |
| 861 Type* Type::NormalizeUnion(Type* union_type, int size, Zone* zone) { | 827 Type* Type::NormalizeUnion(Type* union_type, int size, Zone* zone) { |
| 862 UnionType* unioned = union_type->AsUnion(); | 828 UnionType* unioned = union_type->AsUnion(); |
| 863 DCHECK(size >= 1); | 829 DCHECK(size >= 1); |
| 864 DCHECK(unioned->Get(0)->IsBitset()); | 830 DCHECK(unioned->Get(0)->IsBitset()); |
| 865 // If the union has just one element, return it. | 831 // If the union has just one element, return it. |
| 866 if (size == 1) { | 832 if (size == 1) { |
| 867 return unioned->Get(0); | 833 return unioned->Get(0); |
| 868 } | 834 } |
| 869 bitset bits = unioned->Get(0)->AsBitset(); | 835 bitset bits = unioned->Get(0)->AsBitset(); |
| 870 // If the union only consists of a range, we can get rid of the union. | 836 // If the union only consists of a range, we can get rid of the union. |
| 871 if (size == 2 && SEMANTIC(bits) == BitsetType::kNone) { | 837 if (size == 2 && bits == BitsetType::kNone) { |
| 872 if (unioned->Get(1)->IsRange()) { | 838 if (unioned->Get(1)->IsRange()) { |
| 873 return RangeType::New(unioned->Get(1)->AsRange()->Min(), | 839 return RangeType::New(unioned->Get(1)->AsRange()->Min(), |
| 874 unioned->Get(1)->AsRange()->Max(), zone); | 840 unioned->Get(1)->AsRange()->Max(), zone); |
| 875 } | 841 } |
| 876 } | 842 } |
| 877 unioned->Shrink(size); | 843 unioned->Shrink(size); |
| 878 SLOW_DCHECK(unioned->Wellformed()); | 844 SLOW_DCHECK(unioned->Wellformed()); |
| 879 return union_type; | 845 return union_type; |
| 880 } | 846 } |
| 881 | 847 |
| 882 // ----------------------------------------------------------------------------- | 848 // ----------------------------------------------------------------------------- |
| 883 // Component extraction | |
| 884 | |
| 885 // static | |
| 886 Type* Type::Semantic(Type* t, Zone* zone) { | |
| 887 return Intersect(t, BitsetType::New(BitsetType::kSemantic), zone); | |
| 888 } | |
| 889 | |
| 890 // ----------------------------------------------------------------------------- | |
| 891 // Iteration. | 849 // Iteration. |
| 892 | 850 |
| 893 int Type::NumConstants() { | 851 int Type::NumConstants() { |
| 894 DisallowHeapAllocation no_allocation; | 852 DisallowHeapAllocation no_allocation; |
| 895 if (this->IsConstant()) { | 853 if (this->IsConstant()) { |
| 896 return 1; | 854 return 1; |
| 897 } else if (this->IsUnion()) { | 855 } else if (this->IsUnion()) { |
| 898 int result = 0; | 856 int result = 0; |
| 899 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 857 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { |
| 900 if (this->AsUnion()->Get(i)->IsConstant()) ++result; | 858 if (this->AsUnion()->Get(i)->IsConstant()) ++result; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 949 return; | 907 return; |
| 950 } | 908 } |
| 951 index_ = -1; | 909 index_ = -1; |
| 952 } | 910 } |
| 953 | 911 |
| 954 // ----------------------------------------------------------------------------- | 912 // ----------------------------------------------------------------------------- |
| 955 // Printing. | 913 // Printing. |
| 956 | 914 |
| 957 const char* BitsetType::Name(bitset bits) { | 915 const char* BitsetType::Name(bitset bits) { |
| 958 switch (bits) { | 916 switch (bits) { |
| 959 #define RETURN_NAMED_SEMANTIC_TYPE(type, value) \ | 917 #define RETURN_NAMED_TYPE(type, value) \ |
| 960 case SEMANTIC(k##type): \ | 918 case k##type: \ |
| 961 return #type; | 919 return #type; |
| 962 SEMANTIC_BITSET_TYPE_LIST(RETURN_NAMED_SEMANTIC_TYPE) | 920 PROPER_BITSET_TYPE_LIST(RETURN_NAMED_TYPE) |
| 963 INTERNAL_BITSET_TYPE_LIST(RETURN_NAMED_SEMANTIC_TYPE) | 921 INTERNAL_BITSET_TYPE_LIST(RETURN_NAMED_TYPE) |
| 964 #undef RETURN_NAMED_SEMANTIC_TYPE | 922 #undef RETURN_NAMED_TYPE |
| 965 | 923 |
| 966 default: | 924 default: |
| 967 return NULL; | 925 return NULL; |
| 968 } | 926 } |
| 969 } | 927 } |
| 970 | 928 |
| 971 void BitsetType::Print(std::ostream& os, // NOLINT | 929 void BitsetType::Print(std::ostream& os, // NOLINT |
| 972 bitset bits) { | 930 bitset bits) { |
| 973 DisallowHeapAllocation no_allocation; | 931 DisallowHeapAllocation no_allocation; |
| 974 const char* name = Name(bits); | 932 const char* name = Name(bits); |
| 975 if (name != NULL) { | 933 if (name != NULL) { |
| 976 os << name; | 934 os << name; |
| 977 return; | 935 return; |
| 978 } | 936 } |
| 979 | 937 |
| 980 // clang-format off | 938 // clang-format off |
| 981 static const bitset named_bitsets[] = { | 939 static const bitset named_bitsets[] = { |
| 982 #define BITSET_CONSTANT(type, value) SEMANTIC(k##type), | 940 #define BITSET_CONSTANT(type, value) k##type, |
| 983 INTERNAL_BITSET_TYPE_LIST(BITSET_CONSTANT) | 941 INTERNAL_BITSET_TYPE_LIST(BITSET_CONSTANT) |
| 984 SEMANTIC_BITSET_TYPE_LIST(BITSET_CONSTANT) | 942 PROPER_BITSET_TYPE_LIST(BITSET_CONSTANT) |
| 985 #undef BITSET_CONSTANT | 943 #undef BITSET_CONSTANT |
| 986 }; | 944 }; |
| 987 // clang-format on | 945 // clang-format on |
| 988 | 946 |
| 989 bool is_first = true; | 947 bool is_first = true; |
| 990 os << "("; | 948 os << "("; |
| 991 for (int i(arraysize(named_bitsets) - 1); bits != 0 && i >= 0; --i) { | 949 for (int i(arraysize(named_bitsets) - 1); bits != 0 && i >= 0; --i) { |
| 992 bitset subset = named_bitsets[i]; | 950 bitset subset = named_bitsets[i]; |
| 993 if ((bits & subset) == subset) { | 951 if ((bits & subset) == subset) { |
| 994 if (!is_first) os << " | "; | 952 if (!is_first) os << " | "; |
| 995 is_first = false; | 953 is_first = false; |
| 996 os << Name(subset); | 954 os << Name(subset); |
| 997 bits -= subset; | 955 bits -= subset; |
| 998 } | 956 } |
| 999 } | 957 } |
| 1000 DCHECK(bits == 0); | 958 DCHECK(bits == 0); |
| 1001 os << ")"; | 959 os << ")"; |
| 1002 } | 960 } |
| 1003 | 961 |
| 1004 void Type::PrintTo(std::ostream& os) { | 962 void Type::PrintTo(std::ostream& os) { |
| 1005 DisallowHeapAllocation no_allocation; | 963 DisallowHeapAllocation no_allocation; |
| 1006 if (this->IsBitset()) { | 964 if (this->IsBitset()) { |
| 1007 BitsetType::Print(os, SEMANTIC(this->AsBitset())); | 965 BitsetType::Print(os, this->AsBitset()); |
| 1008 } else if (this->IsConstant()) { | 966 } else if (this->IsConstant()) { |
| 1009 os << "Constant(" << Brief(*this->AsConstant()->Value()) << ")"; | 967 os << "Constant(" << Brief(*this->AsConstant()->Value()) << ")"; |
| 1010 } else if (this->IsRange()) { | 968 } else if (this->IsRange()) { |
| 1011 std::ostream::fmtflags saved_flags = os.setf(std::ios::fixed); | 969 std::ostream::fmtflags saved_flags = os.setf(std::ios::fixed); |
| 1012 std::streamsize saved_precision = os.precision(0); | 970 std::streamsize saved_precision = os.precision(0); |
| 1013 os << "Range(" << this->AsRange()->Min() << ", " << this->AsRange()->Max() | 971 os << "Range(" << this->AsRange()->Min() << ", " << this->AsRange()->Max() |
| 1014 << ")"; | 972 << ")"; |
| 1015 os.flags(saved_flags); | 973 os.flags(saved_flags); |
| 1016 os.precision(saved_precision); | 974 os.precision(saved_precision); |
| 1017 } else if (this->IsUnion()) { | 975 } else if (this->IsUnion()) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1057 } | 1015 } |
| 1058 | 1016 |
| 1059 // ----------------------------------------------------------------------------- | 1017 // ----------------------------------------------------------------------------- |
| 1060 // Instantiations. | 1018 // Instantiations. |
| 1061 | 1019 |
| 1062 template class Type::Iterator<i::Object>; | 1020 template class Type::Iterator<i::Object>; |
| 1063 | 1021 |
| 1064 } // namespace compiler | 1022 } // namespace compiler |
| 1065 } // namespace internal | 1023 } // namespace internal |
| 1066 } // namespace v8 | 1024 } // namespace v8 |
| OLD | NEW |