Index: src/types.cc |
diff --git a/src/types.cc b/src/types.cc |
index 868b073efaadd8c8faa854225467065b02a9448e..af1700254bb824370552ed2d884c844bb9f22322 100644 |
--- a/src/types.cc |
+++ b/src/types.cc |
@@ -152,7 +152,7 @@ TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) { |
} |
-// The smallest bitset subsuming this type. |
+// The smallest bitset subsuming this type, possibly not a proper one. |
template<class Config> |
typename TypeImpl<Config>::bitset |
TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { |
@@ -168,13 +168,9 @@ TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { |
} |
return bitset; |
} |
- if (type->IsClass()) { |
- // Little hack to avoid the need for a region for handlification here... |
- return Config::is_class(type) ? Lub(*Config::as_class(type)) : |
- type->AsClass()->Bound(NULL)->AsBitset(); |
- } |
- if (type->IsConstant()) return type->AsConstant()->Bound()->AsBitset(); |
- if (type->IsRange()) return type->AsRange()->Bound(); |
+ if (type->IsClass()) return type->AsClass()->Lub(); |
+ if (type->IsConstant()) return type->AsConstant()->Lub(); |
+ if (type->IsRange()) return type->AsRange()->Lub(); |
if (type->IsContext()) return kInternal & kTaggedPointer; |
if (type->IsArray()) return kOtherObject; |
if (type->IsFunction()) return kOtherObject; // TODO(rossberg): kFunction |
@@ -341,22 +337,21 @@ TypeImpl<Config>::BitsetType::Lub(double value) { |
if (i::IsMinusZero(value)) return kMinusZero; |
if (std::isnan(value)) return kNaN; |
if (IsUint32Double(value) || IsInt32Double(value)) return Lub(value, value); |
- return kPlainNumber; |
+ return kOtherNumber; |
} |
-// Minimum values of regular numeric bitsets. |
+// Minimum values of plain numeric bitsets. |
template <class Config> |
const typename TypeImpl<Config>::BitsetType::Boundary |
- TypeImpl<Config>::BitsetType::BoundariesArray[] = { |
- {kPlainNumber, -V8_INFINITY}, |
- {kNegative32, kMinInt}, |
- {kNegative31, -0x40000000}, |
- {kUnsigned30, 0}, |
- {kUnsigned31, 0x40000000}, |
- {kUnsigned32, 0x80000000}, |
- {kPlainNumber, static_cast<double>(kMaxUInt32) + 1} |
-}; |
+TypeImpl<Config>::BitsetType::BoundariesArray[] = { |
+ {kOtherNumber, kPlainNumber, -V8_INFINITY}, |
+ {kOtherSigned32, kNegative32, kMinInt}, |
+ {kNegative31, kNegative31, -0x40000000}, |
+ {kUnsigned30, kUnsigned30, 0}, |
+ {kOtherUnsigned31, kUnsigned31, 0x40000000}, |
+ {kOtherUnsigned32, kUnsigned32, 0x80000000}, |
+ {kOtherNumber, kPlainNumber, static_cast<double>(kMaxUInt32) + 1}}; |
template <class Config> |
@@ -374,6 +369,21 @@ size_t TypeImpl<Config>::BitsetType::BoundariesSize() { |
} |
+template <class Config> |
+typename TypeImpl<Config>::bitset TypeImpl<Config>::BitsetType::ExpandInternals( |
+ typename TypeImpl<Config>::bitset bits) { |
+ DisallowHeapAllocation no_allocation; |
+ if (!(bits & SEMANTIC(kPlainNumber))) return bits; // Shortcut. |
+ const Boundary* boundaries = Boundaries(); |
+ for (size_t i = 0; i < BoundariesSize(); ++i) { |
+ DCHECK(BitsetType::Is(boundaries[i].internal, boundaries[i].external)); |
+ if (bits & SEMANTIC(boundaries[i].internal)) |
+ bits |= SEMANTIC(boundaries[i].external); |
+ } |
+ return bits; |
+} |
+ |
+ |
template<class Config> |
typename TypeImpl<Config>::bitset |
TypeImpl<Config>::BitsetType::Lub(double min, double max) { |
@@ -381,18 +391,13 @@ TypeImpl<Config>::BitsetType::Lub(double min, double max) { |
int lub = kNone; |
const Boundary* mins = Boundaries(); |
- // Make sure the min-max range touches 0, so we are guaranteed no holes |
- // in unions of valid bitsets. |
- if (max < -1) max = -1; |
- if (min > 0) min = 0; |
- |
for (size_t i = 1; i < BoundariesSize(); ++i) { |
if (min < mins[i].min) { |
- lub |= mins[i-1].bits; |
+ lub |= mins[i-1].internal; |
if (max < mins[i].min) return lub; |
} |
} |
- return lub |= mins[BoundariesSize() - 1].bits; |
+ return lub | mins[BoundariesSize() - 1].internal; |
} |
@@ -404,16 +409,6 @@ typename TypeImpl<Config>::bitset TypeImpl<Config>::BitsetType::NumberBits( |
template <class Config> |
-void TypeImpl<Config>::BitsetType::CheckNumberBits(bitset bits) { |
- // Check that the bitset does not contain any holes in number ranges. |
- bitset number_bits = NumberBits(bits); |
- if (number_bits != 0) { |
- bitset lub = SEMANTIC(Lub(Min(number_bits), Max(number_bits))); |
- CHECK(lub == number_bits); |
- } |
-} |
- |
-template <class Config> |
typename TypeImpl<Config>::bitset TypeImpl<Config>::BitsetType::Glb( |
double min, double max) { |
DisallowHeapAllocation no_allocation; |
@@ -426,13 +421,11 @@ typename TypeImpl<Config>::bitset TypeImpl<Config>::BitsetType::Glb( |
for (size_t i = 1; i + 1 < BoundariesSize(); ++i) { |
if (min <= mins[i].min) { |
if (max + 1 < mins[i + 1].min) break; |
- glb |= mins[i].bits; |
+ glb |= mins[i].external; |
} |
} |
// OtherNumber also contains float numbers, so it can never be |
- // in the greatest lower bound. (There is also the small trouble |
- // of kOtherNumber having a range hole, which we can conveniently |
- // ignore here.) |
+ // in the greatest lower bound. |
return glb & ~(SEMANTIC(kOtherNumber)); |
} |
@@ -444,7 +437,7 @@ double TypeImpl<Config>::BitsetType::Min(bitset bits) { |
const Boundary* mins = Boundaries(); |
bool mz = SEMANTIC(bits & kMinusZero); |
for (size_t i = 0; i < BoundariesSize(); ++i) { |
- if (Is(SEMANTIC(mins[i].bits), bits)) { |
+ if (Is(SEMANTIC(mins[i].internal), bits)) { |
return mz ? std::min(0.0, mins[i].min) : mins[i].min; |
} |
} |
@@ -459,11 +452,11 @@ double TypeImpl<Config>::BitsetType::Max(bitset bits) { |
DCHECK(Is(SEMANTIC(bits), kNumber)); |
const Boundary* mins = Boundaries(); |
bool mz = SEMANTIC(bits & kMinusZero); |
- if (BitsetType::Is(SEMANTIC(mins[BoundariesSize() - 1].bits), bits)) { |
+ if (BitsetType::Is(SEMANTIC(mins[BoundariesSize() - 1].internal), bits)) { |
return +V8_INFINITY; |
} |
for (size_t i = BoundariesSize() - 1; i-- > 0;) { |
- if (Is(SEMANTIC(mins[i].bits), bits)) { |
+ if (Is(SEMANTIC(mins[i].internal), bits)) { |
return mz ? |
std::max(0.0, mins[i+1].min - 1) : mins[i+1].min - 1; |
} |
@@ -944,7 +937,7 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NormalizeRangeAndBitset( |
// If the range is semantically contained within the bitset, return None and |
// leave the bitset untouched. |
bitset range_lub = SEMANTIC(range->BitsetLub()); |
- if (BitsetType::Is(BitsetType::NumberBits(range_lub), *bits)) { |
+ if (BitsetType::Is(range_lub, *bits)) { |
return None(region); |
} |
@@ -956,6 +949,8 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NormalizeRangeAndBitset( |
double range_max = range->Max(); |
// Remove the number bits from the bitset, they would just confuse us now. |
+ // NOTE: bits contains OtherNumber iff bits contains PlainNumber, in which |
+ // case we already returned after the subtype check above. |
*bits &= ~number_bits; |
if (range_min <= bitset_min && range_max >= bitset_max) { |