Make ImmutableArray a sub class of AllStatic.
This enables Array to be a FINAL_HEAP_OBJECT and the operators
'=' and '^=' would be a simpler implementation which does not
require a call to initializeHandle().
R=iposva@google.com
Review URL: https://codereview.chromium.org//16390002
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@23884 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 0afd8df..bf35ec2 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -2043,7 +2043,7 @@
const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list));
// If the list is immutable we call into Dart for the indexed setter to
// get the unsupported operation exception as the result.
- if (obj.IsArray() && !obj.IsImmutableArray()) {
+ if (obj.IsArray() && !Array::Cast(obj).IsImmutable()) {
SET_LIST_ELEMENT(isolate, Array, obj, index, value);
} else if (obj.IsGrowableObjectArray()) {
SET_LIST_ELEMENT(isolate, GrowableObjectArray, obj, index, value);
@@ -2297,7 +2297,7 @@
return Api::NewError("Invalid length passed in to access list elements");
}
}
- if (obj.IsArray() && !obj.IsImmutableArray()) {
+ if (obj.IsArray() && !Array::Cast(obj).IsImmutable()) {
// If the list is immutable we call into Dart for the indexed setter to
// get the unsupported operation exception as the result.
SET_LIST_ELEMENT_AS_BYTES(isolate,
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index b5259dd..ced4460 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -530,7 +530,7 @@
cls = Class::New<Array>();
isolate->object_store()->set_array_class(cls);
cls.set_type_arguments_field_offset(Array::type_arguments_offset());
- cls = Class::New<ImmutableArray>();
+ cls = Class::New<Array>(kImmutableArrayCid);
isolate->object_store()->set_immutable_array_class(cls);
cls.set_type_arguments_field_offset(Array::type_arguments_offset());
cls = Class::NewStringClass(kOneByteStringCid);
@@ -832,10 +832,11 @@
RegisterPrivateClass(cls, Symbols::GrowableObjectArray(), core_lib);
pending_classes.Add(cls, Heap::kOld);
- cls = Class::New<ImmutableArray>();
+ cls = Class::New<Array>(kImmutableArrayCid);
object_store->set_immutable_array_class(cls);
cls.set_type_arguments_field_offset(Array::type_arguments_offset());
ASSERT(object_store->immutable_array_class() != object_store->array_class());
+ cls.set_is_prefinalized();
RegisterPrivateClass(cls, Symbols::ImmutableArray(), core_lib);
pending_classes.Add(cls, Heap::kOld);
@@ -1120,7 +1121,7 @@
cls = Class::New<Array>();
object_store->set_array_class(cls);
- cls = Class::New<ImmutableArray>();
+ cls = Class::New<Array>(kImmutableArrayCid);
object_store->set_immutable_array_class(cls);
cls = Class::New<GrowableObjectArray>();
@@ -12542,9 +12543,10 @@
const char* Array::ToCString() const {
if (IsNull()) {
- return "Array NULL";
+ return IsImmutable() ? "ImmutableArray NULL" : "Array NULL";
}
- const char* format = "Array len:%"Pd"";
+ const char* format = !IsImmutable() ? "Array len:%"Pd"" :
+ "Immutable Array len:%"Pd"";
intptr_t len = OS::SNPrint(NULL, 0, format, Length()) + 1;
char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
OS::SNPrint(chars, len, format, Length());
@@ -12612,18 +12614,6 @@
}
-const char* ImmutableArray::ToCString() const {
- if (IsNull()) {
- return "ImmutableArray NULL";
- }
- const char* format = "ImmutableArray len:%"Pd"";
- intptr_t len = OS::SNPrint(NULL, 0, format, Length()) + 1;
- char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
- OS::SNPrint(chars, len, format, Length());
- return chars;
-}
-
-
void GrowableObjectArray::Add(const Object& value, Heap::Space space) const {
ASSERT(!IsNull());
if (Length() == Capacity()) {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 149b390..35786cb 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4932,6 +4932,10 @@
StorePointer(ObjectAddr(index), value.raw());
}
+ bool IsImmutable() const {
+ return raw()->GetClassId() == kImmutableArrayCid;
+ }
+
virtual RawAbstractTypeArguments* GetTypeArguments() const {
return raw_ptr()->type_arguments_;
}
@@ -5005,19 +5009,38 @@
raw_ptr()->length_ = Smi::New(value);
}
- HEAP_OBJECT_IMPLEMENTATION(Array, Instance);
+ FINAL_HEAP_OBJECT_IMPLEMENTATION(Array, Instance);
friend class Class;
+ friend class ImmutableArray;
friend class Object;
friend class String;
};
-class ImmutableArray : public Array {
+class ImmutableArray : public AllStatic {
public:
static RawImmutableArray* New(intptr_t len, Heap::Space space = Heap::kNew);
+ static RawImmutableArray* ReadFrom(SnapshotReader* reader,
+ intptr_t object_id,
+ intptr_t tags,
+ Snapshot::Kind kind);
+
+ static const ClassId kClassId = kImmutableArrayCid;
+
+ static intptr_t InstanceSize() {
+ return Array::InstanceSize();
+ }
+
+ static intptr_t InstanceSize(intptr_t len) {
+ return Array::InstanceSize(len);
+ }
+
private:
- FINAL_HEAP_OBJECT_IMPLEMENTATION(ImmutableArray, Array);
+ static RawImmutableArray* raw(const Array& array) {
+ return reinterpret_cast<RawImmutableArray*>(array.raw());
+ }
+
friend class Class;
};
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 0d57f54..4a51160 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -211,7 +211,7 @@
if (class_id < kNumPredefinedCids) {
switch (class_id) {
#define RAW_VISITPOINTERS(clazz) \
- case clazz::kClassId: { \
+ case k##clazz##Cid: { \
Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(this); \
size = Raw##clazz::Visit##clazz##Pointers(raw_obj, visitor); \
break; \
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index fab5eec..1ef30f4 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -13,7 +13,7 @@
namespace dart {
// Macrobatics to define the Object hierarchy of VM implementation classes.
-#define CLASS_LIST_NO_OBJECT_OR_STRING(V) \
+#define CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V) \
V(Class) \
V(UnresolvedClass) \
V(AbstractTypeArguments) \
@@ -60,8 +60,6 @@
V(Bigint) \
V(Double) \
V(Bool) \
- V(Array) \
- V(ImmutableArray) \
V(GrowableObjectArray) \
V(TypedData) \
V(ExternalTypedData) \
@@ -72,6 +70,9 @@
V(Float32x4) \
V(Uint32x4) \
+#define CLASS_LIST_ARRAYS(V) \
+ V(Array) \
+ V(ImmutableArray) \
#define CLASS_LIST_STRINGS(V) \
V(String) \
@@ -95,11 +96,13 @@
V(Float32x4Array) \
#define CLASS_LIST_FOR_HANDLES(V) \
- CLASS_LIST_NO_OBJECT_OR_STRING(V) \
+ CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V) \
+ V(Array) \
V(String)
#define CLASS_LIST_NO_OBJECT(V) \
- CLASS_LIST_NO_OBJECT_OR_STRING(V) \
+ CLASS_LIST_NO_OBJECT_NOR_STRING_NOR_ARRAY(V) \
+ CLASS_LIST_ARRAYS(V) \
CLASS_LIST_STRINGS(V)
#define CLASS_LIST(V) \
@@ -1602,9 +1605,9 @@
inline bool RawObject::IsBuiltinListClassId(intptr_t index) {
// Make sure this function is updated when new builtin List types are added.
ASSERT(kImmutableArrayCid == kArrayCid + 1 &&
- kGrowableObjectArrayCid == kArrayCid + 2 &&
- kTypedDataCid == kArrayCid + 3);
- return ((index >= kArrayCid && index < kTypedDataCid) ||
+ kTypedDataCid == kGrowableObjectArrayCid + 1);
+ return ((index >= kArrayCid && index < kImmutableArrayCid) ||
+ (index >= kGrowableObjectArrayCid && index < kTypedDataCid) ||
IsTypedDataClassId(index) ||
IsTypedDataViewClassId(index) ||
IsExternalTypedDataClassId(index));
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index cd4e0e5..d4f39a7 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -2082,16 +2082,15 @@
// Read the length so that we can determine instance size to allocate.
intptr_t len = reader->ReadSmiValue();
- ImmutableArray* array = reinterpret_cast<ImmutableArray*>(
- reader->GetBackRef(object_id));
+ Array* array = reinterpret_cast<Array*>(reader->GetBackRef(object_id));
if (array == NULL) {
- array = &(ImmutableArray::ZoneHandle(
+ array = &(Array::ZoneHandle(
reader->isolate(),
NEW_OBJECT_WITH_LEN_SPACE(ImmutableArray, len, kind)));
reader->AddBackRef(object_id, array, kIsDeserialized);
}
reader->ArrayReadFrom(*array, len, tags);
- return array->raw();
+ return raw(*array);
}
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index c94965d..ff22e03 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -33,6 +33,8 @@
// Check if this is a class which is stored in the object store.
return (class_id == kObjectCid ||
(class_id >= kInstanceCid && class_id <= kWeakPropertyCid) ||
+ class_id == kArrayCid ||
+ class_id == kImmutableArrayCid ||
RawObject::IsStringClassId(class_id) ||
RawObject::IsTypedDataClassId(class_id) ||
RawObject::IsExternalTypedDataClassId(class_id));
@@ -296,7 +298,7 @@
if (class_id == kImmutableArrayCid) {
// Read the length and allocate an object based on the len.
intptr_t len = ReadSmiValue();
- ImmutableArray& array = ImmutableArray::ZoneHandle(
+ Array& array = Array::ZoneHandle(
isolate(),
(kind_ == Snapshot::kFull) ?
NewImmutableArray(len) : ImmutableArray::New(len, HEAP_SPACE(kind_)));