Commit 372457a7 authored by rossberg@chromium.org's avatar rossberg@chromium.org

Allow smis for singleton types

To that end, introduce a generic Box struct.

R=danno@chromium.org
BUG=

Review URL: https://codereview.chromium.org/16562003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14987 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 8165d491
...@@ -5293,10 +5293,10 @@ class Internals { ...@@ -5293,10 +5293,10 @@ class Internals {
static const int kNodeIsIndependentShift = 4; static const int kNodeIsIndependentShift = 4;
static const int kNodeIsPartiallyDependentShift = 5; static const int kNodeIsPartiallyDependentShift = 5;
static const int kJSObjectType = 0xae; static const int kJSObjectType = 0xaf;
static const int kFirstNonstringType = 0x80; static const int kFirstNonstringType = 0x80;
static const int kOddballType = 0x83; static const int kOddballType = 0x83;
static const int kForeignType = 0x86; static const int kForeignType = 0x87;
static const int kUndefinedOddballKind = 5; static const int kUndefinedOddballKind = 5;
static const int kNullOddballKind = 3; static const int kNullOddballKind = 3;
......
...@@ -41,6 +41,14 @@ namespace v8 { ...@@ -41,6 +41,14 @@ namespace v8 {
namespace internal { namespace internal {
Handle<Box> Factory::NewBox(Handle<Object> value, PretenureFlag pretenure) {
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateBox(*value, pretenure),
Box);
}
Handle<FixedArray> Factory::NewFixedArray(int size, PretenureFlag pretenure) { Handle<FixedArray> Factory::NewFixedArray(int size, PretenureFlag pretenure) {
ASSERT(0 <= size); ASSERT(0 <= size);
CALL_HEAP_FUNCTION( CALL_HEAP_FUNCTION(
......
...@@ -39,6 +39,11 @@ namespace internal { ...@@ -39,6 +39,11 @@ namespace internal {
class Factory { class Factory {
public: public:
// Allocate a new boxed value.
Handle<Box> NewBox(
Handle<Object> value,
PretenureFlag pretenure = NOT_TENURED);
// Allocate a new uninitialized fixed array. // Allocate a new uninitialized fixed array.
Handle<FixedArray> NewFixedArray( Handle<FixedArray> NewFixedArray(
int size, int size,
......
...@@ -2701,6 +2701,15 @@ MaybeObject* Heap::AllocateJSGlobalPropertyCell(Object* value) { ...@@ -2701,6 +2701,15 @@ MaybeObject* Heap::AllocateJSGlobalPropertyCell(Object* value) {
} }
MaybeObject* Heap::AllocateBox(Object* value, PretenureFlag pretenure) {
Box* result;
MaybeObject* maybe_result = AllocateStruct(BOX_TYPE);
if (!maybe_result->To(&result)) return maybe_result;
result->set_value(value);
return result;
}
MaybeObject* Heap::CreateOddball(const char* to_string, MaybeObject* Heap::CreateOddball(const char* to_string,
Object* to_number, Object* to_number,
byte kind) { byte kind) {
......
...@@ -939,6 +939,10 @@ class Heap { ...@@ -939,6 +939,10 @@ class Heap {
// Please note this does not perform a garbage collection. // Please note this does not perform a garbage collection.
MUST_USE_RESULT MaybeObject* AllocateJSGlobalPropertyCell(Object* value); MUST_USE_RESULT MaybeObject* AllocateJSGlobalPropertyCell(Object* value);
// Allocate Box.
MUST_USE_RESULT MaybeObject* AllocateBox(Object* value,
PretenureFlag pretenure);
// Allocates a fixed array initialized with undefined values // Allocates a fixed array initialized with undefined values
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
// failed. // failed.
......
...@@ -778,6 +778,12 @@ void Foreign::ForeignVerify() { ...@@ -778,6 +778,12 @@ void Foreign::ForeignVerify() {
} }
void Box::BoxVerify() {
CHECK(IsBox());
value()->Verify();
}
void AccessorInfo::AccessorInfoVerify() { void AccessorInfo::AccessorInfoVerify() {
VerifyPointer(name()); VerifyPointer(name());
VerifyPointer(flag()); VerifyPointer(flag());
......
...@@ -4383,6 +4383,8 @@ ACCESSORS(ExecutableAccessorInfo, getter, Object, kGetterOffset) ...@@ -4383,6 +4383,8 @@ ACCESSORS(ExecutableAccessorInfo, getter, Object, kGetterOffset)
ACCESSORS(ExecutableAccessorInfo, setter, Object, kSetterOffset) ACCESSORS(ExecutableAccessorInfo, setter, Object, kSetterOffset)
ACCESSORS(ExecutableAccessorInfo, data, Object, kDataOffset) ACCESSORS(ExecutableAccessorInfo, data, Object, kDataOffset)
ACCESSORS(Box, value, Object, kValueOffset)
ACCESSORS(AccessorPair, getter, Object, kGetterOffset) ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
ACCESSORS(AccessorPair, setter, Object, kSetterOffset) ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
......
...@@ -970,6 +970,13 @@ void DeclaredAccessorDescriptor::DeclaredAccessorDescriptorPrint(FILE* out) { ...@@ -970,6 +970,13 @@ void DeclaredAccessorDescriptor::DeclaredAccessorDescriptorPrint(FILE* out) {
} }
void Box::BoxPrint(FILE* out) {
HeapObject::PrintHeader(out, "Box");
PrintF(out, "\n - value: ");
value()->ShortPrint(out);
}
void AccessorPair::AccessorPairPrint(FILE* out) { void AccessorPair::AccessorPairPrint(FILE* out) {
HeapObject::PrintHeader(out, "AccessorPair"); HeapObject::PrintHeader(out, "AccessorPair");
PrintF(out, "\n - getter: "); PrintF(out, "\n - getter: ");
......
...@@ -125,6 +125,7 @@ ...@@ -125,6 +125,7 @@
// - Foreign // - Foreign
// - SharedFunctionInfo // - SharedFunctionInfo
// - Struct // - Struct
// - Box
// - DeclaredAccessorDescriptor // - DeclaredAccessorDescriptor
// - AccessorInfo // - AccessorInfo
// - DeclaredAccessorInfo // - DeclaredAccessorInfo
...@@ -348,6 +349,7 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits; ...@@ -348,6 +349,7 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
V(CODE_TYPE) \ V(CODE_TYPE) \
V(ODDBALL_TYPE) \ V(ODDBALL_TYPE) \
V(JS_GLOBAL_PROPERTY_CELL_TYPE) \ V(JS_GLOBAL_PROPERTY_CELL_TYPE) \
V(BOX_TYPE) \
\ \
V(HEAP_NUMBER_TYPE) \ V(HEAP_NUMBER_TYPE) \
V(FOREIGN_TYPE) \ V(FOREIGN_TYPE) \
...@@ -526,6 +528,7 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits; ...@@ -526,6 +528,7 @@ const int kStubMinorKeyBits = kBitsPerInt - kSmiTagSize - kStubMajorKeyBits;
// type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST // type tags, elements in this list have to be added to the INSTANCE_TYPE_LIST
// manually. // manually.
#define STRUCT_LIST_ALL(V) \ #define STRUCT_LIST_ALL(V) \
V(BOX, Box, box) \
V(DECLARED_ACCESSOR_DESCRIPTOR, \ V(DECLARED_ACCESSOR_DESCRIPTOR, \
DeclaredAccessorDescriptor, \ DeclaredAccessorDescriptor, \
declared_accessor_descriptor) \ declared_accessor_descriptor) \
...@@ -667,6 +670,7 @@ enum InstanceType { ...@@ -667,6 +670,7 @@ enum InstanceType {
CODE_TYPE, CODE_TYPE,
ODDBALL_TYPE, ODDBALL_TYPE,
JS_GLOBAL_PROPERTY_CELL_TYPE, JS_GLOBAL_PROPERTY_CELL_TYPE,
BOX_TYPE,
// "Data", objects that cannot contain non-map-word pointers to heap // "Data", objects that cannot contain non-map-word pointers to heap
// objects. // objects.
...@@ -5685,6 +5689,26 @@ class Struct: public HeapObject { ...@@ -5685,6 +5689,26 @@ class Struct: public HeapObject {
}; };
// A simple one-element struct, useful where smis need to be boxed.
class Box : public Struct {
public:
// [value]: the boxed contents.
DECL_ACCESSORS(value, Object)
static inline Box* cast(Object* obj);
// Dispatched behavior.
DECLARE_PRINTER(Box)
DECLARE_VERIFIER(Box)
static const int kValueOffset = HeapObject::kHeaderSize;
static const int kSize = kValueOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Box);
};
// Script describes a script which has been added to the VM. // Script describes a script which has been added to the VM.
class Script: public Struct { class Script: public Struct {
public: public:
......
...@@ -42,8 +42,14 @@ int Type::LubBitset() { ...@@ -42,8 +42,14 @@ int Type::LubBitset() {
} }
return bitset; return bitset;
} else { } else {
Map* map = Map* map = NULL;
this->is_class() ? *this->as_class() : this->as_constant()->map(); if (this->is_class()) {
map = *this->as_class();
} else {
v8::internal::Object* value = this->as_constant()->value();
if (value->IsSmi()) return kSmi;
map = HeapObject::cast(value)->map();
}
switch (map->instance_type()) { switch (map->instance_type()) {
case STRING_TYPE: case STRING_TYPE:
case ASCII_STRING_TYPE: case ASCII_STRING_TYPE:
...@@ -126,7 +132,8 @@ bool Type::Is(Handle<Type> that) { ...@@ -126,7 +132,8 @@ bool Type::Is(Handle<Type> that) {
return this->is_class() && *this->as_class() == *that->as_class(); return this->is_class() && *this->as_class() == *that->as_class();
} }
if (that->is_constant()) { if (that->is_constant()) {
return this->is_constant() && *this->as_constant() == *that->as_constant(); return this->is_constant() &&
this->as_constant()->value() == that->as_constant()->value();
} }
// (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T) // (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T)
...@@ -169,7 +176,8 @@ bool Type::Maybe(Handle<Type> that) { ...@@ -169,7 +176,8 @@ bool Type::Maybe(Handle<Type> that) {
return that->is_class() && *this->as_class() == *that->as_class(); return that->is_class() && *this->as_class() == *that->as_class();
} }
if (this->is_constant()) { if (this->is_constant()) {
return that->is_constant() && *this->as_constant() == *that->as_constant(); return that->is_constant() &&
this->as_constant()->value() == that->as_constant()->value();
} }
// (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T) // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T)
......
...@@ -79,8 +79,8 @@ namespace internal { ...@@ -79,8 +79,8 @@ namespace internal {
// existing assumptions or tests. // existing assumptions or tests.
// //
// Internally, all 'primitive' types, and their unions, are represented as // Internally, all 'primitive' types, and their unions, are represented as
// bitsets via smis. Class and Constant are heap pointers to the respective // bitsets via smis. Class is a heap pointer to the respective map. Only
// argument. Only unions containing Class'es or Constant's require allocation. // Constant's, or unions containing Class'es or Constant's, require allocation.
// //
// The type representation is heap-allocated, so cannot (currently) be used in // The type representation is heap-allocated, so cannot (currently) be used in
// a parallel compilation context. // a parallel compilation context.
...@@ -113,8 +113,10 @@ class Type : public Object { ...@@ -113,8 +113,10 @@ class Type : public Object {
static Type* Class(Handle<Map> map) { return from_handle(map); } static Type* Class(Handle<Map> map) { return from_handle(map); }
static Type* Constant(Handle<HeapObject> value) { static Type* Constant(Handle<HeapObject> value) {
ASSERT(!value->IsMap() && !value->IsFixedArray()); return Constant(value, value->GetIsolate());
return from_handle(value); }
static Type* Constant(Handle<v8::internal::Object> value, Isolate* isolate) {
return from_handle(isolate->factory()->NewBox(value));
} }
static Type* Union(Handle<Type> type1, Handle<Type> type2); static Type* Union(Handle<Type> type1, Handle<Type> type2);
...@@ -159,15 +161,12 @@ class Type : public Object { ...@@ -159,15 +161,12 @@ class Type : public Object {
bool is_bitset() { return this->IsSmi(); } bool is_bitset() { return this->IsSmi(); }
bool is_class() { return this->IsMap(); } bool is_class() { return this->IsMap(); }
bool is_constant() { return !(is_bitset() || is_class() || is_union()); } bool is_constant() { return this->IsBox(); }
bool is_union() { return this->IsFixedArray(); } bool is_union() { return this->IsFixedArray(); }
int as_bitset() { return Smi::cast(this)->value(); } int as_bitset() { return Smi::cast(this)->value(); }
Handle<Map> as_class() { return Handle<Map>::cast(handle()); } Handle<Map> as_class() { return Handle<Map>::cast(handle()); }
Handle<HeapObject> as_constant() { Handle<Box> as_constant() { return Handle<Box>::cast(handle()); }
ASSERT(is_constant());
return Handle<HeapObject>::cast(handle());
}
Handle<Unioned> as_union() { return Handle<Unioned>::cast(handle()); } Handle<Unioned> as_union() { return Handle<Unioned>::cast(handle()); }
Handle<Type> handle() { return handle_via_isolate_of(this); } Handle<Type> handle() { return handle_via_isolate_of(this); }
......
...@@ -33,14 +33,12 @@ using namespace v8::internal; ...@@ -33,14 +33,12 @@ using namespace v8::internal;
// Testing auxiliaries (breaking the Type abstraction). // Testing auxiliaries (breaking the Type abstraction).
static bool IsBitset(Type* type) { return type->IsSmi(); } static bool IsBitset(Type* type) { return type->IsSmi(); }
static bool IsClass(Type* type) { return type->IsMap(); } 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 IsUnion(Type* type) { return type->IsFixedArray(); }
static bool IsConstant(Type* type) {
return !(IsBitset(type) || IsClass(type) || IsUnion(type));
}
static int AsBitset(Type* type) { return Smi::cast(type)->value(); } static int AsBitset(Type* type) { return Smi::cast(type)->value(); }
static Map* AsClass(Type* type) { return Map::cast(type); } static Map* AsClass(Type* type) { return Map::cast(type); }
static HeapObject* AsConstant(Type* type) { return HeapObject::cast(type); } static Object* AsConstant(Type* type) { return Box::cast(type)->value(); }
static FixedArray* AsUnion(Type* type) { return FixedArray::cast(type); } static FixedArray* AsUnion(Type* type) { return FixedArray::cast(type); }
class HandlifiedTypes { class HandlifiedTypes {
...@@ -68,11 +66,13 @@ class HandlifiedTypes { ...@@ -68,11 +66,13 @@ class HandlifiedTypes {
object_map(isolate->factory()->NewMap(JS_OBJECT_TYPE, 3 * kPointerSize)), object_map(isolate->factory()->NewMap(JS_OBJECT_TYPE, 3 * kPointerSize)),
array_map(isolate->factory()->NewMap(JS_ARRAY_TYPE, 4 * kPointerSize)), array_map(isolate->factory()->NewMap(JS_ARRAY_TYPE, 4 * kPointerSize)),
isolate_(isolate) { isolate_(isolate) {
smi = handle(Smi::FromInt(666), isolate);
object1 = isolate->factory()->NewJSObjectFromMap(object_map); object1 = isolate->factory()->NewJSObjectFromMap(object_map);
object2 = isolate->factory()->NewJSObjectFromMap(object_map); object2 = isolate->factory()->NewJSObjectFromMap(object_map);
array = isolate->factory()->NewJSArray(20); array = isolate->factory()->NewJSArray(20);
ObjectClass = handle(Type::Class(object_map), isolate); ObjectClass = handle(Type::Class(object_map), isolate);
ArrayClass = handle(Type::Class(array_map), isolate); ArrayClass = handle(Type::Class(array_map), isolate);
SmiConstant = handle(Type::Constant(smi, isolate), isolate);
ObjectConstant1 = handle(Type::Constant(object1), isolate); ObjectConstant1 = handle(Type::Constant(object1), isolate);
ObjectConstant2 = handle(Type::Constant(object2), isolate); ObjectConstant2 = handle(Type::Constant(object2), isolate);
ArrayConstant = handle(Type::Constant(array), isolate); ArrayConstant = handle(Type::Constant(array), isolate);
...@@ -100,6 +100,8 @@ class HandlifiedTypes { ...@@ -100,6 +100,8 @@ class HandlifiedTypes {
Handle<Type> ObjectClass; Handle<Type> ObjectClass;
Handle<Type> ArrayClass; Handle<Type> ArrayClass;
Handle<Type> SmiConstant;
Handle<Type> ObjectConstant1; Handle<Type> ObjectConstant1;
Handle<Type> ObjectConstant2; Handle<Type> ObjectConstant2;
Handle<Type> ArrayConstant; Handle<Type> ArrayConstant;
...@@ -107,6 +109,7 @@ class HandlifiedTypes { ...@@ -107,6 +109,7 @@ class HandlifiedTypes {
Handle<Map> object_map; Handle<Map> object_map;
Handle<Map> array_map; Handle<Map> array_map;
Handle<v8::internal::Smi> smi;
Handle<JSObject> object1; Handle<JSObject> object1;
Handle<JSObject> object2; Handle<JSObject> object2;
Handle<JSArray> array; Handle<JSArray> array;
...@@ -165,10 +168,12 @@ TEST(Constant) { ...@@ -165,10 +168,12 @@ TEST(Constant) {
HandleScope scope(isolate); HandleScope scope(isolate);
HandlifiedTypes T(isolate); HandlifiedTypes T(isolate);
CHECK(IsConstant(*T.SmiConstant));
CHECK(IsConstant(*T.ObjectConstant1)); CHECK(IsConstant(*T.ObjectConstant1));
CHECK(IsConstant(*T.ObjectConstant2)); CHECK(IsConstant(*T.ObjectConstant2));
CHECK(IsConstant(*T.ArrayConstant)); CHECK(IsConstant(*T.ArrayConstant));
CHECK(*T.smi == AsConstant(*T.SmiConstant));
CHECK(*T.object1 == AsConstant(*T.ObjectConstant1)); CHECK(*T.object1 == AsConstant(*T.ObjectConstant1));
CHECK(*T.object2 == AsConstant(*T.ObjectConstant2)); CHECK(*T.object2 == AsConstant(*T.ObjectConstant2));
CHECK(*T.object1 != AsConstant(*T.ObjectConstant2)); CHECK(*T.object1 != AsConstant(*T.ObjectConstant2));
...@@ -250,6 +255,8 @@ TEST(Is) { ...@@ -250,6 +255,8 @@ TEST(Is) {
CheckSub(T.ArrayClass, T.Object); CheckSub(T.ArrayClass, T.Object);
CheckUnordered(T.ObjectClass, T.ArrayClass); CheckUnordered(T.ObjectClass, T.ArrayClass);
CheckSub(T.SmiConstant, T.Smi);
CheckSub(T.SmiConstant, T.Number);
CheckSub(T.ObjectConstant1, T.Object); CheckSub(T.ObjectConstant1, T.Object);
CheckSub(T.ObjectConstant2, T.Object); CheckSub(T.ObjectConstant2, T.Object);
CheckSub(T.ArrayConstant, T.Object); CheckSub(T.ArrayConstant, T.Object);
...@@ -333,6 +340,9 @@ TEST(Maybe) { ...@@ -333,6 +340,9 @@ TEST(Maybe) {
CheckOverlap(T.ArrayClass, T.ArrayClass); CheckOverlap(T.ArrayClass, T.ArrayClass);
CheckDisjoint(T.ObjectClass, T.ArrayClass); CheckDisjoint(T.ObjectClass, T.ArrayClass);
CheckOverlap(T.SmiConstant, T.Smi);
CheckOverlap(T.SmiConstant, T.Number);
CheckDisjoint(T.SmiConstant, T.Double);
CheckOverlap(T.ObjectConstant1, T.Object); CheckOverlap(T.ObjectConstant1, T.Object);
CheckOverlap(T.ObjectConstant2, T.Object); CheckOverlap(T.ObjectConstant2, T.Object);
CheckOverlap(T.ArrayConstant, T.Object); CheckOverlap(T.ArrayConstant, T.Object);
...@@ -422,9 +432,11 @@ TEST(Union) { ...@@ -422,9 +432,11 @@ TEST(Union) {
CheckDisjoint(T.Union(T.ObjectClass, T.String), T.Number); CheckDisjoint(T.Union(T.ObjectClass, T.String), T.Number);
// Bitset-constant // Bitset-constant
CHECK(IsBitset(Type::Union(T.SmiConstant, T.Number)));
CHECK(IsBitset(Type::Union(T.ObjectConstant1, T.Object))); CHECK(IsBitset(Type::Union(T.ObjectConstant1, T.Object)));
CHECK(IsUnion(Type::Union(T.ObjectConstant2, T.Number))); 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.ObjectConstant1, T.Object), T.Object);
CheckSub(T.Union(T.ObjectConstant1, T.Number), T.Any); CheckSub(T.Union(T.ObjectConstant1, T.Number), T.Any);
CheckSub(T.Union(T.ObjectConstant1, T.Smi), T.Union(T.Object, T.Number)); CheckSub(T.Union(T.ObjectConstant1, T.Smi), T.Union(T.Object, T.Number));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment