| Index: src/types.cc
|
| diff --git a/src/types.cc b/src/types.cc
|
| index 485ba885187364ed2b99098865eec3197b2c47dc..2aa60817e5f4f30e221085507ef3ae497a846e8e 100644
|
| --- a/src/types.cc
|
| +++ b/src/types.cc
|
| @@ -31,14 +31,15 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| -int Type::NumClasses() {
|
| - if (is_class()) {
|
| +template<class Config>
|
| +int TypeImpl<Config>::NumClasses() {
|
| + if (this->IsClass()) {
|
| return 1;
|
| - } else if (is_union()) {
|
| - Handle<Unioned> unioned = as_union();
|
| + } else if (this->IsUnion()) {
|
| + UnionedHandle unioned = this->AsUnion();
|
| int result = 0;
|
| for (int i = 0; i < unioned->length(); ++i) {
|
| - if (union_get(unioned, i)->is_class()) ++result;
|
| + if (Config::union_get(unioned, i)->IsClass()) ++result;
|
| }
|
| return result;
|
| } else {
|
| @@ -47,14 +48,15 @@ int Type::NumClasses() {
|
| }
|
|
|
|
|
| -int Type::NumConstants() {
|
| - if (is_constant()) {
|
| +template<class Config>
|
| +int TypeImpl<Config>::NumConstants() {
|
| + if (this->IsConstant()) {
|
| return 1;
|
| - } else if (is_union()) {
|
| - Handle<Unioned> unioned = as_union();
|
| + } else if (this->IsUnion()) {
|
| + UnionedHandle unioned = this->AsUnion();
|
| int result = 0;
|
| for (int i = 0; i < unioned->length(); ++i) {
|
| - if (union_get(unioned, i)->is_constant()) ++result;
|
| + if (Config::union_get(unioned, i)->IsConstant()) ++result;
|
| }
|
| return result;
|
| } else {
|
| @@ -63,41 +65,61 @@ int Type::NumConstants() {
|
| }
|
|
|
|
|
| -template<class T>
|
| -Handle<Type> Type::Iterator<T>::get_type() {
|
| +template<class Config> template<class T>
|
| +typename TypeImpl<Config>::TypeHandle
|
| +TypeImpl<Config>::Iterator<T>::get_type() {
|
| ASSERT(!Done());
|
| - return type_->is_union() ? union_get(type_->as_union(), index_) : type_;
|
| + return type_->IsUnion() ? Config::union_get(type_->AsUnion(), index_) : type_;
|
| }
|
|
|
| -template<>
|
| -Handle<i::Map> Type::Iterator<i::Map>::Current() {
|
| - return get_type()->as_class();
|
| -}
|
|
|
| -template<>
|
| -Handle<i::Object> Type::Iterator<i::Object>::Current() {
|
| - return get_type()->as_constant();
|
| -}
|
| +// C++ cannot specialise nested templates, so we have to go through this
|
| +// contortion with an auxiliary template to simulate it.
|
| +template<class Config, class T>
|
| +struct TypeImplIteratorAux {
|
| + static bool matches(typename TypeImpl<Config>::TypeHandle type);
|
| + static i::Handle<T> current(typename TypeImpl<Config>::TypeHandle type);
|
| +};
|
| +
|
| +template<class Config>
|
| +struct TypeImplIteratorAux<Config, i::Map> {
|
| + static bool matches(typename TypeImpl<Config>::TypeHandle type) {
|
| + return type->IsClass();
|
| + }
|
| + static i::Handle<i::Map> current(typename TypeImpl<Config>::TypeHandle type) {
|
| + return type->AsClass();
|
| + }
|
| +};
|
|
|
| +template<class Config>
|
| +struct TypeImplIteratorAux<Config, i::Object> {
|
| + static bool matches(typename TypeImpl<Config>::TypeHandle type) {
|
| + return type->IsConstant();
|
| + }
|
| + static i::Handle<i::Object> current(
|
| + typename TypeImpl<Config>::TypeHandle type) {
|
| + return type->AsConstant();
|
| + }
|
| +};
|
|
|
| -template<>
|
| -bool Type::Iterator<i::Map>::matches(Handle<Type> type) {
|
| - return type->is_class();
|
| +template<class Config> template<class T>
|
| +bool TypeImpl<Config>::Iterator<T>::matches(TypeHandle type) {
|
| + return TypeImplIteratorAux<Config, T>::matches(type);
|
| }
|
|
|
| -template<>
|
| -bool Type::Iterator<i::Object>::matches(Handle<Type> type) {
|
| - return type->is_constant();
|
| +template<class Config> template<class T>
|
| +i::Handle<T> TypeImpl<Config>::Iterator<T>::Current() {
|
| + return TypeImplIteratorAux<Config, T>::current(get_type());
|
| }
|
|
|
|
|
| -template<class T>
|
| -void Type::Iterator<T>::Advance() {
|
| +template<class Config> template<class T>
|
| +void TypeImpl<Config>::Iterator<T>::Advance() {
|
| ++index_;
|
| - if (type_->is_union()) {
|
| - Handle<Unioned> unioned = type_->as_union();
|
| + if (type_->IsUnion()) {
|
| + UnionedHandle unioned = type_->AsUnion();
|
| for (; index_ < unioned->length(); ++index_) {
|
| - if (matches(union_get(unioned, index_))) return;
|
| + if (matches(Config::union_get(unioned, index_))) return;
|
| }
|
| } else if (index_ == 0 && matches(type_)) {
|
| return;
|
| @@ -105,30 +127,29 @@ void Type::Iterator<T>::Advance() {
|
| index_ = -1;
|
| }
|
|
|
| -template class Type::Iterator<i::Map>;
|
| -template class Type::Iterator<i::Object>;
|
| -
|
|
|
| // Get the smallest bitset subsuming this type.
|
| -int Type::LubBitset() {
|
| - if (this->is_bitset()) {
|
| - return this->as_bitset();
|
| - } else if (this->is_union()) {
|
| - Handle<Unioned> unioned = this->as_union();
|
| +template<class Config>
|
| +int TypeImpl<Config>::LubBitset() {
|
| + if (this->IsBitset()) {
|
| + return this->AsBitset();
|
| + } else if (this->IsUnion()) {
|
| + UnionedHandle unioned = this->AsUnion();
|
| int bitset = kNone;
|
| for (int i = 0; i < unioned->length(); ++i) {
|
| - bitset |= union_get(unioned, i)->LubBitset();
|
| + bitset |= Config::union_get(unioned, i)->LubBitset();
|
| }
|
| return bitset;
|
| - } else if (this->is_class()) {
|
| - return LubBitset(*this->as_class());
|
| + } else if (this->IsClass()) {
|
| + return LubBitset(*this->AsClass());
|
| } else {
|
| - return LubBitset(*this->as_constant());
|
| + return LubBitset(*this->AsConstant());
|
| }
|
| }
|
|
|
|
|
| -int Type::LubBitset(i::Object* value) {
|
| +template<class Config>
|
| +int TypeImpl<Config>::LubBitset(i::Object* value) {
|
| if (value->IsSmi()) return kSmi;
|
| i::Map* map = i::HeapObject::cast(value)->map();
|
| if (map->instance_type() == HEAP_NUMBER_TYPE) {
|
| @@ -145,11 +166,12 @@ int Type::LubBitset(i::Object* value) {
|
| if (value->IsTheHole()) return kAny; // TODO(rossberg): kNone?
|
| UNREACHABLE();
|
| }
|
| - return Type::LubBitset(map);
|
| + return LubBitset(map);
|
| }
|
|
|
|
|
| -int Type::LubBitset(i::Map* map) {
|
| +template<class Config>
|
| +int TypeImpl<Config>::LubBitset(i::Map* map) {
|
| switch (map->instance_type()) {
|
| case STRING_TYPE:
|
| case ASCII_STRING_TYPE:
|
| @@ -231,12 +253,13 @@ int Type::LubBitset(i::Map* map) {
|
|
|
|
|
| // Get the largest bitset subsumed by this type.
|
| -int Type::GlbBitset() {
|
| - if (this->is_bitset()) {
|
| - return this->as_bitset();
|
| - } else if (this->is_union()) {
|
| +template<class Config>
|
| +int TypeImpl<Config>::GlbBitset() {
|
| + if (this->IsBitset()) {
|
| + return this->AsBitset();
|
| + } else if (this->IsUnion()) {
|
| // All but the first are non-bitsets and thus would yield kNone anyway.
|
| - return union_get(this->as_union(), 0)->GlbBitset();
|
| + return Config::union_get(this->AsUnion(), 0)->GlbBitset();
|
| } else {
|
| return kNone;
|
| }
|
| @@ -244,37 +267,40 @@ int Type::GlbBitset() {
|
|
|
|
|
| // Most precise _current_ type of a value (usually its class).
|
| -Type* Type::OfCurrently(Handle<i::Object> value) {
|
| - if (value->IsSmi()) return Smi();
|
| +template<class Config>
|
| +typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::OfCurrently(
|
| + i::Handle<i::Object> value, Region* region) {
|
| + if (value->IsSmi()) return Smi(region);
|
| i::Map* map = i::HeapObject::cast(*value)->map();
|
| if (map->instance_type() == HEAP_NUMBER_TYPE ||
|
| map->instance_type() == ODDBALL_TYPE) {
|
| - return Type::Of(value);
|
| + return Of(value, region);
|
| }
|
| - return Class(i::handle(map));
|
| + return Class(i::handle(map), region);
|
| }
|
|
|
|
|
| // Check this <= that.
|
| -bool Type::SlowIs(Type* that) {
|
| +template<class Config>
|
| +bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
|
| // Fast path for bitsets.
|
| - if (this->is_none()) return true;
|
| - if (that->is_bitset()) {
|
| - return (this->LubBitset() | that->as_bitset()) == that->as_bitset();
|
| + if (this->IsNone()) return true;
|
| + if (that->IsBitset()) {
|
| + return (this->LubBitset() | that->AsBitset()) == that->AsBitset();
|
| }
|
|
|
| - if (that->is_class()) {
|
| - return this->is_class() && *this->as_class() == *that->as_class();
|
| + if (that->IsClass()) {
|
| + return this->IsClass() && *this->AsClass() == *that->AsClass();
|
| }
|
| - if (that->is_constant()) {
|
| - return this->is_constant() && *this->as_constant() == *that->as_constant();
|
| + if (that->IsConstant()) {
|
| + return this->IsConstant() && *this->AsConstant() == *that->AsConstant();
|
| }
|
|
|
| // (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T)
|
| - if (this->is_union()) {
|
| - Handle<Unioned> unioned = this->as_union();
|
| + if (this->IsUnion()) {
|
| + UnionedHandle unioned = this->AsUnion();
|
| for (int i = 0; i < unioned->length(); ++i) {
|
| - Handle<Type> this_i = union_get(unioned, i);
|
| + TypeHandle this_i = Config::union_get(unioned, i);
|
| if (!this_i->Is(that)) return false;
|
| }
|
| return true;
|
| @@ -282,13 +308,13 @@ bool Type::SlowIs(Type* that) {
|
|
|
| // T <= (T1 \/ ... \/ Tn) <=> (T <= T1) \/ ... \/ (T <= Tn)
|
| // (iff T is not a union)
|
| - ASSERT(!this->is_union());
|
| - if (that->is_union()) {
|
| - Handle<Unioned> unioned = that->as_union();
|
| + ASSERT(!this->IsUnion());
|
| + if (that->IsUnion()) {
|
| + UnionedHandle unioned = that->AsUnion();
|
| for (int i = 0; i < unioned->length(); ++i) {
|
| - Handle<Type> that_i = union_get(unioned, i);
|
| + TypeHandle that_i = Config::union_get(unioned, i);
|
| if (this->Is(that_i)) return true;
|
| - if (this->is_bitset()) break; // Fast fail, no other field is a bitset.
|
| + if (this->IsBitset()) break; // Fast fail, only first field is a bitset.
|
| }
|
| return false;
|
| }
|
| @@ -297,60 +323,63 @@ bool Type::SlowIs(Type* that) {
|
| }
|
|
|
|
|
| -bool Type::IsCurrently(Type* that) {
|
| +template<class Config>
|
| +bool TypeImpl<Config>::IsCurrently(TypeImpl* that) {
|
| return this->Is(that) ||
|
| - (this->is_constant() && that->is_class() &&
|
| - this->as_constant()->IsHeapObject() &&
|
| - i::HeapObject::cast(*this->as_constant())->map() == *that->as_class());
|
| + (this->IsConstant() && that->IsClass() &&
|
| + this->AsConstant()->IsHeapObject() &&
|
| + i::HeapObject::cast(*this->AsConstant())->map() == *that->AsClass());
|
| }
|
|
|
|
|
| // Check this overlaps that.
|
| -bool Type::Maybe(Type* that) {
|
| +template<class Config>
|
| +bool TypeImpl<Config>::Maybe(TypeImpl* that) {
|
| // Fast path for bitsets.
|
| - if (this->is_bitset()) {
|
| - return (this->as_bitset() & that->LubBitset()) != 0;
|
| + if (this->IsBitset()) {
|
| + return (this->AsBitset() & that->LubBitset()) != 0;
|
| }
|
| - if (that->is_bitset()) {
|
| - return (this->LubBitset() & that->as_bitset()) != 0;
|
| + if (that->IsBitset()) {
|
| + return (this->LubBitset() & that->AsBitset()) != 0;
|
| }
|
|
|
| // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T)
|
| - if (this->is_union()) {
|
| - Handle<Unioned> unioned = this->as_union();
|
| + if (this->IsUnion()) {
|
| + UnionedHandle unioned = this->AsUnion();
|
| for (int i = 0; i < unioned->length(); ++i) {
|
| - Handle<Type> this_i = union_get(unioned, i);
|
| + TypeHandle this_i = Config::union_get(unioned, i);
|
| if (this_i->Maybe(that)) return true;
|
| }
|
| return false;
|
| }
|
|
|
| // T overlaps (T1 \/ ... \/ Tn) <=> (T overlaps T1) \/ ... \/ (T overlaps Tn)
|
| - if (that->is_union()) {
|
| - Handle<Unioned> unioned = that->as_union();
|
| + if (that->IsUnion()) {
|
| + UnionedHandle unioned = that->AsUnion();
|
| for (int i = 0; i < unioned->length(); ++i) {
|
| - Handle<Type> that_i = union_get(unioned, i);
|
| + TypeHandle that_i = Config::union_get(unioned, i);
|
| if (this->Maybe(that_i)) return true;
|
| }
|
| return false;
|
| }
|
|
|
| - ASSERT(!that->is_union());
|
| - if (this->is_class()) {
|
| - return that->is_class() && *this->as_class() == *that->as_class();
|
| + ASSERT(!this->IsUnion() && !that->IsUnion());
|
| + if (this->IsClass()) {
|
| + return that->IsClass() && *this->AsClass() == *that->AsClass();
|
| }
|
| - if (this->is_constant()) {
|
| - return that->is_constant() && *this->as_constant() == *that->as_constant();
|
| + if (this->IsConstant()) {
|
| + return that->IsConstant() && *this->AsConstant() == *that->AsConstant();
|
| }
|
|
|
| return false;
|
| }
|
|
|
|
|
| -bool Type::InUnion(Handle<Unioned> unioned, int current_size) {
|
| - ASSERT(!this->is_union());
|
| +template<class Config>
|
| +bool TypeImpl<Config>::InUnion(UnionedHandle unioned, int current_size) {
|
| + ASSERT(!this->IsUnion());
|
| for (int i = 0; i < current_size; ++i) {
|
| - Handle<Type> type = union_get(unioned, i);
|
| + TypeHandle type = Config::union_get(unioned, i);
|
| if (this->Is(type)) return true;
|
| }
|
| return false;
|
| @@ -359,17 +388,20 @@ bool Type::InUnion(Handle<Unioned> unioned, int current_size) {
|
|
|
| // Get non-bitsets from this which are not subsumed by union, store at unioned,
|
| // starting at index. Returns updated index.
|
| -int Type::ExtendUnion(Handle<Unioned> result, int current_size) {
|
| +template<class Config>
|
| +int TypeImpl<Config>::ExtendUnion(UnionedHandle result, int current_size) {
|
| int old_size = current_size;
|
| - if (this->is_class() || this->is_constant()) {
|
| + if (this->IsClass() || this->IsConstant()) {
|
| if (!this->InUnion(result, old_size)) result->set(current_size++, this);
|
| - } else if (this->is_union()) {
|
| - Handle<Unioned> unioned = this->as_union();
|
| + } else if (this->IsUnion()) {
|
| + UnionedHandle unioned = this->AsUnion();
|
| for (int i = 0; i < unioned->length(); ++i) {
|
| - Handle<Type> type = union_get(unioned, i);
|
| - ASSERT(i == 0 || !(type->is_bitset() || type->Is(union_get(unioned, 0))));
|
| - if (type->is_bitset()) continue;
|
| - if (!type->InUnion(result, old_size)) result->set(current_size++, *type);
|
| + TypeHandle type = Config::union_get(unioned, i);
|
| + ASSERT(i == 0 ||
|
| + !(type->IsBitset() || type->Is(Config::union_get(unioned, 0))));
|
| + if (!type->IsBitset() && !type->InUnion(result, old_size)) {
|
| + result->set(current_size++, *type);
|
| + }
|
| }
|
| }
|
| return current_size;
|
| @@ -378,74 +410,75 @@ int Type::ExtendUnion(Handle<Unioned> result, int current_size) {
|
|
|
| // Union is O(1) on simple bit unions, but O(n*m) on structured unions.
|
| // TODO(rossberg): Should we use object sets somehow? Is it worth it?
|
| -Type* Type::Union(Handle<Type> type1, Handle<Type> type2) {
|
| +template<class Config>
|
| +typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union(
|
| + TypeHandle type1, TypeHandle type2, Region* region) {
|
| // Fast case: bit sets.
|
| - if (type1->is_bitset() && type2->is_bitset()) {
|
| - return from_bitset(type1->as_bitset() | type2->as_bitset());
|
| + if (type1->IsBitset() && type2->IsBitset()) {
|
| + return Config::from_bitset(type1->AsBitset() | type2->AsBitset(), region);
|
| }
|
|
|
| // Fast case: top or bottom types.
|
| - if (type1->SameValue(Type::Any())) return *type1;
|
| - if (type2->SameValue(Type::Any())) return *type2;
|
| - if (type1->SameValue(Type::None())) return *type2;
|
| - if (type2->SameValue(Type::None())) return *type1;
|
| + if (type1->IsAny()) return type1;
|
| + if (type2->IsAny()) return type2;
|
| + if (type1->IsNone()) return type2;
|
| + if (type2->IsNone()) return type1;
|
|
|
| // Semi-fast case: Unioned objects are neither involved nor produced.
|
| - if (!(type1->is_union() || type2->is_union())) {
|
| - if (type1->Is(type2)) return *type2;
|
| - if (type2->Is(type1)) return *type1;
|
| + if (!(type1->IsUnion() || type2->IsUnion())) {
|
| + if (type1->Is(type2)) return type2;
|
| + if (type2->Is(type1)) return type1;
|
| }
|
|
|
| // Slow case: may need to produce a Unioned object.
|
| - Isolate* isolate = NULL;
|
| - int size = type1->is_bitset() || type2->is_bitset() ? 1 : 0;
|
| - if (!type1->is_bitset()) {
|
| - isolate = i::HeapObject::cast(*type1)->GetIsolate();
|
| - size += (type1->is_union() ? type1->as_union()->length() : 1);
|
| + int size = type1->IsBitset() || type2->IsBitset() ? 1 : 0;
|
| + if (!type1->IsBitset()) {
|
| + size += (type1->IsUnion() ? type1->AsUnion()->length() : 1);
|
| }
|
| - if (!type2->is_bitset()) {
|
| - isolate = i::HeapObject::cast(*type2)->GetIsolate();
|
| - size += (type2->is_union() ? type2->as_union()->length() : 1);
|
| + if (!type2->IsBitset()) {
|
| + size += (type2->IsUnion() ? type2->AsUnion()->length() : 1);
|
| }
|
| - ASSERT(isolate != NULL);
|
| ASSERT(size >= 2);
|
| - Handle<Unioned> unioned = isolate->factory()->NewFixedArray(size);
|
| + UnionedHandle unioned = Config::union_create(size, region);
|
| size = 0;
|
|
|
| int bitset = type1->GlbBitset() | type2->GlbBitset();
|
| - if (bitset != kNone) unioned->set(size++, from_bitset(bitset));
|
| + if (bitset != kNone) unioned->set(size++, Config::from_bitset(bitset));
|
| size = type1->ExtendUnion(unioned, size);
|
| size = type2->ExtendUnion(unioned, size);
|
|
|
| if (size == 1) {
|
| - return *union_get(unioned, 0);
|
| + return Config::union_get(unioned, 0);
|
| } else if (size == unioned->length()) {
|
| - return from_handle(unioned);
|
| + return Config::from_union(unioned);
|
| }
|
|
|
| // There was an overlap. Copy to smaller union.
|
| - Handle<Unioned> result = isolate->factory()->NewFixedArray(size);
|
| + UnionedHandle result = Config::union_create(size, region);
|
| for (int i = 0; i < size; ++i) result->set(i, unioned->get(i));
|
| - return from_handle(result);
|
| + return Config::from_union(result);
|
| }
|
|
|
|
|
| // Get non-bitsets from this which are also in that, store at unioned,
|
| // starting at index. Returns updated index.
|
| -int Type::ExtendIntersection(
|
| - Handle<Unioned> result, Handle<Type> that, int current_size) {
|
| +template<class Config>
|
| +int TypeImpl<Config>::ExtendIntersection(
|
| + UnionedHandle result, TypeHandle that, int current_size) {
|
| int old_size = current_size;
|
| - if (this->is_class() || this->is_constant()) {
|
| + if (this->IsClass() || this->IsConstant()) {
|
| if (this->Is(that) && !this->InUnion(result, old_size))
|
| result->set(current_size++, this);
|
| - } else if (this->is_union()) {
|
| - Handle<Unioned> unioned = this->as_union();
|
| + } else if (this->IsUnion()) {
|
| + UnionedHandle unioned = this->AsUnion();
|
| for (int i = 0; i < unioned->length(); ++i) {
|
| - Handle<Type> type = union_get(unioned, i);
|
| - ASSERT(i == 0 || !(type->is_bitset() || type->Is(union_get(unioned, 0))));
|
| - if (type->is_bitset()) continue;
|
| - if (type->Is(that) && !type->InUnion(result, old_size))
|
| + TypeHandle type = Config::union_get(unioned, i);
|
| + ASSERT(i == 0 ||
|
| + !(type->IsBitset() || type->Is(Config::union_get(unioned, 0))));
|
| + if (!type->IsBitset() && type->Is(that) &&
|
| + !type->InUnion(result, old_size)) {
|
| result->set(current_size++, *type);
|
| + }
|
| }
|
| }
|
| return current_size;
|
| @@ -454,68 +487,60 @@ int Type::ExtendIntersection(
|
|
|
| // Intersection is O(1) on simple bit unions, but O(n*m) on structured unions.
|
| // TODO(rossberg): Should we use object sets somehow? Is it worth it?
|
| -Type* Type::Intersect(Handle<Type> type1, Handle<Type> type2) {
|
| +template<class Config>
|
| +typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect(
|
| + TypeHandle type1, TypeHandle type2, Region* region) {
|
| // Fast case: bit sets.
|
| - if (type1->is_bitset() && type2->is_bitset()) {
|
| - return from_bitset(type1->as_bitset() & type2->as_bitset());
|
| + if (type1->IsBitset() && type2->IsBitset()) {
|
| + return Config::from_bitset(type1->AsBitset() & type2->AsBitset(), region);
|
| }
|
|
|
| // Fast case: top or bottom types.
|
| - if (type1->SameValue(Type::None())) return *type1;
|
| - if (type2->SameValue(Type::None())) return *type2;
|
| - if (type1->SameValue(Type::Any())) return *type2;
|
| - if (type2->SameValue(Type::Any())) return *type1;
|
| + if (type1->IsNone()) return type1;
|
| + if (type2->IsNone()) return type2;
|
| + if (type1->IsAny()) return type2;
|
| + if (type2->IsAny()) return type1;
|
|
|
| // Semi-fast case: Unioned objects are neither involved nor produced.
|
| - if (!(type1->is_union() || type2->is_union())) {
|
| - if (type1->Is(type2)) return *type1;
|
| - if (type2->Is(type1)) return *type2;
|
| + if (!(type1->IsUnion() || type2->IsUnion())) {
|
| + if (type1->Is(type2)) return type1;
|
| + if (type2->Is(type1)) return type2;
|
| }
|
|
|
| // Slow case: may need to produce a Unioned object.
|
| - Isolate* isolate = NULL;
|
| int size = 0;
|
| - if (!type1->is_bitset()) {
|
| - isolate = i::HeapObject::cast(*type1)->GetIsolate();
|
| - size = (type1->is_union() ? type1->as_union()->length() : 2);
|
| + if (!type1->IsBitset()) {
|
| + size = (type1->IsUnion() ? type1->AsUnion()->length() : 2);
|
| }
|
| - if (!type2->is_bitset()) {
|
| - isolate = i::HeapObject::cast(*type2)->GetIsolate();
|
| - int size2 = (type2->is_union() ? type2->as_union()->length() : 2);
|
| + if (!type2->IsBitset()) {
|
| + int size2 = (type2->IsUnion() ? type2->AsUnion()->length() : 2);
|
| size = (size == 0 ? size2 : Min(size, size2));
|
| }
|
| - ASSERT(isolate != NULL);
|
| ASSERT(size >= 2);
|
| - Handle<Unioned> unioned = isolate->factory()->NewFixedArray(size);
|
| + UnionedHandle unioned = Config::union_create(size, region);
|
| size = 0;
|
|
|
| int bitset = type1->GlbBitset() & type2->GlbBitset();
|
| - if (bitset != kNone) unioned->set(size++, from_bitset(bitset));
|
| + if (bitset != kNone) unioned->set(size++, Config::from_bitset(bitset));
|
| size = type1->ExtendIntersection(unioned, type2, size);
|
| size = type2->ExtendIntersection(unioned, type1, size);
|
|
|
| if (size == 0) {
|
| - return None();
|
| + return None(region);
|
| } else if (size == 1) {
|
| - return *union_get(unioned, 0);
|
| + return Config::union_get(unioned, 0);
|
| } else if (size == unioned->length()) {
|
| - return from_handle(unioned);
|
| + return Config::from_union(unioned);
|
| }
|
|
|
| // There were dropped cases. Copy to smaller union.
|
| - Handle<Unioned> result = isolate->factory()->NewFixedArray(size);
|
| + UnionedHandle result = Config::union_create(size, region);
|
| for (int i = 0; i < size; ++i) result->set(i, unioned->get(i));
|
| - return from_handle(result);
|
| -}
|
| -
|
| -
|
| -Type* Type::Optional(Handle<Type> type) {
|
| - return type->is_bitset()
|
| - ? from_bitset(type->as_bitset() | kUndefined)
|
| - : Union(type, Undefined()->handle_via_isolate_of(*type));
|
| + return Config::from_union(result);
|
| }
|
|
|
|
|
| +// TODO(rossberg): this does not belong here.
|
| Representation Representation::FromType(Handle<Type> type) {
|
| if (type->Is(Type::None())) return Representation::None();
|
| if (type->Is(Type::Smi())) return Representation::Smi();
|
| @@ -526,14 +551,16 @@ Representation Representation::FromType(Handle<Type> type) {
|
|
|
|
|
| #ifdef OBJECT_PRINT
|
| -void Type::TypePrint() {
|
| +template<class Config>
|
| +void TypeImpl<Config>::TypePrint() {
|
| TypePrint(stdout);
|
| PrintF(stdout, "\n");
|
| Flush(stdout);
|
| }
|
|
|
|
|
| -const char* Type::bitset_name(int bitset) {
|
| +template<class Config>
|
| +const char* TypeImpl<Config>::bitset_name(int bitset) {
|
| switch (bitset) {
|
| #define PRINT_COMPOSED_TYPE(type, value) case k##type: return #type;
|
| BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE)
|
| @@ -544,9 +571,10 @@ const char* Type::bitset_name(int bitset) {
|
| }
|
|
|
|
|
| -void Type::TypePrint(FILE* out) {
|
| - if (is_bitset()) {
|
| - int bitset = as_bitset();
|
| +template<class Config>
|
| +void TypeImpl<Config>::TypePrint(FILE* out) {
|
| + if (this->IsBitset()) {
|
| + int bitset = this->AsBitset();
|
| const char* name = bitset_name(bitset);
|
| if (name != NULL) {
|
| PrintF(out, "%s", name);
|
| @@ -562,19 +590,19 @@ void Type::TypePrint(FILE* out) {
|
| }
|
| PrintF(out, ")");
|
| }
|
| - } else if (is_constant()) {
|
| - PrintF(out, "Constant(%p : ", static_cast<void*>(*as_constant()));
|
| - from_bitset(LubBitset())->TypePrint(out);
|
| + } else if (this->IsConstant()) {
|
| + PrintF(out, "Constant(%p : ", static_cast<void*>(*this->AsConstant()));
|
| + Config::from_bitset(this->LubBitset())->TypePrint(out);
|
| PrintF(")");
|
| - } else if (is_class()) {
|
| - PrintF(out, "Class(%p < ", static_cast<void*>(*as_class()));
|
| - from_bitset(LubBitset())->TypePrint(out);
|
| + } else if (this->IsClass()) {
|
| + PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()));
|
| + Config::from_bitset(this->LubBitset())->TypePrint(out);
|
| PrintF(")");
|
| - } else if (is_union()) {
|
| + } else if (this->IsUnion()) {
|
| PrintF(out, "(");
|
| - Handle<Unioned> unioned = as_union();
|
| + UnionedHandle unioned = this->AsUnion();
|
| for (int i = 0; i < unioned->length(); ++i) {
|
| - Handle<Type> type_i = union_get(unioned, i);
|
| + TypeHandle type_i = Config::union_get(unioned, i);
|
| if (i > 0) PrintF(out, " | ");
|
| type_i->TypePrint(out);
|
| }
|
| @@ -584,4 +612,9 @@ void Type::TypePrint(FILE* out) {
|
| #endif
|
|
|
|
|
| +template class TypeImpl<HeapTypeConfig>;
|
| +template class TypeImpl<HeapTypeConfig>::Iterator<i::Map>;
|
| +template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>;
|
| +
|
| +
|
| } } // namespace v8::internal
|
|
|