| Index: runtime/vm/object_id_ring.cc
|
| diff --git a/runtime/vm/object_id_ring.cc b/runtime/vm/object_id_ring.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f7199bddbcd652d82b5c4337e63aba8f632fc968
|
| --- /dev/null
|
| +++ b/runtime/vm/object_id_ring.cc
|
| @@ -0,0 +1,164 @@
|
| +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +#include "platform/assert.h"
|
| +#include "vm/dart_api_state.h"
|
| +#include "vm/object_id_ring.h"
|
| +
|
| +namespace dart {
|
| +
|
| +void ObjectIdRing::Init(Isolate* isolate, int32_t capacity) {
|
| + ObjectIdRing* ring = new ObjectIdRing(isolate, capacity);
|
| + isolate->set_object_id_ring(ring);
|
| +}
|
| +
|
| +
|
| +ObjectIdRing::~ObjectIdRing() {
|
| + ASSERT(table_ != NULL);
|
| + free(table_);
|
| + table_ = NULL;
|
| + if (isolate_ != NULL) {
|
| + isolate_->set_object_id_ring(NULL);
|
| + isolate_ = NULL;
|
| + }
|
| +}
|
| +
|
| +
|
| +int32_t ObjectIdRing::GetIdForObject(RawObject* object) {
|
| + return AllocateNewId(object);
|
| +}
|
| +
|
| +
|
| +RawObject* ObjectIdRing::GetObjectForId(int32_t id) {
|
| + int32_t index = IndexOfId(id);
|
| + if (index == kInvalidId) {
|
| + return Object::null();
|
| + }
|
| + ASSERT(index >= 0);
|
| + ASSERT(index < capacity_);
|
| + return table_[index];
|
| +}
|
| +
|
| +
|
| +void ObjectIdRing::VisitPointers(ObjectPointerVisitor* visitor) {
|
| + ASSERT(table_ != NULL);
|
| + visitor->VisitPointers(table_, capacity_);
|
| +}
|
| +
|
| +
|
| +ObjectIdRing::ObjectIdRing(Isolate* isolate, int32_t capacity) {
|
| + ASSERT(capacity > 0);
|
| + isolate_ = isolate;
|
| + serial_num_ = 0;
|
| + wrapped_ = false;
|
| + table_ = NULL;
|
| + SetCapacityAndMaxSerial(capacity, kMaxId);
|
| +}
|
| +
|
| +
|
| +void ObjectIdRing::SetCapacityAndMaxSerial(int32_t capacity,
|
| + int32_t max_serial) {
|
| + ASSERT(max_serial <= kMaxId);
|
| + capacity_ = capacity;
|
| + if (table_ != NULL) {
|
| + free(table_);
|
| + }
|
| + table_ = reinterpret_cast<RawObject**>(calloc(capacity_, kWordSize));
|
| + for (int i = 0; i < capacity_; i++) {
|
| + table_[i] = Object::null();
|
| + }
|
| + // The maximum serial number is a multiple of the capacity, so that when
|
| + // the serial number wraps, the index into table_ wraps with it.
|
| + max_serial_ = max_serial - (max_serial % capacity_);
|
| +}
|
| +
|
| +
|
| +int32_t ObjectIdRing::NextSerial() {
|
| + int32_t r = serial_num_;
|
| + serial_num_++;
|
| + if (serial_num_ >= max_serial_) {
|
| + serial_num_ = 0;
|
| + wrapped_ = true;
|
| + }
|
| + return r;
|
| +}
|
| +
|
| +
|
| +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;
|
| + return id;
|
| +}
|
| +
|
| +
|
| +int32_t ObjectIdRing::IndexOfId(int32_t id) {
|
| + if (!IsValidId(id)) {
|
| + return kInvalidId;
|
| + }
|
| + ASSERT((id >= 0) && (id < max_serial_));
|
| + return id % capacity_;
|
| +}
|
| +
|
| +
|
| +bool ObjectIdRing::IsValidContiguous(int32_t id) {
|
| + ASSERT(id != kInvalidId);
|
| + ASSERT((id >= 0) && (id < max_serial_));
|
| + if (id >= serial_num_) {
|
| + // Too large.
|
| + return false;
|
| + }
|
| + int32_t bottom = 0;
|
| + if (serial_num_ >= capacity_) {
|
| + bottom = serial_num_ - capacity_;
|
| + }
|
| + return id >= bottom;
|
| +}
|
| +
|
| +
|
| +bool ObjectIdRing::IsValidId(int32_t id) {
|
| + if (id == kInvalidId) {
|
| + return false;
|
| + }
|
| + if (id >= max_serial_) {
|
| + return false;
|
| + }
|
| + ASSERT((id >= 0) && (id < max_serial_));
|
| + if (wrapped_) {
|
| + // Serial number has wrapped around to 0.
|
| + if (serial_num_ >= capacity_) {
|
| + // Serial number is larger than capacity, the serial
|
| + // numbers are contiguous again.
|
| + wrapped_ = false;
|
| + return IsValidContiguous(id);
|
| + } else {
|
| + // When the serial number first wraps, the valid serial number range
|
| + // spans two intervals:
|
| + // #1 [0, serial_num_)
|
| + // #2 [max_serial_ - (capacity_ - serial_num), max_serial_)
|
| + //
|
| + // Check for both.
|
| + if (id < serial_num_) {
|
| + // Interval #1
|
| + return true;
|
| + }
|
| + // Interval #2
|
| + const int32_t max_serial_num = max_serial_;
|
| + const int32_t bottom = max_serial_num - (capacity_ - serial_num_);
|
| + return id >= bottom && bottom < max_serial_num;
|
| + }
|
| + }
|
| + ASSERT(wrapped_ == false);
|
| + return IsValidContiguous(id);
|
| +}
|
| +
|
| +} // namespace dart
|
|
|