Index: runtime/vm/dart_api_state.h |
diff --git a/runtime/vm/dart_api_state.h b/runtime/vm/dart_api_state.h |
index 81f65d9a75e3af2e80269e4aad03ad9491242892..aea8010c62e19d3bf00aa362ecc6ca1c6c52fbe6 100644 |
--- a/runtime/vm/dart_api_state.h |
+++ b/runtime/vm/dart_api_state.h |
@@ -74,37 +74,64 @@ class LocalHandle { |
// A distinguished callback which indicates that a persistent handle |
// should not be deleted from the dart api. |
-void ProtectedHandleCallback(); |
+void ProtectedHandleCallback(void* peer); |
// Implementation of persistent handles which are handed out through the |
// dart API. |
class PersistentHandle { |
public: |
- enum { |
+ 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; |
+ } |
+ |
+ void Visit(uword* addr) { |
+ PersistentHandle* handle = reinterpret_cast<PersistentHandle*>(addr); |
+ if (handle->kind() == kind_) { |
+ object_pointer_visitor_->VisitPointer(&handle->raw_); |
+ } |
+ } |
+ |
+ ~Visitor() {} |
+ |
+ private: |
+ Kind kind_; |
+ ObjectPointerVisitor* object_pointer_visitor_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Visitor); |
+ }; |
+ |
// Accessors. |
RawObject* raw() const { return 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_); } |
- void* callback() const { return callback_; } |
- void set_callback(void* value) { callback_ = value; } |
- intptr_t type() const { return type_; } |
- void set_type(intptr_t value) { type_ = value; } |
+ Kind kind() const { return kind_; } |
+ void set_kind(Kind kind) { kind_ = kind; } |
+ 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; |
+ return callback() == ProtectedHandleCallback; |
} |
private: |
friend class PersistentHandles; |
- PersistentHandle() { } |
+ PersistentHandle() : kind_(StrongReference), peer_(NULL), callback_(NULL) { } |
~PersistentHandle() { } |
// Overload the callback_ field as a next pointer when adding freed |
@@ -113,7 +140,7 @@ class PersistentHandle { |
return reinterpret_cast<PersistentHandle*>(callback_); |
} |
void SetNext(PersistentHandle* free_list) { |
- callback_ = reinterpret_cast<void*>(free_list); |
+ callback_ = reinterpret_cast<Dart_PeerFinalizer>(free_list); |
} |
void FreeHandle(PersistentHandle* free_list) { |
raw_ = NULL; |
@@ -121,8 +148,9 @@ class PersistentHandle { |
} |
RawObject* raw_; |
- void* callback_; |
- intptr_t type_; |
+ Kind kind_; |
+ void* peer_; |
+ Dart_PeerFinalizer callback_; |
DISALLOW_ALLOCATION(); // Allocated through AllocateHandle methods. |
DISALLOW_COPY_AND_ASSIGN(PersistentHandle); |
}; |
@@ -199,6 +227,24 @@ 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() { |
@@ -210,7 +256,7 @@ class PersistentHandles : Handles<kPersistentHandleSizeInWords, |
handle = reinterpret_cast<PersistentHandle*>(AllocateScopedHandle()); |
} |
handle->set_callback(NULL); |
- handle->set_type(PersistentHandle::StrongReference); |
+ handle->set_kind(PersistentHandle::StrongReference); |
return handle; |
} |
@@ -301,13 +347,23 @@ class ApiState { |
} |
} |
- void VisitObjectPointers(ObjectPointerVisitor* visitor) { |
+ void VisitStrongObjectPointers(ObjectPointerVisitor* visitor) { |
ApiLocalScope* scope = top_scope_; |
while (scope != NULL) { |
scope->local_handles()->VisitObjectPointers(visitor); |
scope = scope->previous(); |
} |
- persistent_handles().VisitObjectPointers(visitor); |
+ |
+ persistent_handles().VisitStrongObjectPointers(visitor); |
+ } |
+ |
+ void VisitWeakObjectPointers(ObjectPointerVisitor* visitor) { |
+ persistent_handles().VisitWeakObjectPointers(visitor); |
+ } |
+ |
+ void VisitObjectPointers(ObjectPointerVisitor* visitor) { |
+ VisitStrongObjectPointers(visitor); |
+ VisitWeakObjectPointers(visitor); |
} |
bool IsValidLocalHandle(Dart_Handle object) const { |
@@ -352,7 +408,7 @@ class ApiState { |
Object& null_object = Object::Handle(); |
null_ = persistent_handles().AllocateHandle(); |
null_->set_raw(null_object); |
- null_->set_callback(reinterpret_cast<void*>(&ProtectedHandleCallback)); |
+ null_->set_callback(ProtectedHandleCallback); |
} |
return null_; |
} |
@@ -363,7 +419,7 @@ class ApiState { |
const Object& true_object = Object::Handle(Bool::True()); |
true_ = persistent_handles().AllocateHandle(); |
true_->set_raw(true_object); |
- true_->set_callback(reinterpret_cast<void*>(&ProtectedHandleCallback)); |
+ true_->set_callback(ProtectedHandleCallback); |
} |
return true_; |
} |
@@ -374,7 +430,7 @@ class ApiState { |
const Object& false_object = Object::Handle(Bool::False()); |
false_ = persistent_handles().AllocateHandle(); |
false_->set_raw(false_object); |
- false_->set_callback(reinterpret_cast<void*>(&ProtectedHandleCallback)); |
+ false_->set_callback(ProtectedHandleCallback); |
} |
return false_; |
} |