Re-revert "Use unsigned type bitsets to limit undefined behaviour"
...and the various debug CLs. R=machenbach@chromium.org BUG= Review URL: https://codereview.chromium.org/564413004 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23955 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
89db44a94e
commit
2dbd871eb1
@ -70,7 +70,7 @@ T* ZoneTypeConfig::cast(Type* type) {
|
||||
|
||||
// static
|
||||
bool ZoneTypeConfig::is_bitset(Type* type) {
|
||||
return reinterpret_cast<uintptr_t>(type) & 1;
|
||||
return reinterpret_cast<intptr_t>(type) & 1;
|
||||
}
|
||||
|
||||
|
||||
@ -87,9 +87,9 @@ bool ZoneTypeConfig::is_class(Type* type) {
|
||||
|
||||
|
||||
// static
|
||||
ZoneTypeConfig::Type::bitset ZoneTypeConfig::as_bitset(Type* type) {
|
||||
int ZoneTypeConfig::as_bitset(Type* type) {
|
||||
DCHECK(is_bitset(type));
|
||||
return reinterpret_cast<Type::bitset>(type) ^ 1u;
|
||||
return static_cast<int>(reinterpret_cast<intptr_t>(type) >> 1);
|
||||
}
|
||||
|
||||
|
||||
@ -108,14 +108,13 @@ i::Handle<i::Map> ZoneTypeConfig::as_class(Type* type) {
|
||||
|
||||
|
||||
// static
|
||||
ZoneTypeConfig::Type* ZoneTypeConfig::from_bitset(Type::bitset bitset) {
|
||||
return reinterpret_cast<Type*>(bitset | 1u);
|
||||
ZoneTypeConfig::Type* ZoneTypeConfig::from_bitset(int bitset) {
|
||||
return reinterpret_cast<Type*>((bitset << 1) | 1);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
ZoneTypeConfig::Type* ZoneTypeConfig::from_bitset(
|
||||
Type::bitset bitset, Zone* Zone) {
|
||||
ZoneTypeConfig::Type* ZoneTypeConfig::from_bitset(int bitset, Zone* Zone) {
|
||||
return from_bitset(bitset);
|
||||
}
|
||||
|
||||
@ -230,9 +229,8 @@ bool HeapTypeConfig::is_struct(Type* type, int tag) {
|
||||
|
||||
|
||||
// static
|
||||
HeapTypeConfig::Type::bitset HeapTypeConfig::as_bitset(Type* type) {
|
||||
// TODO(rossberg): Breaks the Smi abstraction. Fix once there is a better way.
|
||||
return reinterpret_cast<Type::bitset>(type);
|
||||
int HeapTypeConfig::as_bitset(Type* type) {
|
||||
return i::Smi::cast(type)->value();
|
||||
}
|
||||
|
||||
|
||||
@ -249,15 +247,14 @@ i::Handle<HeapTypeConfig::Struct> HeapTypeConfig::as_struct(Type* type) {
|
||||
|
||||
|
||||
// static
|
||||
HeapTypeConfig::Type* HeapTypeConfig::from_bitset(Type::bitset bitset) {
|
||||
// TODO(rossberg): Breaks the Smi abstraction. Fix once there is a better way.
|
||||
return reinterpret_cast<Type*>(bitset);
|
||||
HeapTypeConfig::Type* HeapTypeConfig::from_bitset(int bitset) {
|
||||
return Type::cast(i::Smi::FromInt(bitset));
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
i::Handle<HeapTypeConfig::Type> HeapTypeConfig::from_bitset(
|
||||
Type::bitset bitset, Isolate* isolate) {
|
||||
int bitset, Isolate* isolate) {
|
||||
return i::handle(from_bitset(bitset), isolate);
|
||||
}
|
||||
|
||||
|
109
src/types.cc
109
src/types.cc
@ -30,8 +30,7 @@ static bool deq(double x, double y) {
|
||||
|
||||
// The largest bitset subsumed by this type.
|
||||
template<class Config>
|
||||
typename TypeImpl<Config>::bitset
|
||||
TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) {
|
||||
int TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
if (type->IsBitset()) {
|
||||
return type->AsBitset();
|
||||
@ -47,18 +46,17 @@ TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) {
|
||||
|
||||
// The smallest bitset subsuming this type.
|
||||
template<class Config>
|
||||
typename TypeImpl<Config>::bitset
|
||||
TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) {
|
||||
int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
if (type->IsBitset()) {
|
||||
return type->AsBitset();
|
||||
} else if (type->IsUnion()) {
|
||||
UnionHandle unioned = handle(type->AsUnion());
|
||||
bitset result = kNone;
|
||||
int bitset = kNone;
|
||||
for (int i = 0; i < unioned->Length(); ++i) {
|
||||
result |= unioned->Get(i)->BitsetLub();
|
||||
bitset |= unioned->Get(i)->BitsetLub();
|
||||
}
|
||||
return result;
|
||||
return bitset;
|
||||
} else 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)) :
|
||||
@ -82,18 +80,17 @@ TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) {
|
||||
|
||||
// The smallest bitset subsuming this type, ignoring explicit bounds.
|
||||
template<class Config>
|
||||
typename TypeImpl<Config>::bitset
|
||||
TypeImpl<Config>::BitsetType::InherentLub(TypeImpl* type) {
|
||||
int TypeImpl<Config>::BitsetType::InherentLub(TypeImpl* type) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
if (type->IsBitset()) {
|
||||
return type->AsBitset();
|
||||
} else if (type->IsUnion()) {
|
||||
UnionHandle unioned = handle(type->AsUnion());
|
||||
bitset result = kNone;
|
||||
int bitset = kNone;
|
||||
for (int i = 0; i < unioned->Length(); ++i) {
|
||||
result |= unioned->Get(i)->InherentBitsetLub();
|
||||
bitset |= unioned->Get(i)->InherentBitsetLub();
|
||||
}
|
||||
return result;
|
||||
return bitset;
|
||||
} else if (type->IsClass()) {
|
||||
return Lub(*type->AsClass()->Map());
|
||||
} else if (type->IsConstant()) {
|
||||
@ -114,8 +111,7 @@ TypeImpl<Config>::BitsetType::InherentLub(TypeImpl* type) {
|
||||
|
||||
|
||||
template<class Config>
|
||||
typename TypeImpl<Config>::bitset
|
||||
TypeImpl<Config>::BitsetType::Lub(i::Object* value) {
|
||||
int TypeImpl<Config>::BitsetType::Lub(i::Object* value) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
if (value->IsNumber()) {
|
||||
return Lub(value->Number()) & (value->IsSmi() ? kTaggedInt : kTaggedPtr);
|
||||
@ -125,8 +121,7 @@ TypeImpl<Config>::BitsetType::Lub(i::Object* value) {
|
||||
|
||||
|
||||
template<class Config>
|
||||
typename TypeImpl<Config>::bitset
|
||||
TypeImpl<Config>::BitsetType::Lub(double value) {
|
||||
int TypeImpl<Config>::BitsetType::Lub(double value) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
if (i::IsMinusZero(value)) return kMinusZero;
|
||||
if (std::isnan(value)) return kNaN;
|
||||
@ -137,21 +132,19 @@ TypeImpl<Config>::BitsetType::Lub(double value) {
|
||||
|
||||
|
||||
template<class Config>
|
||||
typename TypeImpl<Config>::bitset
|
||||
TypeImpl<Config>::BitsetType::Lub(double min, double max) {
|
||||
int TypeImpl<Config>::BitsetType::Lub(double min, double max) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
DCHECK(dle(min, max));
|
||||
if (deq(min, max)) return BitsetType::Lub(min); // Singleton range.
|
||||
bitset result = BitsetType::kNumber ^ SEMANTIC(BitsetType::kNaN);
|
||||
if (dle(0, min) || max < 0) result ^= SEMANTIC(BitsetType::kMinusZero);
|
||||
return result;
|
||||
int bitset = BitsetType::kNumber ^ SEMANTIC(BitsetType::kNaN);
|
||||
if (dle(0, min) || max < 0) bitset ^= SEMANTIC(BitsetType::kMinusZero);
|
||||
return bitset;
|
||||
// TODO(neis): Could refine this further by doing more checks on min/max.
|
||||
}
|
||||
|
||||
|
||||
template<class Config>
|
||||
typename TypeImpl<Config>::bitset
|
||||
TypeImpl<Config>::BitsetType::Lub(int32_t value) {
|
||||
int TypeImpl<Config>::BitsetType::Lub(int32_t value) {
|
||||
if (value >= 0x40000000) {
|
||||
return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall;
|
||||
}
|
||||
@ -162,8 +155,7 @@ TypeImpl<Config>::BitsetType::Lub(int32_t value) {
|
||||
|
||||
|
||||
template<class Config>
|
||||
typename TypeImpl<Config>::bitset
|
||||
TypeImpl<Config>::BitsetType::Lub(uint32_t value) {
|
||||
int TypeImpl<Config>::BitsetType::Lub(uint32_t value) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
if (value >= 0x80000000u) return kOtherUnsigned32;
|
||||
if (value >= 0x40000000u) {
|
||||
@ -174,8 +166,7 @@ TypeImpl<Config>::BitsetType::Lub(uint32_t value) {
|
||||
|
||||
|
||||
template<class Config>
|
||||
typename TypeImpl<Config>::bitset
|
||||
TypeImpl<Config>::BitsetType::Lub(i::Map* map) {
|
||||
int TypeImpl<Config>::BitsetType::Lub(i::Map* map) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
switch (map->instance_type()) {
|
||||
case STRING_TYPE:
|
||||
@ -466,8 +457,8 @@ bool TypeImpl<Config>::UnionType::Wellformed() {
|
||||
|
||||
template<class Config>
|
||||
typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Rebound(
|
||||
bitset bitset_bound, Region* region) {
|
||||
TypeHandle bound = BitsetType::New(bitset_bound, region);
|
||||
int bitset, Region* region) {
|
||||
TypeHandle bound = BitsetType::New(bitset, region);
|
||||
if (this->IsClass()) {
|
||||
return ClassType::New(this->AsClass()->Map(), bound, region);
|
||||
} else if (this->IsConstant()) {
|
||||
@ -495,16 +486,16 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Rebound(
|
||||
|
||||
|
||||
template<class Config>
|
||||
typename TypeImpl<Config>::bitset TypeImpl<Config>::BoundBy(TypeImpl* that) {
|
||||
int TypeImpl<Config>::BoundBy(TypeImpl* that) {
|
||||
DCHECK(!this->IsUnion());
|
||||
if (that->IsUnion()) {
|
||||
UnionType* unioned = that->AsUnion();
|
||||
int length = unioned->Length();
|
||||
bitset result = BitsetType::kNone;
|
||||
int bitset = BitsetType::kNone;
|
||||
for (int i = 0; i < length; ++i) {
|
||||
result |= BoundBy(unioned->Get(i)->unhandle());
|
||||
bitset |= BoundBy(unioned->Get(i)->unhandle());
|
||||
}
|
||||
return result;
|
||||
return bitset;
|
||||
} else if (that->IsClass() && this->IsClass() &&
|
||||
*this->AsClass()->Map() == *that->AsClass()->Map()) {
|
||||
return that->BitsetLub();
|
||||
@ -524,7 +515,7 @@ typename TypeImpl<Config>::bitset TypeImpl<Config>::BoundBy(TypeImpl* that) {
|
||||
|
||||
template<class Config>
|
||||
int TypeImpl<Config>::IndexInUnion(
|
||||
bitset bound, UnionHandle unioned, int current_size) {
|
||||
int bound, UnionHandle unioned, int current_size) {
|
||||
DCHECK(!this->IsUnion());
|
||||
for (int i = 0; i < current_size; ++i) {
|
||||
TypeHandle that = unioned->Get(i);
|
||||
@ -554,7 +545,7 @@ int TypeImpl<Config>::ExtendUnion(
|
||||
UnionHandle result, int size, TypeHandle type,
|
||||
TypeHandle other, bool is_intersect, Region* region) {
|
||||
if (type->IsUnion()) {
|
||||
UnionHandle unioned = Config::template cast<UnionType>(type);
|
||||
UnionHandle unioned = handle(type->AsUnion());
|
||||
for (int i = 0; i < unioned->Length(); ++i) {
|
||||
TypeHandle type_i = unioned->Get(i);
|
||||
DCHECK(i == 0 || !(type_i->IsBitset() || type_i->Is(unioned->Get(0))));
|
||||
@ -565,10 +556,10 @@ int TypeImpl<Config>::ExtendUnion(
|
||||
} else if (!type->IsBitset()) {
|
||||
DCHECK(type->IsClass() || type->IsConstant() || type->IsRange() ||
|
||||
type->IsContext() || type->IsArray() || type->IsFunction());
|
||||
bitset inherent_bound = type->InherentBitsetLub();
|
||||
bitset old_bound = type->BitsetLub();
|
||||
bitset other_bound = type->BoundBy(other->unhandle()) & inherent_bound;
|
||||
bitset new_bound =
|
||||
int inherent_bound = type->InherentBitsetLub();
|
||||
int old_bound = type->BitsetLub();
|
||||
int other_bound = type->BoundBy(other->unhandle()) & inherent_bound;
|
||||
int new_bound =
|
||||
is_intersect ? (old_bound & other_bound) : (old_bound | other_bound);
|
||||
if (new_bound != BitsetType::kNone) {
|
||||
int i = type->IndexInUnion(new_bound, result, size);
|
||||
@ -577,7 +568,7 @@ int TypeImpl<Config>::ExtendUnion(
|
||||
} else if (result->Get(i)->IsBitset()) {
|
||||
return size; // Already fully subsumed.
|
||||
} else {
|
||||
bitset type_i_bound = result->Get(i)->BitsetLub();
|
||||
int type_i_bound = result->Get(i)->BitsetLub();
|
||||
new_bound |= type_i_bound;
|
||||
if (new_bound == type_i_bound) return size;
|
||||
}
|
||||
@ -616,14 +607,14 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union(
|
||||
if (!type2->IsBitset()) {
|
||||
size += (type2->IsUnion() ? type2->AsUnion()->Length() : 1);
|
||||
}
|
||||
bitset bits = type1->BitsetGlb() | type2->BitsetGlb();
|
||||
if (bits != BitsetType::kNone) ++size;
|
||||
int bitset = type1->BitsetGlb() | type2->BitsetGlb();
|
||||
if (bitset != BitsetType::kNone) ++size;
|
||||
DCHECK(size >= 1);
|
||||
|
||||
UnionHandle unioned = UnionType::New(size, region);
|
||||
size = 0;
|
||||
if (bits != BitsetType::kNone) {
|
||||
unioned->Set(size++, BitsetType::New(bits, region));
|
||||
if (bitset != BitsetType::kNone) {
|
||||
unioned->Set(size++, BitsetType::New(bitset, region));
|
||||
}
|
||||
size = ExtendUnion(unioned, size, type1, type2, false, region);
|
||||
size = ExtendUnion(unioned, size, type2, type1, false, region);
|
||||
@ -665,14 +656,14 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect(
|
||||
if (!type2->IsBitset()) {
|
||||
size += (type2->IsUnion() ? type2->AsUnion()->Length() : 1);
|
||||
}
|
||||
bitset bits = type1->BitsetGlb() & type2->BitsetGlb();
|
||||
if (bits != BitsetType::kNone) ++size;
|
||||
int bitset = type1->BitsetGlb() & type2->BitsetGlb();
|
||||
if (bitset != BitsetType::kNone) ++size;
|
||||
DCHECK(size >= 1);
|
||||
|
||||
UnionHandle unioned = UnionType::New(size, region);
|
||||
size = 0;
|
||||
if (bits != BitsetType::kNone) {
|
||||
unioned->Set(size++, BitsetType::New(bits, region));
|
||||
if (bitset != BitsetType::kNone) {
|
||||
unioned->Set(size++, BitsetType::New(bitset, region));
|
||||
}
|
||||
size = ExtendUnion(unioned, size, type1, type2, true, region);
|
||||
size = ExtendUnion(unioned, size, type2, type1, true, region);
|
||||
@ -781,7 +772,7 @@ void TypeImpl<Config>::Iterator<T>::Advance() {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
++index_;
|
||||
if (type_->IsUnion()) {
|
||||
UnionHandle unioned = Config::template cast<UnionType>(type_);
|
||||
UnionHandle unioned = handle(type_->AsUnion());
|
||||
for (; index_ < unioned->Length(); ++index_) {
|
||||
if (matches(unioned->Get(index_))) return;
|
||||
}
|
||||
@ -850,8 +841,8 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert(
|
||||
// Printing.
|
||||
|
||||
template<class Config>
|
||||
const char* TypeImpl<Config>::BitsetType::Name(bitset bits) {
|
||||
switch (bits) {
|
||||
const char* TypeImpl<Config>::BitsetType::Name(int bitset) {
|
||||
switch (bitset) {
|
||||
case REPRESENTATION(kAny): return "Any";
|
||||
#define RETURN_NAMED_REPRESENTATION_TYPE(type, value) \
|
||||
case REPRESENTATION(k##type): return #type;
|
||||
@ -871,15 +862,15 @@ const char* TypeImpl<Config>::BitsetType::Name(bitset bits) {
|
||||
|
||||
template <class Config>
|
||||
void TypeImpl<Config>::BitsetType::Print(OStream& os, // NOLINT
|
||||
bitset bits) {
|
||||
int bitset) {
|
||||
DisallowHeapAllocation no_allocation;
|
||||
const char* name = Name(bits);
|
||||
const char* name = Name(bitset);
|
||||
if (name != NULL) {
|
||||
os << name;
|
||||
return;
|
||||
}
|
||||
|
||||
static const bitset named_bitsets[] = {
|
||||
static const int named_bitsets[] = {
|
||||
#define BITSET_CONSTANT(type, value) REPRESENTATION(k##type),
|
||||
REPRESENTATION_BITSET_TYPE_LIST(BITSET_CONSTANT)
|
||||
#undef BITSET_CONSTANT
|
||||
@ -891,16 +882,16 @@ void TypeImpl<Config>::BitsetType::Print(OStream& os, // NOLINT
|
||||
|
||||
bool is_first = true;
|
||||
os << "(";
|
||||
for (int i(arraysize(named_bitsets) - 1); bits != 0 && i >= 0; --i) {
|
||||
bitset subset = named_bitsets[i];
|
||||
if ((bits & subset) == subset) {
|
||||
for (int i(arraysize(named_bitsets) - 1); bitset != 0 && i >= 0; --i) {
|
||||
int subset = named_bitsets[i];
|
||||
if ((bitset & subset) == subset) {
|
||||
if (!is_first) os << " | ";
|
||||
is_first = false;
|
||||
os << Name(subset);
|
||||
bits -= subset;
|
||||
bitset -= subset;
|
||||
}
|
||||
}
|
||||
DCHECK(bits == 0);
|
||||
DCHECK(bitset == 0);
|
||||
os << ")";
|
||||
}
|
||||
|
||||
|
161
src/types.h
161
src/types.h
@ -122,8 +122,8 @@ namespace internal {
|
||||
// IMPLEMENTATION
|
||||
//
|
||||
// Internally, all 'primitive' types, and their unions, are represented as
|
||||
// bitsets. Bit 0 is reserved for tagging. Class is a heap pointer to the
|
||||
// respective map. Only structured types require allocation.
|
||||
// bitsets. Class is a heap pointer to the respective map. Only Constant's, or
|
||||
// unions containing Class'es or Constant's, currently require allocation.
|
||||
// Note that the bitset representation is closed under both Union and Intersect.
|
||||
//
|
||||
// There are two type representations, using different allocation:
|
||||
@ -139,23 +139,24 @@ namespace internal {
|
||||
// Values for bitset types
|
||||
|
||||
#define MASK_BITSET_TYPE_LIST(V) \
|
||||
V(Representation, 0xff800000u) \
|
||||
V(Semantic, 0x007ffffeu)
|
||||
V(Representation, static_cast<int>(0xffc00000)) \
|
||||
V(Semantic, static_cast<int>(0x003fffff))
|
||||
|
||||
#define REPRESENTATION(k) ((k) & BitsetType::kRepresentation)
|
||||
#define SEMANTIC(k) ((k) & BitsetType::kSemantic)
|
||||
|
||||
#define REPRESENTATION_BITSET_TYPE_LIST(V) \
|
||||
V(None, 0) \
|
||||
V(UntaggedInt1, 1u << 23 | kSemantic) \
|
||||
V(UntaggedInt8, 1u << 24 | kSemantic) \
|
||||
V(UntaggedInt16, 1u << 25 | kSemantic) \
|
||||
V(UntaggedInt32, 1u << 26 | kSemantic) \
|
||||
V(UntaggedFloat32, 1u << 27 | kSemantic) \
|
||||
V(UntaggedFloat64, 1u << 28 | kSemantic) \
|
||||
V(UntaggedPtr, 1u << 29 | kSemantic) \
|
||||
V(TaggedInt, 1u << 30 | kSemantic) \
|
||||
V(TaggedPtr, 1u << 31 | kSemantic) \
|
||||
V(UntaggedInt1, 1 << 22 | kSemantic) \
|
||||
V(UntaggedInt8, 1 << 23 | kSemantic) \
|
||||
V(UntaggedInt16, 1 << 24 | kSemantic) \
|
||||
V(UntaggedInt32, 1 << 25 | kSemantic) \
|
||||
V(UntaggedFloat32, 1 << 26 | kSemantic) \
|
||||
V(UntaggedFloat64, 1 << 27 | kSemantic) \
|
||||
V(UntaggedPtr, 1 << 28 | kSemantic) \
|
||||
V(TaggedInt, 1 << 29 | kSemantic) \
|
||||
/* MSB has to be sign-extended */ \
|
||||
V(TaggedPtr, static_cast<int>(~0u << 30) | kSemantic) \
|
||||
\
|
||||
V(UntaggedInt, kUntaggedInt1 | kUntaggedInt8 | \
|
||||
kUntaggedInt16 | kUntaggedInt32) \
|
||||
@ -165,28 +166,28 @@ namespace internal {
|
||||
V(Tagged, kTaggedInt | kTaggedPtr)
|
||||
|
||||
#define SEMANTIC_BITSET_TYPE_LIST(V) \
|
||||
V(Null, 1u << 1 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Undefined, 1u << 2 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Boolean, 1u << 3 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(UnsignedSmall, 1u << 4 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherSignedSmall, 1u << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherUnsigned31, 1u << 6 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherUnsigned32, 1u << 7 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherSigned32, 1u << 8 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(MinusZero, 1u << 9 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(NaN, 1u << 10 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherNumber, 1u << 11 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(Symbol, 1u << 12 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(InternalizedString, 1u << 13 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(OtherString, 1u << 14 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Undetectable, 1u << 15 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Array, 1u << 16 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Buffer, 1u << 17 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Function, 1u << 18 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(RegExp, 1u << 19 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(OtherObject, 1u << 20 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Proxy, 1u << 21 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Internal, 1u << 22 | REPRESENTATION(kTagged | kUntagged)) \
|
||||
V(Null, 1 << 0 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Undefined, 1 << 1 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Boolean, 1 << 2 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(UnsignedSmall, 1 << 3 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherSignedSmall, 1 << 4 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherUnsigned31, 1 << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherUnsigned32, 1 << 6 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherSigned32, 1 << 7 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(MinusZero, 1 << 8 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(NaN, 1 << 9 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(OtherNumber, 1 << 10 | REPRESENTATION(kTagged | kUntaggedNumber)) \
|
||||
V(Symbol, 1 << 11 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(InternalizedString, 1 << 12 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(OtherString, 1 << 13 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Undetectable, 1 << 14 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Array, 1 << 15 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Buffer, 1 << 16 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Function, 1 << 17 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(RegExp, 1 << 18 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(OtherObject, 1 << 19 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Proxy, 1 << 20 | REPRESENTATION(kTaggedPtr)) \
|
||||
V(Internal, 1 << 21 | REPRESENTATION(kTagged | kUntagged)) \
|
||||
\
|
||||
V(SignedSmall, kUnsignedSmall | kOtherSignedSmall) \
|
||||
V(Signed32, kSignedSmall | kOtherUnsigned31 | kOtherSigned32) \
|
||||
@ -206,7 +207,7 @@ namespace internal {
|
||||
V(Receiver, kObject | kProxy) \
|
||||
V(NonNumber, kBoolean | kName | kNull | kReceiver | \
|
||||
kUndefined | kInternal) \
|
||||
V(Any, 0xfffffffeu)
|
||||
V(Any, -1)
|
||||
|
||||
#define BITSET_TYPE_LIST(V) \
|
||||
MASK_BITSET_TYPE_LIST(V) \
|
||||
@ -228,11 +229,11 @@ namespace internal {
|
||||
// static bool is_bitset(Type*);
|
||||
// static bool is_class(Type*);
|
||||
// static bool is_struct(Type*, int tag);
|
||||
// static bitset as_bitset(Type*);
|
||||
// static int as_bitset(Type*);
|
||||
// static i::Handle<i::Map> as_class(Type*);
|
||||
// static Handle<Struct>::type as_struct(Type*);
|
||||
// static Type* from_bitset(bitset);
|
||||
// static Handle<Type>::type from_bitset(bitset, Region*);
|
||||
// static Type* from_bitset(int bitset);
|
||||
// static Handle<Type>::type from_bitset(int bitset, Region*);
|
||||
// static Handle<Type>::type from_class(i::Handle<Map>, Region*);
|
||||
// static Handle<Type>::type from_struct(Handle<Struct>::type, int tag);
|
||||
// static Handle<Struct>::type struct_create(int tag, int length, Region*);
|
||||
@ -251,10 +252,9 @@ class TypeImpl : public Config::Base {
|
||||
public:
|
||||
// Auxiliary types.
|
||||
|
||||
typedef uintptr_t bitset; // Internal
|
||||
class BitsetType; // Internal
|
||||
class StructuralType; // Internal
|
||||
class UnionType; // Internal
|
||||
class BitsetType; // Internal
|
||||
class StructuralType; // Internal
|
||||
class UnionType; // Internal
|
||||
|
||||
class ClassType;
|
||||
class ConstantType;
|
||||
@ -275,13 +275,10 @@ class TypeImpl : public Config::Base {
|
||||
|
||||
// Constructors.
|
||||
|
||||
// Explicitly mask, since VS on Win64 (wrongly?) sign extends the enum value.
|
||||
#define DEFINE_TYPE_CONSTRUCTOR(type, value) \
|
||||
static TypeImpl* type() { \
|
||||
return BitsetType::New(BitsetType::k##type & 0xffffffffu); \
|
||||
} \
|
||||
static TypeImpl* type() { return BitsetType::New(BitsetType::k##type); } \
|
||||
static TypeHandle type(Region* region) { \
|
||||
return BitsetType::New(BitsetType::k##type & 0xffffffffu, region); \
|
||||
return BitsetType::New(BitsetType::k##type, region); \
|
||||
}
|
||||
BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
|
||||
#undef DEFINE_TYPE_CONSTRUCTOR
|
||||
@ -460,7 +457,7 @@ class TypeImpl : public Config::Base {
|
||||
bool IsBitset() { return Config::is_bitset(this); }
|
||||
bool IsUnion() { return Config::is_struct(this, StructuralType::kUnionTag); }
|
||||
|
||||
bitset AsBitset() {
|
||||
int AsBitset() {
|
||||
DCHECK(this->IsBitset());
|
||||
return static_cast<BitsetType*>(this)->Bitset();
|
||||
}
|
||||
@ -468,15 +465,15 @@ class TypeImpl : public Config::Base {
|
||||
|
||||
// Auxiliary functions.
|
||||
|
||||
bitset BitsetGlb() { return BitsetType::Glb(this); }
|
||||
bitset BitsetLub() { return BitsetType::Lub(this); }
|
||||
bitset InherentBitsetLub() { return BitsetType::InherentLub(this); }
|
||||
int BitsetGlb() { return BitsetType::Glb(this); }
|
||||
int BitsetLub() { return BitsetType::Lub(this); }
|
||||
int InherentBitsetLub() { return BitsetType::InherentLub(this); }
|
||||
|
||||
bool SlowIs(TypeImpl* that);
|
||||
|
||||
TypeHandle Rebound(bitset bound, Region* region);
|
||||
bitset BoundBy(TypeImpl* that);
|
||||
int IndexInUnion(bitset bound, UnionHandle unioned, int current_size);
|
||||
TypeHandle Rebound(int bitset, Region* region);
|
||||
int BoundBy(TypeImpl* that);
|
||||
int IndexInUnion(int bound, UnionHandle unioned, int current_size);
|
||||
static int ExtendUnion(
|
||||
UnionHandle unioned, int current_size, TypeHandle t,
|
||||
TypeHandle other, bool is_intersect, Region* region);
|
||||
@ -488,7 +485,7 @@ class TypeImpl : public Config::Base {
|
||||
|
||||
template<class Config>
|
||||
class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
|
||||
public: // protected:
|
||||
protected:
|
||||
friend class TypeImpl<Config>;
|
||||
|
||||
enum {
|
||||
@ -498,33 +495,35 @@ class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
|
||||
kUnusedEOL = 0
|
||||
};
|
||||
|
||||
bitset Bitset() { return Config::as_bitset(this); }
|
||||
int Bitset() { return Config::as_bitset(this); }
|
||||
|
||||
static TypeImpl* New(bitset bits) { return Config::from_bitset(bits); }
|
||||
static TypeHandle New(bitset bits, Region* region) {
|
||||
return Config::from_bitset(bits, region);
|
||||
static TypeImpl* New(int bitset) {
|
||||
return static_cast<BitsetType*>(Config::from_bitset(bitset));
|
||||
}
|
||||
static TypeHandle New(int bitset, Region* region) {
|
||||
return Config::from_bitset(bitset, region);
|
||||
}
|
||||
|
||||
static bool IsInhabited(bitset bits) {
|
||||
return (bits & kRepresentation) && (bits & kSemantic);
|
||||
static bool IsInhabited(int bitset) {
|
||||
return (bitset & kRepresentation) && (bitset & kSemantic);
|
||||
}
|
||||
|
||||
static bool Is(bitset bits1, bitset bits2) {
|
||||
return (bits1 | bits2) == bits2;
|
||||
static bool Is(int bitset1, int bitset2) {
|
||||
return (bitset1 | bitset2) == bitset2;
|
||||
}
|
||||
|
||||
static bitset Glb(TypeImpl* type); // greatest lower bound that's a bitset
|
||||
static bitset Lub(TypeImpl* type); // least upper bound that's a bitset
|
||||
static bitset Lub(i::Object* value);
|
||||
static bitset Lub(double value);
|
||||
static bitset Lub(int32_t value);
|
||||
static bitset Lub(uint32_t value);
|
||||
static bitset Lub(i::Map* map);
|
||||
static bitset Lub(double min, double max);
|
||||
static bitset InherentLub(TypeImpl* type);
|
||||
static int Glb(TypeImpl* type); // greatest lower bound that's a bitset
|
||||
static int Lub(TypeImpl* type); // least upper bound that's a bitset
|
||||
static int Lub(i::Object* value);
|
||||
static int Lub(double value);
|
||||
static int Lub(int32_t value);
|
||||
static int Lub(uint32_t value);
|
||||
static int Lub(i::Map* map);
|
||||
static int Lub(double min, double max);
|
||||
static int InherentLub(TypeImpl* type);
|
||||
|
||||
static const char* Name(bitset);
|
||||
static void Print(OStream& os, bitset); // NOLINT
|
||||
static const char* Name(int bitset);
|
||||
static void Print(OStream& os, int bitset); // NOLINT
|
||||
using TypeImpl::PrintTo;
|
||||
};
|
||||
|
||||
@ -867,12 +866,12 @@ struct ZoneTypeConfig {
|
||||
static inline bool is_class(Type* type);
|
||||
static inline bool is_struct(Type* type, int tag);
|
||||
|
||||
static inline Type::bitset as_bitset(Type* type);
|
||||
static inline int as_bitset(Type* type);
|
||||
static inline i::Handle<i::Map> as_class(Type* type);
|
||||
static inline Struct* as_struct(Type* type);
|
||||
|
||||
static inline Type* from_bitset(Type::bitset);
|
||||
static inline Type* from_bitset(Type::bitset, Zone* zone);
|
||||
static inline Type* from_bitset(int bitset);
|
||||
static inline Type* from_bitset(int bitset, Zone* zone);
|
||||
static inline Type* from_class(i::Handle<i::Map> map, Zone* zone);
|
||||
static inline Type* from_struct(Struct* structured);
|
||||
|
||||
@ -914,12 +913,12 @@ struct HeapTypeConfig {
|
||||
static inline bool is_class(Type* type);
|
||||
static inline bool is_struct(Type* type, int tag);
|
||||
|
||||
static inline Type::bitset as_bitset(Type* type);
|
||||
static inline int as_bitset(Type* type);
|
||||
static inline i::Handle<i::Map> as_class(Type* type);
|
||||
static inline i::Handle<Struct> as_struct(Type* type);
|
||||
|
||||
static inline Type* from_bitset(Type::bitset);
|
||||
static inline i::Handle<Type> from_bitset(Type::bitset, Isolate* isolate);
|
||||
static inline Type* from_bitset(int bitset);
|
||||
static inline i::Handle<Type> from_bitset(int bitset, Isolate* isolate);
|
||||
static inline i::Handle<Type> from_class(
|
||||
i::Handle<i::Map> map, Isolate* isolate);
|
||||
static inline i::Handle<Type> from_struct(i::Handle<Struct> structure);
|
||||
|
@ -12,22 +12,20 @@
|
||||
using namespace v8::internal;
|
||||
|
||||
// Testing auxiliaries (breaking the Type abstraction).
|
||||
typedef uintptr_t bitset;
|
||||
|
||||
struct ZoneRep {
|
||||
typedef void* Struct;
|
||||
|
||||
static bool IsStruct(Type* t, int tag) {
|
||||
return !IsBitset(t) && reinterpret_cast<intptr_t>(AsStruct(t)[0]) == tag;
|
||||
}
|
||||
static bool IsBitset(Type* t) { return reinterpret_cast<bitset>(t) & 1; }
|
||||
static bool IsBitset(Type* t) { return reinterpret_cast<intptr_t>(t) & 1; }
|
||||
static bool IsUnion(Type* t) { return IsStruct(t, 6); }
|
||||
|
||||
static Struct* AsStruct(Type* t) {
|
||||
return reinterpret_cast<Struct*>(t);
|
||||
}
|
||||
static bitset AsBitset(Type* t) {
|
||||
return reinterpret_cast<bitset>(t) ^ 1u;
|
||||
static int AsBitset(Type* t) {
|
||||
return static_cast<int>(reinterpret_cast<intptr_t>(t) >> 1);
|
||||
}
|
||||
static Struct* AsUnion(Type* t) {
|
||||
return AsStruct(t);
|
||||
@ -57,9 +55,7 @@ struct HeapRep {
|
||||
static bool IsUnion(Handle<HeapType> t) { return IsStruct(t, 6); }
|
||||
|
||||
static Struct* AsStruct(Handle<HeapType> t) { return FixedArray::cast(*t); }
|
||||
static bitset AsBitset(Handle<HeapType> t) {
|
||||
return reinterpret_cast<bitset>(*t);
|
||||
}
|
||||
static int AsBitset(Handle<HeapType> t) { return Smi::cast(*t)->value(); }
|
||||
static Struct* AsUnion(Handle<HeapType> t) { return AsStruct(t); }
|
||||
static int Length(Struct* structured) { return structured->length() - 1; }
|
||||
|
||||
@ -70,11 +66,9 @@ struct HeapRep {
|
||||
using HeapType::BitsetType::Glb;
|
||||
using HeapType::BitsetType::Lub;
|
||||
using HeapType::BitsetType::InherentLub;
|
||||
static bitset Glb(Handle<HeapType> type) { return Glb(*type); }
|
||||
static bitset Lub(Handle<HeapType> type) { return Lub(*type); }
|
||||
static bitset InherentLub(Handle<HeapType> type) {
|
||||
return InherentLub(*type);
|
||||
}
|
||||
static int Glb(Handle<HeapType> type) { return Glb(*type); }
|
||||
static int Lub(Handle<HeapType> type) { return Lub(*type); }
|
||||
static int InherentLub(Handle<HeapType> type) { return InherentLub(*type); }
|
||||
};
|
||||
};
|
||||
|
||||
@ -371,7 +365,7 @@ struct Tests : Rep {
|
||||
CHECK(type1->Is(type2));
|
||||
CHECK(!type2->Is(type1));
|
||||
if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) {
|
||||
CHECK(Rep::AsBitset(type1) != Rep::AsBitset(type2));
|
||||
CHECK_NE(Rep::AsBitset(type1), Rep::AsBitset(type2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,7 +373,7 @@ struct Tests : Rep {
|
||||
CHECK(!type1->Is(type2));
|
||||
CHECK(!type2->Is(type1));
|
||||
if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) {
|
||||
CHECK(Rep::AsBitset(type1) != Rep::AsBitset(type2));
|
||||
CHECK_NE(Rep::AsBitset(type1), Rep::AsBitset(type2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -387,8 +381,8 @@ struct Tests : Rep {
|
||||
CHECK(type1->Maybe(type2));
|
||||
CHECK(type2->Maybe(type1));
|
||||
if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) {
|
||||
CHECK(0 !=
|
||||
(Rep::AsBitset(type1) & Rep::AsBitset(type2) & Rep::AsBitset(mask)));
|
||||
CHECK_NE(0,
|
||||
Rep::AsBitset(type1) & Rep::AsBitset(type2) & Rep::AsBitset(mask));
|
||||
}
|
||||
}
|
||||
|
||||
@ -398,8 +392,8 @@ struct Tests : Rep {
|
||||
CHECK(!type1->Maybe(type2));
|
||||
CHECK(!type2->Maybe(type1));
|
||||
if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) {
|
||||
CHECK(0 ==
|
||||
(Rep::AsBitset(type1) & Rep::AsBitset(type2) & Rep::AsBitset(mask)));
|
||||
CHECK_EQ(0,
|
||||
Rep::AsBitset(type1) & Rep::AsBitset(type2) & Rep::AsBitset(mask));
|
||||
}
|
||||
}
|
||||
|
||||
@ -408,16 +402,8 @@ struct Tests : Rep {
|
||||
CHECK(this->IsBitset(T.None));
|
||||
CHECK(this->IsBitset(T.Any));
|
||||
|
||||
CHECK(bitset(0) == this->AsBitset(T.None));
|
||||
printf("[BitSet] value=%p enum=%p bitset=%p any=%p this=%p any=%p\n",
|
||||
reinterpret_cast<void*>(bitset(0xfffffffeu)),
|
||||
reinterpret_cast<void*>(bitset(HeapType::BitsetType::kAny)),
|
||||
reinterpret_cast<void*>(
|
||||
HeapTypeConfig::from_bitset(HeapType::BitsetType::kAny)),
|
||||
reinterpret_cast<void*>(HeapType::Any()),
|
||||
reinterpret_cast<void*>(this->AsBitset(T.Any)),
|
||||
reinterpret_cast<void*>(*T.Any));
|
||||
CHECK(bitset(0xfffffffeu) == this->AsBitset(T.Any));
|
||||
CHECK_EQ(0, this->AsBitset(T.None));
|
||||
CHECK_EQ(-1, this->AsBitset(T.Any));
|
||||
|
||||
// Union(T1, T2) is bitset for bitsets T1,T2
|
||||
for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
|
||||
@ -459,8 +445,8 @@ struct Tests : Rep {
|
||||
TypeHandle type2 = *it2;
|
||||
TypeHandle union12 = T.Union(type1, type2);
|
||||
if (this->IsBitset(type1) && this->IsBitset(type2)) {
|
||||
CHECK(
|
||||
(this->AsBitset(type1) | this->AsBitset(type2)) ==
|
||||
CHECK_EQ(
|
||||
this->AsBitset(type1) | this->AsBitset(type2),
|
||||
this->AsBitset(union12));
|
||||
}
|
||||
}
|
||||
@ -473,8 +459,8 @@ struct Tests : Rep {
|
||||
TypeHandle type2 = *it2;
|
||||
TypeHandle intersect12 = T.Intersect(type1, type2);
|
||||
if (this->IsBitset(type1) && this->IsBitset(type2)) {
|
||||
CHECK(
|
||||
(this->AsBitset(type1) & this->AsBitset(type2)) ==
|
||||
CHECK_EQ(
|
||||
this->AsBitset(type1) & this->AsBitset(type2),
|
||||
this->AsBitset(intersect12));
|
||||
}
|
||||
}
|
||||
@ -1831,7 +1817,7 @@ typedef Tests<HeapType, Handle<HeapType>, Isolate, HeapRep> HeapTests;
|
||||
|
||||
TEST(BitsetType) {
|
||||
CcTest::InitializeVM();
|
||||
// ZoneTests().Bitset();
|
||||
ZoneTests().Bitset();
|
||||
HeapTests().Bitset();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user