| Index: runtime/vm/object_id_ring.cc
|
| diff --git a/runtime/vm/object_id_ring.cc b/runtime/vm/object_id_ring.cc
|
| index 0b396e83cae8c5a49953dbfd048cb46626e9087d..9ae8b92bf52c50e62c5f2586742eadbebff77c04 100644
|
| --- a/runtime/vm/object_id_ring.cc
|
| +++ b/runtime/vm/object_id_ring.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "platform/assert.h"
|
| #include "vm/dart_api_state.h"
|
| +#include "vm/json_stream.h"
|
| #include "vm/object_id_ring.h"
|
|
|
| namespace dart {
|
| @@ -25,14 +26,33 @@ ObjectIdRing::~ObjectIdRing() {
|
| }
|
|
|
|
|
| -int32_t ObjectIdRing::GetIdForObject(RawObject* object) {
|
| +int32_t ObjectIdRing::GetIdForObject(RawObject* object, IdPolicy policy) {
|
| // We do not allow inserting null because null is how we detect as entry was
|
| // reclaimed by the GC.
|
| ASSERT(object != Object::null());
|
| + if (policy == kAllocateId) {
|
| + return AllocateNewId(object);
|
| + }
|
| + ASSERT(policy == kReuseId);
|
| + int32_t id = FindExistingIdForObject(object);
|
| + if (id != kInvalidId) {
|
| + // Return a previous id for |object|.
|
| + return id;
|
| + }
|
| return AllocateNewId(object);
|
| }
|
|
|
|
|
| +int32_t ObjectIdRing::FindExistingIdForObject(RawObject* raw_obj) {
|
| + for (int32_t i = 0; i < capacity_; i++) {
|
| + if (table_[i] == raw_obj) {
|
| + return IdOfIndex(i);
|
| + }
|
| + }
|
| + return kInvalidId;
|
| +}
|
| +
|
| +
|
| RawObject* ObjectIdRing::GetObjectForId(int32_t id, LookupResult* kind) {
|
| int32_t index = IndexOfId(id);
|
| if (index == kInvalidId) {
|
| @@ -46,6 +66,7 @@ RawObject* ObjectIdRing::GetObjectForId(int32_t id, LookupResult* kind) {
|
| return Object::null();
|
| }
|
| *kind = kValid;
|
| + ASSERT(IdOfIndex(index) == id);
|
| return table_[index];
|
| }
|
|
|
| @@ -56,6 +77,28 @@ void ObjectIdRing::VisitPointers(ObjectPointerVisitor* visitor) {
|
| }
|
|
|
|
|
| +void ObjectIdRing::PrintJSON(JSONStream* js) {
|
| + Thread* thread = Thread::Current();
|
| + Zone* zone = thread->zone();
|
| + ASSERT(zone != NULL);
|
| + JSONObject jsobj(js);
|
| + jsobj.AddProperty("type", "_IdZone");
|
| + jsobj.AddProperty("name", "default");
|
| + {
|
| + JSONArray objects(&jsobj, "objects");
|
| + Object& obj = Object::Handle();
|
| + for (int32_t i = 0; i < capacity_; i++) {
|
| + obj = table_[i];
|
| + if (obj.IsNull()) {
|
| + // Collected object.
|
| + continue;
|
| + }
|
| + objects.AddValue(obj, false);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| ObjectIdRing::ObjectIdRing(Isolate* isolate, int32_t capacity) {
|
| ASSERT(capacity > 0);
|
| isolate_ = isolate;
|
| @@ -74,7 +117,7 @@ void ObjectIdRing::SetCapacityAndMaxSerial(int32_t capacity,
|
| free(table_);
|
| }
|
| table_ = reinterpret_cast<RawObject**>(calloc(capacity_, kWordSize));
|
| - for (int i = 0; i < capacity_; i++) {
|
| + for (int32_t i = 0; i < capacity_; i++) {
|
| table_[i] = Object::null();
|
| }
|
| // The maximum serial number is a multiple of the capacity, so that when
|
| @@ -98,14 +141,9 @@ int32_t ObjectIdRing::AllocateNewId(RawObject* raw_obj) {
|
| ASSERT(raw_obj->IsHeapObject());
|
| int32_t id = NextSerial();
|
| ASSERT(id != kInvalidId);
|
| - int32_t cursor = IndexOfId(id);
|
| - ASSERT(cursor != kInvalidId);
|
| - if (table_[cursor] != Object::null()) {
|
| - // Free old handle.
|
| - table_[cursor] = Object::null();
|
| - }
|
| - ASSERT(table_[cursor] == Object::null());
|
| - table_[cursor] = raw_obj;
|
| + int32_t index = IndexOfId(id);
|
| + ASSERT(index != kInvalidId);
|
| + table_[index] = raw_obj;
|
| return id;
|
| }
|
|
|
| @@ -119,6 +157,48 @@ int32_t ObjectIdRing::IndexOfId(int32_t id) {
|
| }
|
|
|
|
|
| +int32_t ObjectIdRing::IdOfIndex(int32_t index) {
|
| + if (index < 0) {
|
| + return kInvalidId;
|
| + }
|
| + if (index >= capacity_) {
|
| + return kInvalidId;
|
| + }
|
| + int32_t id = kInvalidId;
|
| + if (wrapped_) {
|
| + // Serial numbers have wrapped around 0.
|
| + ASSERT(serial_num_ < capacity_);
|
| + if (index < serial_num_) {
|
| + // index < serial_num_ have been handed out and are sequential starting
|
| + // at 0.
|
| + id = index;
|
| + } else {
|
| + // the other end of the array has the high ids.
|
| + const int32_t bottom = max_serial_ - capacity_;
|
| + id = bottom + index;
|
| + }
|
| + } else if (index < serial_num_) {
|
| + // Index into the array where id range splits.
|
| + int32_t split_point = serial_num_ % capacity_;
|
| + if (index < split_point) {
|
| + // index < split_point has serial_numbers starting at
|
| + // serial_num_ - split_point.
|
| + int bottom = serial_num_ - split_point;
|
| + ASSERT(bottom >= 0);
|
| + id = bottom + index;
|
| + } else {
|
| + // index >= split_point has serial_numbers starting at
|
| + // serial_num_ - split_point - capacity_.
|
| + int bottom = serial_num_ - capacity_ - split_point;
|
| + ASSERT(bottom >= 0);
|
| + id = bottom + index;
|
| + }
|
| + }
|
| + ASSERT(!IsValidId(id) || (IndexOfId(id) == index));
|
| + return id;
|
| +}
|
| +
|
| +
|
| bool ObjectIdRing::IsValidContiguous(int32_t id) {
|
| ASSERT(id != kInvalidId);
|
| ASSERT((id >= 0) && (id < max_serial_));
|
|
|