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

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

Issue 2809863002: Remove background finalization. (Closed)
Patch Set: . Created 3 years, 8 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
« no previous file with comments | « runtime/observatory/lib/src/service/object.dart ('k') | runtime/vm/dart_api_state.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 RUNTIME_VM_DART_API_STATE_H_ 5 #ifndef RUNTIME_VM_DART_API_STATE_H_
6 #define RUNTIME_VM_DART_API_STATE_H_ 6 #define RUNTIME_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/os_thread.h"
19 #include "vm/raw_object.h" 19 #include "vm/raw_object.h"
20 #include "vm/thread_pool.h" 20 #include "vm/thread_pool.h"
21 #include "vm/visitor.h" 21 #include "vm/visitor.h"
22 #include "vm/weak_table.h" 22 #include "vm/weak_table.h"
23 23
24 #include "vm/handles_impl.h" 24 #include "vm/handles_impl.h"
25 25
26 namespace dart { 26 namespace dart {
27 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
47 // Implementation of Zone support for very fast allocation of small chunks 28 // Implementation of Zone support for very fast allocation of small chunks
48 // of memory. The chunks cannot be deallocated individually, but instead 29 // of memory. The chunks cannot be deallocated individually, but instead
49 // zones support deallocating all chunks in one fast operation when the 30 // zones support deallocating all chunks in one fast operation when the
50 // scope is exited. 31 // scope is exited.
51 class ApiZone { 32 class ApiZone {
52 public: 33 public:
53 // Create an empty zone. 34 // Create an empty zone.
54 ApiZone() : zone_() { 35 ApiZone() : zone_() {
55 Thread* thread = Thread::Current(); 36 Thread* thread = Thread::Current();
56 Zone* zone = thread != NULL ? thread->zone() : NULL; 37 Zone* zone = thread != NULL ? thread->zone() : NULL;
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 void SetExternalSize(intptr_t size, Isolate* isolate) { 218 void SetExternalSize(intptr_t size, Isolate* isolate) {
238 ASSERT(size >= 0); 219 ASSERT(size >= 0);
239 set_external_size(size); 220 set_external_size(size);
240 if (SpaceForExternal() == Heap::kNew) { 221 if (SpaceForExternal() == Heap::kNew) {
241 SetExternalNewSpaceBit(); 222 SetExternalNewSpaceBit();
242 } 223 }
243 isolate->heap()->AllocateExternal(external_size(), SpaceForExternal()); 224 isolate->heap()->AllocateExternal(external_size(), SpaceForExternal());
244 } 225 }
245 226
246 // Called when the referent becomes unreachable. 227 // Called when the referent becomes unreachable.
247 void UpdateUnreachable(Isolate* isolate, FinalizationQueue* queue) { 228 void UpdateUnreachable(Isolate* isolate) {
248 if (is_queued_for_finalization()) {
249 return;
250 }
251 EnsureFreeExternal(isolate); 229 EnsureFreeExternal(isolate);
252 if (queue == NULL) { 230 Finalize(isolate, this);
253 Finalize(isolate, this);
254 } else {
255 MarkForFinalization();
256 queue->Add(this);
257 set_is_queued_for_finalization(true);
258 }
259 } 231 }
260 232
261 // Called when the referent has moved, potentially between generations. 233 // Called when the referent has moved, potentially between generations.
262 void UpdateRelocated(Isolate* isolate) { 234 void UpdateRelocated(Isolate* isolate) {
263 if (IsSetNewSpaceBit() && (SpaceForExternal() == Heap::kOld)) { 235 if (IsSetNewSpaceBit() && (SpaceForExternal() == Heap::kOld)) {
264 isolate->heap()->PromoteExternal(external_size()); 236 isolate->heap()->PromoteExternal(external_size());
265 ClearExternalNewSpaceBit(); 237 ClearExternalNewSpaceBit();
266 } 238 }
267 } 239 }
268 240
269 // Idempotent. Called when the handle is explicitly deleted or the 241 // Idempotent. Called when the handle is explicitly deleted or the
270 // referent becomes unreachable. 242 // referent becomes unreachable.
271 void EnsureFreeExternal(Isolate* isolate) { 243 void EnsureFreeExternal(Isolate* isolate) {
272 isolate->heap()->FreeExternal(external_size(), SpaceForExternal()); 244 isolate->heap()->FreeExternal(external_size(), SpaceForExternal());
273 set_external_size(0); 245 set_external_size(0);
274 } 246 }
275 247
276 static FinalizablePersistentHandle* Cast(Dart_WeakPersistentHandle handle); 248 static FinalizablePersistentHandle* Cast(Dart_WeakPersistentHandle handle);
277 249
278 private: 250 private:
279 enum { 251 enum {
280 kExternalNewSpaceBit = 0, 252 kExternalNewSpaceBit = 0,
281 kQueuedForFinalizationBit = 1, 253 kExternalSizeBits = 1,
282 kExternalSizeBits = 2, 254 kExternalSizeBitsSize = (kBitsPerWord - 1),
283 kExternalSizeBitsSize = (kBitsPerWord - 2),
284 }; 255 };
285 256
286 // This part of external_data_ is the number of externally allocated bytes. 257 // This part of external_data_ is the number of externally allocated bytes.
287 class ExternalSizeInWordsBits : public BitField<uword, 258 class ExternalSizeInWordsBits : public BitField<uword,
288 intptr_t, 259 intptr_t,
289 kExternalSizeBits, 260 kExternalSizeBits,
290 kExternalSizeBitsSize> {}; 261 kExternalSizeBitsSize> {};
291 // This bit of external_data_ is true if the referent was created in new 262 // This bit of external_data_ is true if the referent was created in new
292 // space and UpdateRelocated has not yet detected any promotion. 263 // space and UpdateRelocated has not yet detected any promotion.
293 class ExternalNewSpaceBit 264 class ExternalNewSpaceBit
294 : public BitField<uword, bool, kExternalNewSpaceBit, 1> {}; 265 : public BitField<uword, bool, kExternalNewSpaceBit, 1> {};
295 class QueuedForFinalizationBit
296 : public BitField<uword, bool, kQueuedForFinalizationBit, 1> {};
297 266
298 friend class FinalizablePersistentHandles; 267 friend class FinalizablePersistentHandles;
299 268
300 FinalizablePersistentHandle() 269 FinalizablePersistentHandle()
301 : raw_(NULL), peer_(NULL), external_data_(0), callback_(NULL) {} 270 : raw_(NULL), peer_(NULL), external_data_(0), callback_(NULL) {}
302 ~FinalizablePersistentHandle() {} 271 ~FinalizablePersistentHandle() {}
303 272
304 static void Finalize(Isolate* isolate, FinalizablePersistentHandle* handle); 273 static void Finalize(Isolate* isolate, FinalizablePersistentHandle* handle);
305 274
306 // Overload the raw_ field as a next pointer when adding freed 275 // Overload the raw_ field as a next pointer when adding freed
(...skipping 10 matching lines...) Expand all
317 SetNext(free_list); 286 SetNext(free_list);
318 } 287 }
319 288
320 void Clear() { 289 void Clear() {
321 raw_ = Object::null(); 290 raw_ = Object::null();
322 peer_ = NULL; 291 peer_ = NULL;
323 external_data_ = 0; 292 external_data_ = 0;
324 callback_ = NULL; 293 callback_ = NULL;
325 } 294 }
326 295
327 void MarkForFinalization() {
328 raw_ = Object::null();
329 ASSERT(callback_ != NULL);
330 }
331
332 void set_raw(RawObject* raw) { raw_ = raw; } 296 void set_raw(RawObject* raw) { raw_ = raw; }
333 void set_raw(const LocalHandle& ref) { raw_ = ref.raw(); } 297 void set_raw(const LocalHandle& ref) { raw_ = ref.raw(); }
334 void set_raw(const Object& object) { raw_ = object.raw(); } 298 void set_raw(const Object& object) { raw_ = object.raw(); }
335 299
336 void set_peer(void* peer) { peer_ = peer; } 300 void set_peer(void* peer) { peer_ = peer; }
337 301
338 void set_callback(Dart_WeakPersistentHandleFinalizer callback) { 302 void set_callback(Dart_WeakPersistentHandleFinalizer callback) {
339 callback_ = callback; 303 callback_ = callback;
340 } 304 }
341 305
342 void set_external_size(intptr_t size) { 306 void set_external_size(intptr_t size) {
343 intptr_t size_in_words = Utils::RoundUp(size, kObjectAlignment) / kWordSize; 307 intptr_t size_in_words = Utils::RoundUp(size, kObjectAlignment) / kWordSize;
344 ASSERT(ExternalSizeInWordsBits::is_valid(size_in_words)); 308 ASSERT(ExternalSizeInWordsBits::is_valid(size_in_words));
345 external_data_ = 309 external_data_ =
346 ExternalSizeInWordsBits::update(size_in_words, external_data_); 310 ExternalSizeInWordsBits::update(size_in_words, external_data_);
347 } 311 }
348 312
349 bool is_queued_for_finalization() const {
350 return QueuedForFinalizationBit::decode(external_data_);
351 }
352 void set_is_queued_for_finalization(bool value) {
353 external_data_ = QueuedForFinalizationBit::update(value, external_data_);
354 }
355
356 bool IsSetNewSpaceBit() const { 313 bool IsSetNewSpaceBit() const {
357 return ExternalNewSpaceBit::decode(external_data_); 314 return ExternalNewSpaceBit::decode(external_data_);
358 } 315 }
359 316
360 void SetExternalNewSpaceBit() { 317 void SetExternalNewSpaceBit() {
361 external_data_ = ExternalNewSpaceBit::update(true, external_data_); 318 external_data_ = ExternalNewSpaceBit::update(true, external_data_);
362 } 319 }
363 320
364 void ClearExternalNewSpaceBit() { 321 void ClearExternalNewSpaceBit() {
365 external_data_ = ExternalNewSpaceBit::update(false, external_data_); 322 external_data_ = ExternalNewSpaceBit::update(false, external_data_);
366 } 323 }
367 324
368 // Returns the space to charge for the external size. 325 // Returns the space to charge for the external size.
369 Heap::Space SpaceForExternal() const { 326 Heap::Space SpaceForExternal() const {
370 // Non-heap and VM-heap objects count as old space here. 327 // Non-heap and VM-heap objects count as old space here.
371 return (raw_->IsHeapObject() && raw_->IsNewObject()) ? Heap::kNew 328 return (raw_->IsHeapObject() && raw_->IsNewObject()) ? Heap::kNew
372 : Heap::kOld; 329 : Heap::kOld;
373 } 330 }
374 331
375 friend class BackgroundFinalizer;
376
377 RawObject* raw_; 332 RawObject* raw_;
378 void* peer_; 333 void* peer_;
379 uword external_data_; 334 uword external_data_;
380 Dart_WeakPersistentHandleFinalizer callback_; 335 Dart_WeakPersistentHandleFinalizer callback_;
381 336
382 DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods. 337 DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods.
383 DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandle); 338 DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandle);
384 }; 339 };
385 340
386 341
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 static const int kOffsetOfRawPtrInFinalizablePersistentHandle = 0; 494 static const int kOffsetOfRawPtrInFinalizablePersistentHandle = 0;
540 class FinalizablePersistentHandles 495 class FinalizablePersistentHandles
541 : Handles<kFinalizablePersistentHandleSizeInWords, 496 : Handles<kFinalizablePersistentHandleSizeInWords,
542 kFinalizablePersistentHandlesPerChunk, 497 kFinalizablePersistentHandlesPerChunk,
543 kOffsetOfRawPtrInFinalizablePersistentHandle> { 498 kOffsetOfRawPtrInFinalizablePersistentHandle> {
544 public: 499 public:
545 FinalizablePersistentHandles() 500 FinalizablePersistentHandles()
546 : Handles<kFinalizablePersistentHandleSizeInWords, 501 : Handles<kFinalizablePersistentHandleSizeInWords,
547 kFinalizablePersistentHandlesPerChunk, 502 kFinalizablePersistentHandlesPerChunk,
548 kOffsetOfRawPtrInFinalizablePersistentHandle>(), 503 kOffsetOfRawPtrInFinalizablePersistentHandle>(),
549 free_list_(NULL), 504 free_list_(NULL) {}
550 mutex_(new Mutex()) {}
551 ~FinalizablePersistentHandles() { 505 ~FinalizablePersistentHandles() {
552 free_list_ = NULL; 506 free_list_ = NULL;
553 delete mutex_;
554 mutex_ = NULL;
555 } 507 }
556 508
557 // Accessors. 509 // Accessors.
558 FinalizablePersistentHandle* free_list() const { return free_list_; } 510 FinalizablePersistentHandle* free_list() const { return free_list_; }
559 void set_free_list(FinalizablePersistentHandle* value) { free_list_ = value; } 511 void set_free_list(FinalizablePersistentHandle* value) { free_list_ = value; }
560 512
561 // Visit all handles stored in the various handle blocks. 513 // Visit all handles stored in the various handle blocks.
562 void VisitHandles(HandleVisitor* visitor) { 514 void VisitHandles(HandleVisitor* visitor) {
563 Handles<kFinalizablePersistentHandleSizeInWords, 515 Handles<kFinalizablePersistentHandleSizeInWords,
564 kFinalizablePersistentHandlesPerChunk, 516 kFinalizablePersistentHandlesPerChunk,
565 kOffsetOfRawPtrInFinalizablePersistentHandle>::Visit(visitor); 517 kOffsetOfRawPtrInFinalizablePersistentHandle>::Visit(visitor);
566 } 518 }
567 519
568 // Visit all object pointers stored in the various handles. 520 // Visit all object pointers stored in the various handles.
569 void VisitObjectPointers(ObjectPointerVisitor* visitor) { 521 void VisitObjectPointers(ObjectPointerVisitor* visitor) {
570 Handles<kFinalizablePersistentHandleSizeInWords, 522 Handles<kFinalizablePersistentHandleSizeInWords,
571 kFinalizablePersistentHandlesPerChunk, 523 kFinalizablePersistentHandlesPerChunk,
572 kOffsetOfRawPtrInFinalizablePersistentHandle>:: 524 kOffsetOfRawPtrInFinalizablePersistentHandle>::
573 VisitObjectPointers(visitor); 525 VisitObjectPointers(visitor);
574 } 526 }
575 527
576 // Allocates a persistent handle, these have to be destroyed explicitly 528 // Allocates a persistent handle, these have to be destroyed explicitly
577 // by calling FreeHandle. 529 // by calling FreeHandle.
578 FinalizablePersistentHandle* AllocateHandle() { 530 FinalizablePersistentHandle* AllocateHandle() {
579 FinalizablePersistentHandle* handle; 531 FinalizablePersistentHandle* handle;
580 { 532 if (free_list_ != NULL) {
581 MutexLocker ml(mutex_); 533 handle = free_list_;
582 if (free_list_ != NULL) { 534 free_list_ = handle->Next();
583 handle = free_list_; 535 handle->set_raw(Object::null());
584 free_list_ = handle->Next(); 536 return handle;
585 handle->set_raw(Object::null());
586 return handle;
587 }
588 } 537 }
589 538
590 handle = 539 handle =
591 reinterpret_cast<FinalizablePersistentHandle*>(AllocateScopedHandle()); 540 reinterpret_cast<FinalizablePersistentHandle*>(AllocateScopedHandle());
592 handle->Clear(); 541 handle->Clear();
593 return handle; 542 return handle;
594 } 543 }
595 544
596 void FreeHandle(FinalizablePersistentHandle* handle) { 545 void FreeHandle(FinalizablePersistentHandle* handle) {
597 MutexLocker ml(mutex_);
598 handle->FreeHandle(free_list()); 546 handle->FreeHandle(free_list());
599 set_free_list(handle); 547 set_free_list(handle);
600 } 548 }
601 549
602 // Validate if passed in handle is a Persistent Handle. 550 // Validate if passed in handle is a Persistent Handle.
603 bool IsValidHandle(Dart_WeakPersistentHandle object) const { 551 bool IsValidHandle(Dart_WeakPersistentHandle object) const {
604 MutexLocker ml(mutex_);
605 return IsValidScopedHandle(reinterpret_cast<uword>(object)); 552 return IsValidScopedHandle(reinterpret_cast<uword>(object));
606 } 553 }
607 554
608 bool IsFreeHandle(Dart_WeakPersistentHandle object) const { 555 bool IsFreeHandle(Dart_WeakPersistentHandle object) const {
609 MutexLocker ml(mutex_);
610 FinalizablePersistentHandle* handle = free_list_; 556 FinalizablePersistentHandle* handle = free_list_;
611 while (handle != NULL) { 557 while (handle != NULL) {
612 if (handle == reinterpret_cast<FinalizablePersistentHandle*>(object)) { 558 if (handle == reinterpret_cast<FinalizablePersistentHandle*>(object)) {
613 return true; 559 return true;
614 } 560 }
615 handle = handle->Next(); 561 handle = handle->Next();
616 } 562 }
617 return false; 563 return false;
618 } 564 }
619 565
620 // Returns a count of active handles (used for testing purposes). 566 // Returns a count of active handles (used for testing purposes).
621 int CountHandles() const { return CountScopedHandles(); } 567 int CountHandles() const { return CountScopedHandles(); }
622 568
623 private: 569 private:
624 FinalizablePersistentHandle* free_list_; 570 FinalizablePersistentHandle* free_list_;
625 Mutex* mutex_;
626 DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandles); 571 DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandles);
627 }; 572 };
628 573
629 574
630 // Structure used for the implementation of local scopes used in dart_api. 575 // Structure used for the implementation of local scopes used in dart_api.
631 // These local scopes manage handles and memory allocated in the scope. 576 // These local scopes manage handles and memory allocated in the scope.
632 class ApiLocalScope { 577 class ApiLocalScope {
633 public: 578 public:
634 ApiLocalScope(ApiLocalScope* previous, uword stack_marker) 579 ApiLocalScope(ApiLocalScope* previous, uword stack_marker)
635 : previous_(previous), stack_marker_(stack_marker) {} 580 : previous_(previous), stack_marker_(stack_marker) {}
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
854 void* peer, 799 void* peer,
855 Dart_WeakPersistentHandleFinalizer callback, 800 Dart_WeakPersistentHandleFinalizer callback,
856 intptr_t external_size) { 801 intptr_t external_size) {
857 ApiState* state = isolate->api_state(); 802 ApiState* state = isolate->api_state();
858 ASSERT(state != NULL); 803 ASSERT(state != NULL);
859 FinalizablePersistentHandle* ref = 804 FinalizablePersistentHandle* ref =
860 state->weak_persistent_handles().AllocateHandle(); 805 state->weak_persistent_handles().AllocateHandle();
861 ref->set_raw(object); 806 ref->set_raw(object);
862 ref->set_peer(peer); 807 ref->set_peer(peer);
863 ref->set_callback(callback); 808 ref->set_callback(callback);
864 ref->set_is_queued_for_finalization(false);
865 // This may trigger GC, so it must be called last. 809 // This may trigger GC, so it must be called last.
866 ref->SetExternalSize(external_size, isolate); 810 ref->SetExternalSize(external_size, isolate);
867 return ref; 811 return ref;
868 } 812 }
869 813
870 } // namespace dart 814 } // namespace dart
871 815
872 #endif // RUNTIME_VM_DART_API_STATE_H_ 816 #endif // RUNTIME_VM_DART_API_STATE_H_
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/service/object.dart ('k') | runtime/vm/dart_api_state.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698