Index: runtime/vm/dart_api_state.h |
diff --git a/runtime/vm/dart_api_state.h b/runtime/vm/dart_api_state.h |
index aea8010c62e19d3bf00aa362ecc6ca1c6c52fbe6..9badcc4fb9447228d1ad0ca6c148d081686b6f06 100644 |
--- a/runtime/vm/dart_api_state.h |
+++ b/runtime/vm/dart_api_state.h |
@@ -81,78 +81,89 @@ void ProtectedHandleCallback(void* peer); |
// dart API. |
class PersistentHandle { |
public: |
- enum Kind { |
- StrongReference = 0, |
- WeakReference, |
- }; |
- |
- // Adaptor for visiting handles with matching reference kind. |
- class Visitor : public HandleVisitor { |
- public: |
- Visitor(ObjectPointerVisitor* visitor, Kind kind) { |
- ASSERT(visitor != NULL); |
- kind_ = kind; |
- object_pointer_visitor_ = visitor; |
- } |
+ // Accessors. |
+ RawObject* raw() const { return raw_; } |
+ void set_raw(RawObject* ref) { raw_ = ref; } |
+ void set_raw(const LocalHandle& ref) { raw_ = ref.raw(); } |
+ void set_raw(const Object& object) { raw_ = object.raw(); } |
+ static intptr_t raw_offset() { return OFFSET_OF(PersistentHandle, raw_); } |
- void Visit(uword* addr) { |
- PersistentHandle* handle = reinterpret_cast<PersistentHandle*>(addr); |
- if (handle->kind() == kind_) { |
- object_pointer_visitor_->VisitPointer(&handle->raw_); |
- } |
- } |
+ private: |
+ friend class PersistentHandles; |
+ |
+ PersistentHandle() { } |
+ ~PersistentHandle() { } |
- ~Visitor() {} |
+ // Overload the raw_ field as a next pointer when adding freed |
+ // handles to the free list. |
+ PersistentHandle* Next() { |
+ return reinterpret_cast<PersistentHandle*>(raw_); |
+ } |
+ void SetNext(PersistentHandle* free_list) { |
+ raw_ = reinterpret_cast<RawObject*>(free_list); |
+ } |
+ void FreeHandle(PersistentHandle* free_list) { |
+ SetNext(free_list); |
+ } |
- private: |
- Kind kind_; |
- ObjectPointerVisitor* object_pointer_visitor_; |
+ RawObject* raw_; |
+ DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods. |
+ DISALLOW_COPY_AND_ASSIGN(PersistentHandle); |
+}; |
- DISALLOW_COPY_AND_ASSIGN(Visitor); |
- }; |
+// Implementation of persistent handles which are handed out through the |
+// dart API. |
+class WeakPersistentHandle { |
+ public: |
// Accessors. |
RawObject* raw() const { return raw_; } |
+ 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(); } |
- static intptr_t raw_offset() { return OFFSET_OF(PersistentHandle, raw_); } |
- Kind kind() const { return kind_; } |
- void set_kind(Kind kind) { kind_ = kind; } |
+ static intptr_t raw_offset() { return OFFSET_OF(WeakPersistentHandle, raw_); } |
void* peer() const { return peer_; } |
void set_peer(void* peer) { peer_ = peer; } |
Dart_PeerFinalizer callback() const { return callback_; } |
void set_callback(Dart_PeerFinalizer callback) { callback_ = callback; } |
- // Some handles are protected from being freed via the external dart api. |
- bool IsProtected() { |
- return callback() == ProtectedHandleCallback; |
+ void Finalize() { |
+ if (callback_ != NULL) { |
+ (*callback_)(peer_); |
+ } |
+ Clear(); |
} |
private: |
- friend class PersistentHandles; |
+ friend class WeakPersistentHandles; |
- PersistentHandle() : kind_(StrongReference), peer_(NULL), callback_(NULL) { } |
- ~PersistentHandle() { } |
+ WeakPersistentHandle() : raw_(NULL), peer_(NULL), callback_(NULL) { } |
+ ~WeakPersistentHandle() { } |
// Overload the callback_ field as a next pointer when adding freed |
// handles to the free list. |
- PersistentHandle* Next() { |
- return reinterpret_cast<PersistentHandle*>(callback_); |
+ WeakPersistentHandle* Next() { |
+ return reinterpret_cast<WeakPersistentHandle*>(callback_); |
} |
- void SetNext(PersistentHandle* free_list) { |
+ void SetNext(WeakPersistentHandle* free_list) { |
callback_ = reinterpret_cast<Dart_PeerFinalizer>(free_list); |
} |
- void FreeHandle(PersistentHandle* free_list) { |
+ void FreeHandle(WeakPersistentHandle* free_list) { |
raw_ = NULL; |
SetNext(free_list); |
} |
+ void Clear() { |
+ raw_ = Object::null(); |
+ peer_ = NULL; |
+ callback_ = NULL; |
+ } |
+ |
RawObject* raw_; |
- Kind kind_; |
void* peer_; |
Dart_PeerFinalizer callback_; |
DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods. |
- DISALLOW_COPY_AND_ASSIGN(PersistentHandle); |
+ DISALLOW_COPY_AND_ASSIGN(WeakPersistentHandle); |
}; |
@@ -227,24 +238,6 @@ class PersistentHandles : Handles<kPersistentHandleSizeInWords, |
kOffsetOfRawPtrInPersistentHandle>::VisitObjectPointers(visitor); |
} |
- // Visits the object pointers in strong persistent handles. |
- void VisitStrongObjectPointers(ObjectPointerVisitor* visitor) { |
- PersistentHandle::Visitor strong_visitor(visitor, |
- PersistentHandle::StrongReference); |
- Handles<kPersistentHandleSizeInWords, |
- kPersistentHandlesPerChunk, |
- kOffsetOfRawPtrInPersistentHandle>::Visit(&strong_visitor); |
- } |
- |
- // Visits the object pointers in weak persistent handles. |
- void VisitWeakObjectPointers(ObjectPointerVisitor* visitor) { |
- PersistentHandle::Visitor weak_visitor(visitor, |
- PersistentHandle::WeakReference); |
- Handles<kPersistentHandleSizeInWords, |
- kPersistentHandlesPerChunk, |
- kOffsetOfRawPtrInPersistentHandle>::Visit(&weak_visitor); |
- } |
- |
// Allocates a persistent handle, these have to be destroyed explicitly |
// by calling FreeHandle. |
PersistentHandle* AllocateHandle() { |
@@ -255,8 +248,7 @@ class PersistentHandles : Handles<kPersistentHandleSizeInWords, |
} else { |
handle = reinterpret_cast<PersistentHandle*>(AllocateScopedHandle()); |
} |
- handle->set_callback(NULL); |
- handle->set_kind(PersistentHandle::StrongReference); |
+ handle->set_raw(NULL); |
return handle; |
} |
@@ -281,6 +273,69 @@ class PersistentHandles : Handles<kPersistentHandleSizeInWords, |
}; |
+// Weak persistent handles repository structure. |
+static const int kWeakPersistentHandleSizeInWords = |
+ sizeof(WeakPersistentHandle) / kWordSize; |
+static const int kWeakPersistentHandlesPerChunk = 64; |
+static const int kOffsetOfRawPtrInWeakPersistentHandle = 0; |
+class WeakPersistentHandles : Handles<kWeakPersistentHandleSizeInWords, |
+ kWeakPersistentHandlesPerChunk, |
+ kOffsetOfRawPtrInWeakPersistentHandle> { |
+ public: |
+ WeakPersistentHandles() : Handles<kWeakPersistentHandleSizeInWords, |
+ kWeakPersistentHandlesPerChunk, |
+ kOffsetOfRawPtrInWeakPersistentHandle>(), |
+ free_list_(NULL) { } |
+ ~WeakPersistentHandles() { |
+ free_list_ = NULL; |
+ } |
+ |
+ // Accessors. |
+ WeakPersistentHandle* free_list() const { return free_list_; } |
+ void set_free_list(WeakPersistentHandle* value) { free_list_ = value; } |
+ |
+ // Visit all handles stored in the various handle blocks. |
+ void VisitWeakPersistentHandles(HandleVisitor* visitor) { |
+ Handles<kWeakPersistentHandleSizeInWords, |
+ kWeakPersistentHandlesPerChunk, |
+ kOffsetOfRawPtrInWeakPersistentHandle>::Visit(visitor); |
+ } |
+ |
+ // Allocates a persistent handle, these have to be destroyed explicitly |
+ // by calling FreeHandle. |
+ WeakPersistentHandle* AllocateHandle() { |
+ WeakPersistentHandle* handle; |
+ if (free_list_ != NULL) { |
+ handle = free_list_; |
+ free_list_ = handle->Next(); |
+ } else { |
+ handle = reinterpret_cast<WeakPersistentHandle*>(AllocateScopedHandle()); |
+ } |
+ handle->set_callback(NULL); |
+ return handle; |
+ } |
+ |
+ void FreeHandle(WeakPersistentHandle* handle) { |
+ handle->FreeHandle(free_list()); |
+ set_free_list(handle); |
+ } |
+ |
+ // Validate if passed in handle is a Persistent Handle. |
+ bool IsValidHandle(Dart_Handle object) const { |
+ return IsValidScopedHandle(reinterpret_cast<uword>(object)); |
+ } |
+ |
+ // Returns a count of active handles (used for testing purposes). |
+ int CountHandles() const { |
+ return CountScopedHandles(); |
+ } |
+ |
+ private: |
+ WeakPersistentHandle* free_list_; |
+ DISALLOW_COPY_AND_ASSIGN(WeakPersistentHandles); |
+}; |
+ |
+ |
// Structure used for the implementation of local scopes used in dart_api. |
// These local scopes manage handles and memory allocated in the scope. |
class ApiLocalScope { |
@@ -338,6 +393,9 @@ class ApiState { |
ApiLocalScope* top_scope() const { return top_scope_; } |
void set_top_scope(ApiLocalScope* value) { top_scope_ = value; } |
PersistentHandles& persistent_handles() { return persistent_handles_; } |
+ WeakPersistentHandles& weak_persistent_handles() { |
+ return weak_persistent_handles_; |
+ } |
void UnwindScopes(uword sp) { |
while (top_scope_ != NULL && top_scope_->stack_marker() < sp) { |
@@ -347,23 +405,17 @@ class ApiState { |
} |
} |
- void VisitStrongObjectPointers(ObjectPointerVisitor* visitor) { |
+ void VisitObjectPointers(ObjectPointerVisitor* visitor) { |
ApiLocalScope* scope = top_scope_; |
while (scope != NULL) { |
scope->local_handles()->VisitObjectPointers(visitor); |
scope = scope->previous(); |
} |
- |
- persistent_handles().VisitStrongObjectPointers(visitor); |
+ persistent_handles().VisitObjectPointers(visitor); |
} |
- void VisitWeakObjectPointers(ObjectPointerVisitor* visitor) { |
- persistent_handles().VisitWeakObjectPointers(visitor); |
- } |
- |
- void VisitObjectPointers(ObjectPointerVisitor* visitor) { |
- VisitStrongObjectPointers(visitor); |
- VisitWeakObjectPointers(visitor); |
+ void VisitWeakHandles(HandleVisitor* visitor) { |
+ weak_persistent_handles().VisitWeakPersistentHandles(visitor); |
} |
bool IsValidLocalHandle(Dart_Handle object) const { |
@@ -376,10 +428,20 @@ class ApiState { |
} |
return false; |
} |
+ |
bool IsValidPersistentHandle(Dart_Handle object) const { |
return persistent_handles_.IsValidHandle(object); |
} |
+ bool IsValidWeakPersistentHandle(Dart_Handle object) const { |
+ return weak_persistent_handles_.IsValidHandle(object); |
+ } |
+ |
+ bool IsProtectedHandle(PersistentHandle* object) const { |
+ if (object == NULL) return false; |
+ return object == null_ || object == true_ || object == false_; |
+ } |
+ |
int CountLocalHandles() const { |
int total = 0; |
ApiLocalScope* scope = top_scope_; |
@@ -408,7 +470,6 @@ class ApiState { |
Object& null_object = Object::Handle(); |
null_ = persistent_handles().AllocateHandle(); |
null_->set_raw(null_object); |
- null_->set_callback(ProtectedHandleCallback); |
} |
return null_; |
} |
@@ -419,7 +480,6 @@ class ApiState { |
const Object& true_object = Object::Handle(Bool::True()); |
true_ = persistent_handles().AllocateHandle(); |
true_->set_raw(true_object); |
- true_->set_callback(ProtectedHandleCallback); |
} |
return true_; |
} |
@@ -430,13 +490,13 @@ class ApiState { |
const Object& false_object = Object::Handle(Bool::False()); |
false_ = persistent_handles().AllocateHandle(); |
false_->set_raw(false_object); |
- false_->set_callback(ProtectedHandleCallback); |
} |
return false_; |
} |
private: |
PersistentHandles persistent_handles_; |
+ WeakPersistentHandles weak_persistent_handles_; |
ApiLocalScope* top_scope_; |
// Persistent handles to important objects. |