| 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/types.h" | 7 #include "src/types.h" |
| 8 | 8 |
| 9 #include "src/ostreams.h" | 9 #include "src/ostreams.h" |
| 10 #include "src/types-inl.h" | 10 #include "src/types-inl.h" |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 } else if (type->IsRange()) { | 145 } else if (type->IsRange()) { |
| 146 bitset glb = SEMANTIC( | 146 bitset glb = SEMANTIC( |
| 147 BitsetType::Glb(type->AsRange()->Min(), type->AsRange()->Max())); | 147 BitsetType::Glb(type->AsRange()->Min(), type->AsRange()->Max())); |
| 148 return glb | REPRESENTATION(type->BitsetLub()); | 148 return glb | REPRESENTATION(type->BitsetLub()); |
| 149 } else { | 149 } else { |
| 150 return type->Representation(); | 150 return type->Representation(); |
| 151 } | 151 } |
| 152 } | 152 } |
| 153 | 153 |
| 154 | 154 |
| 155 // The smallest bitset subsuming this type. | 155 // The smallest bitset subsuming this type, possibly not a proper one. |
| 156 template<class Config> | 156 template<class Config> |
| 157 typename TypeImpl<Config>::bitset | 157 typename TypeImpl<Config>::bitset |
| 158 TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { | 158 TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { |
| 159 DisallowHeapAllocation no_allocation; | 159 DisallowHeapAllocation no_allocation; |
| 160 if (type->IsBitset()) return type->AsBitset(); | 160 if (type->IsBitset()) return type->AsBitset(); |
| 161 if (type->IsUnion()) { | 161 if (type->IsUnion()) { |
| 162 // Take the representation from the first element, which is always | 162 // Take the representation from the first element, which is always |
| 163 // a bitset. | 163 // a bitset. |
| 164 int bitset = type->AsUnion()->Get(0)->BitsetLub(); | 164 int bitset = type->AsUnion()->Get(0)->BitsetLub(); |
| 165 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { | 165 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { |
| 166 // Other elements only contribute their semantic part. | 166 // Other elements only contribute their semantic part. |
| 167 bitset |= SEMANTIC(type->AsUnion()->Get(i)->BitsetLub()); | 167 bitset |= SEMANTIC(type->AsUnion()->Get(i)->BitsetLub()); |
| 168 } | 168 } |
| 169 return bitset; | 169 return bitset; |
| 170 } | 170 } |
| 171 if (type->IsClass()) { | 171 if (type->IsClass()) return type->AsClass()->Lub(); |
| 172 // Little hack to avoid the need for a region for handlification here... | 172 if (type->IsConstant()) return type->AsConstant()->Lub(); |
| 173 return Config::is_class(type) ? Lub(*Config::as_class(type)) : | 173 if (type->IsRange()) return type->AsRange()->Lub(); |
| 174 type->AsClass()->Bound(NULL)->AsBitset(); | |
| 175 } | |
| 176 if (type->IsConstant()) return type->AsConstant()->Bound()->AsBitset(); | |
| 177 if (type->IsRange()) return type->AsRange()->Bound(); | |
| 178 if (type->IsContext()) return kInternal & kTaggedPointer; | 174 if (type->IsContext()) return kInternal & kTaggedPointer; |
| 179 if (type->IsArray()) return kOtherObject; | 175 if (type->IsArray()) return kOtherObject; |
| 180 if (type->IsFunction()) return kOtherObject; // TODO(rossberg): kFunction | 176 if (type->IsFunction()) return kOtherObject; // TODO(rossberg): kFunction |
| 181 UNREACHABLE(); | 177 UNREACHABLE(); |
| 182 return kNone; | 178 return kNone; |
| 183 } | 179 } |
| 184 | 180 |
| 185 | 181 |
| 186 template<class Config> | 182 template<class Config> |
| 187 typename TypeImpl<Config>::bitset | 183 typename TypeImpl<Config>::bitset |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 } | 330 } |
| 335 | 331 |
| 336 | 332 |
| 337 template<class Config> | 333 template<class Config> |
| 338 typename TypeImpl<Config>::bitset | 334 typename TypeImpl<Config>::bitset |
| 339 TypeImpl<Config>::BitsetType::Lub(double value) { | 335 TypeImpl<Config>::BitsetType::Lub(double value) { |
| 340 DisallowHeapAllocation no_allocation; | 336 DisallowHeapAllocation no_allocation; |
| 341 if (i::IsMinusZero(value)) return kMinusZero; | 337 if (i::IsMinusZero(value)) return kMinusZero; |
| 342 if (std::isnan(value)) return kNaN; | 338 if (std::isnan(value)) return kNaN; |
| 343 if (IsUint32Double(value) || IsInt32Double(value)) return Lub(value, value); | 339 if (IsUint32Double(value) || IsInt32Double(value)) return Lub(value, value); |
| 344 return kPlainNumber; | 340 return kOtherNumber; |
| 345 } | 341 } |
| 346 | 342 |
| 347 | 343 |
| 348 // Minimum values of regular numeric bitsets. | 344 // Minimum values of plain numeric bitsets. |
| 349 template <class Config> | 345 template <class Config> |
| 350 const typename TypeImpl<Config>::BitsetType::Boundary | 346 const typename TypeImpl<Config>::BitsetType::Boundary |
| 351 TypeImpl<Config>::BitsetType::BoundariesArray[] = { | 347 TypeImpl<Config>::BitsetType::BoundariesArray[] = { |
| 352 {kPlainNumber, -V8_INFINITY}, | 348 {kOtherNumber, kPlainNumber, -V8_INFINITY}, |
| 353 {kNegative32, kMinInt}, | 349 {kOtherSigned32, kNegative32, kMinInt}, |
| 354 {kNegative31, -0x40000000}, | 350 {kNegative31, kNegative31, -0x40000000}, |
| 355 {kUnsigned30, 0}, | 351 {kUnsigned30, kUnsigned30, 0}, |
| 356 {kUnsigned31, 0x40000000}, | 352 {kOtherUnsigned31, kUnsigned31, 0x40000000}, |
| 357 {kUnsigned32, 0x80000000}, | 353 {kOtherUnsigned32, kUnsigned32, 0x80000000}, |
| 358 {kPlainNumber, static_cast<double>(kMaxUInt32) + 1} | 354 {kOtherNumber, kPlainNumber, static_cast<double>(kMaxUInt32) + 1}}; |
| 359 }; | |
| 360 | 355 |
| 361 | 356 |
| 362 template <class Config> | 357 template <class Config> |
| 363 const typename TypeImpl<Config>::BitsetType::Boundary* | 358 const typename TypeImpl<Config>::BitsetType::Boundary* |
| 364 TypeImpl<Config>::BitsetType::Boundaries() { | 359 TypeImpl<Config>::BitsetType::Boundaries() { |
| 365 return BoundariesArray; | 360 return BoundariesArray; |
| 366 } | 361 } |
| 367 | 362 |
| 368 | 363 |
| 369 template <class Config> | 364 template <class Config> |
| 370 size_t TypeImpl<Config>::BitsetType::BoundariesSize() { | 365 size_t TypeImpl<Config>::BitsetType::BoundariesSize() { |
| 371 // Windows doesn't like arraysize here. | 366 // Windows doesn't like arraysize here. |
| 372 // return arraysize(BoundariesArray); | 367 // return arraysize(BoundariesArray); |
| 373 return 7; | 368 return 7; |
| 374 } | 369 } |
| 375 | 370 |
| 376 | 371 |
| 372 template <class Config> |
| 373 typename TypeImpl<Config>::bitset TypeImpl<Config>::BitsetType::ExpandInternals( |
| 374 typename TypeImpl<Config>::bitset bits) { |
| 375 DisallowHeapAllocation no_allocation; |
| 376 if (!(bits & SEMANTIC(kPlainNumber))) return bits; // Shortcut. |
| 377 const Boundary* boundaries = Boundaries(); |
| 378 for (size_t i = 0; i < BoundariesSize(); ++i) { |
| 379 DCHECK(BitsetType::Is(boundaries[i].internal, boundaries[i].external)); |
| 380 if (bits & SEMANTIC(boundaries[i].internal)) |
| 381 bits |= SEMANTIC(boundaries[i].external); |
| 382 } |
| 383 return bits; |
| 384 } |
| 385 |
| 386 |
| 377 template<class Config> | 387 template<class Config> |
| 378 typename TypeImpl<Config>::bitset | 388 typename TypeImpl<Config>::bitset |
| 379 TypeImpl<Config>::BitsetType::Lub(double min, double max) { | 389 TypeImpl<Config>::BitsetType::Lub(double min, double max) { |
| 380 DisallowHeapAllocation no_allocation; | 390 DisallowHeapAllocation no_allocation; |
| 381 int lub = kNone; | 391 int lub = kNone; |
| 382 const Boundary* mins = Boundaries(); | 392 const Boundary* mins = Boundaries(); |
| 383 | 393 |
| 384 // Make sure the min-max range touches 0, so we are guaranteed no holes | |
| 385 // in unions of valid bitsets. | |
| 386 if (max < -1) max = -1; | |
| 387 if (min > 0) min = 0; | |
| 388 | |
| 389 for (size_t i = 1; i < BoundariesSize(); ++i) { | 394 for (size_t i = 1; i < BoundariesSize(); ++i) { |
| 390 if (min < mins[i].min) { | 395 if (min < mins[i].min) { |
| 391 lub |= mins[i-1].bits; | 396 lub |= mins[i-1].internal; |
| 392 if (max < mins[i].min) return lub; | 397 if (max < mins[i].min) return lub; |
| 393 } | 398 } |
| 394 } | 399 } |
| 395 return lub |= mins[BoundariesSize() - 1].bits; | 400 return lub | mins[BoundariesSize() - 1].internal; |
| 396 } | 401 } |
| 397 | 402 |
| 398 | 403 |
| 399 template <class Config> | 404 template <class Config> |
| 400 typename TypeImpl<Config>::bitset TypeImpl<Config>::BitsetType::NumberBits( | 405 typename TypeImpl<Config>::bitset TypeImpl<Config>::BitsetType::NumberBits( |
| 401 bitset bits) { | 406 bitset bits) { |
| 402 return SEMANTIC(bits & kPlainNumber); | 407 return SEMANTIC(bits & kPlainNumber); |
| 403 } | 408 } |
| 404 | 409 |
| 405 | 410 |
| 406 template <class Config> | 411 template <class Config> |
| 407 void TypeImpl<Config>::BitsetType::CheckNumberBits(bitset bits) { | |
| 408 // Check that the bitset does not contain any holes in number ranges. | |
| 409 bitset number_bits = NumberBits(bits); | |
| 410 if (number_bits != 0) { | |
| 411 bitset lub = SEMANTIC(Lub(Min(number_bits), Max(number_bits))); | |
| 412 CHECK(lub == number_bits); | |
| 413 } | |
| 414 } | |
| 415 | |
| 416 template <class Config> | |
| 417 typename TypeImpl<Config>::bitset TypeImpl<Config>::BitsetType::Glb( | 412 typename TypeImpl<Config>::bitset TypeImpl<Config>::BitsetType::Glb( |
| 418 double min, double max) { | 413 double min, double max) { |
| 419 DisallowHeapAllocation no_allocation; | 414 DisallowHeapAllocation no_allocation; |
| 420 int glb = kNone; | 415 int glb = kNone; |
| 421 const Boundary* mins = Boundaries(); | 416 const Boundary* mins = Boundaries(); |
| 422 | 417 |
| 423 // If the range does not touch 0, the bound is empty. | 418 // If the range does not touch 0, the bound is empty. |
| 424 if (max < -1 || min > 0) return glb; | 419 if (max < -1 || min > 0) return glb; |
| 425 | 420 |
| 426 for (size_t i = 1; i + 1 < BoundariesSize(); ++i) { | 421 for (size_t i = 1; i + 1 < BoundariesSize(); ++i) { |
| 427 if (min <= mins[i].min) { | 422 if (min <= mins[i].min) { |
| 428 if (max + 1 < mins[i + 1].min) break; | 423 if (max + 1 < mins[i + 1].min) break; |
| 429 glb |= mins[i].bits; | 424 glb |= mins[i].external; |
| 430 } | 425 } |
| 431 } | 426 } |
| 432 // OtherNumber also contains float numbers, so it can never be | 427 // OtherNumber also contains float numbers, so it can never be |
| 433 // in the greatest lower bound. (There is also the small trouble | 428 // in the greatest lower bound. |
| 434 // of kOtherNumber having a range hole, which we can conveniently | |
| 435 // ignore here.) | |
| 436 return glb & ~(SEMANTIC(kOtherNumber)); | 429 return glb & ~(SEMANTIC(kOtherNumber)); |
| 437 } | 430 } |
| 438 | 431 |
| 439 | 432 |
| 440 template <class Config> | 433 template <class Config> |
| 441 double TypeImpl<Config>::BitsetType::Min(bitset bits) { | 434 double TypeImpl<Config>::BitsetType::Min(bitset bits) { |
| 442 DisallowHeapAllocation no_allocation; | 435 DisallowHeapAllocation no_allocation; |
| 443 DCHECK(Is(SEMANTIC(bits), kNumber)); | 436 DCHECK(Is(SEMANTIC(bits), kNumber)); |
| 444 const Boundary* mins = Boundaries(); | 437 const Boundary* mins = Boundaries(); |
| 445 bool mz = SEMANTIC(bits & kMinusZero); | 438 bool mz = SEMANTIC(bits & kMinusZero); |
| 446 for (size_t i = 0; i < BoundariesSize(); ++i) { | 439 for (size_t i = 0; i < BoundariesSize(); ++i) { |
| 447 if (Is(SEMANTIC(mins[i].bits), bits)) { | 440 if (Is(SEMANTIC(mins[i].internal), bits)) { |
| 448 return mz ? std::min(0.0, mins[i].min) : mins[i].min; | 441 return mz ? std::min(0.0, mins[i].min) : mins[i].min; |
| 449 } | 442 } |
| 450 } | 443 } |
| 451 if (mz) return 0; | 444 if (mz) return 0; |
| 452 return std::numeric_limits<double>::quiet_NaN(); | 445 return std::numeric_limits<double>::quiet_NaN(); |
| 453 } | 446 } |
| 454 | 447 |
| 455 | 448 |
| 456 template<class Config> | 449 template<class Config> |
| 457 double TypeImpl<Config>::BitsetType::Max(bitset bits) { | 450 double TypeImpl<Config>::BitsetType::Max(bitset bits) { |
| 458 DisallowHeapAllocation no_allocation; | 451 DisallowHeapAllocation no_allocation; |
| 459 DCHECK(Is(SEMANTIC(bits), kNumber)); | 452 DCHECK(Is(SEMANTIC(bits), kNumber)); |
| 460 const Boundary* mins = Boundaries(); | 453 const Boundary* mins = Boundaries(); |
| 461 bool mz = SEMANTIC(bits & kMinusZero); | 454 bool mz = SEMANTIC(bits & kMinusZero); |
| 462 if (BitsetType::Is(SEMANTIC(mins[BoundariesSize() - 1].bits), bits)) { | 455 if (BitsetType::Is(SEMANTIC(mins[BoundariesSize() - 1].internal), bits)) { |
| 463 return +V8_INFINITY; | 456 return +V8_INFINITY; |
| 464 } | 457 } |
| 465 for (size_t i = BoundariesSize() - 1; i-- > 0;) { | 458 for (size_t i = BoundariesSize() - 1; i-- > 0;) { |
| 466 if (Is(SEMANTIC(mins[i].bits), bits)) { | 459 if (Is(SEMANTIC(mins[i].internal), bits)) { |
| 467 return mz ? | 460 return mz ? |
| 468 std::max(0.0, mins[i+1].min - 1) : mins[i+1].min - 1; | 461 std::max(0.0, mins[i+1].min - 1) : mins[i+1].min - 1; |
| 469 } | 462 } |
| 470 } | 463 } |
| 471 if (mz) return 0; | 464 if (mz) return 0; |
| 472 return std::numeric_limits<double>::quiet_NaN(); | 465 return std::numeric_limits<double>::quiet_NaN(); |
| 473 } | 466 } |
| 474 | 467 |
| 475 | 468 |
| 476 // ----------------------------------------------------------------------------- | 469 // ----------------------------------------------------------------------------- |
| (...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 937 // Fast path: If the bitset does not mention numbers, we can just keep the | 930 // Fast path: If the bitset does not mention numbers, we can just keep the |
| 938 // range. | 931 // range. |
| 939 bitset number_bits = BitsetType::NumberBits(*bits); | 932 bitset number_bits = BitsetType::NumberBits(*bits); |
| 940 if (number_bits == 0) { | 933 if (number_bits == 0) { |
| 941 return range; | 934 return range; |
| 942 } | 935 } |
| 943 | 936 |
| 944 // If the range is semantically contained within the bitset, return None and | 937 // If the range is semantically contained within the bitset, return None and |
| 945 // leave the bitset untouched. | 938 // leave the bitset untouched. |
| 946 bitset range_lub = SEMANTIC(range->BitsetLub()); | 939 bitset range_lub = SEMANTIC(range->BitsetLub()); |
| 947 if (BitsetType::Is(BitsetType::NumberBits(range_lub), *bits)) { | 940 if (BitsetType::Is(range_lub, *bits)) { |
| 948 return None(region); | 941 return None(region); |
| 949 } | 942 } |
| 950 | 943 |
| 951 // Slow path: reconcile the bitset range and the range. | 944 // Slow path: reconcile the bitset range and the range. |
| 952 double bitset_min = BitsetType::Min(number_bits); | 945 double bitset_min = BitsetType::Min(number_bits); |
| 953 double bitset_max = BitsetType::Max(number_bits); | 946 double bitset_max = BitsetType::Max(number_bits); |
| 954 | 947 |
| 955 double range_min = range->Min(); | 948 double range_min = range->Min(); |
| 956 double range_max = range->Max(); | 949 double range_max = range->Max(); |
| 957 | 950 |
| 958 // Remove the number bits from the bitset, they would just confuse us now. | 951 // Remove the number bits from the bitset, they would just confuse us now. |
| 952 // NOTE: bits contains OtherNumber iff bits contains PlainNumber, in which |
| 953 // case we already returned after the subtype check above. |
| 959 *bits &= ~number_bits; | 954 *bits &= ~number_bits; |
| 960 | 955 |
| 961 if (range_min <= bitset_min && range_max >= bitset_max) { | 956 if (range_min <= bitset_min && range_max >= bitset_max) { |
| 962 // Bitset is contained within the range, just return the range. | 957 // Bitset is contained within the range, just return the range. |
| 963 return range; | 958 return range; |
| 964 } | 959 } |
| 965 | 960 |
| 966 if (bitset_min < range_min) { | 961 if (bitset_min < range_min) { |
| 967 range_min = bitset_min; | 962 range_min = bitset_min; |
| 968 } | 963 } |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1400 | 1395 |
| 1401 template TypeImpl<ZoneTypeConfig>::TypeHandle | 1396 template TypeImpl<ZoneTypeConfig>::TypeHandle |
| 1402 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( | 1397 TypeImpl<ZoneTypeConfig>::Convert<HeapType>( |
| 1403 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); | 1398 TypeImpl<HeapTypeConfig>::TypeHandle, TypeImpl<ZoneTypeConfig>::Region*); |
| 1404 template TypeImpl<HeapTypeConfig>::TypeHandle | 1399 template TypeImpl<HeapTypeConfig>::TypeHandle |
| 1405 TypeImpl<HeapTypeConfig>::Convert<Type>( | 1400 TypeImpl<HeapTypeConfig>::Convert<Type>( |
| 1406 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); | 1401 TypeImpl<ZoneTypeConfig>::TypeHandle, TypeImpl<HeapTypeConfig>::Region*); |
| 1407 | 1402 |
| 1408 } // namespace internal | 1403 } // namespace internal |
| 1409 } // namespace v8 | 1404 } // namespace v8 |
| OLD | NEW |