Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "platform/assert.h" | 5 #include "platform/assert.h" |
| 6 #include "vm/dart_api_state.h" | 6 #include "vm/dart_api_state.h" |
| 7 #include "vm/json_stream.h" | |
| 7 #include "vm/object_id_ring.h" | 8 #include "vm/object_id_ring.h" |
| 8 | 9 |
| 9 namespace dart { | 10 namespace dart { |
| 10 | 11 |
| 11 void ObjectIdRing::Init(Isolate* isolate, int32_t capacity) { | 12 void ObjectIdRing::Init(Isolate* isolate, int32_t capacity) { |
| 12 ObjectIdRing* ring = new ObjectIdRing(isolate, capacity); | 13 ObjectIdRing* ring = new ObjectIdRing(isolate, capacity); |
| 13 isolate->set_object_id_ring(ring); | 14 isolate->set_object_id_ring(ring); |
| 14 } | 15 } |
| 15 | 16 |
| 16 | 17 |
| 17 ObjectIdRing::~ObjectIdRing() { | 18 ObjectIdRing::~ObjectIdRing() { |
| 18 ASSERT(table_ != NULL); | 19 ASSERT(table_ != NULL); |
| 19 free(table_); | 20 free(table_); |
| 20 table_ = NULL; | 21 table_ = NULL; |
| 21 if (isolate_ != NULL) { | 22 if (isolate_ != NULL) { |
| 22 isolate_->set_object_id_ring(NULL); | 23 isolate_->set_object_id_ring(NULL); |
| 23 isolate_ = NULL; | 24 isolate_ = NULL; |
| 24 } | 25 } |
| 25 } | 26 } |
| 26 | 27 |
| 27 | 28 |
| 28 int32_t ObjectIdRing::GetIdForObject(RawObject* object) { | 29 int32_t ObjectIdRing::GetIdForObject(RawObject* object, IdPolicy policy) { |
| 29 // We do not allow inserting null because null is how we detect as entry was | 30 // We do not allow inserting null because null is how we detect as entry was |
| 30 // reclaimed by the GC. | 31 // reclaimed by the GC. |
| 31 ASSERT(object != Object::null()); | 32 ASSERT(object != Object::null()); |
| 33 if (policy == kNewId) { | |
| 34 return AllocateNewId(object); | |
| 35 } | |
| 36 ASSERT(policy == kExistingOrNewId); | |
| 37 int32_t id = FindExistingIdForObject(object); | |
| 38 if (id != kInvalidId) { | |
| 39 // Return a previous id for |object|. | |
| 40 return id; | |
| 41 } | |
| 32 return AllocateNewId(object); | 42 return AllocateNewId(object); |
| 33 } | 43 } |
| 34 | 44 |
| 35 | 45 |
| 46 int32_t ObjectIdRing::FindExistingIdForObject(RawObject* raw_obj) { | |
| 47 ASSERT(ids_ != NULL); | |
| 48 for (int32_t i = 0; i < capacity_; i++) { | |
| 49 if (table_[i] == raw_obj) { | |
| 50 return IdOfIndex(i); | |
| 51 } | |
| 52 } | |
| 53 return kInvalidId; | |
| 54 } | |
| 55 | |
| 56 | |
| 36 RawObject* ObjectIdRing::GetObjectForId(int32_t id, LookupResult* kind) { | 57 RawObject* ObjectIdRing::GetObjectForId(int32_t id, LookupResult* kind) { |
| 37 int32_t index = IndexOfId(id); | 58 int32_t index = IndexOfId(id); |
| 38 if (index == kInvalidId) { | 59 if (index == kInvalidId) { |
| 39 *kind = kExpired; | 60 *kind = kExpired; |
| 40 return Object::null(); | 61 return Object::null(); |
| 41 } | 62 } |
| 42 ASSERT(index >= 0); | 63 ASSERT(index >= 0); |
| 43 ASSERT(index < capacity_); | 64 ASSERT(index < capacity_); |
| 44 if (table_[index] == Object::null()) { | 65 if (table_[index] == Object::null()) { |
| 45 *kind = kCollected; | 66 *kind = kCollected; |
| 46 return Object::null(); | 67 return Object::null(); |
| 47 } | 68 } |
| 48 *kind = kValid; | 69 *kind = kValid; |
| 70 ASSERT(ids_[index] == id); | |
| 49 return table_[index]; | 71 return table_[index]; |
| 50 } | 72 } |
| 51 | 73 |
| 52 | 74 |
| 53 void ObjectIdRing::VisitPointers(ObjectPointerVisitor* visitor) { | 75 void ObjectIdRing::VisitPointers(ObjectPointerVisitor* visitor) { |
| 54 ASSERT(table_ != NULL); | 76 ASSERT(table_ != NULL); |
| 55 visitor->VisitPointers(table_, capacity_); | 77 visitor->VisitPointers(table_, capacity_); |
| 56 } | 78 } |
| 57 | 79 |
| 58 | 80 |
| 81 void ObjectIdRing::PrintGetObjectRequestsToJSON(JSONStream* js) { | |
|
turnidge
2015/05/11 19:48:45
Maybe PrintContentsToJSON or DumpToJSON?
Cutch
2015/05/12 14:59:57
::PrintJSON
| |
| 82 Thread* thread = Thread::Current(); | |
| 83 Zone* zone = thread->zone(); | |
| 84 ASSERT(zone != NULL); | |
| 85 ServiceIdZone* service_id_zone = js->service_id_zone(); | |
| 86 JSONObject jsobj(js); | |
| 87 jsobj.AddProperty("type", "_ObjectIdRingRequests"); | |
|
turnidge
2015/05/11 19:48:45
I don't like exposing the name "Ring" in the respo
Cutch
2015/05/12 14:59:57
Acknowledged.
| |
| 88 const char* request_format = "getObject?objectId=%s"; | |
|
turnidge
2015/05/11 19:48:45
Currently this returns a map from (request) => (re
Cutch
2015/05/12 14:59:57
Acknowledged.
| |
| 89 { | |
| 90 JSONObject ring_requests(&jsobj, "ringRequests"); | |
|
turnidge
2015/05/11 19:48:45
In almost everyplace else in our protocol, the pro
Cutch
2015/05/12 14:59:57
Acknowledged.
| |
| 91 Object& obj = Object::Handle(); | |
| 92 for (int32_t i = 0; i < capacity_; i++) { | |
| 93 obj = table_[i]; | |
| 94 if (obj.IsNull()) { | |
| 95 // Collected object. | |
| 96 continue; | |
| 97 } | |
| 98 // Get the service id for obj. | |
| 99 const char* service_id = service_id_zone->GetServiceId(obj); | |
| 100 // Construct a fake request. | |
| 101 const char* request = zone->PrintToString(request_format, service_id); | |
| 102 // Add to ringRequests. | |
| 103 ring_requests.AddProperty(request, obj, false); | |
| 104 } | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 | |
| 59 ObjectIdRing::ObjectIdRing(Isolate* isolate, int32_t capacity) { | 109 ObjectIdRing::ObjectIdRing(Isolate* isolate, int32_t capacity) { |
| 60 ASSERT(capacity > 0); | 110 ASSERT(capacity > 0); |
| 61 isolate_ = isolate; | 111 isolate_ = isolate; |
| 62 serial_num_ = 0; | 112 serial_num_ = 0; |
| 63 wrapped_ = false; | 113 wrapped_ = false; |
| 64 table_ = NULL; | 114 table_ = NULL; |
| 115 ids_ = NULL; | |
| 65 SetCapacityAndMaxSerial(capacity, kMaxId); | 116 SetCapacityAndMaxSerial(capacity, kMaxId); |
| 66 } | 117 } |
| 67 | 118 |
| 68 | 119 |
| 69 void ObjectIdRing::SetCapacityAndMaxSerial(int32_t capacity, | 120 void ObjectIdRing::SetCapacityAndMaxSerial(int32_t capacity, |
| 70 int32_t max_serial) { | 121 int32_t max_serial) { |
| 71 ASSERT(max_serial <= kMaxId); | 122 ASSERT(max_serial <= kMaxId); |
| 72 capacity_ = capacity; | 123 capacity_ = capacity; |
| 73 if (table_ != NULL) { | 124 if (table_ != NULL) { |
| 74 free(table_); | 125 free(table_); |
| 75 } | 126 } |
| 76 table_ = reinterpret_cast<RawObject**>(calloc(capacity_, kWordSize)); | 127 table_ = reinterpret_cast<RawObject**>(calloc(capacity_, kWordSize)); |
| 77 for (int i = 0; i < capacity_; i++) { | 128 for (int32_t i = 0; i < capacity_; i++) { |
| 78 table_[i] = Object::null(); | 129 table_[i] = Object::null(); |
| 79 } | 130 } |
| 131 // Allocate buffer to remember ids. | |
| 132 ids_ = reinterpret_cast<int32_t*>(calloc(capacity_, sizeof(int32_t))); | |
| 133 for (int32_t i = 0; i < capacity_; i++) { | |
| 134 ids_[i] = kInvalidId; | |
| 135 } | |
| 80 // The maximum serial number is a multiple of the capacity, so that when | 136 // The maximum serial number is a multiple of the capacity, so that when |
| 81 // the serial number wraps, the index into table_ wraps with it. | 137 // the serial number wraps, the index into table_ wraps with it. |
| 82 max_serial_ = max_serial - (max_serial % capacity_); | 138 max_serial_ = max_serial - (max_serial % capacity_); |
| 83 } | 139 } |
| 84 | 140 |
| 85 | 141 |
| 86 int32_t ObjectIdRing::NextSerial() { | 142 int32_t ObjectIdRing::NextSerial() { |
| 87 int32_t r = serial_num_; | 143 int32_t r = serial_num_; |
| 88 serial_num_++; | 144 serial_num_++; |
| 89 if (serial_num_ >= max_serial_) { | 145 if (serial_num_ >= max_serial_) { |
| 90 serial_num_ = 0; | 146 serial_num_ = 0; |
| 91 wrapped_ = true; | 147 wrapped_ = true; |
| 92 } | 148 } |
| 93 return r; | 149 return r; |
| 94 } | 150 } |
| 95 | 151 |
| 96 | 152 |
| 97 int32_t ObjectIdRing::AllocateNewId(RawObject* raw_obj) { | 153 int32_t ObjectIdRing::AllocateNewId(RawObject* raw_obj) { |
| 98 ASSERT(raw_obj->IsHeapObject()); | 154 ASSERT(raw_obj->IsHeapObject()); |
| 99 int32_t id = NextSerial(); | 155 int32_t id = NextSerial(); |
| 100 ASSERT(id != kInvalidId); | 156 ASSERT(id != kInvalidId); |
| 101 int32_t cursor = IndexOfId(id); | 157 int32_t index = IndexOfId(id); |
| 102 ASSERT(cursor != kInvalidId); | 158 ASSERT(index != kInvalidId); |
| 103 if (table_[cursor] != Object::null()) { | 159 table_[index] = raw_obj; |
| 104 // Free old handle. | 160 if (ids_ != NULL) { |
| 105 table_[cursor] = Object::null(); | 161 // Remember id. |
| 162 ids_[index] = id; | |
| 106 } | 163 } |
| 107 ASSERT(table_[cursor] == Object::null()); | |
| 108 table_[cursor] = raw_obj; | |
| 109 return id; | 164 return id; |
| 110 } | 165 } |
| 111 | 166 |
| 112 | 167 |
| 113 int32_t ObjectIdRing::IndexOfId(int32_t id) { | 168 int32_t ObjectIdRing::IndexOfId(int32_t id) { |
| 114 if (!IsValidId(id)) { | 169 if (!IsValidId(id)) { |
| 115 return kInvalidId; | 170 return kInvalidId; |
| 116 } | 171 } |
| 117 ASSERT((id >= 0) && (id < max_serial_)); | 172 ASSERT((id >= 0) && (id < max_serial_)); |
| 118 return id % capacity_; | 173 return id % capacity_; |
| 119 } | 174 } |
| 120 | 175 |
| 121 | 176 |
| 177 int32_t ObjectIdRing::IdOfIndex(int32_t index) { | |
| 178 ASSERT(ids_ != NULL); | |
| 179 int32_t id = ids_[index]; | |
| 180 ASSERT(IsValidId(id)); | |
| 181 return id; | |
| 182 } | |
| 183 | |
| 184 | |
| 122 bool ObjectIdRing::IsValidContiguous(int32_t id) { | 185 bool ObjectIdRing::IsValidContiguous(int32_t id) { |
| 123 ASSERT(id != kInvalidId); | 186 ASSERT(id != kInvalidId); |
| 124 ASSERT((id >= 0) && (id < max_serial_)); | 187 ASSERT((id >= 0) && (id < max_serial_)); |
| 125 if (id >= serial_num_) { | 188 if (id >= serial_num_) { |
| 126 // Too large. | 189 // Too large. |
| 127 return false; | 190 return false; |
| 128 } | 191 } |
| 129 int32_t bottom = 0; | 192 int32_t bottom = 0; |
| 130 if (serial_num_ >= capacity_) { | 193 if (serial_num_ >= capacity_) { |
| 131 bottom = serial_num_ - capacity_; | 194 bottom = serial_num_ - capacity_; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 167 const int32_t max_serial_num = max_serial_; | 230 const int32_t max_serial_num = max_serial_; |
| 168 const int32_t bottom = max_serial_num - (capacity_ - serial_num_); | 231 const int32_t bottom = max_serial_num - (capacity_ - serial_num_); |
| 169 return id >= bottom && bottom < max_serial_num; | 232 return id >= bottom && bottom < max_serial_num; |
| 170 } | 233 } |
| 171 } | 234 } |
| 172 ASSERT(wrapped_ == false); | 235 ASSERT(wrapped_ == false); |
| 173 return IsValidContiguous(id); | 236 return IsValidContiguous(id); |
| 174 } | 237 } |
| 175 | 238 |
| 176 } // namespace dart | 239 } // namespace dart |
| OLD | NEW |