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 |