: 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, handle(Type::Number(), isolate()));
+ return BuildNumberToString(number, Type::Number(isolate()));
}
{
Push(BuildBinaryOperation(
state.op(), left, right,
- handle(Type::String(), isolate()), right_type,
+ Type::String(isolate()), right_type,
result_type, state.fixed_right_arg(),
allocation_mode));
}
{
Push(BuildBinaryOperation(
state.op(), left, right,
- left_type, handle(Type::String(), isolate()),
+ left_type, Type::String(isolate()),
result_type, state.fixed_right_arg(),
allocation_mode));
}
Isolate* isolate,
Handle<Map> map) {
if (state_.Contains(CompareNilICStub::GENERIC)) {
- return handle(Type::Any(), isolate);
+ return Type::Any(isolate);
}
- Handle<Type> result(Type::None(), isolate);
+ Handle<Type> result = Type::None(isolate);
if (state_.Contains(CompareNilICStub::UNDEFINED)) {
- result = handle(Type::Union(result, handle(Type::Undefined(), isolate)),
- isolate);
+ result = Type::Union(result, Type::Undefined(isolate), isolate);
}
if (state_.Contains(CompareNilICStub::NULL_TYPE)) {
- result = handle(Type::Union(result, handle(Type::Null(), isolate)),
- isolate);
+ result = Type::Union(result, Type::Null(isolate), isolate);
}
if (state_.Contains(CompareNilICStub::MONOMORPHIC_MAP)) {
- Type* type = map.is_null() ? Type::Detectable() : Type::Class(map);
- result = handle(Type::Union(result, handle(type, isolate)), isolate);
+ Handle<Type> type = map.is_null()
+ ? Type::Detectable(isolate) : Type::Class(map, isolate);
+ result = Type::Union(result, type, isolate);
}
return result;
Isolate* isolate,
Handle<Map> map) {
Handle<Type> output_type = GetType(isolate, map);
- Handle<Type> nil_type = handle(nil_value_ == kNullValue
- ? Type::Null() : Type::Undefined(), isolate);
- return handle(Type::Union(output_type, nil_type), isolate);
+ Handle<Type> nil_type = nil_value_ == kNullValue
+ ? Type::Null(isolate) : Type::Undefined(isolate);
+ return Type::Union(output_type, nil_type, isolate);
}
HConstant* constant = HConstant::cast(value);
Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone());
if (number.has_value) {
- *expected = handle(Type::Number(), isolate());
+ *expected = Type::Number(isolate());
return AddInstruction(number.value);
}
}
Handle<Type> expected_type = *expected;
// Separate the number type from the rest.
- 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());
+ Handle<Type> expected_obj = Type::Intersect(
+ expected_type, Type::NonNumber(isolate()), isolate());
+ Handle<Type> expected_number = Type::Intersect(
+ expected_type, 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 = handle(Type::Union(
- expected_number, handle(Type::Double(), isolate())), isolate());
+ *expected = Type::Union(
+ expected_number, Type::Double(isolate()), isolate());
return value;
}
Deoptimizer::SOFT);
// TODO(rossberg): we should be able to get rid of non-continuous
// defaults.
- left_type = handle(Type::Any(), isolate());
+ left_type = 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 = handle(Type::Any(), isolate());
+ right_type = 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 = handle(Type::Any(), isolate());
+ combined_type = left_type = right_type = 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())
- ? handle(Type::Any(), isolate_)
- : expr->combined_type();
+ ? 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, handle(Type::Number(), isolate()));
+ HValue* result = BuildNumberToString(number, Type::Number(isolate()));
return ast_context()->ReturnValue(result);
}
Handle<Type> IC::CurrentTypeOf(Handle<Object> object, Isolate* isolate) {
- Type* type = object->IsJSGlobalObject()
- ? Type::Constant(Handle<JSGlobalObject>::cast(object))
- : Type::OfCurrently(object);
- return handle(type, isolate);
+ return object->IsJSGlobalObject()
+ ? Type::Constant(Handle<JSGlobalObject>::cast(object), isolate)
+ : Type::OfCurrently(object, isolate);
}
}
-Type* IC::MapToType(Handle<Map> map) {
- if (map->instance_type() == HEAP_NUMBER_TYPE) return Type::Number();
+Handle<Type> IC::MapToType(Handle<Map> map) {
+ Isolate* isolate = map->GetIsolate();
+ if (map->instance_type() == HEAP_NUMBER_TYPE) return Type::Number(isolate);
// The only oddballs that can be recorded in ICs are booleans.
- if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean();
- return Type::Class(map);
+ if (map->instance_type() == ODDBALL_TYPE) return Type::Boolean(isolate);
+ return Type::Class(map, isolate);
}
}
-bool IC::IsTransitionOfMonomorphicTarget(Type* type) {
+bool IC::IsTransitionOfMonomorphicTarget(Handle<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 handle(Type::Union(handle(Type::Number(), isolate),
- handle(Type::String(), isolate)), isolate);
+ return Type::Union(Type::Number(isolate), Type::String(isolate), isolate);
} else if (result_kind == NUMBER && op_ == Token::SHR) {
- return handle(Type::Unsigned32(), isolate);
+ return 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: 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;
+ 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);
}
- return handle(type, isolate);
+ UNREACHABLE();
+ return Handle<Type>();
}
CompareIC::State state,
Handle<Map> map) {
switch (state) {
- 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::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::INTERNALIZED_STRING:
- return handle(Type::InternalizedString(), isolate);
- case CompareIC::UNIQUE_NAME:
- return handle(Type::UniqueName(), isolate);
- case CompareIC::OBJECT:
- return handle(Type::Receiver(), isolate);
+ return Type::InternalizedString(isolate);
+ case CompareIC::UNIQUE_NAME: return Type::UniqueName(isolate);
+ case CompareIC::OBJECT: return Type::Receiver(isolate);
case CompareIC::KNOWN_OBJECT:
- return handle(
- map.is_null() ? Type::Receiver() : Type::Class(map), isolate);
- case CompareIC::GENERIC:
- return handle(Type::Any(), isolate);
+ return map.is_null()
+ ? Type::Receiver(isolate) : Type::Class(map, isolate);
+ case CompareIC::GENERIC: return 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 Type* MapToType(Handle<Map> type);
+ static Handle<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(Type* type);
+ bool IsTransitionOfMonomorphicTarget(Handle<Type> type);
void PatchCache(Handle<Type> type,
Handle<String> name,
Handle<Code> code);
class Map;
-class Type;
+template<class> class TypeImpl;
+class HeapTypeConfig;
+typedef TypeImpl<HeapTypeConfig> 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(handle(IC::MapToType(map), isolate));
+ types->Add(IC::MapToType(map));
}
}
}
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()
- : Type::Constant(value, isolate), isolate);
+ Handle<Type> new_type = value->IsConsString() || value->IsTheHole()
+ ? Type::Any(isolate) : Type::Constant(value, isolate);
if (new_type->Is(old_type)) {
return old_type;
return new_type;
}
- return handle(Type::Any(), isolate);
+ return Type::Any(isolate);
}
class GlobalObject;
class ObjectVisitor;
class StringStream;
-class Type;
+// We cannot just say "class Type;" if it is created from a template... =8-?
+template<class> class TypeImpl;
+class HeapTypeConfig;
+typedef TypeImpl<HeapTypeConfig> Type;
// A template-ized version of the IsXXX functions.
namespace internal {
class Smi;
-class Type;
+template<class> class TypeImpl;
+class HeapTypeConfig;
+typedef TypeImpl<HeapTypeConfig> 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(handle(Type::Class(receiver_maps->at(i)), isolate()));
+ types.Add(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 = handle(Type::None(), isolate_);
+ *left_type = *right_type = *combined_type = 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 = handle(Type::None(), isolate_);
+ *left = *right = *result = 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 handle(Type::None(), isolate_);
+ if (!object->IsCode()) return 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 {
-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 {
}
-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 {
}
-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;
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) {
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:
// 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;
}
// 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;
// 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;
}
}
-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;
// 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;
// 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;
// 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();
#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)
}
-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);
}
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);
}
#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)
-class Type : public Object {
+// 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 {
public:
- #define DEFINE_TYPE_CONSTRUCTOR(type, value) \
- static Type* type() { return from_bitset(k##type); }
+ 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); \
+ }
BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
#undef DEFINE_TYPE_CONSTRUCTOR
- 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 Class(i::Handle<i::Map> map, Region* region) {
+ return Config::from_class(map, region);
}
- static Type* Constant(Handle<i::Object> value, Isolate* isolate) {
- return from_handle(isolate->factory()->NewBox(value));
+ static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
+ return Config::from_constant(value, region);
}
- 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 Union(TypeHandle type1, TypeHandle type2, Region* reg);
+ static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg);
- static Type* Of(Handle<i::Object> value) {
- return from_bitset(LubBitset(*value));
+ static TypeHandle Of(i::Handle<i::Object> value, Region* region) {
+ return Config::from_bitset(LubBitset(*value), region);
}
- 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); }
+ 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); }
// State-dependent versions of Of and Is that consider subtyping between
// a constant and its map class.
- static Type* OfCurrently(Handle<i::Object> value);
- bool IsCurrently(Type* that);
- bool IsCurrently(Handle<Type> that) { return this->IsCurrently(*that); }
+ static TypeHandle OfCurrently(i::Handle<i::Object> value, Region* region);
+ bool IsCurrently(TypeImpl* that);
+ bool IsCurrently(TypeHandle that) { return this->IsCurrently(*that); }
- bool IsClass() { return is_class(); }
- bool IsConstant() { return is_constant(); }
- Handle<i::Map> AsClass() { return as_class(); }
- Handle<i::Object> AsConstant() { return as_constant(); }
+ 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); }
int NumClasses();
int NumConstants();
class Iterator {
public:
bool Done() const { return index_ < 0; }
- Handle<T> Current();
+ i::Handle<T> Current();
void Advance();
private:
- friend class Type;
+ template<class> friend class TypeImpl;
Iterator() : index_(-1) {}
- explicit Iterator(Handle<Type> type) : type_(type), index_(-1) {
+ explicit Iterator(TypeHandle type) : type_(type), index_(-1) {
Advance();
}
- inline bool matches(Handle<Type> type);
- inline Handle<Type> get_type();
+ inline bool matches(TypeHandle type);
+ inline TypeHandle get_type();
- Handle<Type> type_;
+ TypeHandle type_;
int index_;
};
Iterator<i::Map> Classes() {
- if (this->is_bitset()) return Iterator<i::Map>();
- return Iterator<i::Map>(this->handle());
+ if (this->IsBitset()) return Iterator<i::Map>();
+ return Iterator<i::Map>(Config::handle(this));
}
Iterator<i::Object> Constants() {
- if (this->is_bitset()) return Iterator<i::Object>();
- return Iterator<i::Object>(this->handle());
+ if (this->IsBitset()) return Iterator<i::Object>();
+ return Iterator<i::Object>(Config::handle(this));
}
- 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());
+ static TypeImpl* cast(i::Object* object) {
+ TypeImpl* t = static_cast<Type*>(object);
+ ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsUnion());
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 FixedArray Unioned;
+ typedef typename Config::Unioned Unioned;
+ typedef typename Config::template Handle<Unioned>::type UnionedHandle;
enum {
#define DECLARE_TYPE(type, value) k##type = (value),
kUnusedEOL = 0
};
- 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 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 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));
- }
+ bool SlowIs(TypeImpl* that);
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(Handle<Unioned> unioned, int current_size);
- int ExtendUnion(Handle<Unioned> unioned, int current_size);
+ bool InUnion(UnionedHandle unioned, int current_size);
+ int ExtendUnion(UnionedHandle unioned, int current_size);
int ExtendIntersection(
- Handle<Unioned> unioned, Handle<Type> type, int current_size);
+ UnionedHandle unioned, TypeHandle type, int current_size);
static const char* bitset_name(int bitset);
};
-// A simple struct to represent a pair of lower/upper type bounds.
-struct Bounds {
- Handle<Type> lower;
- Handle<Type> upper;
+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; };
- Bounds() {}
- Bounds(Handle<Type> l, Handle<Type> u) : lower(l), upper(u) {
- ASSERT(lower->Is(upper));
+ static i::Handle<Type> handle(Type* type) {
+ return i::handle(type, i::HeapObject::cast(type)->GetIsolate());
}
- Bounds(Type* l, Type* u, Isolate* isl) : lower(l, isl), upper(u, isl) {
- ASSERT(lower->Is(upper));
+
+ 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();
}
- explicit Bounds(Handle<Type> t) : lower(t), upper(t) {
- ASSERT(lower->Is(upper));
+ static i::Handle<i::Map> as_class(Type* type) {
+ return i::handle(i::Map::cast(type));
}
- Bounds(Type* t, Isolate* isl) : lower(t, isl), upper(t, isl) {
+ 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));
+ }
+
+ 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));
+ }
+
+ static i::Handle<Unioned> union_create(int size, Isolate* isolate) {
+ return isolate->factory()->NewFixedArray(size);
+ }
+ 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());
+ }
+};
+
+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) {
ASSERT(lower->Is(upper));
}
// Unrestricted bounds.
- static Bounds Unbounded(Isolate* isl) {
- return Bounds(Type::None(), Type::Any(), isl);
+ static BoundsImpl Unbounded(Region* region) {
+ return BoundsImpl(Type::None(region), Type::Any(region));
}
// Meet: both b1 and b2 are known to hold.
- 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);
+ 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);
// Lower bounds are considered approximate, correct as necessary.
- lower = handle(Type::Intersect(lower, upper), isl);
- return Bounds(lower, upper);
+ lower = Type::Intersect(lower, upper, region);
+ return BoundsImpl(lower, upper);
}
// Join: either b1 or b2 is known to hold.
- 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 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 NarrowLower(Bounds b, Handle<Type> t, Isolate* isl) {
+ static BoundsImpl NarrowLower(BoundsImpl b, TypeHandle t, Region* region) {
// Lower bounds are considered approximate, correct as necessary.
- t = handle(Type::Intersect(t, b.upper), isl);
- return Bounds(handle(Type::Union(b.lower, t), isl), b.upper);
+ t = Type::Intersect(t, b.upper, region);
+ TypeHandle lower = Type::Union(b.lower, t, region);
+ return BoundsImpl(lower, b.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));
+ 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);
}
};
+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) {
- Type* type = Type::Constant(expr->value(), isolate_);
- NarrowType(expr, Bounds(type, isolate_));
+ Handle<Type> type = Type::Constant(expr->value(), isolate_);
+ NarrowType(expr, Bounds(type));
}
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(), Type::Number(), isolate_));
+ NarrowType(expr, Bounds(Type::Smi(isolate_), 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 = handle(Type::Signed32(), isolate_);
- Handle<Type> lower(Type::Intersect(
- handle(Type::Smi(), isolate_), upper), isolate_);
+ upper = Type::Signed32(isolate_);
+ Handle<Type> lower =
+ Type::Intersect(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(), Type::Signed32(), isolate_));
+ NarrowType(expr, Bounds(Type::Smi(isolate_), 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(), Type::Number(), isolate_));
+ NarrowType(expr, Bounds(Type::Smi(isolate_), 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();
- Type* lower =
+ Handle<Type> lower =
l.lower->Is(Type::None()) || r.lower->Is(Type::None()) ?
- Type::None() :
+ Type::None(isolate_) :
l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ?
- Type::String() :
+ Type::String(isolate_) :
l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ?
- Type::Smi() : Type::None();
- Type* upper =
+ Type::Smi(isolate_) : Type::None(isolate_);
+ Handle<Type> upper =
l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ?
- Type::String() :
+ Type::String(isolate_) :
l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ?
- Type::Number() : Type::NumberOrString();
- NarrowType(expr, Bounds(lower, upper, isolate_));
+ Type::Number(isolate_) : Type::NumberOrString(isolate_);
+ NarrowType(expr, Bounds(lower, upper));
break;
}
case Token::SUB:
case Token::MOD:
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
- NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_));
+ NarrowType(expr, Bounds(Type::Smi(isolate_), 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(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 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 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 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 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 = 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);
+ 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);
}
Handle<Type> None;
Handle<JSObject> object2;
Handle<JSArray> array;
- Handle<Type> Class(Handle<Map> map) {
- return handle(Type::Class(map), isolate_);
+ Handle<Type> Union(Handle<Type> t1, Handle<Type> t2) {
+ return Type::Union(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_);
+ Handle<Type> Intersect(Handle<Type> t1, Handle<Type> t2) {
+ return Type::Intersect(t1, t2, 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(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)));
+ 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)));
}
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(Type::Union(T.Object, T.Number)));
- CHECK(IsBitset(Type::Union(T.Object, T.Object)));
- CHECK(IsBitset(Type::Union(T.Any, T.None)));
+ CHECK(IsBitset(T.Union(T.Object, T.Number)));
+ CHECK(IsBitset(T.Union(T.Object, T.Object)));
+ CHECK(IsBitset(T.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(Type::Union(T.ObjectClass, T.ObjectClass)));
- CHECK(IsUnion(Type::Union(T.ObjectClass, T.ArrayClass)));
+ CHECK(IsClass(T.Union(T.ObjectClass, T.ObjectClass)));
+ CHECK(IsUnion(T.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(Type::Union(T.ObjectConstant1, T.ObjectConstant1)));
- CHECK(IsConstant(Type::Union(T.ArrayConstant1, T.ArrayConstant1)));
- CHECK(IsUnion(Type::Union(T.ObjectConstant1, T.ObjectConstant2)));
+ CHECK(IsConstant(T.Union(T.ObjectConstant1, T.ObjectConstant1)));
+ CHECK(IsConstant(T.Union(T.ArrayConstant1, T.ArrayConstant1)));
+ CHECK(IsUnion(T.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(Type::Union(T.ObjectClass, T.Object)));
- CHECK(IsUnion(Type::Union(T.ObjectClass, T.Number)));
+ CHECK(IsBitset(T.Union(T.ObjectClass, T.Object)));
+ CHECK(IsUnion(T.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(Type::Union(T.SmiConstant, T.Number)));
- CHECK(IsBitset(Type::Union(T.ObjectConstant1, T.Object)));
- CHECK(IsUnion(Type::Union(T.ObjectConstant2, T.Number)));
+ CHECK(IsBitset(T.Union(T.SmiConstant, T.Number)));
+ CHECK(IsBitset(T.Union(T.ObjectConstant1, T.Object)));
+ CHECK(IsUnion(T.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(Type::Union(T.ObjectConstant1, T.ObjectClass)));
- CHECK(IsUnion(Type::Union(T.ArrayClass, T.ObjectConstant2)));
+ CHECK(IsUnion(T.Union(T.ObjectConstant1, T.ObjectClass)));
+ CHECK(IsUnion(T.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(
- Type::Union(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass))));
- CHECK(IsUnion(
- Type::Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number)));
+ CHECK(IsBitset(T.Union(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass))));
+ CHECK(IsUnion(T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number)));
CheckEqual(
T.Union(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)),
// Class-union
CHECK(IsUnion(
- Type::Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass)));
+ T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass)));
CHECK(IsUnion(
- Type::Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ObjectClass)));
+ T.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(Type::Union(
+ CHECK(IsUnion(T.Union(
T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2))));
- CHECK(IsUnion(Type::Union(
+ CHECK(IsUnion(T.Union(
T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1)));
- CHECK(IsUnion(Type::Union(
+ CHECK(IsUnion(T.Union(
T.Union(T.ArrayConstant1, T.ObjectConstant2), T.ObjectConstant1)));
CheckEqual(
T.Union(T.ObjectConstant2, T.Union(T.ArrayConstant1, T.ObjectConstant1)));
// Union-union
- CHECK(IsBitset(Type::Union(
+ CHECK(IsBitset(T.Union(
T.Union(T.Number, T.ArrayClass), T.Union(T.Signed32, T.Array))));
- CHECK(IsUnion(Type::Union(
+ CHECK(IsUnion(T.Union(
T.Union(T.Number, T.ArrayClass), T.Union(T.ObjectClass, T.ArrayClass))));
CheckEqual(
HandlifiedTypes T(isolate);
// Bitset-bitset
- CHECK(IsBitset(Type::Intersect(T.Object, T.Number)));
- CHECK(IsBitset(Type::Intersect(T.Object, T.Object)));
- CHECK(IsBitset(Type::Intersect(T.Any, T.None)));
+ CHECK(IsBitset(T.Intersect(T.Object, T.Number)));
+ CHECK(IsBitset(T.Intersect(T.Object, T.Object)));
+ CHECK(IsBitset(T.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(Type::Intersect(T.ObjectClass, T.ObjectClass)));
- CHECK(IsBitset(Type::Intersect(T.ObjectClass, T.ArrayClass)));
+ CHECK(IsClass(T.Intersect(T.ObjectClass, T.ObjectClass)));
+ CHECK(IsBitset(T.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(Type::Intersect(T.ObjectConstant1, T.ObjectConstant1)));
- CHECK(IsConstant(Type::Intersect(T.ArrayConstant1, T.ArrayConstant2)));
- CHECK(IsBitset(Type::Intersect(T.ObjectConstant1, T.ObjectConstant2)));
+ CHECK(IsConstant(T.Intersect(T.ObjectConstant1, T.ObjectConstant1)));
+ CHECK(IsConstant(T.Intersect(T.ArrayConstant1, T.ArrayConstant2)));
+ CHECK(IsBitset(T.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(Type::Intersect(T.ObjectClass, T.Object)));
- CHECK(IsBitset(Type::Intersect(T.ObjectClass, T.Number)));
+ CHECK(IsClass(T.Intersect(T.ObjectClass, T.Object)));
+ CHECK(IsBitset(T.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(Type::Intersect(T.Smi, T.Number)));
- CHECK(IsConstant(Type::Intersect(T.SmiConstant, T.Number)));
- CHECK(IsConstant(Type::Intersect(T.ObjectConstant1, T.Object)));
+ CHECK(IsBitset(T.Intersect(T.Smi, T.Number)));
+ CHECK(IsConstant(T.Intersect(T.SmiConstant, T.Number)));
+ CHECK(IsConstant(T.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(Type::Intersect(T.ObjectConstant1, T.ObjectClass)));
- CHECK(IsBitset(Type::Intersect(T.ArrayClass, T.ObjectConstant2)));
+ CHECK(IsBitset(T.Intersect(T.ObjectConstant1, T.ObjectClass)));
+ CHECK(IsBitset(T.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(
- Type::Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass))));
+ T.Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass))));
CHECK(IsBitset(
- Type::Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number)));
+ T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number)));
CheckEqual(
T.Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)),
// Class-union
CHECK(IsClass(
- Type::Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass)));
+ T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass)));
CHECK(IsClass(
- Type::Intersect(T.Union(T.Object, T.SmiConstant), T.ArrayClass)));
+ T.Intersect(T.Union(T.Object, T.SmiConstant), T.ArrayClass)));
CHECK(IsBitset(
- Type::Intersect(T.Union(T.ObjectClass, T.ArrayConstant1), T.ArrayClass)));
+ T.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(Type::Intersect(
+ CHECK(IsConstant(T.Intersect(
T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2))));
- CHECK(IsConstant(Type::Intersect(
+ CHECK(IsConstant(T.Intersect(
T.Union(T.Number, T.ObjectClass), T.SmiConstant)));
- CHECK(IsBitset(Type::Intersect(
+ CHECK(IsBitset(T.Intersect(
T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1)));
CheckEqual(
T.None);
// Union-union
- CHECK(IsUnion(Type::Intersect(
+ CHECK(IsUnion(T.Intersect(
T.Union(T.Number, T.ArrayClass), T.Union(T.Signed32, T.Array))));
- CHECK(IsBitset(Type::Intersect(
+ CHECK(IsBitset(T.Intersect(
T.Union(T.Number, T.ObjectClass), T.Union(T.Signed32, T.Array))));
CheckEqual(