Flutter Engine
The Flutter Engine
object_id_ring.cc
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/object_id_ring.h"
6
7#include "platform/assert.h"
8#include "vm/dart_api_state.h"
9#include "vm/json_stream.h"
10
11namespace dart {
12
13#ifndef PRODUCT
14
16 ASSERT(table_ != nullptr);
17 free(table_);
18 table_ = nullptr;
19}
20
22 // We do not allow inserting null because null is how we detect as entry was
23 // reclaimed by the GC.
24 ASSERT(object != Object::null());
25 if (policy == kAllocateId) {
26 return AllocateNewId(object);
27 }
29 int32_t id = FindExistingIdForObject(object);
30 if (id != kInvalidId) {
31 // Return a previous id for |object|.
32 return id;
33 }
34 return AllocateNewId(object);
35}
36
37int32_t ObjectIdRing::FindExistingIdForObject(ObjectPtr raw_obj) {
38 for (int32_t i = 0; i < capacity_; i++) {
39 if (table_[i] == raw_obj) {
40 return IdOfIndex(i);
41 }
42 }
43 return kInvalidId;
44}
45
47 int32_t index = IndexOfId(id);
48 if (index == kInvalidId) {
49 *kind = kExpired;
50 return Object::null();
51 }
52 ASSERT(index >= 0);
53 ASSERT(index < capacity_);
54 if (table_[index] == Object::null()) {
55 *kind = kCollected;
56 return Object::null();
57 }
58 *kind = kValid;
59 ASSERT(IdOfIndex(index) == id);
60 return table_[index];
61}
62
64 ASSERT(table_ != nullptr);
65 visitor->VisitPointers(table_, capacity_);
66}
67
69 Thread* thread = Thread::Current();
70 Zone* zone = thread->zone();
71 ASSERT(zone != nullptr);
72 JSONObject jsobj(js);
73 jsobj.AddProperty("type", "_IdZone");
74 jsobj.AddProperty("name", "default");
75 {
76 JSONArray objects(&jsobj, "objects");
77 Object& obj = Object::Handle();
78 for (int32_t i = 0; i < capacity_; i++) {
79 obj = table_[i];
80 if (obj.IsNull()) {
81 // Collected object.
82 continue;
83 }
84 objects.AddValue(obj, false);
85 }
86 }
87}
88
90 serial_num_ = 0;
91 wrapped_ = false;
92 table_ = nullptr;
93 SetCapacityAndMaxSerial(kDefaultCapacity, kMaxId);
94}
95
96void ObjectIdRing::SetCapacityAndMaxSerial(int32_t capacity,
97 int32_t max_serial) {
98 ASSERT(capacity > 0);
99 ASSERT(max_serial <= kMaxId);
100 capacity_ = capacity;
101 if (table_ != nullptr) {
102 free(table_);
103 }
104 table_ = reinterpret_cast<ObjectPtr*>(calloc(capacity_, kWordSize));
105 for (int32_t i = 0; i < capacity_; i++) {
106 table_[i] = Object::null();
107 }
108 // The maximum serial number is a multiple of the capacity, so that when
109 // the serial number wraps, the index into table_ wraps with it.
110 max_serial_ = max_serial - (max_serial % capacity_);
111}
112
113int32_t ObjectIdRing::NextSerial() {
114 int32_t r = serial_num_;
115 serial_num_++;
116 if (serial_num_ >= max_serial_) {
117 serial_num_ = 0;
118 wrapped_ = true;
119 }
120 return r;
121}
122
123int32_t ObjectIdRing::AllocateNewId(ObjectPtr raw_obj) {
124 ASSERT(raw_obj->IsHeapObject());
125 int32_t id = NextSerial();
126 ASSERT(id != kInvalidId);
127 int32_t index = IndexOfId(id);
128 ASSERT(index != kInvalidId);
129 table_[index] = raw_obj;
130 return id;
131}
132
133int32_t ObjectIdRing::IndexOfId(int32_t id) {
134 if (!IsValidId(id)) {
135 return kInvalidId;
136 }
137 ASSERT((id >= 0) && (id < max_serial_));
138 return id % capacity_;
139}
140
141int32_t ObjectIdRing::IdOfIndex(int32_t index) {
142 if (index < 0) {
143 return kInvalidId;
144 }
145 if (index >= capacity_) {
146 return kInvalidId;
147 }
148 int32_t id = kInvalidId;
149 if (wrapped_) {
150 // Serial numbers have wrapped around 0.
151 ASSERT(serial_num_ < capacity_);
152 if (index < serial_num_) {
153 // index < serial_num_ have been handed out and are sequential starting
154 // at 0.
155 id = index;
156 } else {
157 // the other end of the array has the high ids.
158 const int32_t bottom = max_serial_ - capacity_;
159 id = bottom + index;
160 }
161 } else if (index < serial_num_) {
162 // Index into the array where id range splits.
163 int32_t split_point = serial_num_ % capacity_;
164 if (index < split_point) {
165 // index < split_point has serial_numbers starting at
166 // serial_num_ - split_point.
167 int bottom = serial_num_ - split_point;
168 ASSERT(bottom >= 0);
169 id = bottom + index;
170 } else {
171 // index >= split_point has serial_numbers starting at
172 // serial_num_ - split_point - capacity_.
173 int bottom = serial_num_ - capacity_ - split_point;
174 ASSERT(bottom >= 0);
175 id = bottom + index;
176 }
177 }
178 ASSERT(!IsValidId(id) || (IndexOfId(id) == index));
179 return id;
180}
181
182bool ObjectIdRing::IsValidContiguous(int32_t id) {
183 ASSERT(id != kInvalidId);
184 ASSERT((id >= 0) && (id < max_serial_));
185 if (id >= serial_num_) {
186 // Too large.
187 return false;
188 }
189 int32_t bottom = 0;
190 if (serial_num_ >= capacity_) {
191 bottom = serial_num_ - capacity_;
192 }
193 return id >= bottom;
194}
195
196bool ObjectIdRing::IsValidId(int32_t id) {
197 if (id == kInvalidId) {
198 return false;
199 }
200 if (id < 0) {
201 return false;
202 }
203 if (id >= max_serial_) {
204 return false;
205 }
206 ASSERT((id >= 0) && (id < max_serial_));
207 if (wrapped_) {
208 // Serial number has wrapped around to 0.
209 if (serial_num_ >= capacity_) {
210 // Serial number is larger than capacity, the serial
211 // numbers are contiguous again.
212 wrapped_ = false;
213 return IsValidContiguous(id);
214 } else {
215 // When the serial number first wraps, the valid serial number range
216 // spans two intervals:
217 // #1 [0, serial_num_)
218 // #2 [max_serial_ - (capacity_ - serial_num), max_serial_)
219 //
220 // Check for both.
221 if (id < serial_num_) {
222 // Interval #1
223 return true;
224 }
225 // Interval #2
226 const int32_t max_serial_num = max_serial_;
227 const int32_t bottom = max_serial_num - (capacity_ - serial_num_);
228 return id >= bottom && bottom < max_serial_num;
229 }
230 }
231 ASSERT(wrapped_ == false);
232 return IsValidContiguous(id);
233}
234
235#endif // !PRODUCT
236
237} // namespace dart
void AddValue(bool b) const
Definition: json_stream.h:494
void AddProperty(const char *name, bool b) const
Definition: json_stream.h:395
static constexpr int32_t kDefaultCapacity
static constexpr int32_t kInvalidId
ObjectPtr GetObjectForId(int32_t id, LookupResult *kind)
static constexpr int32_t kMaxId
void VisitPointers(ObjectPointerVisitor *visitor)
int32_t GetIdForObject(ObjectPtr raw_obj, IdPolicy policy=kAllocateId)
void PrintJSON(JSONStream *js)
virtual void VisitPointers(ObjectPtr *first, ObjectPtr *last)=0
static ObjectPtr null()
Definition: object.h:433
bool IsNull() const
Definition: object.h:363
static Object & Handle()
Definition: object.h:407
Zone * zone() const
Definition: thread_state.h:37
static Thread * Current()
Definition: thread.h:362
#define ASSERT(E)
Definition: dart_vm.cc:33
void * calloc(size_t n, size_t size)
Definition: allocation.cc:11
constexpr intptr_t kWordSize
Definition: globals.h:509
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network policy
Definition: switches.h:248
const uintptr_t id