Index: runtime/vm/object.cc |
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc |
index 1d0e862e03e53ef805ca38fdb661568f1dc4084f..ae14d2332745387ddd7dd65865cb9c4e0c2f918a 100644 |
--- a/runtime/vm/object.cc |
+++ b/runtime/vm/object.cc |
@@ -517,7 +517,7 @@ RawError* Object::Init(Isolate* isolate) { |
GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld)); |
object_store->set_pending_classes(pending_classes); |
- Context& context = Context::Handle(Context::New(0)); |
+ Context& context = Context::Handle(Context::New(0, Heap::kOld)); |
object_store->set_empty_context(context); |
// Now that the symbol table is initialized and that the core dictionary as |
@@ -1003,6 +1003,39 @@ RawObject* Object::Allocate(const Class& cls, |
} |
+class StoreBufferObjectPointerVisitor : public ObjectPointerVisitor { |
+ public: |
+ explicit StoreBufferObjectPointerVisitor(Isolate* isolate) : |
+ ObjectPointerVisitor(isolate) { |
+ } |
+ void VisitPointers(RawObject** first, RawObject** last) { |
+ for (RawObject** curr = first; curr <= last; ++curr) { |
+ if ((*curr)->IsNewObject()) { |
+ uword ptr = reinterpret_cast<uword>(curr); |
+ isolate()->store_buffer()->AddPointer(ptr); |
+ } |
+ } |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(StoreBufferObjectPointerVisitor); |
+}; |
+ |
+ |
+RawObject* Object::Clone(const Object& src, Heap::Space space) { |
+ const Class& cls = Class::Handle(src.clazz()); |
+ intptr_t size = src.raw()->Size(); |
+ RawObject* raw_obj = Object::Allocate(cls, size, space); |
+ NoGCScope no_gc; |
+ memmove(raw_obj->ptr(), src.raw()->ptr(), size); |
+ if (space == Heap::kOld) { |
+ StoreBufferObjectPointerVisitor visitor(Isolate::Current()); |
+ raw_obj->VisitPointers(&visitor); |
+ } |
+ return raw_obj; |
+} |
+ |
+ |
RawString* Class::Name() const { |
if (raw_ptr()->name_ != String::null()) { |
return raw_ptr()->name_; |
@@ -2761,7 +2794,6 @@ RawAbstractType* Type::Canonicalize() const { |
index++; |
} |
// The type needs to be added to the list. Grow the list if it is full. |
- // TODO(srdjan): Copy type into old space if canonicalized? |
if (index == canonical_types_len) { |
const intptr_t kLengthIncrement = 2; // Raw and parameterized. |
const intptr_t new_length = canonical_types.Length() + kLengthIncrement; |
@@ -2772,6 +2804,7 @@ RawAbstractType* Type::Canonicalize() const { |
} else { |
canonical_types.SetAt(index, *this); |
} |
+ ASSERT(IsOld()); |
SetCanonical(); |
return this->raw(); |
} |
@@ -3414,23 +3447,27 @@ RawAbstractTypeArguments* TypeArguments::Canonicalize() const { |
Array& table = Array::Handle(object_store->canonical_type_arguments()); |
ASSERT(table.Length() > 0); |
intptr_t index = 0; |
- TypeArguments& other = TypeArguments::Handle(); |
- other ^= table.At(index); |
- while (!other.IsNull()) { |
- if (this->Equals(other)) { |
- return other.raw(); |
+ TypeArguments& result = TypeArguments::Handle(); |
+ result ^= table.At(index); |
+ while (!result.IsNull()) { |
+ if (this->Equals(result)) { |
+ return result.raw(); |
} |
- other ^= table.At(++index); |
+ result ^= table.At(++index); |
} |
// Not found. Add 'this' to table. |
- // TODO(srdjan): Copy 'this' into old space if canonicalized? |
+ result ^= this->raw(); |
+ if (result.IsNew()) { |
+ result ^= Object::Clone(result, Heap::kOld); |
+ } |
+ ASSERT(result.IsOld()); |
if (index == table.Length() - 1) { |
table = Array::Grow(table, table.Length() + 4, Heap::kOld); |
object_store->set_canonical_type_arguments(table); |
} |
- table.SetAt(index, *this); |
- SetCanonical(); |
- return this->raw(); |
+ table.SetAt(index, result); |
+ result.SetCanonical(); |
+ return result.raw(); |
} |
@@ -4423,6 +4460,7 @@ RawLiteralToken* LiteralToken::New(Token::Kind kind, const String& literal) { |
result.set_literal(literal); |
if (kind == Token::kINTEGER) { |
const Integer& value = Integer::Handle(Integer::New(literal, Heap::kOld)); |
+ ASSERT(value.IsSmi() || value.IsOld()); |
result.set_value(value); |
} else if (kind == Token::kDOUBLE) { |
const Double& value = Double::Handle(Double::NewCanonical(literal)); |
@@ -7548,31 +7586,37 @@ bool Instance::Equals(const Instance& other) const { |
RawInstance* Instance::Canonicalize() const { |
ASSERT(!IsNull()); |
- if (!IsCanonical()) { |
- const Class& cls = Class::Handle(this->clazz()); |
- Array& constants = Array::Handle(cls.constants()); |
- const intptr_t constants_len = constants.Length(); |
- // Linear search to see whether this value is already present in the |
- // list of canonicalized constants. |
- Instance& norm_value = Instance::Handle(); |
- intptr_t index = 0; |
- while (index < constants_len) { |
- norm_value ^= constants.At(index); |
- if (norm_value.IsNull()) { |
- break; |
- } |
- if (this->Equals(norm_value)) { |
- return norm_value.raw(); |
- } |
- index++; |
+ if (this->IsCanonical()) { |
+ return this->raw(); |
+ } |
+ Instance& result = Instance::Handle(); |
+ const Class& cls = Class::Handle(this->clazz()); |
+ Array& constants = Array::Handle(cls.constants()); |
+ const intptr_t constants_len = constants.Length(); |
+ // Linear search to see whether this value is already present in the |
+ // list of canonicalized constants. |
+ intptr_t index = 0; |
+ while (index < constants_len) { |
+ result ^= constants.At(index); |
+ if (result.IsNull()) { |
+ break; |
+ } |
+ if (this->Equals(result)) { |
+ return result.raw(); |
} |
- // The value needs to be added to the list. Grow the list if |
- // it is full. |
- // TODO(srdjan): Copy instance into old space if canonicalized? |
- cls.InsertCanonicalConstant(index, *this); |
- SetCanonical(); |
+ index++; |
} |
- return this->raw(); |
+ // The value needs to be added to the list. Grow the list if |
+ // it is full. |
+ result ^= this->raw(); |
+ if (result.IsNew()) { |
+ // Create a canonical object in old space. |
+ result ^= Object::Clone(result, Heap::kOld); |
+ } |
+ ASSERT(result.IsOld()); |
+ cls.InsertCanonicalConstant(index, result); |
+ result.SetCanonical(); |
+ return result.raw(); |
} |