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

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

Issue 2084193003: Reapply "Background finalization." (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 6 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS 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 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 "platform/utils.h" 10 #include "platform/utils.h"
11 #include "vm/bitfield.h" 11 #include "vm/bitfield.h"
12 #include "vm/dart_api_impl.h" 12 #include "vm/dart_api_impl.h"
13 #include "vm/flags.h" 13 #include "vm/flags.h"
14 #include "vm/growable_array.h" 14 #include "vm/growable_array.h"
15 #include "vm/handles.h" 15 #include "vm/handles.h"
16 #include "vm/object.h" 16 #include "vm/object.h"
17 #include "vm/os.h" 17 #include "vm/os.h"
18 #include "vm/os_thread.h"
18 #include "vm/raw_object.h" 19 #include "vm/raw_object.h"
19 #include "vm/os_thread.h" 20 #include "vm/thread_pool.h"
20 #include "vm/visitor.h" 21 #include "vm/visitor.h"
21 #include "vm/weak_table.h" 22 #include "vm/weak_table.h"
22 23
23 #include "vm/handles_impl.h" 24 #include "vm/handles_impl.h"
24 25
25 namespace dart { 26 namespace dart {
26 27
28 class FinalizablePersistentHandle;
29 typedef MallocGrowableArray<FinalizablePersistentHandle*> FinalizationQueue;
30
31
32 class BackgroundFinalizer : public ThreadPool::Task {
33 public:
34 BackgroundFinalizer(Isolate* isolate, FinalizationQueue* queue);
35 virtual ~BackgroundFinalizer() { }
36
37 void Run();
38
39 private:
40 Isolate* isolate_;
41 FinalizationQueue* queue_;
42
43 DISALLOW_IMPLICIT_CONSTRUCTORS(BackgroundFinalizer);
44 };
45
46
27 // Implementation of Zone support for very fast allocation of small chunks 47 // Implementation of Zone support for very fast allocation of small chunks
28 // of memory. The chunks cannot be deallocated individually, but instead 48 // of memory. The chunks cannot be deallocated individually, but instead
29 // zones support deallocating all chunks in one fast operation when the 49 // zones support deallocating all chunks in one fast operation when the
30 // scope is exited. 50 // scope is exited.
31 class ApiZone { 51 class ApiZone {
32 public: 52 public:
33 // Create an empty zone. 53 // Create an empty zone.
34 ApiZone() : zone_() { 54 ApiZone() : zone_() {
35 Thread* thread = Thread::Current(); 55 Thread* thread = Thread::Current();
36 Zone* zone = thread != NULL ? thread->zone() : NULL; 56 Zone* zone = thread != NULL ? thread->zone() : NULL;
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 static intptr_t raw_offset() { 227 static intptr_t raw_offset() {
208 return OFFSET_OF(FinalizablePersistentHandle, raw_); 228 return OFFSET_OF(FinalizablePersistentHandle, raw_);
209 } 229 }
210 void* peer() const { return peer_; } 230 void* peer() const { return peer_; }
211 Dart_WeakPersistentHandleFinalizer callback() const { return callback_; } 231 Dart_WeakPersistentHandleFinalizer callback() const { return callback_; }
212 Dart_WeakPersistentHandle apiHandle() { 232 Dart_WeakPersistentHandle apiHandle() {
213 return reinterpret_cast<Dart_WeakPersistentHandle>(this); 233 return reinterpret_cast<Dart_WeakPersistentHandle>(this);
214 } 234 }
215 235
216 intptr_t external_size() const { 236 intptr_t external_size() const {
217 return ExternalSizeBits::decode(external_data_); 237 return ExternalSizeInWordsBits::decode(external_data_) * kWordSize;
218 } 238 }
219 239
220 void SetExternalSize(intptr_t size, Isolate* isolate) { 240 void SetExternalSize(intptr_t size, Isolate* isolate) {
221 ASSERT(size >= 0); 241 ASSERT(size >= 0);
222 set_external_size(Utils::RoundUp(size, kObjectAlignment)); 242 set_external_size(size);
223 if (SpaceForExternal() == Heap::kNew) { 243 if (SpaceForExternal() == Heap::kNew) {
224 SetExternalNewSpaceBit(); 244 SetExternalNewSpaceBit();
225 } 245 }
226 isolate->heap()->AllocateExternal(external_size(), SpaceForExternal()); 246 isolate->heap()->AllocateExternal(external_size(), SpaceForExternal());
227 } 247 }
228 248
229 // Called when the referent becomes unreachable. 249 // Called when the referent becomes unreachable.
230 void UpdateUnreachable(Isolate* isolate) { 250 void UpdateUnreachable(Isolate* isolate, FinalizationQueue* queue) {
251 if (is_queued_for_finalization()) {
252 return;
253 }
231 EnsureFreeExternal(isolate); 254 EnsureFreeExternal(isolate);
232 Finalize(isolate, this); 255 if (queue == NULL) {
256 Finalize(isolate, this);
257 } else {
258 MarkForFinalization();
259 queue->Add(this);
260 set_is_queued_for_finalization(true);
261 }
233 } 262 }
234 263
235 // Called when the referent has moved, potentially between generations. 264 // Called when the referent has moved, potentially between generations.
236 void UpdateRelocated(Isolate* isolate) { 265 void UpdateRelocated(Isolate* isolate) {
237 if (IsSetNewSpaceBit() && (SpaceForExternal() == Heap::kOld)) { 266 if (IsSetNewSpaceBit() && (SpaceForExternal() == Heap::kOld)) {
238 isolate->heap()->PromoteExternal(external_size()); 267 isolate->heap()->PromoteExternal(external_size());
239 ClearExternalNewSpaceBit(); 268 ClearExternalNewSpaceBit();
240 } 269 }
241 } 270 }
242 271
243 // Idempotent. Called when the handle is explicitly deleted or the 272 // Idempotent. Called when the handle is explicitly deleted or the
244 // referent becomes unreachable. 273 // referent becomes unreachable.
245 void EnsureFreeExternal(Isolate* isolate) { 274 void EnsureFreeExternal(Isolate* isolate) {
246 isolate->heap()->FreeExternal(external_size(), SpaceForExternal()); 275 isolate->heap()->FreeExternal(external_size(), SpaceForExternal());
247 set_external_size(0); 276 set_external_size(0);
248 } 277 }
249 278
250 static FinalizablePersistentHandle* Cast(Dart_WeakPersistentHandle handle); 279 static FinalizablePersistentHandle* Cast(Dart_WeakPersistentHandle handle);
251 280
252 private: 281 private:
253 enum { 282 enum {
254 kExternalNewSpaceBit = 0, 283 kExternalNewSpaceBit = 0,
255 kExternalSizeBits = 1, 284 kQueuedForFinalizationBit = 1,
256 kExternalSizeBitsSize = (kBitsPerWord - 1), 285 kExternalSizeBits = 2,
286 kExternalSizeBitsSize = (kBitsPerWord - 2),
257 }; 287 };
258 288
259 // This part of external_data_ is the number of externally allocated bytes. 289 // This part of external_data_ is the number of externally allocated bytes.
260 // TODO(koda): Measure size in words instead. 290 class ExternalSizeInWordsBits : public BitField<uword,
261 class ExternalSizeBits : public BitField<uword, 291 intptr_t,
262 intptr_t, 292 kExternalSizeBits,
263 kExternalSizeBits, 293 kExternalSizeBitsSize> {};
264 kExternalSizeBitsSize> {};
265 // This bit of external_data_ is true if the referent was created in new 294 // This bit of external_data_ is true if the referent was created in new
266 // space and UpdateRelocated has not yet detected any promotion. 295 // space and UpdateRelocated has not yet detected any promotion.
267 class ExternalNewSpaceBit : 296 class ExternalNewSpaceBit :
268 public BitField<uword, bool, kExternalNewSpaceBit, 1> {}; 297 public BitField<uword, bool, kExternalNewSpaceBit, 1> {};
298 class QueuedForFinalizationBit :
299 public BitField<uword, bool, kQueuedForFinalizationBit, 1> {};
269 300
270 friend class FinalizablePersistentHandles; 301 friend class FinalizablePersistentHandles;
271 302
272 FinalizablePersistentHandle() 303 FinalizablePersistentHandle()
273 : raw_(NULL), 304 : raw_(NULL),
274 peer_(NULL), 305 peer_(NULL),
275 external_data_(0), 306 external_data_(0),
276 callback_(NULL) { } 307 callback_(NULL) { }
277 ~FinalizablePersistentHandle() { } 308 ~FinalizablePersistentHandle() { }
278 309
(...skipping 13 matching lines...) Expand all
292 SetNext(free_list); 323 SetNext(free_list);
293 } 324 }
294 325
295 void Clear() { 326 void Clear() {
296 raw_ = Object::null(); 327 raw_ = Object::null();
297 peer_ = NULL; 328 peer_ = NULL;
298 external_data_ = 0; 329 external_data_ = 0;
299 callback_ = NULL; 330 callback_ = NULL;
300 } 331 }
301 332
333 void MarkForFinalization() {
334 raw_ = Object::null();
335 ASSERT(callback_ != NULL);
336 }
337
302 void set_raw(RawObject* raw) { raw_ = raw; } 338 void set_raw(RawObject* raw) { raw_ = raw; }
303 void set_raw(const LocalHandle& ref) { raw_ = ref.raw(); } 339 void set_raw(const LocalHandle& ref) { raw_ = ref.raw(); }
304 void set_raw(const Object& object) { raw_ = object.raw(); } 340 void set_raw(const Object& object) { raw_ = object.raw(); }
305 341
306 void set_peer(void* peer) { peer_ = peer; } 342 void set_peer(void* peer) { peer_ = peer; }
307 343
308 void set_callback(Dart_WeakPersistentHandleFinalizer callback) { 344 void set_callback(Dart_WeakPersistentHandleFinalizer callback) {
309 callback_ = callback; 345 callback_ = callback;
310 } 346 }
311 347
312 void set_external_size(intptr_t size) { 348 void set_external_size(intptr_t size) {
313 ASSERT(ExternalSizeBits::is_valid(size)); 349 intptr_t size_in_words = Utils::RoundUp(size, kObjectAlignment) / kWordSize;
314 external_data_ = ExternalSizeBits::update(size, external_data_); 350 ASSERT(ExternalSizeInWordsBits::is_valid(size_in_words));
351 external_data_ = ExternalSizeInWordsBits::update(size_in_words,
352 external_data_);
353 }
354
355 bool is_queued_for_finalization() const {
356 return QueuedForFinalizationBit::decode(external_data_);
357 }
358 void set_is_queued_for_finalization(bool value) {
359 external_data_ = QueuedForFinalizationBit::update(value, external_data_);
315 } 360 }
316 361
317 bool IsSetNewSpaceBit() const { 362 bool IsSetNewSpaceBit() const {
318 return ExternalNewSpaceBit::decode(external_data_); 363 return ExternalNewSpaceBit::decode(external_data_);
319 } 364 }
320 365
321 void SetExternalNewSpaceBit() { 366 void SetExternalNewSpaceBit() {
322 external_data_ = ExternalNewSpaceBit::update(true, external_data_); 367 external_data_ = ExternalNewSpaceBit::update(true, external_data_);
323 } 368 }
324 369
325 void ClearExternalNewSpaceBit() { 370 void ClearExternalNewSpaceBit() {
326 external_data_ = ExternalNewSpaceBit::update(false, external_data_); 371 external_data_ = ExternalNewSpaceBit::update(false, external_data_);
327 } 372 }
328 373
329 // Returns the space to charge for the external size. 374 // Returns the space to charge for the external size.
330 Heap::Space SpaceForExternal() const { 375 Heap::Space SpaceForExternal() const {
331 // Non-heap and VM-heap objects count as old space here. 376 // Non-heap and VM-heap objects count as old space here.
332 return (raw_->IsHeapObject() && raw_->IsNewObject()) ? 377 return (raw_->IsHeapObject() && raw_->IsNewObject()) ?
333 Heap::kNew : Heap::kOld; 378 Heap::kNew : Heap::kOld;
334 } 379 }
335 380
381 friend class BackgroundFinalizer;
382
336 RawObject* raw_; 383 RawObject* raw_;
337 void* peer_; 384 void* peer_;
338 uword external_data_; 385 uword external_data_;
339 Dart_WeakPersistentHandleFinalizer callback_; 386 Dart_WeakPersistentHandleFinalizer callback_;
387
340 DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods. 388 DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods.
341 DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandle); 389 DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandle);
342 }; 390 };
343 391
344 392
345 // Local handles repository structure. 393 // Local handles repository structure.
346 static const int kLocalHandleSizeInWords = sizeof(LocalHandle) / kWordSize; 394 static const int kLocalHandleSizeInWords = sizeof(LocalHandle) / kWordSize;
347 static const int kLocalHandlesPerChunk = 64; 395 static const int kLocalHandlesPerChunk = 64;
348 static const int kOffsetOfRawPtrInLocalHandle = 0; 396 static const int kOffsetOfRawPtrInLocalHandle = 0;
349 class LocalHandles : Handles<kLocalHandleSizeInWords, 397 class LocalHandles : Handles<kLocalHandleSizeInWords,
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 static const int kOffsetOfRawPtrInFinalizablePersistentHandle = 0; 542 static const int kOffsetOfRawPtrInFinalizablePersistentHandle = 0;
495 class FinalizablePersistentHandles 543 class FinalizablePersistentHandles
496 : Handles<kFinalizablePersistentHandleSizeInWords, 544 : Handles<kFinalizablePersistentHandleSizeInWords,
497 kFinalizablePersistentHandlesPerChunk, 545 kFinalizablePersistentHandlesPerChunk,
498 kOffsetOfRawPtrInFinalizablePersistentHandle> { 546 kOffsetOfRawPtrInFinalizablePersistentHandle> {
499 public: 547 public:
500 FinalizablePersistentHandles() 548 FinalizablePersistentHandles()
501 : Handles<kFinalizablePersistentHandleSizeInWords, 549 : Handles<kFinalizablePersistentHandleSizeInWords,
502 kFinalizablePersistentHandlesPerChunk, 550 kFinalizablePersistentHandlesPerChunk,
503 kOffsetOfRawPtrInFinalizablePersistentHandle>(), 551 kOffsetOfRawPtrInFinalizablePersistentHandle>(),
504 free_list_(NULL) { } 552 free_list_(NULL), mutex_(new Mutex()) { }
505 ~FinalizablePersistentHandles() { 553 ~FinalizablePersistentHandles() {
506 free_list_ = NULL; 554 free_list_ = NULL;
555 delete mutex_;
556 mutex_ = NULL;
507 } 557 }
508 558
509 // Accessors. 559 // Accessors.
510 FinalizablePersistentHandle* free_list() const { return free_list_; } 560 FinalizablePersistentHandle* free_list() const { return free_list_; }
511 void set_free_list(FinalizablePersistentHandle* value) { free_list_ = value; } 561 void set_free_list(FinalizablePersistentHandle* value) { free_list_ = value; }
512 562
513 // Visit all handles stored in the various handle blocks. 563 // Visit all handles stored in the various handle blocks.
514 void VisitHandles(HandleVisitor* visitor) { 564 void VisitHandles(HandleVisitor* visitor) {
515 Handles<kFinalizablePersistentHandleSizeInWords, 565 Handles<kFinalizablePersistentHandleSizeInWords,
516 kFinalizablePersistentHandlesPerChunk, 566 kFinalizablePersistentHandlesPerChunk,
517 kOffsetOfRawPtrInFinalizablePersistentHandle>::Visit( 567 kOffsetOfRawPtrInFinalizablePersistentHandle>::Visit(
518 visitor); 568 visitor);
519 } 569 }
520 570
521 // Visit all object pointers stored in the various handles. 571 // Visit all object pointers stored in the various handles.
522 void VisitObjectPointers(ObjectPointerVisitor* visitor) { 572 void VisitObjectPointers(ObjectPointerVisitor* visitor) {
523 Handles<kFinalizablePersistentHandleSizeInWords, 573 Handles<kFinalizablePersistentHandleSizeInWords,
524 kFinalizablePersistentHandlesPerChunk, 574 kFinalizablePersistentHandlesPerChunk,
525 kOffsetOfRawPtrInFinalizablePersistentHandle>::VisitObjectPointers( 575 kOffsetOfRawPtrInFinalizablePersistentHandle>::VisitObjectPointers(
526 visitor); 576 visitor);
527 } 577 }
528 578
529 // Allocates a persistent handle, these have to be destroyed explicitly 579 // Allocates a persistent handle, these have to be destroyed explicitly
530 // by calling FreeHandle. 580 // by calling FreeHandle.
531 FinalizablePersistentHandle* AllocateHandle() { 581 FinalizablePersistentHandle* AllocateHandle() {
532 FinalizablePersistentHandle* handle; 582 FinalizablePersistentHandle* handle;
533 if (free_list_ != NULL) { 583 {
534 handle = free_list_; 584 MutexLocker ml(mutex_);
535 free_list_ = handle->Next(); 585 if (free_list_ != NULL) {
536 handle->set_raw(Object::null()); 586 handle = free_list_;
537 } else { 587 free_list_ = handle->Next();
538 handle = reinterpret_cast<FinalizablePersistentHandle*>( 588 handle->set_raw(Object::null());
589 return handle;
590 }
591 }
592
593 handle = reinterpret_cast<FinalizablePersistentHandle*>(
539 AllocateScopedHandle()); 594 AllocateScopedHandle());
540 handle->Clear(); 595 handle->Clear();
541 }
542 return handle; 596 return handle;
543 } 597 }
544 598
545 void FreeHandle(FinalizablePersistentHandle* handle) { 599 void FreeHandle(FinalizablePersistentHandle* handle) {
600 MutexLocker ml(mutex_);
546 handle->FreeHandle(free_list()); 601 handle->FreeHandle(free_list());
547 set_free_list(handle); 602 set_free_list(handle);
548 } 603 }
549 604
550 // Validate if passed in handle is a Persistent Handle. 605 // Validate if passed in handle is a Persistent Handle.
551 bool IsValidHandle(Dart_WeakPersistentHandle object) const { 606 bool IsValidHandle(Dart_WeakPersistentHandle object) const {
607 MutexLocker ml(mutex_);
552 return IsValidScopedHandle(reinterpret_cast<uword>(object)); 608 return IsValidScopedHandle(reinterpret_cast<uword>(object));
553 } 609 }
554 610
555 // Returns a count of active handles (used for testing purposes). 611 // Returns a count of active handles (used for testing purposes).
556 int CountHandles() const { 612 int CountHandles() const {
557 return CountScopedHandles(); 613 return CountScopedHandles();
558 } 614 }
559 615
560 private: 616 private:
561 FinalizablePersistentHandle* free_list_; 617 FinalizablePersistentHandle* free_list_;
618 Mutex* mutex_;
562 DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandles); 619 DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandles);
563 }; 620 };
564 621
565 622
566 // Structure used for the implementation of local scopes used in dart_api. 623 // Structure used for the implementation of local scopes used in dart_api.
567 // These local scopes manage handles and memory allocated in the scope. 624 // These local scopes manage handles and memory allocated in the scope.
568 class ApiLocalScope { 625 class ApiLocalScope {
569 public: 626 public:
570 ApiLocalScope(ApiLocalScope* previous, uword stack_marker) : 627 ApiLocalScope(ApiLocalScope* previous, uword stack_marker) :
571 previous_(previous), stack_marker_(stack_marker) { } 628 previous_(previous), stack_marker_(stack_marker) { }
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 void* peer, 811 void* peer,
755 Dart_WeakPersistentHandleFinalizer callback, 812 Dart_WeakPersistentHandleFinalizer callback,
756 intptr_t external_size) { 813 intptr_t external_size) {
757 ApiState* state = isolate->api_state(); 814 ApiState* state = isolate->api_state();
758 ASSERT(state != NULL); 815 ASSERT(state != NULL);
759 FinalizablePersistentHandle* ref = 816 FinalizablePersistentHandle* ref =
760 state->weak_persistent_handles().AllocateHandle(); 817 state->weak_persistent_handles().AllocateHandle();
761 ref->set_raw(object); 818 ref->set_raw(object);
762 ref->set_peer(peer); 819 ref->set_peer(peer);
763 ref->set_callback(callback); 820 ref->set_callback(callback);
821 ref->set_is_queued_for_finalization(false);
764 // This may trigger GC, so it must be called last. 822 // This may trigger GC, so it must be called last.
765 ref->SetExternalSize(external_size, isolate); 823 ref->SetExternalSize(external_size, isolate);
766 return ref; 824 return ref;
767 } 825 }
768 826
769 } // namespace dart 827 } // namespace dart
770 828
771 #endif // VM_DART_API_STATE_H_ 829 #endif // VM_DART_API_STATE_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698