*/
inline void MakeWeak(void* parameters, WeakReferenceCallback callback);
- /** Clears the weak reference to this object.*/
+ /** Clears the weak reference to this object. */
inline void ClearWeak();
/**
*/
inline void MarkIndependent();
- /**
- *Checks if the handle holds the only reference to an object.
- */
+ /** Returns true if this handle was previously marked as independent. */
+ inline bool IsIndependent() const;
+
+ /** Checks if the handle holds the only reference to an object. */
inline bool IsNearDeath() const;
- /**
- * Returns true if the handle's reference is weak.
- */
+ /** Returns true if the handle's reference is weak. */
inline bool IsWeak() const;
/**
*/
inline void SetWrapperClassId(uint16_t class_id);
+ /**
+ * Returns the class ID previously assigned to this handle or 0 if no class
+ * ID was previously assigned.
+ */
+ inline uint16_t WrapperClassId() const;
+
private:
friend class ImplementationUtilities;
friend class ObjectTemplate;
/**
- * Interface for iterating though all external resources in the heap.
+ * Interface for iterating through all external resources in the heap.
*/
class V8EXPORT ExternalResourceVisitor { // NOLINT
public:
/**
+ * Interface for iterating through all the persistent handles in the heap.
+ */
+class V8EXPORT PersistentHandleVisitor { // NOLINT
+ public:
+ virtual ~PersistentHandleVisitor() {}
+ virtual void VisitPersistentHandle(Persistent<Value> value,
+ uint16_t class_id) {}
+};
+
+
+/**
* Container class for static utility functions.
*/
class V8EXPORT V8 {
static void VisitExternalResources(ExternalResourceVisitor* visitor);
/**
+ * Iterates through all the persistent handles in the current isolate's heap
+ * that have class_ids.
+ */
+ static void VisitHandlesWithClassIds(PersistentHandleVisitor* visitor);
+
+ /**
* Optional notification that the embedder is idle.
* V8 uses the notification to reduce memory footprint.
* This call can be used repeatedly if the embedder remains idle.
WeakReferenceCallback);
static void ClearWeak(internal::Object** global_handle);
static void MarkIndependent(internal::Object** global_handle);
+ static bool IsGlobalIndependent(internal::Object** global_handle);
static bool IsGlobalNearDeath(internal::Object** global_handle);
static bool IsGlobalWeak(internal::Object** global_handle);
static void SetWrapperClassId(internal::Object** global_handle,
uint16_t class_id);
+ static uint16_t GetWrapperClassId(internal::Object** global_handle);
template <class T> friend class Handle;
template <class T> friend class Local;
template <class T>
+bool Persistent<T>::IsIndependent() const {
+ if (this->IsEmpty()) return false;
+ return V8::IsGlobalIndependent(reinterpret_cast<internal::Object**>(**this));
+}
+
+
+template <class T>
bool Persistent<T>::IsNearDeath() const {
if (this->IsEmpty()) return false;
return V8::IsGlobalNearDeath(reinterpret_cast<internal::Object**>(**this));
V8::SetWrapperClassId(reinterpret_cast<internal::Object**>(**this), class_id);
}
+template <class T>
+uint16_t Persistent<T>::WrapperClassId() const {
+ return V8::GetWrapperClassId(reinterpret_cast<internal::Object**>(**this));
+}
+
Arguments::Arguments(internal::Object** implicit_args,
internal::Object** values, int length,
bool is_construct_call)
}
+bool V8::IsGlobalIndependent(i::Object** obj) {
+ i::Isolate* isolate = i::Isolate::Current();
+ LOG_API(isolate, "IsGlobalIndependent");
+ if (!isolate->IsInitialized()) return false;
+ return i::GlobalHandles::IsIndependent(obj);
+}
+
+
bool V8::IsGlobalNearDeath(i::Object** obj) {
i::Isolate* isolate = i::Isolate::Current();
LOG_API(isolate, "IsGlobalNearDeath");
}
+void v8::V8::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) {
+ i::Isolate* isolate = i::Isolate::Current();
+ IsDeadCheck(isolate, "v8::V8::VisitHandlesWithClassId");
+
+ i::AssertNoAllocation no_allocation;
+
+ class VisitorAdapter : public i::ObjectVisitor {
+ public:
+ explicit VisitorAdapter(PersistentHandleVisitor* visitor)
+ : visitor_(visitor) {}
+ virtual void VisitPointers(i::Object** start, i::Object** end) {
+ UNREACHABLE();
+ }
+ virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) {
+ visitor_->VisitPersistentHandle(ToApi<Value>(i::Handle<i::Object>(p)),
+ class_id);
+ }
+ private:
+ PersistentHandleVisitor* visitor_;
+ } visitor_adapter(visitor);
+ isolate->global_handles()->IterateAllRootsWithClassIds(&visitor_adapter);
+}
+
+
bool v8::V8::IdleNotification(int hint) {
// Returning true tells the caller that it need not
// continue to call IdleNotification.
}
+uint16_t V8::GetWrapperClassId(internal::Object** global_handle) {
+ return i::GlobalHandles::GetWrapperClassId(global_handle);
+}
+
+
Local<v8::Object> ObjectTemplate::NewInstance() {
i::Isolate* isolate = i::Isolate::Current();
ON_BAILOUT(isolate, "v8::ObjectTemplate::NewInstance()",
}
+bool GlobalHandles::IsIndependent(Object** location) {
+ return Node::FromLocation(location)->is_independent();
+}
+
+
bool GlobalHandles::IsNearDeath(Object** location) {
return Node::FromLocation(location)->IsNearDeath();
}
Node::FromLocation(location)->set_wrapper_class_id(class_id);
}
+uint16_t GlobalHandles::GetWrapperClassId(Object** location) {
+ return Node::FromLocation(location)->wrapper_class_id();
+}
void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
for (NodeIterator it(this); !it.done(); it.Advance()) {
WeakReferenceCallback callback);
static void SetWrapperClassId(Object** location, uint16_t class_id);
+ static uint16_t GetWrapperClassId(Object** location);
// Returns the current number of weak handles.
int NumberOfWeakHandles() { return number_of_weak_handles_; }
// Clear the weakness of a global handle.
void MarkIndependent(Object** location);
+ static bool IsIndependent(Object** location);
+
// Tells whether global handle is near death.
static bool IsNearDeath(Object** location);
bool object_a_disposed = false;
object_a.MakeWeak(&object_a_disposed, &DisposeAndSetFlag);
+ CHECK(!object_a.IsIndependent());
object_a.MarkIndependent();
+ CHECK(object_a.IsIndependent());
HEAP->PerformScavenge();
CHECK(object_a_disposed);
}
}
+TEST(PersistentHandleVisitor) {
+ v8::HandleScope scope;
+ LocalContext context;
+ v8::Persistent<v8::Object> object =
+ v8::Persistent<v8::Object>::New(v8::Object::New());
+ CHECK_EQ(0, object.WrapperClassId());
+ object.SetWrapperClassId(42);
+ CHECK_EQ(42, object.WrapperClassId());
+
+ class Visitor : public v8::PersistentHandleVisitor {
+ public:
+ explicit Visitor(v8::Persistent<v8::Object> object)
+ : counter_(0), object_(object) { }
+
+ virtual void VisitPersistentHandle(Persistent<Value> value,
+ uint16_t class_id) {
+ if (class_id == 42) {
+ CHECK(value->IsObject());
+ v8::Persistent<v8::Object> visited =
+ v8::Persistent<v8::Object>::Cast(value);
+ CHECK_EQ(42, visited.WrapperClassId());
+ CHECK_EQ(object_, visited);
+ ++counter_;
+ }
+ }
+
+ int counter_;
+ v8::Persistent<v8::Object> object_;
+ } visitor(object);
+
+ v8::V8::VisitHandlesWithClassIds(&visitor);
+ CHECK_EQ(1, visitor.counter_);
+
+ object.Dispose();
+}
+
+
TEST(RegExp) {
v8::HandleScope scope;
LocalContext context;