| Index: runtime/vm/freelist.cc
|
| diff --git a/runtime/vm/freelist.cc b/runtime/vm/freelist.cc
|
| index a88a948641e3e8bb9e7fd79fd8a7811dfbabfc69..4aa544c7324b9474a3594d1b2e501da5a8518d7d 100644
|
| --- a/runtime/vm/freelist.cc
|
| +++ b/runtime/vm/freelist.cc
|
| @@ -10,20 +10,50 @@
|
| namespace dart {
|
|
|
|
|
| +// Allocate a fake class to be used as the class for elements of the free list.
|
| +// These raw classes are only used to identify free list elements in the heap.
|
| +// These classes cannot be allocated in the heap as the elements of the free
|
| +// list are not live objects and their class references would not be updated
|
| +// during a moving collection. In the general case these classes are also used
|
| +// to implement RawObject::Size() to allow other code to safely traverse
|
| +// the heap without any knowledge of the embedded free list elements.
|
| +RawClass* AllocateFakeClass() {
|
| + RawClass* result =
|
| + reinterpret_cast<RawClass*>(calloc(1, Class::InstanceSize()));
|
| + result->instance_kind_ = kFreeListElement;
|
| + return reinterpret_cast<RawClass*>(RawObject::FromAddr(
|
| + reinterpret_cast<uword>(result)));
|
| +}
|
| +
|
| +
|
| +RawClass* FreeListElement::element_class_ = NULL;
|
| +
|
| +
|
| FreeListElement* FreeListElement::AsElement(uword addr, intptr_t size) {
|
| ASSERT(size >= kObjectAlignment);
|
| ASSERT(Utils::IsAligned(size, kObjectAlignment));
|
|
|
| FreeListElement* result = reinterpret_cast<FreeListElement*>(addr);
|
| - result->size_ = size;
|
| +
|
| + uword tags = 0;
|
| + tags = RawObject::FreeBit::update(true, tags);
|
| + tags = RawObject::SizeTag::update(size, tags);
|
| + tags = RawObject::ClassIdTag::update(kFreeListElement, tags);
|
| +
|
| + result->tags_ = tags;
|
| + if (size > RawObject::SizeTag::kMaxSizeTag) {
|
| + *result->SizeAddress() = size;
|
| + }
|
| result->set_next(NULL);
|
| +
|
| return result;
|
| }
|
|
|
|
|
| void FreeListElement::InitOnce() {
|
| ASSERT(sizeof(FreeListElement) == kObjectAlignment);
|
| - ASSERT(OFFSET_OF(FreeListElement, next_) == Object::tags_offset());
|
| + ASSERT(OFFSET_OF(FreeListElement, tags_) == Object::tags_offset());
|
| + element_class_ = AllocateFakeClass();
|
| }
|
|
|
|
|
| @@ -60,7 +90,7 @@ uword FreeList::TryAllocate(intptr_t size) {
|
| FreeListElement* previous = NULL;
|
| FreeListElement* current = free_lists_[kNumLists];
|
| while (current != NULL) {
|
| - if (current->size() >= size) {
|
| + if (current->Size() >= size) {
|
| // Found an element large enough to hold the requested size. Dequeue,
|
| // split and enqueue the remainder.
|
| if (previous == NULL) {
|
| @@ -118,7 +148,7 @@ FreeListElement* FreeList::DequeueElement(intptr_t index) {
|
|
|
| void FreeList::SplitElementAfterAndEnqueue(FreeListElement* element,
|
| intptr_t size) {
|
| - intptr_t remainder_size = element->size() - size;
|
| + intptr_t remainder_size = element->Size() - size;
|
| if (remainder_size == 0) return;
|
|
|
| element = FreeListElement::AsElement(reinterpret_cast<uword>(element) + size,
|
|
|