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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/dart_api_impl_test.cc ('k') | runtime/vm/dart_api_state.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/dart_api_state.h
diff --git a/runtime/vm/dart_api_state.h b/runtime/vm/dart_api_state.h
index b510377352cdc294d017c4922a86bd2e052e0c5f..f687fb2a914f01f1323af97c0aa713f5d6a7f525 100644
--- a/runtime/vm/dart_api_state.h
+++ b/runtime/vm/dart_api_state.h
@@ -15,8 +15,9 @@
#include "vm/handles.h"
#include "vm/object.h"
#include "vm/os.h"
-#include "vm/raw_object.h"
#include "vm/os_thread.h"
+#include "vm/raw_object.h"
+#include "vm/thread_pool.h"
#include "vm/visitor.h"
#include "vm/weak_table.h"
@@ -24,6 +25,25 @@
namespace dart {
+class FinalizablePersistentHandle;
+typedef MallocGrowableArray<FinalizablePersistentHandle*> FinalizationQueue;
+
+
+class BackgroundFinalizer : public ThreadPool::Task {
+ public:
+ BackgroundFinalizer(Isolate* isolate, FinalizationQueue* queue);
+ virtual ~BackgroundFinalizer() { }
+
+ void Run();
+
+ private:
+ Isolate* isolate_;
+ FinalizationQueue* queue_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(BackgroundFinalizer);
+};
+
+
// Implementation of Zone support for very fast allocation of small chunks
// of memory. The chunks cannot be deallocated individually, but instead
// zones support deallocating all chunks in one fast operation when the
@@ -214,12 +234,12 @@ class FinalizablePersistentHandle {
}
intptr_t external_size() const {
- return ExternalSizeBits::decode(external_data_);
+ return ExternalSizeInWordsBits::decode(external_data_) * kWordSize;
}
void SetExternalSize(intptr_t size, Isolate* isolate) {
ASSERT(size >= 0);
- set_external_size(Utils::RoundUp(size, kObjectAlignment));
+ set_external_size(size);
if (SpaceForExternal() == Heap::kNew) {
SetExternalNewSpaceBit();
}
@@ -227,9 +247,18 @@ class FinalizablePersistentHandle {
}
// Called when the referent becomes unreachable.
- void UpdateUnreachable(Isolate* isolate) {
+ void UpdateUnreachable(Isolate* isolate, FinalizationQueue* queue) {
+ if (is_queued_for_finalization()) {
+ return;
+ }
EnsureFreeExternal(isolate);
- Finalize(isolate, this);
+ if (queue == NULL) {
+ Finalize(isolate, this);
+ } else {
+ MarkForFinalization();
+ queue->Add(this);
+ set_is_queued_for_finalization(true);
+ }
}
// Called when the referent has moved, potentially between generations.
@@ -252,20 +281,22 @@ class FinalizablePersistentHandle {
private:
enum {
kExternalNewSpaceBit = 0,
- kExternalSizeBits = 1,
- kExternalSizeBitsSize = (kBitsPerWord - 1),
+ kQueuedForFinalizationBit = 1,
+ kExternalSizeBits = 2,
+ kExternalSizeBitsSize = (kBitsPerWord - 2),
};
// This part of external_data_ is the number of externally allocated bytes.
- // TODO(koda): Measure size in words instead.
- class ExternalSizeBits : public BitField<uword,
- intptr_t,
- kExternalSizeBits,
- kExternalSizeBitsSize> {};
+ class ExternalSizeInWordsBits : public BitField<uword,
+ intptr_t,
+ kExternalSizeBits,
+ kExternalSizeBitsSize> {};
// This bit of external_data_ is true if the referent was created in new
// space and UpdateRelocated has not yet detected any promotion.
class ExternalNewSpaceBit :
public BitField<uword, bool, kExternalNewSpaceBit, 1> {};
+ class QueuedForFinalizationBit :
+ public BitField<uword, bool, kQueuedForFinalizationBit, 1> {};
friend class FinalizablePersistentHandles;
@@ -299,6 +330,11 @@ class FinalizablePersistentHandle {
callback_ = NULL;
}
+ void MarkForFinalization() {
+ raw_ = Object::null();
+ ASSERT(callback_ != NULL);
+ }
+
void set_raw(RawObject* raw) { raw_ = raw; }
void set_raw(const LocalHandle& ref) { raw_ = ref.raw(); }
void set_raw(const Object& object) { raw_ = object.raw(); }
@@ -310,8 +346,17 @@ class FinalizablePersistentHandle {
}
void set_external_size(intptr_t size) {
- ASSERT(ExternalSizeBits::is_valid(size));
- external_data_ = ExternalSizeBits::update(size, external_data_);
+ intptr_t size_in_words = Utils::RoundUp(size, kObjectAlignment) / kWordSize;
+ ASSERT(ExternalSizeInWordsBits::is_valid(size_in_words));
+ external_data_ = ExternalSizeInWordsBits::update(size_in_words,
+ external_data_);
+ }
+
+ bool is_queued_for_finalization() const {
+ return QueuedForFinalizationBit::decode(external_data_);
+ }
+ void set_is_queued_for_finalization(bool value) {
+ external_data_ = QueuedForFinalizationBit::update(value, external_data_);
}
bool IsSetNewSpaceBit() const {
@@ -333,10 +378,13 @@ class FinalizablePersistentHandle {
Heap::kNew : Heap::kOld;
}
+ friend class BackgroundFinalizer;
+
RawObject* raw_;
void* peer_;
uword external_data_;
Dart_WeakPersistentHandleFinalizer callback_;
+
DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods.
DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandle);
};
@@ -501,9 +549,11 @@ class FinalizablePersistentHandles
: Handles<kFinalizablePersistentHandleSizeInWords,
kFinalizablePersistentHandlesPerChunk,
kOffsetOfRawPtrInFinalizablePersistentHandle>(),
- free_list_(NULL) { }
+ free_list_(NULL), mutex_(new Mutex()) { }
~FinalizablePersistentHandles() {
free_list_ = NULL;
+ delete mutex_;
+ mutex_ = NULL;
}
// Accessors.
@@ -530,25 +580,31 @@ class FinalizablePersistentHandles
// by calling FreeHandle.
FinalizablePersistentHandle* AllocateHandle() {
FinalizablePersistentHandle* handle;
- if (free_list_ != NULL) {
- handle = free_list_;
- free_list_ = handle->Next();
- handle->set_raw(Object::null());
- } else {
- handle = reinterpret_cast<FinalizablePersistentHandle*>(
- AllocateScopedHandle());
- handle->Clear();
+ {
+ MutexLocker ml(mutex_);
+ if (free_list_ != NULL) {
+ handle = free_list_;
+ free_list_ = handle->Next();
+ handle->set_raw(Object::null());
+ return handle;
+ }
}
+
+ handle = reinterpret_cast<FinalizablePersistentHandle*>(
+ AllocateScopedHandle());
+ handle->Clear();
return handle;
}
void FreeHandle(FinalizablePersistentHandle* handle) {
+ MutexLocker ml(mutex_);
handle->FreeHandle(free_list());
set_free_list(handle);
}
// Validate if passed in handle is a Persistent Handle.
bool IsValidHandle(Dart_WeakPersistentHandle object) const {
+ MutexLocker ml(mutex_);
return IsValidScopedHandle(reinterpret_cast<uword>(object));
}
@@ -559,6 +615,7 @@ class FinalizablePersistentHandles
private:
FinalizablePersistentHandle* free_list_;
+ Mutex* mutex_;
DISALLOW_COPY_AND_ASSIGN(FinalizablePersistentHandles);
};
@@ -761,6 +818,7 @@ inline FinalizablePersistentHandle* FinalizablePersistentHandle::New(
ref->set_raw(object);
ref->set_peer(peer);
ref->set_callback(callback);
+ ref->set_is_queued_for_finalization(false);
// This may trigger GC, so it must be called last.
ref->SetExternalSize(external_size, isolate);
return ref;
« no previous file with comments | « runtime/vm/dart_api_impl_test.cc ('k') | runtime/vm/dart_api_state.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698