: Expression(isolate, pos),
label_(label),
statements_(statements),
- compare_type_(Type::None(isolate)),
+ compare_type_(Type::None(), isolate),
compare_id_(AstNode::GetNextId(isolate)),
entry_id_(AstNode::GetNextId(isolate)) {
}
op_(op),
left_(left),
right_(right),
- combined_type_(Type::None(isolate)) {
+ combined_type_(Type::None(), isolate) {
ASSERT(Token::IsCompareOp(op));
}
HValue* CodeStubGraphBuilder<NumberToStringStub>::BuildCodeStub() {
info()->MarkAsSavesCallerDoubles();
HValue* number = GetParameter(NumberToStringStub::kNumber);
- return BuildNumberToString(number, Type::Number(isolate()));
+ return BuildNumberToString(number, handle(Type::Number(), isolate()));
}
{
Push(BuildBinaryOperation(
state.op(), left, right,
- Type::String(isolate()), right_type,
+ handle(Type::String(), isolate()), right_type,
result_type, state.fixed_right_arg(),
allocation_mode));
}
{
Push(BuildBinaryOperation(
state.op(), left, right,
- left_type, Type::String(isolate()),
+ left_type, handle(Type::String(), isolate()),
result_type, state.fixed_right_arg(),
allocation_mode));
}
Isolate* isolate,
Handle<Map> map) {
if (state_.Contains(CompareNilICStub::GENERIC)) {
- return Type::Any(isolate);
+ return handle(Type::Any(), isolate);
}
- Handle<Type> result = Type::None(isolate);
+ Handle<Type> result(Type::None(), isolate);
if (state_.Contains(CompareNilICStub::UNDEFINED)) {
- result = Type::Union(result, Type::Undefined(isolate), isolate);
+ result = handle(Type::Union(result, handle(Type::Undefined(), isolate)),
+ isolate);
}
if (state_.Contains(CompareNilICStub::NULL_TYPE)) {
- result = Type::Union(result, Type::Null(isolate), isolate);
+ result = handle(Type::Union(result, handle(Type::Null(), isolate)),
+ isolate);
}
if (state_.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
- Handle<Type> type = map.is_null()
- ? Type::Detectable(isolate) : Type::Class(map, isolate);
- result = Type::Union(result, type, isolate);
+ Type* type = map.is_null() ? Type::Detectable() : Type::Class(map);
+ result = handle(Type::Union(result, handle(type, isolate)), isolate);
}
return result;
Isolate* isolate,
Handle<Map> map) {
Handle<Type> output_type = GetType(isolate, map);
- Handle<Type> nil_type = nil_value_ == kNullValue
- ? Type::Null(isolate) : Type::Undefined(isolate);
- return Type::Union(output_type, nil_type, isolate);
+ Handle<Type> nil_type = handle(nil_value_ == kNullValue
+ ? Type::Null() : Type::Undefined(), isolate);
+ return handle(Type::Union(output_type, nil_type), isolate);
}
HConstant* constant = HConstant::cast(value);
Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone());
if (number.has_value) {
- *expected = Type::Number(isolate());
+ *expected = handle(Type::Number(), isolate());
return AddInstruction(number.value);
}
}
Handle<Type> expected_type = *expected;
// Separate the number type from the rest.
- Handle<Type> expected_obj = Type::Intersect(
- expected_type, Type::NonNumber(isolate()), isolate());
- Handle<Type> expected_number = Type::Intersect(
- expected_type, Type::Number(isolate()), isolate());
+ Handle<Type> expected_obj = handle(Type::Intersect(
+ expected_type, handle(Type::NonNumber(), isolate())), isolate());
+ Handle<Type> expected_number = handle(Type::Intersect(
+ expected_type, handle(Type::Number(), isolate())), isolate());
// We expect to get a number.
// (We need to check first, since Type::None->Is(Type::Any()) == true.
if (expected_obj->Is(Type::Undefined())) {
// This is already done by HChange.
- *expected = Type::Union(
- expected_number, Type::Double(isolate()), isolate());
+ *expected = handle(Type::Union(
+ expected_number, handle(Type::Double(), isolate())), isolate());
return value;
}
Deoptimizer::SOFT);
// TODO(rossberg): we should be able to get rid of non-continuous
// defaults.
- left_type = Type::Any(isolate());
+ left_type = handle(Type::Any(), isolate());
} else {
if (!maybe_string_add) left = TruncateToNumber(left, &left_type);
left_rep = Representation::FromType(left_type);
if (right_type->Is(Type::None())) {
Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation",
Deoptimizer::SOFT);
- right_type = Type::Any(isolate());
+ right_type = handle(Type::Any(), isolate());
} else {
if (!maybe_string_add) right = TruncateToNumber(right, &right_type);
right_rep = Representation::FromType(right_type);
Add<HDeoptimize>("Insufficient type feedback for combined type "
"of binary operation",
Deoptimizer::SOFT);
- combined_type = left_type = right_type = Type::Any(isolate());
+ combined_type = left_type = right_type = handle(Type::Any(), isolate());
}
Representation left_rep = Representation::FromType(left_type);
} else {
ASSERT_EQ(Token::EQ, expr->op());
Handle<Type> type = expr->combined_type()->Is(Type::None())
- ? Type::Any(isolate_) : expr->combined_type();
+ ? handle(Type::Any(), isolate_)
+ : expr->combined_type();
HIfContinuation continuation;
BuildCompareNil(value, type, &continuation);
return ast_context()->ReturnContinuation(&continuation, expr->id());
ASSERT_EQ(1, call->arguments()->length());
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
HValue* number = Pop();
- HValue* result = BuildNumberToString(number, Type::Number(isolate()));
+ HValue* result = BuildNumberToString(
+ number, handle(Type::Number(), isolate()));
return ast_context()->ReturnValue(result);
}
Handle<Type> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) {
- return object->IsJSGlobalObject()
- ? Type::Constant(Handle<JSGlobalObject>::cast(object), isolate)
- : Type::OfCurrently(object, isolate);
+ Type* type = object->IsJSGlobalObject()
+ ? Type::Constant(Handle<JSGlobalObject>::cast(object))
+ : Type::OfCurrently(object);
+ return handle(type, isolate);
}
}
-Handle<Type> IC::MapToType(Handle<Map> map) {
- Isolate* isolate = map->GetIsolate();
- if (map->instance_type() == HEAP_NUMBER_TYPE) return Type::Number(isolate);
+Type* IC::MapToType(Handle<Map> map) {
+ if (map->instance_type() == HEAP_NUMBER_TYPE) return Type::Number();
// The only oddballs that can be recorded in ICs are booleans.
- if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean(isolate);
- return Type::Class(map, isolate);
+ if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean();
+ return Type::Class(map);
}
}
-bool IC::IsTransitionOfMonomorphicTarget(Handle<Type> type) {
+bool IC::IsTransitionOfMonomorphicTarget(Type* type) {
if (!type->IsClass()) return false;
Map* receiver_map = *type->AsClass();
Map* current_map = target()->FindFirstMap();
target()->is_keyed_call_stub() ||
!target().is_identical_to(code));
Code* old_handler = target()->FindFirstHandler();
- if (old_handler == *code && IsTransitionOfMonomorphicTarget(type)) {
+ if (old_handler == *code && IsTransitionOfMonomorphicTarget(*type)) {
UpdateMonomorphicIC(type, code, name);
break;
}
if (HasSideEffects()) {
result_kind = NONE;
} else if (result_kind == GENERIC && op_ == Token::ADD) {
- return Type::Union(Type::Number(isolate), Type::String(isolate), isolate);
+ return handle(Type::Union(handle(Type::Number(), isolate),
+ handle(Type::String(), isolate)), isolate);
} else if (result_kind == NUMBER && op_ == Token::SHR) {
- return Type::Unsigned32(isolate);
+ return handle(Type::Unsigned32(), isolate);
}
ASSERT_NE(GENERIC, result_kind);
return KindToType(result_kind, isolate);
// static
Handle<Type> BinaryOpIC::State::KindToType(Kind kind, Isolate* isolate) {
+ Type* type = NULL;
switch (kind) {
- case NONE: return Type::None(isolate);
- case SMI: return Type::Smi(isolate);
- case INT32: return Type::Signed32(isolate);
- case NUMBER: return Type::Number(isolate);
- case STRING: return Type::String(isolate);
- case GENERIC: return Type::Any(isolate);
+ case NONE: type = Type::None(); break;
+ case SMI: type = Type::Smi(); break;
+ case INT32: type = Type::Signed32(); break;
+ case NUMBER: type = Type::Number(); break;
+ case STRING: type = Type::String(); break;
+ case GENERIC: type = Type::Any(); break;
}
- UNREACHABLE();
- return Handle<Type>();
+ return handle(type, isolate);
}
CompareIC::State state,
Handle<Map> map) {
switch (state) {
- case CompareIC::UNINITIALIZED: return Type::None(isolate);
- case CompareIC::SMI: return Type::Smi(isolate);
- case CompareIC::NUMBER: return Type::Number(isolate);
- case CompareIC::STRING: return Type::String(isolate);
+ case CompareIC::UNINITIALIZED:
+ return handle(Type::None(), isolate);
+ case CompareIC::SMI:
+ return handle(Type::Smi(), isolate);
+ case CompareIC::NUMBER:
+ return handle(Type::Number(), isolate);
+ case CompareIC::STRING:
+ return handle(Type::String(), isolate);
case CompareIC::INTERNALIZED_STRING:
- return Type::InternalizedString(isolate);
- case CompareIC::UNIQUE_NAME: return Type::UniqueName(isolate);
- case CompareIC::OBJECT: return Type::Receiver(isolate);
+ return handle(Type::InternalizedString(), isolate);
+ case CompareIC::UNIQUE_NAME:
+ return handle(Type::UniqueName(), isolate);
+ case CompareIC::OBJECT:
+ return handle(Type::Receiver(), isolate);
case CompareIC::KNOWN_OBJECT:
- return map.is_null()
- ? Type::Receiver(isolate) : Type::Class(map, isolate);
- case CompareIC::GENERIC: return Type::Any(isolate);
+ return handle(
+ map.is_null() ? Type::Receiver() : Type::Class(map), isolate);
+ case CompareIC::GENERIC:
+ return handle(Type::Any(), isolate);
}
UNREACHABLE();
return Handle<Type>();
// well as smis.
// - The oddball map is only used for booleans.
static Handle<Map> TypeToMap(Type* type, Isolate* isolate);
- static Handle<Type> MapToType(Handle<Map> type);
+ static Type* MapToType(Handle<Map> type);
static Handle<Type> CurrentTypeOf(Handle<Object> object, Isolate* isolate);
ContextualMode contextual_mode() const {
virtual void UpdateMegamorphicCache(Type* type, Name* name, Code* code);
void CopyICToMegamorphicCache(Handle<String> name);
- bool IsTransitionOfMonomorphicTarget(Handle<Type> type);
+ bool IsTransitionOfMonomorphicTarget(Type* type);
void PatchCache(Handle<Type> type,
Handle<String> name,
Handle<Code> code);
class Map;
-template<class> class TypeImpl;
-struct HeapTypeConfig;
-typedef TypeImpl<HeapTypeConfig> Type;
+class Type;
class Code;
template<typename T> class Handle;
typedef List<Map*> MapList;
ASSERT(is_inline_cache_stub());
DisallowHeapAllocation no_allocation;
int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
+ Isolate* isolate = GetIsolate();
for (RelocIterator it(this, mask); !it.done(); it.next()) {
RelocInfo* info = it.rinfo();
Object* object = info->target_object();
if (object->IsMap()) {
Handle<Map> map(Map::cast(object));
- types->Add(IC::MapToType(map));
+ types->Add(handle(IC::MapToType(map), isolate));
}
}
}
Handle<Type> old_type(cell->type(), isolate);
// TODO(2803): Do not track ConsString as constant because they cannot be
// embedded into code.
- Handle<Type> new_type = value->IsConsString() || value->IsTheHole()
- ? Type::Any(isolate) : Type::Constant(value, isolate);
+ Handle<Type> new_type(value->IsConsString() || value->IsTheHole()
+ ? Type::Any()
+ : Type::Constant(value, isolate), isolate);
if (new_type->Is(old_type)) {
return old_type;
return new_type;
}
- return Type::Any(isolate);
+ return handle(Type::Any(), isolate);
}
class GlobalObject;
class ObjectVisitor;
class StringStream;
-// We cannot just say "class Type;" if it is created from a template... =8-?
-template<class> class TypeImpl;
-struct HeapTypeConfig;
-typedef TypeImpl<HeapTypeConfig> Type;
+class Type;
// A template-ized version of the IsXXX functions.
namespace internal {
class Smi;
-template<class> class TypeImpl;
-struct HeapTypeConfig;
-typedef TypeImpl<HeapTypeConfig> Type;
+class Type;
class TypeInfo;
// Type of properties.
static Representation Integer8() { return Representation(kInteger8); }
static Representation UInteger8() { return Representation(kUInteger8); }
static Representation Integer16() { return Representation(kInteger16); }
- static Representation UInteger16() { return Representation(kUInteger16); }
+ static Representation UInteger16() {
+ return Representation(kUInteger16);
+ }
static Representation Smi() { return Representation(kSmi); }
static Representation Integer32() { return Representation(kInteger32); }
static Representation Double() { return Representation(kDouble); }
TypeHandleList types(receiver_maps->length());
for (int i = 0; i < receiver_maps->length(); i++) {
- types.Add(Type::Class(receiver_maps->at(i), isolate()));
+ types.Add(handle(Type::Class(receiver_maps->at(i)), isolate()));
}
CodeHandleList handlers(receiver_maps->length());
KeyedLoadStubCompiler compiler(isolate_);
Handle<Object> info = GetInfo(id);
if (!info->IsCode()) {
// For some comparisons we don't have ICs, e.g. LiteralCompareTypeof.
- *left_type = *right_type = *combined_type = Type::None(isolate_);
+ *left_type = *right_type = *combined_type = handle(Type::None(), isolate_);
return;
}
Handle<Code> code = Handle<Code>::cast(info);
// operations covered by the BinaryOpIC we should always have them.
ASSERT(op < BinaryOpIC::State::FIRST_TOKEN ||
op > BinaryOpIC::State::LAST_TOKEN);
- *left = *right = *result = Type::None(isolate_);
+ *left = *right = *result = handle(Type::None(), isolate_);
*fixed_right_arg = Maybe<int>();
*allocation_site = Handle<AllocationSite>::null();
return;
Handle<Type> TypeFeedbackOracle::CountType(TypeFeedbackId id) {
Handle<Object> object = GetInfo(id);
- if (!object->IsCode()) return Type::None(isolate_);
+ if (!object->IsCode()) return handle(Type::None(), isolate_);
Handle<Code> code = Handle<Code>::cast(object);
ASSERT_EQ(Code::BINARY_OP_IC, code->kind());
BinaryOpIC::State state(code->extended_extra_ic_state());
namespace v8 {
namespace internal {
-template<class Config>
-int TypeImpl<Config>::NumClasses() {
- if (this->IsClass()) {
+int Type::NumClasses() {
+ if (is_class()) {
return 1;
- } else if (this->IsUnion()) {
- UnionedHandle unioned = this->AsUnion();
+ } else if (is_union()) {
+ Handle<Unioned> unioned = as_union();
int result = 0;
for (int i = 0; i < unioned->length(); ++i) {
- if (Config::union_get(unioned, i)->IsClass()) ++result;
+ if (union_get(unioned, i)->is_class()) ++result;
}
return result;
} else {
}
-template<class Config>
-int TypeImpl<Config>::NumConstants() {
- if (this->IsConstant()) {
+int Type::NumConstants() {
+ if (is_constant()) {
return 1;
- } else if (this->IsUnion()) {
- UnionedHandle unioned = this->AsUnion();
+ } else if (is_union()) {
+ Handle<Unioned> unioned = as_union();
int result = 0;
for (int i = 0; i < unioned->length(); ++i) {
- if (Config::union_get(unioned, i)->IsConstant()) ++result;
+ if (union_get(unioned, i)->is_constant()) ++result;
}
return result;
} else {
}
-template<class Config> template<class T>
-typename TypeImpl<Config>::TypeHandle
-TypeImpl<Config>::Iterator<T>::get_type() {
+template<class T>
+Handle<Type> Type::Iterator<T>::get_type() {
ASSERT(!Done());
- return type_->IsUnion() ? Config::union_get(type_->AsUnion(), index_) : type_;
+ return type_->is_union() ? union_get(type_->as_union(), index_) : type_;
}
+template<>
+Handle<i::Map> Type::Iterator<i::Map>::Current() {
+ return get_type()->as_class();
+}
-// 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<>
+Handle<i::Object> Type::Iterator<i::Object>::Current() {
+ return get_type()->as_constant();
+}
-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<class Config> template<class T>
-bool TypeImpl<Config>::Iterator<T>::matches(TypeHandle type) {
- return TypeImplIteratorAux<Config, T>::matches(type);
+template<>
+bool Type::Iterator<i::Map>::matches(Handle<Type> type) {
+ return type->is_class();
}
-template<class Config> template<class T>
-i::Handle<T> TypeImpl<Config>::Iterator<T>::Current() {
- return TypeImplIteratorAux<Config, T>::current(get_type());
+template<>
+bool Type::Iterator<i::Object>::matches(Handle<Type> type) {
+ return type->is_constant();
}
-template<class Config> template<class T>
-void TypeImpl<Config>::Iterator<T>::Advance() {
+template<class T>
+void Type::Iterator<T>::Advance() {
++index_;
- if (type_->IsUnion()) {
- UnionedHandle unioned = type_->AsUnion();
+ if (type_->is_union()) {
+ Handle<Unioned> unioned = type_->as_union();
for (; index_ < unioned->length(); ++index_) {
- if (matches(Config::union_get(unioned, index_))) return;
+ if (matches(union_get(unioned, index_))) return;
}
} else if (index_ == 0 && matches(type_)) {
return;
index_ = -1;
}
+template class Type::Iterator<i::Map>;
+template class Type::Iterator<i::Object>;
+
// Get the smallest bitset subsuming this type.
-template<class Config>
-int TypeImpl<Config>::LubBitset() {
- if (this->IsBitset()) {
- return this->AsBitset();
- } else if (this->IsUnion()) {
- UnionedHandle unioned = this->AsUnion();
+int Type::LubBitset() {
+ if (this->is_bitset()) {
+ return this->as_bitset();
+ } else if (this->is_union()) {
+ Handle<Unioned> unioned = this->as_union();
int bitset = kNone;
for (int i = 0; i < unioned->length(); ++i) {
- bitset |= Config::union_get(unioned, i)->LubBitset();
+ bitset |= union_get(unioned, i)->LubBitset();
}
return bitset;
- } else if (this->IsClass()) {
- return LubBitset(*this->AsClass());
+ } else if (this->is_class()) {
+ return LubBitset(*this->as_class());
} else {
- return LubBitset(*this->AsConstant());
+ return LubBitset(*this->as_constant());
}
}
-template<class Config>
-int TypeImpl<Config>::LubBitset(i::Object* value) {
+int Type::LubBitset(i::Object* value) {
if (value->IsSmi()) return kSmi;
i::Map* map = i::HeapObject::cast(value)->map();
if (map->instance_type() == HEAP_NUMBER_TYPE) {
if (value->IsTheHole()) return kAny; // TODO(rossberg): kNone?
UNREACHABLE();
}
- return LubBitset(map);
+ return Type::LubBitset(map);
}
-template<class Config>
-int TypeImpl<Config>::LubBitset(i::Map* map) {
+int Type::LubBitset(i::Map* map) {
switch (map->instance_type()) {
case STRING_TYPE:
case ASCII_STRING_TYPE:
// Get the largest bitset subsumed by this type.
-template<class Config>
-int TypeImpl<Config>::GlbBitset() {
- if (this->IsBitset()) {
- return this->AsBitset();
- } else if (this->IsUnion()) {
+int Type::GlbBitset() {
+ if (this->is_bitset()) {
+ return this->as_bitset();
+ } else if (this->is_union()) {
// All but the first are non-bitsets and thus would yield kNone anyway.
- return Config::union_get(this->AsUnion(), 0)->GlbBitset();
+ return union_get(this->as_union(), 0)->GlbBitset();
} else {
return kNone;
}
// Most precise _current_ type of a value (usually its class).
-template<class Config>
-typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::OfCurrently(
- i::Handle<i::Object> value, Region* region) {
- if (value->IsSmi()) return Smi(region);
+Type* Type::OfCurrently(Handle<i::Object> value) {
+ if (value->IsSmi()) return Smi();
i::Map* map = i::HeapObject::cast(*value)->map();
if (map->instance_type() == HEAP_NUMBER_TYPE ||
map->instance_type() == ODDBALL_TYPE) {
- return Of(value, region);
+ return Type::Of(value);
}
- return Class(i::handle(map), region);
+ return Class(i::handle(map));
}
// Check this <= that.
-template<class Config>
-bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
+bool Type::SlowIs(Type* that) {
// Fast path for bitsets.
- if (this->IsNone()) return true;
- if (that->IsBitset()) {
- return (this->LubBitset() | that->AsBitset()) == that->AsBitset();
+ if (this->is_none()) return true;
+ if (that->is_bitset()) {
+ return (this->LubBitset() | that->as_bitset()) == that->as_bitset();
}
- if (that->IsClass()) {
- return this->IsClass() && *this->AsClass() == *that->AsClass();
+ if (that->is_class()) {
+ return this->is_class() && *this->as_class() == *that->as_class();
}
- if (that->IsConstant()) {
- return this->IsConstant() && *this->AsConstant() == *that->AsConstant();
+ if (that->is_constant()) {
+ return this->is_constant() && *this->as_constant() == *that->as_constant();
}
// (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T)
- if (this->IsUnion()) {
- UnionedHandle unioned = this->AsUnion();
+ if (this->is_union()) {
+ Handle<Unioned> unioned = this->as_union();
for (int i = 0; i < unioned->length(); ++i) {
- TypeHandle this_i = Config::union_get(unioned, i);
+ Handle<Type> this_i = union_get(unioned, i);
if (!this_i->Is(that)) return false;
}
return true;
// T <= (T1 \/ ... \/ Tn) <=> (T <= T1) \/ ... \/ (T <= Tn)
// (iff T is not a union)
- ASSERT(!this->IsUnion());
- if (that->IsUnion()) {
- UnionedHandle unioned = that->AsUnion();
+ ASSERT(!this->is_union());
+ if (that->is_union()) {
+ Handle<Unioned> unioned = that->as_union();
for (int i = 0; i < unioned->length(); ++i) {
- TypeHandle that_i = Config::union_get(unioned, i);
+ Handle<Type> that_i = union_get(unioned, i);
if (this->Is(that_i)) return true;
- if (this->IsBitset()) break; // Fast fail, only first field is a bitset.
+ if (this->is_bitset()) break; // Fast fail, no other field is a bitset.
}
return false;
}
}
-template<class Config>
-bool TypeImpl<Config>::IsCurrently(TypeImpl* that) {
+bool Type::IsCurrently(Type* that) {
return this->Is(that) ||
- (this->IsConstant() && that->IsClass() &&
- this->AsConstant()->IsHeapObject() &&
- i::HeapObject::cast(*this->AsConstant())->map() == *that->AsClass());
+ (this->is_constant() && that->is_class() &&
+ this->as_constant()->IsHeapObject() &&
+ i::HeapObject::cast(*this->as_constant())->map() == *that->as_class());
}
// Check this overlaps that.
-template<class Config>
-bool TypeImpl<Config>::Maybe(TypeImpl* that) {
+bool Type::Maybe(Type* that) {
// Fast path for bitsets.
- if (this->IsBitset()) {
- return (this->AsBitset() & that->LubBitset()) != 0;
+ if (this->is_bitset()) {
+ return (this->as_bitset() & that->LubBitset()) != 0;
}
- if (that->IsBitset()) {
- return (this->LubBitset() & that->AsBitset()) != 0;
+ if (that->is_bitset()) {
+ return (this->LubBitset() & that->as_bitset()) != 0;
}
// (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T)
- if (this->IsUnion()) {
- UnionedHandle unioned = this->AsUnion();
+ if (this->is_union()) {
+ Handle<Unioned> unioned = this->as_union();
for (int i = 0; i < unioned->length(); ++i) {
- TypeHandle this_i = Config::union_get(unioned, i);
+ Handle<Type> this_i = 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->IsUnion()) {
- UnionedHandle unioned = that->AsUnion();
+ if (that->is_union()) {
+ Handle<Unioned> unioned = that->as_union();
for (int i = 0; i < unioned->length(); ++i) {
- TypeHandle that_i = Config::union_get(unioned, i);
+ Handle<Type> that_i = union_get(unioned, i);
if (this->Maybe(that_i)) return true;
}
return false;
}
- ASSERT(!this->IsUnion() && !that->IsUnion());
- if (this->IsClass()) {
- return that->IsClass() && *this->AsClass() == *that->AsClass();
+ ASSERT(!that->is_union());
+ if (this->is_class()) {
+ return that->is_class() && *this->as_class() == *that->as_class();
}
- if (this->IsConstant()) {
- return that->IsConstant() && *this->AsConstant() == *that->AsConstant();
+ if (this->is_constant()) {
+ return that->is_constant() && *this->as_constant() == *that->as_constant();
}
return false;
}
-template<class Config>
-bool TypeImpl<Config>::InUnion(UnionedHandle unioned, int current_size) {
- ASSERT(!this->IsUnion());
+bool Type::InUnion(Handle<Unioned> unioned, int current_size) {
+ ASSERT(!this->is_union());
for (int i = 0; i < current_size; ++i) {
- TypeHandle type = Config::union_get(unioned, i);
+ Handle<Type> type = union_get(unioned, i);
if (this->Is(type)) return true;
}
return false;
// Get non-bitsets from this which are not subsumed by union, store at unioned,
// starting at index. Returns updated index.
-template<class Config>
-int TypeImpl<Config>::ExtendUnion(UnionedHandle result, int current_size) {
+int Type::ExtendUnion(Handle<Unioned> result, int current_size) {
int old_size = current_size;
- if (this->IsClass() || this->IsConstant()) {
+ if (this->is_class() || this->is_constant()) {
if (!this->InUnion(result, old_size)) result->set(current_size++, this);
- } else if (this->IsUnion()) {
- UnionedHandle unioned = this->AsUnion();
+ } else if (this->is_union()) {
+ Handle<Unioned> unioned = this->as_union();
for (int i = 0; i < unioned->length(); ++i) {
- 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);
- }
+ 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);
}
}
return 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?
-template<class Config>
-typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union(
- TypeHandle type1, TypeHandle type2, Region* region) {
+Type* Type::Union(Handle<Type> type1, Handle<Type> type2) {
// Fast case: bit sets.
- if (type1->IsBitset() && type2->IsBitset()) {
- return Config::from_bitset(type1->AsBitset() | type2->AsBitset(), region);
+ if (type1->is_bitset() && type2->is_bitset()) {
+ return from_bitset(type1->as_bitset() | type2->as_bitset());
}
// Fast case: top or bottom types.
- if (type1->IsAny()) return type1;
- if (type2->IsAny()) return type2;
- if (type1->IsNone()) return type2;
- if (type2->IsNone()) return type1;
+ 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;
// Semi-fast case: Unioned objects are neither involved nor produced.
- if (!(type1->IsUnion() || type2->IsUnion())) {
- if (type1->Is(type2)) return type2;
- if (type2->Is(type1)) return type1;
+ if (!(type1->is_union() || type2->is_union())) {
+ if (type1->Is(type2)) return *type2;
+ if (type2->Is(type1)) return *type1;
}
// Slow case: may need to produce a Unioned object.
- int size = type1->IsBitset() || type2->IsBitset() ? 1 : 0;
- if (!type1->IsBitset()) {
- size += (type1->IsUnion() ? type1->AsUnion()->length() : 1);
+ 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);
}
- if (!type2->IsBitset()) {
- size += (type2->IsUnion() ? type2->AsUnion()->length() : 1);
+ if (!type2->is_bitset()) {
+ isolate = i::HeapObject::cast(*type2)->GetIsolate();
+ size += (type2->is_union() ? type2->as_union()->length() : 1);
}
+ ASSERT(isolate != NULL);
ASSERT(size >= 2);
- UnionedHandle unioned = Config::union_create(size, region);
+ Handle<Unioned> unioned = isolate->factory()->NewFixedArray(size);
size = 0;
int bitset = type1->GlbBitset() | type2->GlbBitset();
- if (bitset != kNone) unioned->set(size++, Config::from_bitset(bitset));
+ if (bitset != kNone) unioned->set(size++, from_bitset(bitset));
size = type1->ExtendUnion(unioned, size);
size = type2->ExtendUnion(unioned, size);
if (size == 1) {
- return Config::union_get(unioned, 0);
+ return *union_get(unioned, 0);
} else if (size == unioned->length()) {
- return Config::from_union(unioned);
+ return from_handle(unioned);
}
// There was an overlap. Copy to smaller union.
- UnionedHandle result = Config::union_create(size, region);
+ Handle<Unioned> result = isolate->factory()->NewFixedArray(size);
for (int i = 0; i < size; ++i) result->set(i, unioned->get(i));
- return Config::from_union(result);
+ return from_handle(result);
}
// Get non-bitsets from this which are also in that, store at unioned,
// starting at index. Returns updated index.
-template<class Config>
-int TypeImpl<Config>::ExtendIntersection(
- UnionedHandle result, TypeHandle that, int current_size) {
+int Type::ExtendIntersection(
+ Handle<Unioned> result, Handle<Type> that, int current_size) {
int old_size = current_size;
- if (this->IsClass() || this->IsConstant()) {
+ if (this->is_class() || this->is_constant()) {
if (this->Is(that) && !this->InUnion(result, old_size))
result->set(current_size++, this);
- } else if (this->IsUnion()) {
- UnionedHandle unioned = this->AsUnion();
+ } else if (this->is_union()) {
+ Handle<Unioned> unioned = this->as_union();
for (int i = 0; i < unioned->length(); ++i) {
- 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)) {
+ 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))
result->set(current_size++, *type);
- }
}
}
return current_size;
// 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?
-template<class Config>
-typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect(
- TypeHandle type1, TypeHandle type2, Region* region) {
+Type* Type::Intersect(Handle<Type> type1, Handle<Type> type2) {
// Fast case: bit sets.
- if (type1->IsBitset() && type2->IsBitset()) {
- return Config::from_bitset(type1->AsBitset() & type2->AsBitset(), region);
+ if (type1->is_bitset() && type2->is_bitset()) {
+ return from_bitset(type1->as_bitset() & type2->as_bitset());
}
// Fast case: top or bottom types.
- if (type1->IsNone()) return type1;
- if (type2->IsNone()) return type2;
- if (type1->IsAny()) return type2;
- if (type2->IsAny()) return type1;
+ 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;
// Semi-fast case: Unioned objects are neither involved nor produced.
- if (!(type1->IsUnion() || type2->IsUnion())) {
- if (type1->Is(type2)) return type1;
- if (type2->Is(type1)) return type2;
+ if (!(type1->is_union() || type2->is_union())) {
+ 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->IsBitset()) {
- size = (type1->IsUnion() ? type1->AsUnion()->length() : 2);
+ if (!type1->is_bitset()) {
+ isolate = i::HeapObject::cast(*type1)->GetIsolate();
+ size = (type1->is_union() ? type1->as_union()->length() : 2);
}
- if (!type2->IsBitset()) {
- int size2 = (type2->IsUnion() ? type2->AsUnion()->length() : 2);
+ if (!type2->is_bitset()) {
+ isolate = i::HeapObject::cast(*type2)->GetIsolate();
+ int size2 = (type2->is_union() ? type2->as_union()->length() : 2);
size = (size == 0 ? size2 : Min(size, size2));
}
+ ASSERT(isolate != NULL);
ASSERT(size >= 2);
- UnionedHandle unioned = Config::union_create(size, region);
+ Handle<Unioned> unioned = isolate->factory()->NewFixedArray(size);
size = 0;
int bitset = type1->GlbBitset() & type2->GlbBitset();
- if (bitset != kNone) unioned->set(size++, Config::from_bitset(bitset));
+ if (bitset != kNone) unioned->set(size++, from_bitset(bitset));
size = type1->ExtendIntersection(unioned, type2, size);
size = type2->ExtendIntersection(unioned, type1, size);
if (size == 0) {
- return None(region);
+ return None();
} else if (size == 1) {
- return Config::union_get(unioned, 0);
+ return *union_get(unioned, 0);
} else if (size == unioned->length()) {
- return Config::from_union(unioned);
+ return from_handle(unioned);
}
// There were dropped cases. Copy to smaller union.
- UnionedHandle result = Config::union_create(size, region);
+ Handle<Unioned> result = isolate->factory()->NewFixedArray(size);
for (int i = 0; i < size; ++i) result->set(i, unioned->get(i));
- return Config::from_union(result);
+ 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));
}
-// 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();
#ifdef OBJECT_PRINT
-template<class Config>
-void TypeImpl<Config>::TypePrint() {
+void Type::TypePrint() {
TypePrint(stdout);
PrintF(stdout, "\n");
Flush(stdout);
}
-template<class Config>
-const char* TypeImpl<Config>::bitset_name(int bitset) {
+const char* Type::bitset_name(int bitset) {
switch (bitset) {
#define PRINT_COMPOSED_TYPE(type, value) case k##type: return #type;
BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE)
}
-template<class Config>
-void TypeImpl<Config>::TypePrint(FILE* out) {
- if (this->IsBitset()) {
- int bitset = this->AsBitset();
+void Type::TypePrint(FILE* out) {
+ if (is_bitset()) {
+ int bitset = as_bitset();
const char* name = bitset_name(bitset);
if (name != NULL) {
PrintF(out, "%s", name);
}
PrintF(out, ")");
}
- } else if (this->IsConstant()) {
- PrintF(out, "Constant(%p : ", static_cast<void*>(*this->AsConstant()));
- Config::from_bitset(this->LubBitset())->TypePrint(out);
+ } else if (is_constant()) {
+ PrintF(out, "Constant(%p : ", static_cast<void*>(*as_constant()));
+ from_bitset(LubBitset())->TypePrint(out);
PrintF(")");
- } else if (this->IsClass()) {
- PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()));
- Config::from_bitset(this->LubBitset())->TypePrint(out);
+ } else if (is_class()) {
+ PrintF(out, "Class(%p < ", static_cast<void*>(*as_class()));
+ from_bitset(LubBitset())->TypePrint(out);
PrintF(")");
- } else if (this->IsUnion()) {
+ } else if (is_union()) {
PrintF(out, "(");
- UnionedHandle unioned = this->AsUnion();
+ Handle<Unioned> unioned = as_union();
for (int i = 0; i < unioned->length(); ++i) {
- TypeHandle type_i = Config::union_get(unioned, i);
+ Handle<Type> type_i = union_get(unioned, i);
if (i > 0) PrintF(out, " | ");
type_i->TypePrint(out);
}
#endif
-template class TypeImpl<HeapTypeConfig>;
-template class TypeImpl<HeapTypeConfig>::Iterator<i::Map>;
-template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>;
-
-
} } // namespace v8::internal
V(Detectable, kAllocated - kUndetectable)
-// struct Config {
-// typedef Base;
-// typedef Unioned;
-// typedef Region;
-// template<class> struct Handle { typedef type; } // No template typedefs...
-// static Handle<Type>::type handle(Type* type); // !is_bitset(type)
-// static bool is_bitset(Type* type);
-// static bool is_class(Type* type);
-// static bool is_constant(Type* type);
-// static bool is_union(Type* type);
-// static int as_bitset(Type* type);
-// static i::Handle<i::Map> as_class(Type* type);
-// static i::Handle<i::Object> as_constant(Type* type);
-// static Handle<Unioned>::type as_union(Type* type);
-// static Type* from_bitset(int bitset);
-// static Handle<Type>::type from_bitset(int bitset, Region* region);
-// static Handle<Type>::type from_class(i::Handle<i::Map> map, Region* region)
-// static Handle<Type>::type from_constant(
-// i::Handle<i::Object> value, Region* region);
-// static Handle<Type>::type from_union(Handle<Unioned>::T unioned);
-// static Handle<Unioned>::type union_create(int size, Region* region);
-// static Handle<Type>::type union_get(Handle<Unioned>::T unioned, int i);
-// }
-template<class Config>
-class TypeImpl : public Config::Base {
+class Type : public Object {
public:
- typedef typename Config::template Handle<TypeImpl>::type TypeHandle;
- typedef typename Config::Region Region;
-
- #define DEFINE_TYPE_CONSTRUCTOR(type, value) \
- static TypeImpl* type() { return Config::from_bitset(k##type); } \
- static TypeHandle type(Region* region) { \
- return Config::from_bitset(k##type, region); \
- }
+ #define DEFINE_TYPE_CONSTRUCTOR(type, value) \
+ static Type* type() { return from_bitset(k##type); }
BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
#undef DEFINE_TYPE_CONSTRUCTOR
- static TypeHandle Class(i::Handle<i::Map> map, Region* region) {
- return Config::from_class(map, region);
+ static Type* Class(Handle<i::Map> map) { return from_handle(map); }
+ static Type* Constant(Handle<i::HeapObject> value) {
+ return Constant(value, value->GetIsolate());
}
- static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
- return Config::from_constant(value, region);
+ static Type* Constant(Handle<i::Object> value, Isolate* isolate) {
+ return from_handle(isolate->factory()->NewBox(value));
}
- static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg);
- static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg);
+ static Type* Union(Handle<Type> type1, Handle<Type> type2);
+ static Type* Intersect(Handle<Type> type1, Handle<Type> type2);
+ static Type* Optional(Handle<Type> type); // type \/ Undefined
- static TypeHandle Of(i::Handle<i::Object> value, Region* region) {
- return Config::from_bitset(LubBitset(*value), region);
+ static Type* Of(Handle<i::Object> value) {
+ return from_bitset(LubBitset(*value));
}
- bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); }
- bool Is(TypeHandle that) { return this->Is(*that); }
- bool Maybe(TypeImpl* that);
- bool Maybe(TypeHandle that) { return this->Maybe(*that); }
+ bool Is(Type* that) { return this == that || SlowIs(that); }
+ bool Is(Handle<Type> that) { return this->Is(*that); }
+ bool Maybe(Type* that);
+ bool Maybe(Handle<Type> that) { return this->Maybe(*that); }
// State-dependent versions of Of and Is that consider subtyping between
// a constant and its map class.
- static TypeHandle OfCurrently(i::Handle<i::Object> value, Region* region);
- bool IsCurrently(TypeImpl* that);
- bool IsCurrently(TypeHandle that) { return this->IsCurrently(*that); }
+ static Type* OfCurrently(Handle<i::Object> value);
+ bool IsCurrently(Type* that);
+ bool IsCurrently(Handle<Type> that) { return this->IsCurrently(*that); }
- bool IsClass() { return Config::is_class(this); }
- bool IsConstant() { return Config::is_constant(this); }
- i::Handle<i::Map> AsClass() { return Config::as_class(this); }
- i::Handle<i::Object> AsConstant() { return Config::as_constant(this); }
+ bool IsClass() { return is_class(); }
+ bool IsConstant() { return is_constant(); }
+ Handle<i::Map> AsClass() { return as_class(); }
+ Handle<i::Object> AsConstant() { return as_constant(); }
int NumClasses();
int NumConstants();
class Iterator {
public:
bool Done() const { return index_ < 0; }
- i::Handle<T> Current();
+ Handle<T> Current();
void Advance();
private:
- template<class> friend class TypeImpl;
+ friend class Type;
Iterator() : index_(-1) {}
- explicit Iterator(TypeHandle type) : type_(type), index_(-1) {
+ explicit Iterator(Handle<Type> type) : type_(type), index_(-1) {
Advance();
}
- inline bool matches(TypeHandle type);
- inline TypeHandle get_type();
+ inline bool matches(Handle<Type> type);
+ inline Handle<Type> get_type();
- TypeHandle type_;
+ Handle<Type> type_;
int index_;
};
Iterator<i::Map> Classes() {
- if (this->IsBitset()) return Iterator<i::Map>();
- return Iterator<i::Map>(Config::handle(this));
+ if (this->is_bitset()) return Iterator<i::Map>();
+ return Iterator<i::Map>(this->handle());
}
Iterator<i::Object> Constants() {
- if (this->IsBitset()) return Iterator<i::Object>();
- return Iterator<i::Object>(Config::handle(this));
+ if (this->is_bitset()) return Iterator<i::Object>();
+ return Iterator<i::Object>(this->handle());
}
- static TypeImpl* cast(i::Object* object) {
- TypeImpl* t = static_cast<Type*>(object);
- ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsUnion());
+ static Type* cast(i::Object* object) {
+ Type* t = static_cast<Type*>(object);
+ ASSERT(t->is_bitset() || t->is_class() ||
+ t->is_constant() || t->is_union());
return t;
}
#endif
private:
- template<class> friend class Iterator;
-
// A union is a fixed array containing types. Invariants:
// - its length is at least 2
// - at most one field is a bitset, and it must go into index 0
// - no field is a union
- typedef typename Config::Unioned Unioned;
- typedef typename Config::template Handle<Unioned>::type UnionedHandle;
+ typedef FixedArray Unioned;
enum {
#define DECLARE_TYPE(type, value) k##type = (value),
kUnusedEOL = 0
};
- bool IsNone() { return this == None(); }
- bool IsAny() { return this == Any(); }
- bool IsBitset() { return Config::is_bitset(this); }
- bool IsUnion() { return Config::is_union(this); }
- int AsBitset() { return Config::as_bitset(this); }
- UnionedHandle AsUnion() { return Config::as_union(this); }
+ bool is_none() { return this == None(); }
+ bool is_bitset() { return this->IsSmi(); }
+ bool is_class() { return this->IsMap(); }
+ bool is_constant() { return this->IsBox(); }
+ bool is_union() { return this->IsFixedArray(); }
- bool SlowIs(TypeImpl* that);
+ bool SlowIs(Type* that);
+
+ int as_bitset() { return Smi::cast(this)->value(); }
+ Handle<i::Map> as_class() { return Handle<i::Map>::cast(handle()); }
+ Handle<i::Object> as_constant() {
+ Handle<i::Box> box = Handle<i::Box>::cast(handle());
+ return i::handle(box->value(), box->GetIsolate());
+ }
+ Handle<Unioned> as_union() { return Handle<Unioned>::cast(handle()); }
+
+ Handle<Type> handle() { return handle_via_isolate_of(this); }
+ Handle<Type> handle_via_isolate_of(Type* type) {
+ ASSERT(type->IsHeapObject());
+ return i::handle(this, i::HeapObject::cast(type)->GetIsolate());
+ }
+
+ static Type* from_bitset(int bitset) {
+ return static_cast<Type*>(i::Object::cast(i::Smi::FromInt(bitset)));
+ }
+ static Type* from_handle(Handle<i::HeapObject> handle) {
+ return static_cast<Type*>(i::Object::cast(*handle));
+ }
+
+ static Handle<Type> union_get(Handle<Unioned> unioned, int i) {
+ Type* type = static_cast<Type*>(unioned->get(i));
+ ASSERT(!type->is_union());
+ return type->handle_via_isolate_of(from_handle(unioned));
+ }
int LubBitset(); // least upper bound that's a bitset
int GlbBitset(); // greatest lower bound that's a bitset
static int LubBitset(i::Object* value);
static int LubBitset(i::Map* map);
- bool InUnion(UnionedHandle unioned, int current_size);
- int ExtendUnion(UnionedHandle unioned, int current_size);
+ bool InUnion(Handle<Unioned> unioned, int current_size);
+ int ExtendUnion(Handle<Unioned> unioned, int current_size);
int ExtendIntersection(
- UnionedHandle unioned, TypeHandle type, int current_size);
+ Handle<Unioned> unioned, Handle<Type> type, int current_size);
static const char* bitset_name(int bitset);
};
-struct HeapTypeConfig {
- typedef TypeImpl<HeapTypeConfig> Type;
- typedef i::Object Base;
- typedef i::FixedArray Unioned;
- typedef i::Isolate Region;
- template<class T> struct Handle { typedef i::Handle<T> type; };
-
- static i::Handle<Type> handle(Type* type) {
- return i::handle(type, i::HeapObject::cast(type)->GetIsolate());
- }
-
- static bool is_bitset(Type* type) { return type->IsSmi(); }
- static bool is_class(Type* type) { return type->IsMap(); }
- static bool is_constant(Type* type) { return type->IsBox(); }
- static bool is_union(Type* type) { return type->IsFixedArray(); }
-
- static int as_bitset(Type* type) {
- return Smi::cast(type)->value();
- }
- static i::Handle<i::Map> as_class(Type* type) {
- return i::handle(i::Map::cast(type));
- }
- static i::Handle<i::Object> as_constant(Type* type) {
- i::Box* box = i::Box::cast(type);
- return i::handle(box->value(), box->GetIsolate());
- }
- static i::Handle<Unioned> as_union(Type* type) {
- return i::handle(i::FixedArray::cast(type));
- }
+// A simple struct to represent a pair of lower/upper type bounds.
+struct Bounds {
+ Handle<Type> lower;
+ Handle<Type> upper;
- static Type* from_bitset(int bitset) {
- return Type::cast(i::Smi::FromInt(bitset));
- }
- static i::Handle<Type> from_bitset(int bitset, Isolate* isolate) {
- return i::handle(from_bitset(bitset), isolate);
- }
- static i::Handle<Type> from_class(i::Handle<i::Map> map, Isolate* isolate) {
- return i::Handle<Type>::cast(i::Handle<Object>::cast(map));
- }
- static i::Handle<Type> from_constant(
- i::Handle<i::Object> value, Isolate* isolate) {
- ASSERT(isolate || value->IsHeapObject());
- if (!isolate) isolate = i::HeapObject::cast(*value)->GetIsolate();
- i::Handle<Box> box = isolate->factory()->NewBox(value);
- return i::Handle<Type>::cast(i::Handle<Object>::cast(box));
- }
- static i::Handle<Type> from_union(i::Handle<Unioned> unioned) {
- return i::Handle<Type>::cast(i::Handle<Object>::cast(unioned));
+ Bounds() {}
+ Bounds(Handle<Type> l, Handle<Type> u) : lower(l), upper(u) {
+ ASSERT(lower->Is(upper));
}
-
- static i::Handle<Unioned> union_create(int size, Isolate* isolate) {
- return isolate->factory()->NewFixedArray(size);
+ Bounds(Type* l, Type* u, Isolate* isl) : lower(l, isl), upper(u, isl) {
+ ASSERT(lower->Is(upper));
}
- static i::Handle<Type> union_get(i::Handle<Unioned> unioned, int i) {
- Type* type = static_cast<Type*>(unioned->get(i));
- ASSERT(!is_union(type));
- return i::handle(type, unioned->GetIsolate());
+ explicit Bounds(Handle<Type> t) : lower(t), upper(t) {
+ ASSERT(lower->Is(upper));
}
-};
-
-typedef TypeImpl<HeapTypeConfig> Type;
-
-
-// A simple struct to represent a pair of lower/upper type bounds.
-template<class Config>
-struct BoundsImpl {
- typedef TypeImpl<Config> Type;
- typedef typename Type::TypeHandle TypeHandle;
- typedef typename Type::Region Region;
-
- TypeHandle lower;
- TypeHandle upper;
-
- BoundsImpl() {}
- explicit BoundsImpl(TypeHandle t) : lower(t), upper(t) {}
- BoundsImpl(TypeHandle l, TypeHandle u) : lower(l), upper(u) {
+ Bounds(Type* t, Isolate* isl) : lower(t, isl), upper(t, isl) {
ASSERT(lower->Is(upper));
}
// Unrestricted bounds.
- static BoundsImpl Unbounded(Region* region) {
- return BoundsImpl(Type::None(region), Type::Any(region));
+ static Bounds Unbounded(Isolate* isl) {
+ return Bounds(Type::None(), Type::Any(), isl);
}
// Meet: both b1 and b2 are known to hold.
- static BoundsImpl Both(BoundsImpl b1, BoundsImpl b2, Region* region) {
- TypeHandle lower = Type::Union(b1.lower, b2.lower, region);
- TypeHandle upper = Type::Intersect(b1.upper, b2.upper, region);
+ static Bounds Both(Bounds b1, Bounds b2, Isolate* isl) {
+ Handle<Type> lower(Type::Union(b1.lower, b2.lower), isl);
+ Handle<Type> upper(Type::Intersect(b1.upper, b2.upper), isl);
// Lower bounds are considered approximate, correct as necessary.
- lower = Type::Intersect(lower, upper, region);
- return BoundsImpl(lower, upper);
+ lower = handle(Type::Intersect(lower, upper), isl);
+ return Bounds(lower, upper);
}
// Join: either b1 or b2 is known to hold.
- static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region* region) {
- TypeHandle lower = Type::Intersect(b1.lower, b2.lower, region);
- TypeHandle upper = Type::Union(b1.upper, b2.upper, region);
- return BoundsImpl(lower, upper);
+ static Bounds Either(Bounds b1, Bounds b2, Isolate* isl) {
+ return Bounds(
+ handle(Type::Intersect(b1.lower, b2.lower), isl),
+ handle(Type::Union(b1.upper, b2.upper), isl));
}
- static BoundsImpl NarrowLower(BoundsImpl b, TypeHandle t, Region* region) {
+ static Bounds NarrowLower(Bounds b, Handle<Type> t, Isolate* isl) {
// Lower bounds are considered approximate, correct as necessary.
- t = Type::Intersect(t, b.upper, region);
- TypeHandle lower = Type::Union(b.lower, t, region);
- return BoundsImpl(lower, b.upper);
+ t = handle(Type::Intersect(t, b.upper), isl);
+ return Bounds(handle(Type::Union(b.lower, t), isl), b.upper);
}
- static BoundsImpl NarrowUpper(BoundsImpl b, TypeHandle t, Region* region) {
- TypeHandle lower = Type::Intersect(b.lower, t, region);
- TypeHandle upper = Type::Intersect(b.upper, t, region);
- return BoundsImpl(lower, upper);
+ static Bounds NarrowUpper(Bounds b, Handle<Type> t, Isolate* isl) {
+ return Bounds(
+ handle(Type::Intersect(b.lower, t), isl),
+ handle(Type::Intersect(b.upper, t), isl));
}
};
-typedef BoundsImpl<HeapTypeConfig> Bounds;
-
-
} } // namespace v8::internal
#endif // V8_TYPES_H_
#undef RECURSE
+Effect AstTyper::ObservedOnStack(Object* value) {
+ Type* lower = Type::OfCurrently(Handle<Object>(value, isolate()));
+ return Effect(Bounds(lower, Type::Any(), isolate()));
+}
+
+
#ifdef OBJECT_PRINT
static void PrintObserved(Variable* var, Object* value, Handle<Type> type) {
PrintF(" observed %s ", var->IsParameter() ? "param" : "local");
#endif // OBJECT_PRINT
-Effect AstTyper::ObservedOnStack(Object* value) {
- Handle<Type> lower = Type::OfCurrently(handle(value, isolate()), isolate());
- return Effect(Bounds(lower, Type::Any(isolate())));
-}
-
-
void AstTyper::ObserveTypesAtOsrEntry(IterationStatement* stmt) {
if (stmt->OsrEntryId() != info_->osr_ast_id()) return;
void AstTyper::VisitLiteral(Literal* expr) {
- Handle<Type> type = Type::Constant(expr->value(), isolate_);
- NarrowType(expr, Bounds(type));
+ Type* type = Type::Constant(expr->value(), isolate_);
+ NarrowType(expr, Bounds(type, isolate_));
}
void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
- NarrowType(expr, Bounds(Type::RegExp(isolate_)));
+ NarrowType(expr, Bounds(Type::RegExp(), isolate_));
}
RECURSE(Visit(prop->value()));
}
- NarrowType(expr, Bounds(Type::Object(isolate_)));
+ NarrowType(expr, Bounds(Type::Object(), isolate_));
}
RECURSE(Visit(value));
}
- NarrowType(expr, Bounds(Type::Array(isolate_)));
+ NarrowType(expr, Bounds(Type::Array(), isolate_));
}
RECURSE(Visit(expr->exception()));
// TODO(rossberg): is it worth having a non-termination effect?
- NarrowType(expr, Bounds(Type::None(isolate_)));
+ NarrowType(expr, Bounds(Type::None(), isolate_));
}
switch (expr->op()) {
case Token::NOT:
case Token::DELETE:
- NarrowType(expr, Bounds(Type::Boolean(isolate_)));
+ NarrowType(expr, Bounds(Type::Boolean(), isolate_));
break;
case Token::VOID:
- NarrowType(expr, Bounds(Type::Undefined(isolate_)));
+ NarrowType(expr, Bounds(Type::Undefined(), isolate_));
break;
case Token::TYPEOF:
- NarrowType(expr, Bounds(Type::InternalizedString(isolate_)));
+ NarrowType(expr, Bounds(Type::InternalizedString(), isolate_));
break;
default:
UNREACHABLE();
RECURSE(Visit(expr->expression()));
- NarrowType(expr, Bounds(Type::Smi(isolate_), Type::Number(isolate_)));
+ NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
VariableProxy* proxy = expr->expression()->AsVariableProxy();
if (proxy != NULL && proxy->var()->IsStackAllocated()) {
case Token::BIT_AND: {
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
- Handle<Type> upper = Type::Union(
- expr->left()->bounds().upper, expr->right()->bounds().upper,
+ Handle<Type> upper(
+ Type::Union(
+ expr->left()->bounds().upper, expr->right()->bounds().upper),
isolate_);
if (!upper->Is(Type::Signed32()))
- upper = Type::Signed32(isolate_);
- Handle<Type> lower =
- Type::Intersect(Type::Smi(isolate_), upper, isolate_);
+ upper = handle(Type::Signed32(), isolate_);
+ Handle<Type> lower(Type::Intersect(
+ handle(Type::Smi(), isolate_), upper), isolate_);
NarrowType(expr, Bounds(lower, upper));
break;
}
case Token::SAR:
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
- NarrowType(expr, Bounds(Type::Smi(isolate_), Type::Signed32(isolate_)));
+ NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_));
break;
case Token::SHR:
RECURSE(Visit(expr->left()));
// TODO(rossberg): The upper bound would be Unsigned32, but since there
// is no 'positive Smi' type for the lower bound, we use the smallest
// union of Smi and Unsigned32 as upper bound instead.
- NarrowType(expr, Bounds(Type::Smi(isolate_), Type::Number(isolate_)));
+ NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
break;
case Token::ADD: {
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
Bounds l = expr->left()->bounds();
Bounds r = expr->right()->bounds();
- Handle<Type> lower =
+ Type* lower =
l.lower->Is(Type::None()) || r.lower->Is(Type::None()) ?
- Type::None(isolate_) :
+ Type::None() :
l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ?
- Type::String(isolate_) :
+ Type::String() :
l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ?
- Type::Smi(isolate_) : Type::None(isolate_);
- Handle<Type> upper =
+ Type::Smi() : Type::None();
+ Type* upper =
l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ?
- Type::String(isolate_) :
+ Type::String() :
l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ?
- Type::Number(isolate_) : Type::NumberOrString(isolate_);
- NarrowType(expr, Bounds(lower, upper));
+ Type::Number() : Type::NumberOrString();
+ NarrowType(expr, Bounds(lower, upper, isolate_));
break;
}
case Token::SUB:
case Token::MOD:
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
- NarrowType(expr, Bounds(Type::Smi(isolate_), Type::Number(isolate_)));
+ NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
break;
default:
UNREACHABLE();
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
- NarrowType(expr, Bounds(Type::Boolean(isolate_)));
+ NarrowType(expr, Bounds(Type::Boolean(), isolate_));
}
using namespace v8::internal;
// Testing auxiliaries (breaking the Type abstraction).
-static bool IsBitset(Handle<Type> t) { return t->IsSmi(); }
-static bool IsClass(Handle<Type> t) { return t->IsMap(); }
-static bool IsConstant(Handle<Type> t) { return t->IsBox(); }
-static bool IsUnion(Handle<Type> t) { return t->IsFixedArray(); }
+static bool IsBitset(Type* type) { return type->IsSmi(); }
+static bool IsClass(Type* type) { return type->IsMap(); }
+static bool IsConstant(Type* type) { return type->IsBox(); }
+static bool IsUnion(Type* type) { return type->IsFixedArray(); }
-static int AsBitset(Handle<Type> t) { return Smi::cast(*t)->value(); }
-static Map* AsClass(Handle<Type> t) { return Map::cast(*t); }
-static Object* AsConstant(Handle<Type> t) { return Box::cast(*t)->value(); }
-static FixedArray* AsUnion(Handle<Type> t) { return FixedArray::cast(*t); }
+static int AsBitset(Type* type) { return Smi::cast(type)->value(); }
+static Map* AsClass(Type* type) { return Map::cast(type); }
+static Object* AsConstant(Type* type) { return Box::cast(type)->value(); }
+static FixedArray* AsUnion(Type* type) { return FixedArray::cast(type); }
static void CheckEqual(Handle<Type> type1, Handle<Type> type2) {
- CHECK_EQ(IsBitset(type1), IsBitset(type2));
- CHECK_EQ(IsClass(type1), IsClass(type2));
- CHECK_EQ(IsConstant(type1), IsConstant(type2));
- CHECK_EQ(IsUnion(type1), IsUnion(type2));
+ CHECK_EQ(IsBitset(*type1), IsBitset(*type2));
+ CHECK_EQ(IsClass(*type1), IsClass(*type2));
+ CHECK_EQ(IsConstant(*type1), IsConstant(*type2));
+ CHECK_EQ(IsUnion(*type1), IsUnion(*type2));
CHECK_EQ(type1->NumClasses(), type2->NumClasses());
CHECK_EQ(type1->NumConstants(), type2->NumConstants());
- if (IsBitset(type1)) {
- CHECK_EQ(AsBitset(type1), AsBitset(type2));
- } else if (IsClass(type1)) {
- CHECK_EQ(AsClass(type1), AsClass(type2));
- } else if (IsConstant(type1)) {
- CHECK_EQ(AsConstant(type1), AsConstant(type2));
- } else if (IsUnion(type1)) {
- CHECK_EQ(AsUnion(type1)->length(), AsUnion(type2)->length());
+ if (IsBitset(*type1)) {
+ CHECK_EQ(AsBitset(*type1), AsBitset(*type2));
+ } else if (IsClass(*type1)) {
+ CHECK_EQ(AsClass(*type1), AsClass(*type2));
+ } else if (IsConstant(*type1)) {
+ CHECK_EQ(AsConstant(*type1), AsConstant(*type2));
+ } else if (IsUnion(*type1)) {
+ CHECK_EQ(AsUnion(*type1)->length(), AsUnion(*type2)->length());
}
CHECK(type1->Is(type2));
CHECK(type2->Is(type1));
static void CheckSub(Handle<Type> type1, Handle<Type> type2) {
CHECK(type1->Is(type2));
CHECK(!type2->Is(type1));
- if (IsBitset(type1) && IsBitset(type2)) {
- CHECK_NE(AsBitset(type1), AsBitset(type2));
+ if (IsBitset(*type1) && IsBitset(*type2)) {
+ CHECK_NE(AsBitset(*type1), AsBitset(*type2));
}
}
static void CheckUnordered(Handle<Type> type1, Handle<Type> type2) {
CHECK(!type1->Is(type2));
CHECK(!type2->Is(type1));
- if (IsBitset(type1) && IsBitset(type2)) {
- CHECK_NE(AsBitset(type1), AsBitset(type2));
+ if (IsBitset(*type1) && IsBitset(*type2)) {
+ CHECK_NE(AsBitset(*type1), AsBitset(*type2));
}
}
static void CheckOverlap(Handle<Type> type1, Handle<Type> type2) {
CHECK(type1->Maybe(type2));
CHECK(type2->Maybe(type1));
- if (IsBitset(type1) && IsBitset(type2)) {
- CHECK_NE(0, AsBitset(type1) & AsBitset(type2));
+ if (IsBitset(*type1) && IsBitset(*type2)) {
+ CHECK_NE(0, AsBitset(*type1) & AsBitset(*type2));
}
}
CHECK(!type2->Is(type1));
CHECK(!type1->Maybe(type2));
CHECK(!type2->Maybe(type1));
- if (IsBitset(type1) && IsBitset(type2)) {
- CHECK_EQ(0, AsBitset(type1) & AsBitset(type2));
+ if (IsBitset(*type1) && IsBitset(*type2)) {
+ CHECK_EQ(0, AsBitset(*type1) & AsBitset(*type2));
}
}
class HandlifiedTypes {
public:
explicit HandlifiedTypes(Isolate* isolate) :
- None(Type::None(isolate)),
- Any(Type::Any(isolate)),
- Oddball(Type::Oddball(isolate)),
- Boolean(Type::Boolean(isolate)),
- Null(Type::Null(isolate)),
- Undefined(Type::Undefined(isolate)),
- Number(Type::Number(isolate)),
- Smi(Type::Smi(isolate)),
- Signed32(Type::Signed32(isolate)),
- Double(Type::Double(isolate)),
- Name(Type::Name(isolate)),
- UniqueName(Type::UniqueName(isolate)),
- String(Type::String(isolate)),
- InternalizedString(Type::InternalizedString(isolate)),
- Symbol(Type::Symbol(isolate)),
- Receiver(Type::Receiver(isolate)),
- Object(Type::Object(isolate)),
- Array(Type::Array(isolate)),
- Function(Type::Function(isolate)),
- Proxy(Type::Proxy(isolate)),
+ None(Type::None(), isolate),
+ Any(Type::Any(), isolate),
+ Oddball(Type::Oddball(), isolate),
+ Boolean(Type::Boolean(), isolate),
+ Null(Type::Null(), isolate),
+ Undefined(Type::Undefined(), isolate),
+ Number(Type::Number(), isolate),
+ Smi(Type::Smi(), isolate),
+ Signed32(Type::Signed32(), isolate),
+ Double(Type::Double(), isolate),
+ Name(Type::Name(), isolate),
+ UniqueName(Type::UniqueName(), isolate),
+ String(Type::String(), isolate),
+ InternalizedString(Type::InternalizedString(), isolate),
+ Symbol(Type::Symbol(), isolate),
+ Receiver(Type::Receiver(), isolate),
+ Object(Type::Object(), isolate),
+ Array(Type::Array(), isolate),
+ Function(Type::Function(), isolate),
+ Proxy(Type::Proxy(), isolate),
object_map(isolate->factory()->NewMap(JS_OBJECT_TYPE, 3 * kPointerSize)),
array_map(isolate->factory()->NewMap(JS_ARRAY_TYPE, 4 * kPointerSize)),
isolate_(isolate) {
object1 = isolate->factory()->NewJSObjectFromMap(object_map);
object2 = isolate->factory()->NewJSObjectFromMap(object_map);
array = isolate->factory()->NewJSArray(20);
- ObjectClass = Type::Class(object_map, isolate);
- ArrayClass = Type::Class(array_map, isolate);
- SmiConstant = Type::Constant(smi, isolate);
- Signed32Constant = Type::Constant(signed32, isolate);
- ObjectConstant1 = Type::Constant(object1, isolate);
- ObjectConstant2 = Type::Constant(object2, isolate);
- ArrayConstant1 = Type::Constant(array, isolate);
- ArrayConstant2 = Type::Constant(array, isolate);
+ ObjectClass = Class(object_map);
+ ArrayClass = Class(array_map);
+ SmiConstant = Constant(smi);
+ Signed32Constant = Constant(signed32);
+ ObjectConstant1 = Constant(object1);
+ ObjectConstant2 = Constant(object2);
+ ArrayConstant1 = Constant(array);
+ ArrayConstant2 = Constant(array);
}
Handle<Type> None;
Handle<JSObject> object2;
Handle<JSArray> array;
- Handle<Type> Union(Handle<Type> t1, Handle<Type> t2) {
- return Type::Union(t1, t2, isolate_);
+ Handle<Type> Class(Handle<Map> map) {
+ return handle(Type::Class(map), isolate_);
}
- Handle<Type> Intersect(Handle<Type> t1, Handle<Type> t2) {
- return Type::Intersect(t1, t2, isolate_);
+ Handle<Type> Constant(Handle<i::Object> value) {
+ return handle(Type::Constant(value, isolate_), isolate_);
+ }
+ Handle<Type> Union(Handle<Type> type1, Handle<Type> type2) {
+ return handle(Type::Union(type1, type2), isolate_);
+ }
+ Handle<Type> Intersect(Handle<Type> type1, Handle<Type> type2) {
+ return handle(Type::Intersect(type1, type2), isolate_);
}
private:
HandleScope scope(isolate);
HandlifiedTypes T(isolate);
- CHECK(IsBitset(T.None));
- CHECK(IsBitset(T.Any));
- CHECK(IsBitset(T.String));
- CHECK(IsBitset(T.Object));
-
- CHECK(IsBitset(T.Union(T.String, T.Number)));
- CHECK(IsBitset(T.Union(T.String, T.Receiver)));
-
- CHECK_EQ(0, AsBitset(T.None));
- CHECK_EQ(AsBitset(T.Number) | AsBitset(T.String),
- AsBitset(T.Union(T.String, T.Number)));
- CHECK_EQ(AsBitset(T.Receiver),
- AsBitset(T.Union(T.Receiver, T.Object)));
+ CHECK(IsBitset(*T.None));
+ CHECK(IsBitset(*T.Any));
+ CHECK(IsBitset(*T.String));
+ CHECK(IsBitset(*T.Object));
+
+ CHECK(IsBitset(Type::Union(T.String, T.Number)));
+ CHECK(IsBitset(Type::Union(T.String, T.Receiver)));
+ CHECK(IsBitset(Type::Optional(T.Object)));
+
+ CHECK_EQ(0, AsBitset(*T.None));
+ CHECK_EQ(AsBitset(*T.Number) | AsBitset(*T.String),
+ AsBitset(Type::Union(T.String, T.Number)));
+ CHECK_EQ(AsBitset(*T.Receiver),
+ AsBitset(Type::Union(T.Receiver, T.Object)));
+ CHECK_EQ(AsBitset(*T.String) | AsBitset(*T.Undefined),
+ AsBitset(Type::Optional(T.String)));
}
HandleScope scope(isolate);
HandlifiedTypes T(isolate);
- CHECK(IsClass(T.ObjectClass));
- CHECK(IsClass(T.ArrayClass));
+ CHECK(IsClass(*T.ObjectClass));
+ CHECK(IsClass(*T.ArrayClass));
- CHECK(*T.object_map == AsClass(T.ObjectClass));
- CHECK(*T.array_map == AsClass(T.ArrayClass));
+ CHECK(*T.object_map == AsClass(*T.ObjectClass));
+ CHECK(*T.array_map == AsClass(*T.ArrayClass));
}
HandleScope scope(isolate);
HandlifiedTypes T(isolate);
- CHECK(IsConstant(T.SmiConstant));
- CHECK(IsConstant(T.ObjectConstant1));
- CHECK(IsConstant(T.ObjectConstant2));
- CHECK(IsConstant(T.ArrayConstant1));
- CHECK(IsConstant(T.ArrayConstant2));
-
- CHECK(*T.smi == AsConstant(T.SmiConstant));
- CHECK(*T.object1 == AsConstant(T.ObjectConstant1));
- CHECK(*T.object2 == AsConstant(T.ObjectConstant2));
- CHECK(*T.object1 != AsConstant(T.ObjectConstant2));
- CHECK(*T.array == AsConstant(T.ArrayConstant1));
- CHECK(*T.array == AsConstant(T.ArrayConstant2));
+ CHECK(IsConstant(*T.SmiConstant));
+ CHECK(IsConstant(*T.ObjectConstant1));
+ CHECK(IsConstant(*T.ObjectConstant2));
+ CHECK(IsConstant(*T.ArrayConstant1));
+ CHECK(IsConstant(*T.ArrayConstant2));
+
+ CHECK(*T.smi == AsConstant(*T.SmiConstant));
+ CHECK(*T.object1 == AsConstant(*T.ObjectConstant1));
+ CHECK(*T.object2 == AsConstant(*T.ObjectConstant2));
+ CHECK(*T.object1 != AsConstant(*T.ObjectConstant2));
+ CHECK(*T.array == AsConstant(*T.ArrayConstant1));
+ CHECK(*T.array == AsConstant(*T.ArrayConstant2));
}
HandlifiedTypes T(isolate);
// Bitset-bitset
- CHECK(IsBitset(T.Union(T.Object, T.Number)));
- CHECK(IsBitset(T.Union(T.Object, T.Object)));
- CHECK(IsBitset(T.Union(T.Any, T.None)));
+ CHECK(IsBitset(Type::Union(T.Object, T.Number)));
+ CHECK(IsBitset(Type::Union(T.Object, T.Object)));
+ CHECK(IsBitset(Type::Union(T.Any, T.None)));
CheckEqual(T.Union(T.None, T.Number), T.Number);
CheckEqual(T.Union(T.Object, T.Proxy), T.Receiver);
CheckSub(T.Union(T.Number, T.String), T.Any);
// Class-class
- CHECK(IsClass(T.Union(T.ObjectClass, T.ObjectClass)));
- CHECK(IsUnion(T.Union(T.ObjectClass, T.ArrayClass)));
+ CHECK(IsClass(Type::Union(T.ObjectClass, T.ObjectClass)));
+ CHECK(IsUnion(Type::Union(T.ObjectClass, T.ArrayClass)));
CheckEqual(T.Union(T.ObjectClass, T.ObjectClass), T.ObjectClass);
CheckSub(T.None, T.Union(T.ObjectClass, T.ArrayClass));
CheckDisjoint(T.Union(T.ObjectClass, T.ArrayClass), T.Number);
// Constant-constant
- CHECK(IsConstant(T.Union(T.ObjectConstant1, T.ObjectConstant1)));
- CHECK(IsConstant(T.Union(T.ArrayConstant1, T.ArrayConstant1)));
- CHECK(IsUnion(T.Union(T.ObjectConstant1, T.ObjectConstant2)));
+ CHECK(IsConstant(Type::Union(T.ObjectConstant1, T.ObjectConstant1)));
+ CHECK(IsConstant(Type::Union(T.ArrayConstant1, T.ArrayConstant1)));
+ CHECK(IsUnion(Type::Union(T.ObjectConstant1, T.ObjectConstant2)));
CheckEqual(T.Union(T.ObjectConstant1, T.ObjectConstant1), T.ObjectConstant1);
CheckEqual(T.Union(T.ArrayConstant1, T.ArrayConstant1), T.ArrayConstant1);
CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.ObjectClass);
// Bitset-class
- CHECK(IsBitset(T.Union(T.ObjectClass, T.Object)));
- CHECK(IsUnion(T.Union(T.ObjectClass, T.Number)));
+ CHECK(IsBitset(Type::Union(T.ObjectClass, T.Object)));
+ CHECK(IsUnion(Type::Union(T.ObjectClass, T.Number)));
CheckEqual(T.Union(T.ObjectClass, T.Object), T.Object);
CheckSub(T.None, T.Union(T.ObjectClass, T.Number));
CheckDisjoint(T.Union(T.ObjectClass, T.String), T.Number);
// Bitset-constant
- CHECK(IsBitset(T.Union(T.SmiConstant, T.Number)));
- CHECK(IsBitset(T.Union(T.ObjectConstant1, T.Object)));
- CHECK(IsUnion(T.Union(T.ObjectConstant2, T.Number)));
+ CHECK(IsBitset(Type::Union(T.SmiConstant, T.Number)));
+ CHECK(IsBitset(Type::Union(T.ObjectConstant1, T.Object)));
+ CHECK(IsUnion(Type::Union(T.ObjectConstant2, T.Number)));
CheckEqual(T.Union(T.SmiConstant, T.Number), T.Number);
CheckEqual(T.Union(T.ObjectConstant1, T.Object), T.Object);
CheckEqual(T.Union(T.Signed32, T.Signed32Constant), T.Signed32);
// Class-constant
- CHECK(IsUnion(T.Union(T.ObjectConstant1, T.ObjectClass)));
- CHECK(IsUnion(T.Union(T.ArrayClass, T.ObjectConstant2)));
+ CHECK(IsUnion(Type::Union(T.ObjectConstant1, T.ObjectClass)));
+ CHECK(IsUnion(Type::Union(T.ArrayClass, T.ObjectConstant2)));
CheckSub(T.None, T.Union(T.ObjectConstant1, T.ArrayClass));
CheckSub(T.Union(T.ObjectConstant1, T.ArrayClass), T.Any);
CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectClass);
// Bitset-union
- CHECK(IsBitset(T.Union(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass))));
- CHECK(IsUnion(T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number)));
+ CHECK(IsBitset(
+ Type::Union(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass))));
+ CHECK(IsUnion(
+ Type::Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number)));
CheckEqual(
T.Union(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)),
// Class-union
CHECK(IsUnion(
- T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass)));
+ Type::Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass)));
CHECK(IsUnion(
- T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ObjectClass)));
+ Type::Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ObjectClass)));
CheckEqual(
T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)),
T.Union(T.ArrayClass, T.ObjectConstant2));
// Constant-union
- CHECK(IsUnion(T.Union(
+ CHECK(IsUnion(Type::Union(
T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2))));
- CHECK(IsUnion(T.Union(
+ CHECK(IsUnion(Type::Union(
T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1)));
- CHECK(IsUnion(T.Union(
+ CHECK(IsUnion(Type::Union(
T.Union(T.ArrayConstant1, T.ObjectConstant2), T.ObjectConstant1)));
CheckEqual(
T.Union(T.ObjectConstant2, T.Union(T.ArrayConstant1, T.ObjectConstant1)));
// Union-union
- CHECK(IsBitset(T.Union(
+ CHECK(IsBitset(Type::Union(
T.Union(T.Number, T.ArrayClass), T.Union(T.Signed32, T.Array))));
- CHECK(IsUnion(T.Union(
+ CHECK(IsUnion(Type::Union(
T.Union(T.Number, T.ArrayClass), T.Union(T.ObjectClass, T.ArrayClass))));
CheckEqual(
HandlifiedTypes T(isolate);
// Bitset-bitset
- CHECK(IsBitset(T.Intersect(T.Object, T.Number)));
- CHECK(IsBitset(T.Intersect(T.Object, T.Object)));
- CHECK(IsBitset(T.Intersect(T.Any, T.None)));
+ CHECK(IsBitset(Type::Intersect(T.Object, T.Number)));
+ CHECK(IsBitset(Type::Intersect(T.Object, T.Object)));
+ CHECK(IsBitset(Type::Intersect(T.Any, T.None)));
CheckEqual(T.Intersect(T.None, T.Number), T.None);
CheckEqual(T.Intersect(T.Object, T.Proxy), T.None);
CheckEqual(T.Intersect(T.UniqueName, T.String), T.InternalizedString);
// Class-class
- CHECK(IsClass(T.Intersect(T.ObjectClass, T.ObjectClass)));
- CHECK(IsBitset(T.Intersect(T.ObjectClass, T.ArrayClass)));
+ CHECK(IsClass(Type::Intersect(T.ObjectClass, T.ObjectClass)));
+ CHECK(IsBitset(Type::Intersect(T.ObjectClass, T.ArrayClass)));
CheckEqual(T.Intersect(T.ObjectClass, T.ObjectClass), T.ObjectClass);
CheckEqual(T.Intersect(T.ObjectClass, T.ArrayClass), T.None);
// Constant-constant
- CHECK(IsConstant(T.Intersect(T.ObjectConstant1, T.ObjectConstant1)));
- CHECK(IsConstant(T.Intersect(T.ArrayConstant1, T.ArrayConstant2)));
- CHECK(IsBitset(T.Intersect(T.ObjectConstant1, T.ObjectConstant2)));
+ CHECK(IsConstant(Type::Intersect(T.ObjectConstant1, T.ObjectConstant1)));
+ CHECK(IsConstant(Type::Intersect(T.ArrayConstant1, T.ArrayConstant2)));
+ CHECK(IsBitset(Type::Intersect(T.ObjectConstant1, T.ObjectConstant2)));
CheckEqual(
T.Intersect(T.ObjectConstant1, T.ObjectConstant1), T.ObjectConstant1);
CheckEqual(T.Intersect(T.ObjectConstant1, T.ObjectConstant2), T.None);
// Bitset-class
- CHECK(IsClass(T.Intersect(T.ObjectClass, T.Object)));
- CHECK(IsBitset(T.Intersect(T.ObjectClass, T.Number)));
+ CHECK(IsClass(Type::Intersect(T.ObjectClass, T.Object)));
+ CHECK(IsBitset(Type::Intersect(T.ObjectClass, T.Number)));
CheckEqual(T.Intersect(T.ObjectClass, T.Object), T.ObjectClass);
CheckEqual(T.Intersect(T.ObjectClass, T.Array), T.None);
CheckEqual(T.Intersect(T.ObjectClass, T.Number), T.None);
// Bitset-constant
- CHECK(IsBitset(T.Intersect(T.Smi, T.Number)));
- CHECK(IsConstant(T.Intersect(T.SmiConstant, T.Number)));
- CHECK(IsConstant(T.Intersect(T.ObjectConstant1, T.Object)));
+ CHECK(IsBitset(Type::Intersect(T.Smi, T.Number)));
+ CHECK(IsConstant(Type::Intersect(T.SmiConstant, T.Number)));
+ CHECK(IsConstant(Type::Intersect(T.ObjectConstant1, T.Object)));
CheckEqual(T.Intersect(T.Smi, T.Number), T.Smi);
CheckEqual(T.Intersect(T.SmiConstant, T.Number), T.SmiConstant);
CheckEqual(T.Intersect(T.ObjectConstant1, T.Object), T.ObjectConstant1);
// Class-constant
- CHECK(IsBitset(T.Intersect(T.ObjectConstant1, T.ObjectClass)));
- CHECK(IsBitset(T.Intersect(T.ArrayClass, T.ObjectConstant2)));
+ CHECK(IsBitset(Type::Intersect(T.ObjectConstant1, T.ObjectClass)));
+ CHECK(IsBitset(Type::Intersect(T.ArrayClass, T.ObjectConstant2)));
CheckEqual(T.Intersect(T.ObjectConstant1, T.ObjectClass), T.None);
CheckEqual(T.Intersect(T.ArrayClass, T.ObjectConstant2), T.None);
// Bitset-union
CHECK(IsUnion(
- T.Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass))));
+ Type::Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass))));
CHECK(IsBitset(
- T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number)));
+ Type::Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number)));
CheckEqual(
T.Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)),
// Class-union
CHECK(IsClass(
- T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass)));
+ Type::Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass)));
CHECK(IsClass(
- T.Intersect(T.Union(T.Object, T.SmiConstant), T.ArrayClass)));
+ Type::Intersect(T.Union(T.Object, T.SmiConstant), T.ArrayClass)));
CHECK(IsBitset(
- T.Intersect(T.Union(T.ObjectClass, T.ArrayConstant1), T.ArrayClass)));
+ Type::Intersect(T.Union(T.ObjectClass, T.ArrayConstant1), T.ArrayClass)));
CheckEqual(
T.Intersect(T.ArrayClass, T.Union(T.ObjectConstant2, T.ArrayClass)),
T.None);
// Constant-union
- CHECK(IsConstant(T.Intersect(
+ CHECK(IsConstant(Type::Intersect(
T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2))));
- CHECK(IsConstant(T.Intersect(
+ CHECK(IsConstant(Type::Intersect(
T.Union(T.Number, T.ObjectClass), T.SmiConstant)));
- CHECK(IsBitset(T.Intersect(
+ CHECK(IsBitset(Type::Intersect(
T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1)));
CheckEqual(
T.None);
// Union-union
- CHECK(IsUnion(T.Intersect(
+ CHECK(IsUnion(Type::Intersect(
T.Union(T.Number, T.ArrayClass), T.Union(T.Signed32, T.Array))));
- CHECK(IsBitset(T.Intersect(
+ CHECK(IsBitset(Type::Intersect(
T.Union(T.Number, T.ObjectClass), T.Union(T.Signed32, T.Array))));
CheckEqual(