Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: runtime/vm/dart_api_state.h

Issue 9148051: Provide API support for weak handles and post-mortem finalization. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: a better strategy for protected handle checks Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 #ifndef VM_DART_API_STATE_H_ 5 #ifndef VM_DART_API_STATE_H_
6 #define VM_DART_API_STATE_H_ 6 #define VM_DART_API_STATE_H_
7 7
8 #include "include/dart_api.h" 8 #include "include/dart_api.h"
9 9
10 #include "vm/dart_api_impl.h" 10 #include "vm/dart_api_impl.h"
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 74
75 // A distinguished callback which indicates that a persistent handle 75 // A distinguished callback which indicates that a persistent handle
76 // should not be deleted from the dart api. 76 // should not be deleted from the dart api.
77 void ProtectedHandleCallback(void* peer); 77 void ProtectedHandleCallback(void* peer);
78 78
79 79
80 // Implementation of persistent handles which are handed out through the 80 // Implementation of persistent handles which are handed out through the
81 // dart API. 81 // dart API.
82 class PersistentHandle { 82 class PersistentHandle {
83 public: 83 public:
84 enum Kind {
85 StrongReference = 0,
86 WeakReference,
87 };
88
89 // Adaptor for visiting handles with matching reference kind.
90 class Visitor : public HandleVisitor {
91 public:
92 Visitor(ObjectPointerVisitor* visitor, Kind kind) {
93 ASSERT(visitor != NULL);
94 kind_ = kind;
95 object_pointer_visitor_ = visitor;
96 }
97
98 void Visit(uword* addr) {
99 PersistentHandle* handle = reinterpret_cast<PersistentHandle*>(addr);
100 if (handle->kind() == kind_) {
101 object_pointer_visitor_->VisitPointer(&handle->raw_);
102 }
103 }
104
105 ~Visitor() {}
106
107 private:
108 Kind kind_;
109 ObjectPointerVisitor* object_pointer_visitor_;
110
111 DISALLOW_COPY_AND_ASSIGN(Visitor);
112 };
113
114 // Accessors. 84 // Accessors.
115 RawObject* raw() const { return raw_; } 85 RawObject* raw() const { return raw_; }
86 void set_raw(RawObject* ref) { raw_ = ref; }
116 void set_raw(const LocalHandle& ref) { raw_ = ref.raw(); } 87 void set_raw(const LocalHandle& ref) { raw_ = ref.raw(); }
117 void set_raw(const Object& object) { raw_ = object.raw(); } 88 void set_raw(const Object& object) { raw_ = object.raw(); }
118 static intptr_t raw_offset() { return OFFSET_OF(PersistentHandle, raw_); } 89 static intptr_t raw_offset() { return OFFSET_OF(PersistentHandle, raw_); }
119 Kind kind() const { return kind_; } 90
120 void set_kind(Kind kind) { kind_ = kind; } 91 private:
92 friend class PersistentHandles;
93
94 PersistentHandle() { }
95 ~PersistentHandle() { }
96
97 // Overload the raw_ field as a next pointer when adding freed
98 // handles to the free list.
99 PersistentHandle* Next() {
100 return reinterpret_cast<PersistentHandle*>(raw_);
101 }
102 void SetNext(PersistentHandle* free_list) {
103 raw_ = reinterpret_cast<RawObject*>(free_list);
104 }
105 void FreeHandle(PersistentHandle* free_list) {
106 SetNext(free_list);
107 }
108
109 RawObject* raw_;
110 DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods.
111 DISALLOW_COPY_AND_ASSIGN(PersistentHandle);
112 };
113
114
115 // Implementation of persistent handles which are handed out through the
116 // dart API.
117 class WeakPersistentHandle {
118 public:
119 // Accessors.
120 RawObject* raw() const { return raw_; }
121 void set_raw(RawObject* raw) { raw_ = raw; }
122 void set_raw(const LocalHandle& ref) { raw_ = ref.raw(); }
123 void set_raw(const Object& object) { raw_ = object.raw(); }
124 static intptr_t raw_offset() { return OFFSET_OF(WeakPersistentHandle, raw_); }
121 void* peer() const { return peer_; } 125 void* peer() const { return peer_; }
122 void set_peer(void* peer) { peer_ = peer; } 126 void set_peer(void* peer) { peer_ = peer; }
123 Dart_PeerFinalizer callback() const { return callback_; } 127 Dart_PeerFinalizer callback() const { return callback_; }
124 void set_callback(Dart_PeerFinalizer callback) { callback_ = callback; } 128 void set_callback(Dart_PeerFinalizer callback) { callback_ = callback; }
125 129
126 // Some handles are protected from being freed via the external dart api. 130 void Finalize() {
127 bool IsProtected() { 131 if (callback_ != NULL) {
128 return callback() == ProtectedHandleCallback; 132 (*callback_)(peer_);
133 }
134 Clear();
129 } 135 }
130 136
131 private: 137 private:
132 friend class PersistentHandles; 138 friend class WeakPersistentHandles;
133 139
134 PersistentHandle() : kind_(StrongReference), peer_(NULL), callback_(NULL) { } 140 WeakPersistentHandle() : raw_(NULL), peer_(NULL), callback_(NULL) { }
135 ~PersistentHandle() { } 141 ~WeakPersistentHandle() { }
136 142
137 // Overload the callback_ field as a next pointer when adding freed 143 // Overload the callback_ field as a next pointer when adding freed
138 // handles to the free list. 144 // handles to the free list.
139 PersistentHandle* Next() { 145 WeakPersistentHandle* Next() {
140 return reinterpret_cast<PersistentHandle*>(callback_); 146 return reinterpret_cast<WeakPersistentHandle*>(callback_);
141 } 147 }
142 void SetNext(PersistentHandle* free_list) { 148 void SetNext(WeakPersistentHandle* free_list) {
143 callback_ = reinterpret_cast<Dart_PeerFinalizer>(free_list); 149 callback_ = reinterpret_cast<Dart_PeerFinalizer>(free_list);
144 } 150 }
145 void FreeHandle(PersistentHandle* free_list) { 151 void FreeHandle(WeakPersistentHandle* free_list) {
146 raw_ = NULL; 152 raw_ = NULL;
147 SetNext(free_list); 153 SetNext(free_list);
148 } 154 }
149 155
156 void Clear() {
157 raw_ = Object::null();
158 peer_ = NULL;
159 callback_ = NULL;
160 }
161
150 RawObject* raw_; 162 RawObject* raw_;
151 Kind kind_;
152 void* peer_; 163 void* peer_;
153 Dart_PeerFinalizer callback_; 164 Dart_PeerFinalizer callback_;
154 DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods. 165 DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods.
155 DISALLOW_COPY_AND_ASSIGN(PersistentHandle); 166 DISALLOW_COPY_AND_ASSIGN(WeakPersistentHandle);
156 }; 167 };
157 168
158 169
159 // Local handles repository structure. 170 // Local handles repository structure.
160 static const int kLocalHandleSizeInWords = sizeof(LocalHandle) / kWordSize; 171 static const int kLocalHandleSizeInWords = sizeof(LocalHandle) / kWordSize;
161 static const int kLocalHandlesPerChunk = 64; 172 static const int kLocalHandlesPerChunk = 64;
162 static const int kOffsetOfRawPtrInLocalHandle = 0; 173 static const int kOffsetOfRawPtrInLocalHandle = 0;
163 class LocalHandles : Handles<kLocalHandleSizeInWords, 174 class LocalHandles : Handles<kLocalHandleSizeInWords,
164 kLocalHandlesPerChunk, 175 kLocalHandlesPerChunk,
165 kOffsetOfRawPtrInLocalHandle> { 176 kOffsetOfRawPtrInLocalHandle> {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 PersistentHandle* free_list() const { return free_list_; } 231 PersistentHandle* free_list() const { return free_list_; }
221 void set_free_list(PersistentHandle* value) { free_list_ = value; } 232 void set_free_list(PersistentHandle* value) { free_list_ = value; }
222 233
223 // Visit all object pointers stored in the various handles. 234 // Visit all object pointers stored in the various handles.
224 void VisitObjectPointers(ObjectPointerVisitor* visitor) { 235 void VisitObjectPointers(ObjectPointerVisitor* visitor) {
225 Handles<kPersistentHandleSizeInWords, 236 Handles<kPersistentHandleSizeInWords,
226 kPersistentHandlesPerChunk, 237 kPersistentHandlesPerChunk,
227 kOffsetOfRawPtrInPersistentHandle>::VisitObjectPointers(visitor); 238 kOffsetOfRawPtrInPersistentHandle>::VisitObjectPointers(visitor);
228 } 239 }
229 240
230 // Visits the object pointers in strong persistent handles.
231 void VisitStrongObjectPointers(ObjectPointerVisitor* visitor) {
232 PersistentHandle::Visitor strong_visitor(visitor,
233 PersistentHandle::StrongReference);
234 Handles<kPersistentHandleSizeInWords,
235 kPersistentHandlesPerChunk,
236 kOffsetOfRawPtrInPersistentHandle>::Visit(&strong_visitor);
237 }
238
239 // Visits the object pointers in weak persistent handles.
240 void VisitWeakObjectPointers(ObjectPointerVisitor* visitor) {
241 PersistentHandle::Visitor weak_visitor(visitor,
242 PersistentHandle::WeakReference);
243 Handles<kPersistentHandleSizeInWords,
244 kPersistentHandlesPerChunk,
245 kOffsetOfRawPtrInPersistentHandle>::Visit(&weak_visitor);
246 }
247
248 // Allocates a persistent handle, these have to be destroyed explicitly 241 // Allocates a persistent handle, these have to be destroyed explicitly
249 // by calling FreeHandle. 242 // by calling FreeHandle.
250 PersistentHandle* AllocateHandle() { 243 PersistentHandle* AllocateHandle() {
251 PersistentHandle* handle; 244 PersistentHandle* handle;
252 if (free_list_ != NULL) { 245 if (free_list_ != NULL) {
253 handle = free_list_; 246 handle = free_list_;
254 free_list_ = handle->Next(); 247 free_list_ = handle->Next();
255 } else { 248 } else {
256 handle = reinterpret_cast<PersistentHandle*>(AllocateScopedHandle()); 249 handle = reinterpret_cast<PersistentHandle*>(AllocateScopedHandle());
257 } 250 }
258 handle->set_callback(NULL); 251 handle->set_raw(NULL);
259 handle->set_kind(PersistentHandle::StrongReference);
260 return handle; 252 return handle;
261 } 253 }
262 254
263 void FreeHandle(PersistentHandle* handle) { 255 void FreeHandle(PersistentHandle* handle) {
264 handle->FreeHandle(free_list()); 256 handle->FreeHandle(free_list());
265 set_free_list(handle); 257 set_free_list(handle);
266 } 258 }
267 259
268 // Validate if passed in handle is a Persistent Handle. 260 // Validate if passed in handle is a Persistent Handle.
269 bool IsValidHandle(Dart_Handle object) const { 261 bool IsValidHandle(Dart_Handle object) const {
270 return IsValidScopedHandle(reinterpret_cast<uword>(object)); 262 return IsValidScopedHandle(reinterpret_cast<uword>(object));
271 } 263 }
272 264
273 // Returns a count of active handles (used for testing purposes). 265 // Returns a count of active handles (used for testing purposes).
274 int CountHandles() const { 266 int CountHandles() const {
275 return CountScopedHandles(); 267 return CountScopedHandles();
276 } 268 }
277 269
278 private: 270 private:
279 PersistentHandle* free_list_; 271 PersistentHandle* free_list_;
280 DISALLOW_COPY_AND_ASSIGN(PersistentHandles); 272 DISALLOW_COPY_AND_ASSIGN(PersistentHandles);
281 }; 273 };
282 274
283 275
276 // Weak persistent handles repository structure.
277 static const int kWeakPersistentHandleSizeInWords =
278 sizeof(WeakPersistentHandle) / kWordSize;
279 static const int kWeakPersistentHandlesPerChunk = 64;
280 static const int kOffsetOfRawPtrInWeakPersistentHandle = 0;
281 class WeakPersistentHandles : Handles<kWeakPersistentHandleSizeInWords,
282 kWeakPersistentHandlesPerChunk,
283 kOffsetOfRawPtrInWeakPersistentHandle> {
284 public:
285 WeakPersistentHandles() : Handles<kWeakPersistentHandleSizeInWords,
286 kWeakPersistentHandlesPerChunk,
287 kOffsetOfRawPtrInWeakPersistentHandle>(),
288 free_list_(NULL) { }
289 ~WeakPersistentHandles() {
290 free_list_ = NULL;
291 }
292
293 // Accessors.
294 WeakPersistentHandle* free_list() const { return free_list_; }
295 void set_free_list(WeakPersistentHandle* value) { free_list_ = value; }
296
297 // Visit all handles stored in the various handle blocks.
298 void VisitWeakPersistentHandles(HandleVisitor* visitor) {
299 Handles<kWeakPersistentHandleSizeInWords,
300 kWeakPersistentHandlesPerChunk,
301 kOffsetOfRawPtrInWeakPersistentHandle>::Visit(visitor);
302 }
303
304 // Allocates a persistent handle, these have to be destroyed explicitly
305 // by calling FreeHandle.
306 WeakPersistentHandle* AllocateHandle() {
307 WeakPersistentHandle* handle;
308 if (free_list_ != NULL) {
309 handle = free_list_;
310 free_list_ = handle->Next();
311 } else {
312 handle = reinterpret_cast<WeakPersistentHandle*>(AllocateScopedHandle());
313 }
314 handle->set_callback(NULL);
315 return handle;
316 }
317
318 void FreeHandle(WeakPersistentHandle* handle) {
319 handle->FreeHandle(free_list());
320 set_free_list(handle);
321 }
322
323 // Validate if passed in handle is a Persistent Handle.
324 bool IsValidHandle(Dart_Handle object) const {
325 return IsValidScopedHandle(reinterpret_cast<uword>(object));
326 }
327
328 // Returns a count of active handles (used for testing purposes).
329 int CountHandles() const {
330 return CountScopedHandles();
331 }
332
333 private:
334 WeakPersistentHandle* free_list_;
335 DISALLOW_COPY_AND_ASSIGN(WeakPersistentHandles);
336 };
337
338
284 // Structure used for the implementation of local scopes used in dart_api. 339 // Structure used for the implementation of local scopes used in dart_api.
285 // These local scopes manage handles and memory allocated in the scope. 340 // These local scopes manage handles and memory allocated in the scope.
286 class ApiLocalScope { 341 class ApiLocalScope {
287 public: 342 public:
288 ApiLocalScope(ApiLocalScope* previous, uword stack_marker) : 343 ApiLocalScope(ApiLocalScope* previous, uword stack_marker) :
289 previous_(previous), stack_marker_(stack_marker) { } 344 previous_(previous), stack_marker_(stack_marker) { }
290 ~ApiLocalScope() { 345 ~ApiLocalScope() {
291 previous_ = NULL; 346 previous_ = NULL;
292 } 347 }
293 348
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 if (false_ != NULL) { 386 if (false_ != NULL) {
332 persistent_handles().FreeHandle(false_); 387 persistent_handles().FreeHandle(false_);
333 false_ = NULL; 388 false_ = NULL;
334 } 389 }
335 } 390 }
336 391
337 // Accessors. 392 // Accessors.
338 ApiLocalScope* top_scope() const { return top_scope_; } 393 ApiLocalScope* top_scope() const { return top_scope_; }
339 void set_top_scope(ApiLocalScope* value) { top_scope_ = value; } 394 void set_top_scope(ApiLocalScope* value) { top_scope_ = value; }
340 PersistentHandles& persistent_handles() { return persistent_handles_; } 395 PersistentHandles& persistent_handles() { return persistent_handles_; }
396 WeakPersistentHandles& weak_persistent_handles() {
397 return weak_persistent_handles_;
398 }
341 399
342 void UnwindScopes(uword sp) { 400 void UnwindScopes(uword sp) {
343 while (top_scope_ != NULL && top_scope_->stack_marker() < sp) { 401 while (top_scope_ != NULL && top_scope_->stack_marker() < sp) {
344 ApiLocalScope* scope = top_scope_; 402 ApiLocalScope* scope = top_scope_;
345 top_scope_ = top_scope_->previous(); 403 top_scope_ = top_scope_->previous();
346 delete scope; 404 delete scope;
347 } 405 }
348 } 406 }
349 407
350 void VisitStrongObjectPointers(ObjectPointerVisitor* visitor) { 408 void VisitObjectPointers(ObjectPointerVisitor* visitor) {
351 ApiLocalScope* scope = top_scope_; 409 ApiLocalScope* scope = top_scope_;
352 while (scope != NULL) { 410 while (scope != NULL) {
353 scope->local_handles()->VisitObjectPointers(visitor); 411 scope->local_handles()->VisitObjectPointers(visitor);
354 scope = scope->previous(); 412 scope = scope->previous();
355 } 413 }
356 414 persistent_handles().VisitObjectPointers(visitor);
357 persistent_handles().VisitStrongObjectPointers(visitor);
358 } 415 }
359 416
360 void VisitWeakObjectPointers(ObjectPointerVisitor* visitor) { 417 void VisitWeakHandles(HandleVisitor* visitor) {
361 persistent_handles().VisitWeakObjectPointers(visitor); 418 weak_persistent_handles().VisitWeakPersistentHandles(visitor);
362 }
363
364 void VisitObjectPointers(ObjectPointerVisitor* visitor) {
365 VisitStrongObjectPointers(visitor);
366 VisitWeakObjectPointers(visitor);
367 } 419 }
368 420
369 bool IsValidLocalHandle(Dart_Handle object) const { 421 bool IsValidLocalHandle(Dart_Handle object) const {
370 ApiLocalScope* scope = top_scope_; 422 ApiLocalScope* scope = top_scope_;
371 while (scope != NULL) { 423 while (scope != NULL) {
372 if (scope->local_handles()->IsValidHandle(object)) { 424 if (scope->local_handles()->IsValidHandle(object)) {
373 return true; 425 return true;
374 } 426 }
375 scope = scope->previous(); 427 scope = scope->previous();
376 } 428 }
377 return false; 429 return false;
378 } 430 }
431
379 bool IsValidPersistentHandle(Dart_Handle object) const { 432 bool IsValidPersistentHandle(Dart_Handle object) const {
380 return persistent_handles_.IsValidHandle(object); 433 return persistent_handles_.IsValidHandle(object);
381 } 434 }
382 435
436 bool IsValidWeakPersistentHandle(Dart_Handle object) const {
437 return weak_persistent_handles_.IsValidHandle(object);
438 }
439
440 bool IsProtectedHandle(PersistentHandle* object) const {
441 if (object == NULL) return false;
442 return object == null_ || object == true_ || object == false_;
443 }
444
383 int CountLocalHandles() const { 445 int CountLocalHandles() const {
384 int total = 0; 446 int total = 0;
385 ApiLocalScope* scope = top_scope_; 447 ApiLocalScope* scope = top_scope_;
386 while (scope != NULL) { 448 while (scope != NULL) {
387 total += scope->local_handles()->CountHandles(); 449 total += scope->local_handles()->CountHandles();
388 scope = scope->previous(); 450 scope = scope->previous();
389 } 451 }
390 return total; 452 return total;
391 } 453 }
392 int CountPersistentHandles() const { 454 int CountPersistentHandles() const {
393 return persistent_handles_.CountHandles(); 455 return persistent_handles_.CountHandles();
394 } 456 }
395 int ZoneSizeInBytes() const { 457 int ZoneSizeInBytes() const {
396 int total = 0; 458 int total = 0;
397 ApiLocalScope* scope = top_scope_; 459 ApiLocalScope* scope = top_scope_;
398 while (scope != NULL) { 460 while (scope != NULL) {
399 total += scope->zone().SizeInBytes(); 461 total += scope->zone().SizeInBytes();
400 scope = scope->previous(); 462 scope = scope->previous();
401 } 463 }
402 return total; 464 return total;
403 } 465 }
404 PersistentHandle* Null() { 466 PersistentHandle* Null() {
405 if (null_ == NULL) { 467 if (null_ == NULL) {
406 DARTSCOPE(Isolate::Current()); 468 DARTSCOPE(Isolate::Current());
407 469
408 Object& null_object = Object::Handle(); 470 Object& null_object = Object::Handle();
409 null_ = persistent_handles().AllocateHandle(); 471 null_ = persistent_handles().AllocateHandle();
410 null_->set_raw(null_object); 472 null_->set_raw(null_object);
411 null_->set_callback(ProtectedHandleCallback);
412 } 473 }
413 return null_; 474 return null_;
414 } 475 }
415 PersistentHandle* True() { 476 PersistentHandle* True() {
416 if (true_ == NULL) { 477 if (true_ == NULL) {
417 DARTSCOPE(Isolate::Current()); 478 DARTSCOPE(Isolate::Current());
418 479
419 const Object& true_object = Object::Handle(Bool::True()); 480 const Object& true_object = Object::Handle(Bool::True());
420 true_ = persistent_handles().AllocateHandle(); 481 true_ = persistent_handles().AllocateHandle();
421 true_->set_raw(true_object); 482 true_->set_raw(true_object);
422 true_->set_callback(ProtectedHandleCallback);
423 } 483 }
424 return true_; 484 return true_;
425 } 485 }
426 PersistentHandle* False() { 486 PersistentHandle* False() {
427 if (false_ == NULL) { 487 if (false_ == NULL) {
428 DARTSCOPE(Isolate::Current()); 488 DARTSCOPE(Isolate::Current());
429 489
430 const Object& false_object = Object::Handle(Bool::False()); 490 const Object& false_object = Object::Handle(Bool::False());
431 false_ = persistent_handles().AllocateHandle(); 491 false_ = persistent_handles().AllocateHandle();
432 false_->set_raw(false_object); 492 false_->set_raw(false_object);
433 false_->set_callback(ProtectedHandleCallback);
434 } 493 }
435 return false_; 494 return false_;
436 } 495 }
437 496
438 private: 497 private:
439 PersistentHandles persistent_handles_; 498 PersistentHandles persistent_handles_;
499 WeakPersistentHandles weak_persistent_handles_;
440 ApiLocalScope* top_scope_; 500 ApiLocalScope* top_scope_;
441 501
442 // Persistent handles to important objects. 502 // Persistent handles to important objects.
443 PersistentHandle* null_; 503 PersistentHandle* null_;
444 PersistentHandle* true_; 504 PersistentHandle* true_;
445 PersistentHandle* false_; 505 PersistentHandle* false_;
446 506
447 DISALLOW_COPY_AND_ASSIGN(ApiState); 507 DISALLOW_COPY_AND_ASSIGN(ApiState);
448 }; 508 };
449 509
450 } // namespace dart 510 } // namespace dart
451 511
452 #endif // VM_DART_API_STATE_H_ 512 #endif // VM_DART_API_STATE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698