Revision: 14987
Author: [email protected]
Date: Thu Jun 6 08:40:28 2013
Log: Allow smis for singleton types
To that end, introduce a generic Box struct.
[email protected]
BUG=
Review URL: https://codereview.chromium.org/16562003
http://code.google.com/p/v8/source/detail?r=14987
Modified:
/branches/bleeding_edge/include/v8.h
/branches/bleeding_edge/src/factory.cc
/branches/bleeding_edge/src/factory.h
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/src/objects-debug.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects-printer.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/types.cc
/branches/bleeding_edge/src/types.h
/branches/bleeding_edge/test/cctest/test-types.cc
=======================================
--- /branches/bleeding_edge/include/v8.h Thu Jun 6 07:21:35 2013
+++ /branches/bleeding_edge/include/v8.h Thu Jun 6 08:40:28 2013
@@ -5293,10 +5293,10 @@
static const int kNodeIsIndependentShift = 4;
static const int kNodeIsPartiallyDependentShift = 5;
- static const int kJSObjectType = 0xae;
+ static const int kJSObjectType = 0xaf;
static const int kFirstNonstringType = 0x80;
static const int kOddballType = 0x83;
- static const int kForeignType = 0x86;
+ static const int kForeignType = 0x87;
static const int kUndefinedOddballKind = 5;
static const int kNullOddballKind = 3;
=======================================
--- /branches/bleeding_edge/src/factory.cc Thu Jun 6 06:28:22 2013
+++ /branches/bleeding_edge/src/factory.cc Thu Jun 6 08:40:28 2013
@@ -41,6 +41,14 @@
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) {
ASSERT(0 <= size);
CALL_HEAP_FUNCTION(
=======================================
--- /branches/bleeding_edge/src/factory.h Thu Jun 6 06:28:22 2013
+++ /branches/bleeding_edge/src/factory.h Thu Jun 6 08:40:28 2013
@@ -39,6 +39,11 @@
class Factory {
public:
+ // Allocate a new boxed value.
+ Handle<Box> NewBox(
+ Handle<Object> value,
+ PretenureFlag pretenure = NOT_TENURED);
+
// Allocate a new uninitialized fixed array.
Handle<FixedArray> NewFixedArray(
int size,
=======================================
--- /branches/bleeding_edge/src/heap.cc Thu Jun 6 07:21:35 2013
+++ /branches/bleeding_edge/src/heap.cc Thu Jun 6 08:40:28 2013
@@ -2699,6 +2699,15 @@
JSGlobalPropertyCell::cast(result)->set_value(value);
return result;
}
+
+
+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,
=======================================
--- /branches/bleeding_edge/src/heap.h Thu Jun 6 07:21:35 2013
+++ /branches/bleeding_edge/src/heap.h Thu Jun 6 08:40:28 2013
@@ -939,6 +939,10 @@
// Please note this does not perform a garbage collection.
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
// Returns Failure::RetryAfterGC(requested_bytes, space) if the
allocation
// failed.
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc Thu Jun 6 07:21:35 2013
+++ /branches/bleeding_edge/src/objects-debug.cc Thu Jun 6 08:40:28 2013
@@ -776,6 +776,12 @@
void Foreign::ForeignVerify() {
CHECK(IsForeign());
}
+
+
+void Box::BoxVerify() {
+ CHECK(IsBox());
+ value()->Verify();
+}
void AccessorInfo::AccessorInfoVerify() {
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Thu Jun 6 07:21:35 2013
+++ /branches/bleeding_edge/src/objects-inl.h Thu Jun 6 08:40:28 2013
@@ -4383,6 +4383,8 @@
ACCESSORS(ExecutableAccessorInfo, setter, Object, kSetterOffset)
ACCESSORS(ExecutableAccessorInfo, data, Object, kDataOffset)
+ACCESSORS(Box, value, Object, kValueOffset)
+
ACCESSORS(AccessorPair, getter, Object, kGetterOffset)
ACCESSORS(AccessorPair, setter, Object, kSetterOffset)
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc Thu Jun 6 05:05:22 2013
+++ /branches/bleeding_edge/src/objects-printer.cc Thu Jun 6 08:40:28 2013
@@ -968,6 +968,13 @@
PrintF(out, "\n - internal field: ");
serialized_data()->ShortPrint(out);
}
+
+
+void Box::BoxPrint(FILE* out) {
+ HeapObject::PrintHeader(out, "Box");
+ PrintF(out, "\n - value: ");
+ value()->ShortPrint(out);
+}
void AccessorPair::AccessorPairPrint(FILE* out) {
=======================================
--- /branches/bleeding_edge/src/objects.h Thu Jun 6 07:21:35 2013
+++ /branches/bleeding_edge/src/objects.h Thu Jun 6 08:40:28 2013
@@ -125,6 +125,7 @@
// - Foreign
// - SharedFunctionInfo
// - Struct
+// - Box
// - DeclaredAccessorDescriptor
// - AccessorInfo
// - DeclaredAccessorInfo
@@ -348,6 +349,7 @@
V(CODE_TYPE)
\
V(ODDBALL_TYPE)
\
V(JS_GLOBAL_PROPERTY_CELL_TYPE)
\
+
V(BOX_TYPE)
\
\
V(HEAP_NUMBER_TYPE)
\
V(FOREIGN_TYPE)
\
@@ -526,6 +528,7 @@
// type tags, elements in this list have to be added to the
INSTANCE_TYPE_LIST
// manually.
#define
STRUCT_LIST_ALL(V) \
+ V(BOX, Box,
box) \
V(DECLARED_ACCESSOR_DESCRIPTOR,
\
DeclaredAccessorDescriptor, \
declared_accessor_descriptor) \
@@ -667,6 +670,7 @@
CODE_TYPE,
ODDBALL_TYPE,
JS_GLOBAL_PROPERTY_CELL_TYPE,
+ BOX_TYPE,
// "Data", objects that cannot contain non-map-word pointers to heap
// objects.
@@ -5685,6 +5689,26 @@
};
+// 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.
class Script: public Struct {
public:
=======================================
--- /branches/bleeding_edge/src/types.cc Wed Jun 5 08:43:53 2013
+++ /branches/bleeding_edge/src/types.cc Thu Jun 6 08:40:28 2013
@@ -42,8 +42,14 @@
}
return bitset;
} else {
- Map* map =
- this->is_class() ? *this->as_class() : this->as_constant()->map();
+ Map* map = NULL;
+ 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()) {
case STRING_TYPE:
case ASCII_STRING_TYPE:
@@ -126,7 +132,8 @@
return this->is_class() && *this->as_class() == *that->as_class();
}
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)
@@ -169,7 +176,8 @@
return that->is_class() && *this->as_class() == *that->as_class();
}
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)
=======================================
--- /branches/bleeding_edge/src/types.h Wed Jun 5 08:43:53 2013
+++ /branches/bleeding_edge/src/types.h Thu Jun 6 08:40:28 2013
@@ -79,8 +79,8 @@
// existing assumptions or tests.
//
// Internally, all 'primitive' types, and their unions, are represented as
-// bitsets via smis. Class and Constant are heap pointers to the respective
-// argument. Only unions containing Class'es or Constant's require
allocation.
+// bitsets via smis. Class is a heap pointer to the respective map. Only
+// Constant's, or unions containing Class'es or Constant's, require
allocation.
//
// The type representation is heap-allocated, so cannot (currently) be
used in
// a parallel compilation context.
@@ -113,8 +113,10 @@
static Type* Class(Handle<Map> map) { return from_handle(map); }
static Type* Constant(Handle<HeapObject> value) {
- ASSERT(!value->IsMap() && !value->IsFixedArray());
- return from_handle(value);
+ return Constant(value, value->GetIsolate());
+ }
+ 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);
@@ -159,15 +161,12 @@
bool is_bitset() { return this->IsSmi(); }
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(); }
int as_bitset() { return Smi::cast(this)->value(); }
Handle<Map> as_class() { return Handle<Map>::cast(handle()); }
- Handle<HeapObject> as_constant() {
- ASSERT(is_constant());
- return Handle<HeapObject>::cast(handle());
- }
+ Handle<Box> as_constant() { return Handle<Box>::cast(handle()); }
Handle<Unioned> as_union() { return Handle<Unioned>::cast(handle()); }
Handle<Type> handle() { return handle_via_isolate_of(this); }
=======================================
--- /branches/bleeding_edge/test/cctest/test-types.cc Wed Jun 5 08:43:53
2013
+++ /branches/bleeding_edge/test/cctest/test-types.cc Thu Jun 6 08:40:28
2013
@@ -33,14 +33,12 @@
// 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 IsConstant(Type* type) {
- return !(IsBitset(type) || IsClass(type) || IsUnion(type));
-}
static int AsBitset(Type* type) { return Smi::cast(type)->value(); }
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); }
class HandlifiedTypes {
@@ -68,11 +66,13 @@
object_map(isolate->factory()->NewMap(JS_OBJECT_TYPE, 3 *
kPointerSize)),
array_map(isolate->factory()->NewMap(JS_ARRAY_TYPE, 4 *
kPointerSize)),
isolate_(isolate) {
+ smi = handle(Smi::FromInt(666), isolate);
object1 = isolate->factory()->NewJSObjectFromMap(object_map);
object2 = isolate->factory()->NewJSObjectFromMap(object_map);
array = isolate->factory()->NewJSArray(20);
ObjectClass = handle(Type::Class(object_map), isolate);
ArrayClass = handle(Type::Class(array_map), isolate);
+ SmiConstant = handle(Type::Constant(smi, isolate), isolate);
ObjectConstant1 = handle(Type::Constant(object1), isolate);
ObjectConstant2 = handle(Type::Constant(object2), isolate);
ArrayConstant = handle(Type::Constant(array), isolate);
@@ -100,6 +100,8 @@
Handle<Type> ObjectClass;
Handle<Type> ArrayClass;
+
+ Handle<Type> SmiConstant;
Handle<Type> ObjectConstant1;
Handle<Type> ObjectConstant2;
Handle<Type> ArrayConstant;
@@ -107,6 +109,7 @@
Handle<Map> object_map;
Handle<Map> array_map;
+ Handle<v8::internal::Smi> smi;
Handle<JSObject> object1;
Handle<JSObject> object2;
Handle<JSArray> array;
@@ -165,10 +168,12 @@
HandleScope scope(isolate);
HandlifiedTypes T(isolate);
+ CHECK(IsConstant(*T.SmiConstant));
CHECK(IsConstant(*T.ObjectConstant1));
CHECK(IsConstant(*T.ObjectConstant2));
CHECK(IsConstant(*T.ArrayConstant));
+ CHECK(*T.smi == AsConstant(*T.SmiConstant));
CHECK(*T.object1 == AsConstant(*T.ObjectConstant1));
CHECK(*T.object2 == AsConstant(*T.ObjectConstant2));
CHECK(*T.object1 != AsConstant(*T.ObjectConstant2));
@@ -250,6 +255,8 @@
CheckSub(T.ArrayClass, T.Object);
CheckUnordered(T.ObjectClass, T.ArrayClass);
+ CheckSub(T.SmiConstant, T.Smi);
+ CheckSub(T.SmiConstant, T.Number);
CheckSub(T.ObjectConstant1, T.Object);
CheckSub(T.ObjectConstant2, T.Object);
CheckSub(T.ArrayConstant, T.Object);
@@ -333,6 +340,9 @@
CheckOverlap(T.ArrayClass, 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.ObjectConstant2, T.Object);
CheckOverlap(T.ArrayConstant, T.Object);
@@ -422,9 +432,11 @@
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)));
+ CheckEqual(T.Union(T.SmiConstant, T.Number), T.Number);
CheckEqual(T.Union(T.ObjectConstant1, T.Object), T.Object);
CheckSub(T.Union(T.ObjectConstant1, T.Number), T.Any);
CheckSub(T.Union(T.ObjectConstant1, T.Smi), T.Union(T.Object, T.Number));
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.