Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Unified Diff: vm/object.cc

Issue 9594028: Add a first class GrowableObjectArray type in the VM and use it internally in the VM at all spots w… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: vm/object.cc
===================================================================
--- vm/object.cc (revision 4983)
+++ vm/object.cc (working copy)
@@ -444,6 +444,11 @@
// has been created.
cls.InitEmptyFields();
+ // Set up the growable object array class (Has to be done after the array
+ // class is setup as one of it's field is an array object.
hausner 2012/03/06 00:30:47 it's -> its Also missing ) in comment.
siva 2012/03/06 23:32:33 Done.
+ cls = Class::New<GrowableObjectArray>();
+ object_store->set_growable_object_array_class(cls);
+
// Setup the symbol table used within the String class.
const int kInitialSymbolTableSize = 16;
array = Array::New(kInitialSymbolTableSize + 1);
@@ -466,7 +471,9 @@
Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary());
ASSERT(!core_impl_lib.IsNull());
- object_store->set_pending_classes(Array::Handle(Array::Empty()));
+ const GrowableObjectArray& pending_classes =
+ GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld));
+ object_store->set_pending_classes(pending_classes);
Context& context = Context::Handle(Context::New(0));
object_store->set_empty_context(context);
@@ -475,83 +482,82 @@
// well as the core implementation dictionary have been setup, preallocate
// remaining classes and register them by name in the dictionaries.
const Script& impl_script = Script::Handle(Bootstrap::LoadImplScript());
- GrowableArray<const Class*> pending_classes;
cls = Class::New<Smi>();
object_store->set_smi_class(cls);
RegisterClass(cls, "Smi", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
cls = Class::New<Mint>();
object_store->set_mint_class(cls);
RegisterClass(cls, "Mint", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
cls = Class::New<Bigint>();
object_store->set_bigint_class(cls);
RegisterClass(cls, "Bigint", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
cls = Class::New<Double>();
object_store->set_double_class(cls);
RegisterClass(cls, "Double", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
cls = Class::New<Bool>();
object_store->set_bool_class(cls);
RegisterClass(cls, "Bool", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
cls = object_store->array_class(); // Was allocated above.
RegisterClass(cls, "ObjectArray", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
cls = Class::New<ImmutableArray>();
object_store->set_immutable_array_class(cls);
cls.set_type_arguments_instance_field_offset(Array::type_arguments_offset());
ASSERT(object_store->immutable_array_class() != object_store->array_class());
RegisterClass(cls, "ImmutableArray", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
cls = object_store->one_byte_string_class(); // Was allocated above.
RegisterClass(cls, "OneByteString", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
cls = Class::New<TwoByteString>();
object_store->set_two_byte_string_class(cls);
RegisterClass(cls, "TwoByteString", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
cls = Class::New<FourByteString>();
object_store->set_four_byte_string_class(cls);
RegisterClass(cls, "FourByteString", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
cls = Class::New<ExternalOneByteString>();
object_store->set_external_one_byte_string_class(cls);
RegisterClass(cls, "ExternalOneByteString", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
cls = Class::New<ExternalTwoByteString>();
object_store->set_external_two_byte_string_class(cls);
RegisterClass(cls, "ExternalTwoByteString", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
cls = Class::New<ExternalFourByteString>();
object_store->set_external_four_byte_string_class(cls);
RegisterClass(cls, "ExternalFourByteString", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
cls = Class::New<Stacktrace>();
object_store->set_stacktrace_class(cls);
RegisterClass(cls, "Stacktrace", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
// Super type set below, after Object is allocated.
cls = Class::New<JSRegExp>();
object_store->set_jsregexp_class(cls);
RegisterClass(cls, "JSSyntaxRegExp", impl_script, core_impl_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
// Initialize the base interfaces used by the core VM classes.
const Script& script = Script::Handle(Bootstrap::LoadScript());
@@ -564,7 +570,7 @@
cls.set_name(String::Handle(String::NewSymbol("Object")));
cls.set_script(script);
core_lib.AddClass(cls);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
type = Type::NewNonParameterizedType(cls);
object_store->set_object_type(type);
@@ -586,42 +592,42 @@
cls.set_super_type(type);
cls = CreateAndRegisterInterface("Function", script, core_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
type = Type::NewNonParameterizedType(cls);
object_store->set_function_interface(type);
cls = CreateAndRegisterInterface("num", script, core_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
type = Type::NewNonParameterizedType(cls);
object_store->set_number_interface(type);
cls = CreateAndRegisterInterface("int", script, core_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
type = Type::NewNonParameterizedType(cls);
object_store->set_int_interface(type);
cls = CreateAndRegisterInterface("double", script, core_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
type = Type::NewNonParameterizedType(cls);
object_store->set_double_interface(type);
cls = CreateAndRegisterInterface("String", script, core_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
type = Type::NewNonParameterizedType(cls);
object_store->set_string_interface(type);
cls = CreateAndRegisterInterface("bool", script, core_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
type = Type::NewNonParameterizedType(cls);
object_store->set_bool_interface(type);
cls = CreateAndRegisterInterface("List", script, core_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
type = Type::NewNonParameterizedType(cls);
object_store->set_list_interface(type);
cls = CreateAndRegisterInterface("ByteArray", script, core_lib);
- pending_classes.Add(&Class::ZoneHandle(cls.raw()));
+ pending_classes.Add(cls, Heap::kOld);
type = Type::NewNonParameterizedType(cls);
object_store->set_byte_array_interface(type);
@@ -646,9 +652,6 @@
object_store->set_dynamic_type(type);
core_lib.AddClass(cls);
- // Add the preallocated classes to the list of classes to be finalized.
- ClassFinalizer::AddPendingClasses(pending_classes);
-
// Allocate pre-initialized values.
Bool& bool_value = Bool::Handle();
bool_value = Bool::New(true);
@@ -713,6 +716,9 @@
cls = Class::New<ImmutableArray>();
object_store->set_immutable_array_class(cls);
+ cls = Class::New<GrowableObjectArray>();
+ object_store->set_growable_object_array_class(cls);
+
cls = Class::New<InternalByteArray>();
object_store->set_internal_byte_array_class(cls);
@@ -1279,6 +1285,9 @@
case kImmutableArray:
ASSERT(object_store->immutable_array_class() != Class::null());
return object_store->immutable_array_class();
+ case kGrowableObjectArray:
+ ASSERT(object_store->growable_object_array_class() != Class::null());
+ return object_store->growable_object_array_class();
case kInternalByteArray:
ASSERT(object_store->internal_byte_array_class() != Class::null());
return object_store->internal_byte_array_class();
@@ -3530,26 +3539,18 @@
}
-template<typename T>
-static RawArray* NewArray(const GrowableArray<T*>& objs) {
- Array& a = Array::Handle(Array::New(objs.length(), Heap::kOld));
- for (int i = 0; i < objs.length(); i++) {
- a.SetAt(i, *objs[i]);
- }
- return a.raw();
-}
-
-
RawString* Function::BuildSignature(
bool instantiate,
const AbstractTypeArguments& instantiator) const {
- GrowableArray<const String*> pieces;
+ const GrowableObjectArray& pieces =
+ GrowableObjectArray::Handle(GrowableObjectArray::New());
const String& kCommaSpace = String::Handle(String::NewSymbol(", "));
const String& kColonSpace = String::Handle(String::NewSymbol(": "));
const String& kLParen = String::Handle(String::NewSymbol("("));
const String& kRParen = String::Handle(String::NewSymbol(") => "));
const String& kLBracket = String::Handle(String::NewSymbol("["));
const String& kRBracket = String::Handle(String::NewSymbol("]"));
+ String& name = String::Handle();
if (!instantiate && !is_static()) {
const String& kSpaceExtendsSpace =
String::Handle(String::NewSymbol(" extends "));
@@ -3561,24 +3562,26 @@
function_class.type_parameters());
if (!type_parameters.IsNull()) {
intptr_t num_type_parameters = type_parameters.Length();
- pieces.Add(&kLAngleBracket);
+ pieces.Add(kLAngleBracket);
const TypeArguments& bounds = TypeArguments::Handle(
function_class.type_parameter_bounds());
AbstractType& type_parameter = AbstractType::Handle();
AbstractType& bound = AbstractType::Handle();
for (intptr_t i = 0; i < num_type_parameters; i++) {
type_parameter ^= type_parameters.TypeAt(i);
- pieces.Add(&String::ZoneHandle(type_parameter.Name()));
+ name = type_parameter.Name();
+ pieces.Add(name);
bound = bounds.TypeAt(i);
if (!bound.IsNull() && !bound.IsDynamicType()) {
- pieces.Add(&kSpaceExtendsSpace);
- pieces.Add(&String::ZoneHandle(bound.Name()));
+ pieces.Add(kSpaceExtendsSpace);
+ name = bound.Name();
+ pieces.Add(name);
}
if (i < num_type_parameters - 1) {
- pieces.Add(&kCommaSpace);
+ pieces.Add(kCommaSpace);
}
}
- pieces.Add(&kRAngleBracket);
+ pieces.Add(kRAngleBracket);
}
}
AbstractType& param_type = AbstractType::Handle();
@@ -3586,42 +3589,46 @@
const intptr_t num_fixed_params = num_fixed_parameters();
const intptr_t num_opt_params = num_optional_parameters();
ASSERT((num_fixed_params + num_opt_params) == num_params);
- pieces.Add(&kLParen);
+ pieces.Add(kLParen);
for (intptr_t i = 0; i < num_fixed_params; i++) {
param_type = ParameterTypeAt(i);
ASSERT(!param_type.IsNull());
if (instantiate && !param_type.IsInstantiated()) {
param_type = param_type.InstantiateFrom(instantiator);
}
- pieces.Add(&String::ZoneHandle(param_type.Name()));
+ name = param_type.Name();
+ pieces.Add(name);
if (i != (num_params - 1)) {
- pieces.Add(&kCommaSpace);
+ pieces.Add(kCommaSpace);
}
}
if (num_opt_params > 0) {
- pieces.Add(&kLBracket);
+ pieces.Add(kLBracket);
for (intptr_t i = num_fixed_params; i < num_params; i++) {
- pieces.Add(&String::ZoneHandle(ParameterNameAt(i)));
- pieces.Add(&kColonSpace);
+ name = ParameterNameAt(i);
+ pieces.Add(name);
+ pieces.Add(kColonSpace);
param_type = ParameterTypeAt(i);
if (instantiate && !param_type.IsInstantiated()) {
param_type = param_type.InstantiateFrom(instantiator);
}
ASSERT(!param_type.IsNull());
- pieces.Add(&String::ZoneHandle(param_type.Name()));
+ name = param_type.Name();
+ pieces.Add(name);
if (i != (num_params - 1)) {
- pieces.Add(&kCommaSpace);
+ pieces.Add(kCommaSpace);
}
}
- pieces.Add(&kRBracket);
+ pieces.Add(kRBracket);
}
- pieces.Add(&kRParen);
+ pieces.Add(kRParen);
AbstractType& res_type = AbstractType::Handle(result_type());
if (instantiate && !res_type.IsInstantiated()) {
res_type = res_type.InstantiateFrom(instantiator);
}
- pieces.Add(&String::Handle(res_type.Name()));
- const Array& strings = Array::Handle(NewArray<const String>(pieces));
+ name = res_type.Name();
+ pieces.Add(name);
+ const Array& strings = Array::Handle(Array::MakeArray(pieces));
return String::NewSymbol(String::Handle(String::ConcatAll(strings)));
}
@@ -4301,13 +4308,15 @@
// cached in loaded_scripts_.
if (loaded_scripts() == Array::null()) {
// Iterate over the library dictionary and collect all scripts.
- GrowableArray<Script*> scripts(8);
+ const GrowableObjectArray& scripts =
+ GrowableObjectArray::Handle(GrowableObjectArray::New(8));
Object& entry = Object::Handle();
Function& func = Function::Handle();
Field& field = Field::Handle();
Class& cls = Class::Handle();
Script& owner_script = Script::Handle();
DictionaryIterator it(*this);
+ Script& script_obj = Script::Handle();
while (it.HasNext()) {
entry = it.GetNext();
if (entry.IsClass()) {
@@ -4326,27 +4335,22 @@
continue;
}
bool is_unique = true;
- for (int i = 0; i < scripts.length(); i++) {
- if (scripts[i]->raw() == owner_script.raw()) {
+ for (int i = 0; i < scripts.Length(); i++) {
+ script_obj ^= scripts.At(i);
+ if (script_obj.raw() == owner_script.raw()) {
// We already have a reference to this script.
is_unique = false;
break;
}
}
if (is_unique) {
- // Create a unique script handle and add it to the list of scripts.
- Script& unique_script = Script::Handle(owner_script.raw());
- scripts.Add(&unique_script);
+ // Add script to the list of scripts.
+ scripts.Add(owner_script);
}
}
// Create the array of scripts and cache it in loaded_scripts_.
- const Array& loaded_scripts =
- Array::Handle(Array::New(scripts.length(), Heap::kOld));
- for (int i = 0; i < scripts.length(); i++) {
- loaded_scripts.SetAt(i, *scripts[i]);
- }
- StorePointer(&raw_ptr()->loaded_scripts_, loaded_scripts.raw());
+ StorePointer(&raw_ptr()->loaded_scripts_, Array::MakeArray(scripts));
}
return loaded_scripts();
}
@@ -7952,6 +7956,58 @@
}
+RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) {
+ intptr_t used_len = growable_array.Length();
+ intptr_t capacity_len = growable_array.Capacity();
+ Isolate* isolate = Isolate::Current();
+ Array& array = Array::Handle(isolate, growable_array.data());
+ Array& new_array = Array::Handle(isolate, Array::null());
+ intptr_t capacity_size = Array::InstanceSize(capacity_len);
+ intptr_t used_size = Array::InstanceSize(used_len);
+
+ // Update the size in the header field and length of the array object.
+ uword tags = 0;
+ tags = RawObject::SizeTag::update(used_size, tags);
+ array.raw_ptr()->tags_ = tags;
+ array.SetLength(used_len);
+
+ // Null the GrowableObjectArray, we are removing it's backing array.
+ growable_array.set_length(0);
+ growable_array.set_capacity(0);
+ growable_array.set_data(new_array);
+
+ // If there is any left over space fill it with either an Array object or
+ // just a plain object (depending on the amount of left over space) so
+ // that it can be traversed over successfully during garbage collection.
+ if (capacity_size != used_size) {
hausner 2012/03/06 00:30:47 Will this filler array/object be collected by the
siva 2012/03/06 23:32:33 Yes, this would be an unreferenced object and henc
+ NoGCScope no_gc;
+ ASSERT(capacity_len > used_len);
+ intptr_t leftover_size = capacity_size - used_size;
+
+ uword addr = RawObject::ToAddr(array.raw()) + used_size;
+ if (leftover_size >= Array::InstanceSize(0)) {
+ // As we have enough space to use an array object, update the leftover
+ // space as an Array object.
+ new_array.raw_ = reinterpret_cast<RawArray*>(RawObject::FromAddr(addr));
+ new_array.raw_ptr()->class_ = isolate->object_store()->array_class();
+ tags = RawObject::SizeTag::update(leftover_size, tags);
+ new_array.raw_ptr()->tags_ = tags;
+ intptr_t leftover_len =
+ ((leftover_size - Array::InstanceSize(0)) / kWordSize);
+ new_array.SetLength(leftover_len);
+ } else {
+ // Update the leftover space as a basic object.
+ ASSERT(leftover_size == Object::InstanceSize());
+ Object& new_object = Object::Handle(isolate, RawObject::FromAddr(addr));
+ new_object.raw()->ptr()->class_ = isolate->object_store()->object_class();
+ tags = RawObject::SizeTag::update(leftover_size, tags);
+ new_object.raw()->ptr()->tags_ = tags;
+ }
+ }
+ return array.raw();
+}
+
+
RawImmutableArray* ImmutableArray::New(intptr_t len,
Heap::Space space) {
ObjectStore* object_store = Isolate::Current()->object_store();
@@ -7965,6 +8021,98 @@
}
+void GrowableObjectArray::Add(const Object& value, Heap::Space space) const {
+ ASSERT(!IsNull());
+ Array& contents = Array::Handle(data());
+ if (Length() == Capacity()) {
+ intptr_t new_capacity = Capacity() * 2;
cshapiro 2012/03/06 00:56:31 Overflow check?
siva 2012/03/06 23:32:33 I added a check to throw an exception if new_capac
+ StorePointer(&(raw_ptr()->data_),
+ Array::Grow(contents, new_capacity, space));
+ set_capacity(new_capacity);
+ contents = data();
+ }
+ ASSERT(Length() < Capacity());
+ intptr_t index = Length();
+ set_length(index + 1);
+ contents.SetAt(index, value);
+}
+
+
+RawObject* GrowableObjectArray::RemoveLast() const {
+ ASSERT(!IsNull());
+ ASSERT(Length() > 0);
+ intptr_t index = Length() - 1;
+ const Array& contents = Array::Handle(data());
+ const Object& obj = Object::Handle(contents.At(index));
+ contents.SetAt(index, Object::Handle());
+ set_length(index);
+ return obj.raw();
+}
+
+
+bool GrowableObjectArray::Equals(const Instance& other) const {
+ // If both handles point to the same raw instance they are equal.
+ if (this->raw() == other.raw()) {
+ return true;
+ }
+
+ // Other instance must be non null and a GrowableObjectArray.
+ if (!other.IsGrowableObjectArray() || other.IsNull()) {
+ return false;
+ }
+
+ // Both must have the same type arguments.
+ if (!AbstractTypeArguments::AreEqual(
hausner 2012/03/06 00:30:47 Would it make sense to compare the length first? I
siva 2012/03/06 23:32:33 Done.
+ AbstractTypeArguments::Handle(GetTypeArguments()),
+ AbstractTypeArguments::Handle(other.GetTypeArguments()))) {
+ return false;
+ }
+
+ GrowableObjectArray& other_arr = GrowableObjectArray::Handle();
+ other_arr ^= other.raw();
+
+ // The capacity and length of both objects must be equal.
+ if (Capacity() != other_arr.Capacity() || Length() != other_arr.Length()) {
+ return false;
+ }
+
+ // The data part in both arrays must be identical.
+ const Array& contents = Array::Handle(data());
+ const Array& other_contents = Array::Handle(other_arr.data());
+ for (intptr_t i = 0; i < Length(); i++) {
+ if (contents.At(i) != other_contents.At(i)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+RawGrowableObjectArray* GrowableObjectArray::New(intptr_t capacity,
+ Heap::Space space) {
+ ObjectStore* object_store = Isolate::Current()->object_store();
+ Class& cls = Class::Handle(object_store->growable_object_array_class());
+ const Array& data = Array::Handle(Array::New(capacity, space));
+ GrowableObjectArray& result = GrowableObjectArray::Handle();
+ {
+ RawObject* raw = Object::Allocate(cls,
+ GrowableObjectArray::InstanceSize(),
+ space);
+ NoGCScope no_gc;
+ result ^= raw;
+ result.set_capacity(capacity);
+ result.set_length(0);
+ result.set_data(data);
+ }
+ return result.raw();
+}
+
+
+const char* GrowableObjectArray::ToCString() const {
+ return "GrowableObjectArray";
+}
+
+
intptr_t ByteArray::Length() const {
// ByteArray is an abstract class.
UNREACHABLE();

Powered by Google App Engine
This is Rietveld 408576698