Flutter Engine
The Flutter Engine
handles_impl.h
Go to the documentation of this file.
1// Copyright (c) 2012, 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#ifndef RUNTIME_VM_HANDLES_IMPL_H_
6#define RUNTIME_VM_HANDLES_IMPL_H_
7
8#include "vm/handle_visitor.h"
9#include "vm/thread.h"
10#include "vm/visitor.h"
11
12namespace dart {
13
14template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
17 // Visit all zone handles.
18 HandlesBlock* block = zone_blocks_;
19 while (block != nullptr) {
20 block->VisitObjectPointers(visitor);
21 block = block->next_block();
22 }
23
24 // Visit all scoped handles.
25 VisitScopedHandles(visitor);
26}
27
28template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
31 HandlesBlock* block = &first_scoped_block_;
32 do {
33 block->VisitObjectPointers(visitor);
34 if (block == scoped_blocks_) {
35 return;
36 }
37 block = block->next_block();
38 } while (block != nullptr);
40}
41
42template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
44 HandleVisitor* visitor) {
45 // Visit all zone handles.
46 HandlesBlock* block = zone_blocks_;
47 while (block != nullptr) {
48 block->Visit(visitor);
49 block = block->next_block();
50 }
51
52 // Visit all scoped handles.
53 block = &first_scoped_block_;
54 do {
55 block->Visit(visitor);
56 block = block->next_block();
57 } while (block != nullptr);
58}
59
60template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
62 // Delete all the extra zone handle blocks allocated and reinit the first
63 // zone block.
64 if (zone_blocks_ != nullptr) {
65 DeleteHandleBlocks(zone_blocks_->next_block());
66 zone_blocks_->ReInit();
67 }
68
69 // Delete all the extra scoped handle blocks allocated and reinit the first
70 // scoped block.
71 DeleteHandleBlocks(first_scoped_block_.next_block());
72 first_scoped_block_.ReInit();
73 scoped_blocks_ = &first_scoped_block_;
74}
75
76// Figure out the current handle scope using the current Zone and
77// allocate a handle in that scope. The function assumes that a
78// current handle scope exists. It asserts for this appropriately.
79template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
81 AllocateHandle(Zone* zone) {
82#if defined(DEBUG)
83 Thread* thread = Thread::Current();
85#endif // DEBUG
86 Handles* handles = zone->handles();
87 ASSERT(handles != nullptr);
88 return handles->AllocateScopedHandle();
89}
90
91// The function assumes that 'zone' is the current zone and asserts for
92// this appropriately.
93template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
96#if defined(DEBUG)
97 Thread* thread = Thread::Current();
98 ASSERT(zone->ContainsNestedZone(thread->zone()));
99 ASSERT(thread->MayAllocateHandles());
100#endif // DEBUG
101 Handles* handles = zone->handles();
102 ASSERT(handles != nullptr);
103 uword address = handles->AllocateHandleInZone();
104 return address;
105}
106
107#if defined(DEBUG)
108// Figure out the current zone using the current Thread and
109// check if the specified handle has been allocated in this zone.
110template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
112 IsZoneHandle(uword handle) {
113 // TODO(5411412): Accessing the current thread is a performance problem,
114 // consider passing it down as a parameter.
115 Thread* thread = Thread::Current();
116 ASSERT(thread != nullptr);
117 ASSERT(thread->zone() != nullptr);
118 Handles* handles = thread->zone()->handles();
119 ASSERT(handles != nullptr);
120 return handles->IsValidZoneHandle(handle);
121}
122#endif
123
124template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
125void Handles<kHandleSizeInWords, kHandlesPerChunk, kOffsetOfRawPtr>::
126 DeleteAll() {
127 // Delete all the zone allocated handle blocks.
128 // GCTrace does not need to trace this call to DeleteHandleBlocks,
129 // since the individual zone deletions will be caught
130 // by instrumentation in the BaseZone destructor.
131 DeleteHandleBlocks(zone_blocks_);
132 zone_blocks_ = nullptr;
133
134 // Delete all the scoped handle blocks.
135 scoped_blocks_ = first_scoped_block_.next_block();
136 DeleteHandleBlocks(scoped_blocks_);
137 first_scoped_block_.ReInit();
138 scoped_blocks_ = &first_scoped_block_;
139}
140
141template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
143 DeleteHandleBlocks(HandlesBlock* blocks) {
144 while (blocks != nullptr) {
145 HandlesBlock* block = blocks;
146 blocks = blocks->next_block();
147 delete block;
148 }
149}
150
151template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
152void Handles<kHandleSizeInWords, kHandlesPerChunk, kOffsetOfRawPtr>::
153 SetupNextScopeBlock() {
154 if (FLAG_trace_handles) {
155 OS::PrintErr("*** Handle Counts for (0x%" Px "):Zone = %d,Scoped = %d\n",
156 reinterpret_cast<intptr_t>(this), CountZoneHandles(),
157 CountScopedHandles());
158 }
159 if (scoped_blocks_->next_block() == nullptr) {
160 HandlesBlock* block = new HandlesBlock(nullptr);
161 scoped_blocks_->set_next_block(block);
162 }
163 scoped_blocks_ = scoped_blocks_->next_block();
164 scoped_blocks_->set_next_handle_slot(0);
165#if defined(DEBUG)
166 scoped_blocks_->ZapFreeHandles();
167#endif
168}
169
170// Validation of the handle involves iterating through all the
171// handle blocks to check if the handle is valid, please
172// use this only in ASSERT code for verification purposes.
173template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
175 IsValidScopedHandle(uword handle) const {
176 const HandlesBlock* iterator = &first_scoped_block_;
177 while (iterator != nullptr) {
178 if (iterator->IsValidHandle(handle)) {
179 return true;
180 }
181 iterator = iterator->next_block();
182 }
183 return false;
184}
185
186template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
188 IsValidZoneHandle(uword handle) const {
189 const HandlesBlock* iterator = zone_blocks_;
190 while (iterator != nullptr) {
191 if (iterator->IsValidHandle(handle)) {
192 return true;
193 }
194 iterator = iterator->next_block();
195 }
196 return false;
197}
198
199template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
202 if (FLAG_trace_handles) {
203 OS::PrintErr("*** Handle Counts for (0x%" Px "):Zone = %d,Scoped = %d\n",
204 reinterpret_cast<intptr_t>(this), CountZoneHandles(),
205 CountScopedHandles());
206 }
207 zone_blocks_ = new HandlesBlock(zone_blocks_);
208}
209
210template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
212 CountScopedHandles() const {
213 int count = 0;
214 const HandlesBlock* block = &first_scoped_block_;
215 do {
216 count += block->HandleCount();
217 if (block == scoped_blocks_) {
218 return count;
219 }
220 block = block->next_block();
221 } while (block != nullptr);
222 UNREACHABLE();
223 return 0;
224}
225
226template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
228 CountZoneHandles() const {
229 int count = 0;
230 const HandlesBlock* block = zone_blocks_;
231 while (block != nullptr) {
232 count += block->HandleCount();
233 block = block->next_block();
234 }
235 return count;
236}
237
238template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
241#if defined(DEBUG)
242 ReInit();
243#endif
244}
245
246template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
247void Handles<kHandleSizeInWords, kHandlesPerChunk, kOffsetOfRawPtr>::
248 HandlesBlock::ReInit() {
249 next_handle_slot_ = 0;
250 next_block_ = nullptr;
251#if defined(DEBUG)
252 ZapFreeHandles();
253#endif
254}
255
256template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
257void Handles<kHandleSizeInWords, kHandlesPerChunk, kOffsetOfRawPtr>::
258 HandlesBlock::VisitObjectPointers(ObjectPointerVisitor* visitor) {
259 ASSERT(visitor != nullptr);
260 for (intptr_t i = 0; i < next_handle_slot_; i += kHandleSizeInWords) {
261 visitor->VisitPointer(
262 reinterpret_cast<ObjectPtr*>(&data_[i + kOffsetOfRawPtr / kWordSize]));
263 }
264}
265
266template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
267void Handles<kHandleSizeInWords, kHandlesPerChunk, kOffsetOfRawPtr>::
268 HandlesBlock::Visit(HandleVisitor* visitor) {
269 ASSERT(visitor != nullptr);
270 for (intptr_t i = 0; i < next_handle_slot_; i += kHandleSizeInWords) {
271 visitor->VisitHandle(reinterpret_cast<uword>(&data_[i]));
272 }
273}
274
275#if defined(DEBUG)
276template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
277void Handles<kHandleSizeInWords, kHandlesPerChunk, kOffsetOfRawPtr>::
278 HandlesBlock::ZapFreeHandles() {
279 // Reinitialize the handle area to some uninitialized value.
280 for (intptr_t i = next_handle_slot_;
281 i < (kHandleSizeInWords * kHandlesPerChunk); i++) {
282 data_[i] = kZapUninitializedWord;
283 }
284}
285#endif
286
287template <int kHandleSizeInWords, int kHandlesPerChunk, int kOffsetOfRawPtr>
288int Handles<kHandleSizeInWords, kHandlesPerChunk, kOffsetOfRawPtr>::
289 HandlesBlock::HandleCount() const {
290 return (next_handle_slot_ / kHandleSizeInWords);
291}
292
293} // namespace dart
294
295#endif // RUNTIME_VM_HANDLES_IMPL_H_
int count
Definition: FontMgrTest.cpp:50
#define UNREACHABLE()
Definition: assert.h:248
int CountZoneHandles() const
Definition: handles_impl.h:228
static uword AllocateZoneHandle(Zone *zone)
Definition: handles_impl.h:95
bool IsValidZoneHandle(uword handle) const
Definition: handles_impl.h:188
void Visit(HandleVisitor *visitor)
Definition: handles_impl.h:43
void VisitObjectPointers(ObjectPointerVisitor *visitor)
Definition: handles_impl.h:16
uword AllocateScopedHandle()
Definition: handles.h:96
int CountScopedHandles() const
Definition: handles_impl.h:212
void VisitScopedHandles(ObjectPointerVisitor *visitor)
Definition: handles_impl.h:30
static uword AllocateHandle(Zone *zone)
Definition: handles_impl.h:81
bool IsValidScopedHandle(uword handle) const
Definition: handles_impl.h:175
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
Zone * zone() const
Definition: thread_state.h:37
static Thread * Current()
Definition: thread.h:362
virtual bool MayAllocateHandles()
Definition: thread.h:1055
bool ContainsNestedZone(Zone *other) const
Definition: zone.h:79
VMHandles * handles()
Definition: zone.h:73
#define ASSERT(E)
Definition: dart_vm.cc:33
uintptr_t uword
Definition: globals.h:501
static constexpr uword kZapUninitializedWord
Definition: globals.h:179
static constexpr int kOffsetOfRawPtr
Definition: handles.h:241
constexpr intptr_t kWordSize
Definition: globals.h:509
#define Px
Definition: globals.h:410