Unify phantom and internal fields weak handle callbacks
authorerikcorry <erikcorry@chromium.org>
Mon, 12 Jan 2015 12:11:49 +0000 (04:11 -0800)
committerCommit bot <commit-bot@chromium.org>
Mon, 12 Jan 2015 12:12:10 +0000 (12:12 +0000)
R=dcarney@chromium.org
BUG=

Review URL: https://codereview.chromium.org/842153004

Cr-Commit-Position: refs/heads/master@{#26022}

include/v8.h
src/api.cc
src/debug.cc
src/global-handles.cc
src/global-handles.h
test/cctest/test-api.cc

index 913866b..a87ad01 100644 (file)
@@ -137,15 +137,18 @@ class PropertyCallbackArguments;
 class FunctionCallbackArguments;
 class GlobalHandles;
 
+template <typename T>
 class CallbackData {
  public:
   V8_INLINE v8::Isolate* GetIsolate() const { return isolate_; }
 
- protected:
-  explicit CallbackData(v8::Isolate* isolate) : isolate_(isolate) {}
+  explicit CallbackData(v8::Isolate* isolate, T* parameter)
+      : isolate_(isolate), parameter_(parameter) {}
+  V8_INLINE T* GetParameter() const { return parameter_; }
 
  private:
   v8::Isolate* isolate_;
+  T* parameter_;
 };
 }
 
@@ -425,23 +428,28 @@ template <class T> class Eternal {
 };
 
 
-template <typename T>
-class PhantomCallbackData : public internal::CallbackData {
+template <typename T, typename U = void, typename V = void>
+class PhantomCallbackData : public internal::CallbackData<T> {
  public:
-  typedef void (*Callback)(const PhantomCallbackData<T>& data);
+  typedef void (*Callback)(const PhantomCallbackData<T, U, V>& data);
 
-  V8_INLINE T* GetParameter() const { return parameter_; }
+  V8_INLINE U* GetInternalField1() const { return internal_field1_; }
+  V8_INLINE V* GetInternalField2() const { return internal_field2_; }
 
-  PhantomCallbackData<T>(Isolate* isolate, T* parameter)
-      : internal::CallbackData(isolate), parameter_(parameter) {}
+  PhantomCallbackData(Isolate* isolate, T* parameter, U* internal_field1,
+                      V* internal_field2)
+      : internal::CallbackData<T>(isolate, parameter),
+        internal_field1_(internal_field1),
+        internal_field2_(internal_field2) {}
 
  private:
-  T* parameter_;
+  U* internal_field1_;
+  V* internal_field2_;
 };
 
 
 template <class T, class P>
-class WeakCallbackData : public PhantomCallbackData<P> {
+class WeakCallbackData : public internal::CallbackData<P> {
  public:
   typedef void (*Callback)(const WeakCallbackData<T, P>& data);
 
@@ -450,31 +458,11 @@ class WeakCallbackData : public PhantomCallbackData<P> {
  private:
   friend class internal::GlobalHandles;
   WeakCallbackData(Isolate* isolate, P* parameter, Local<T> handle)
-      : PhantomCallbackData<P>(isolate, parameter), handle_(handle) {}
+      : internal::CallbackData<P>(isolate, parameter), handle_(handle) {}
   Local<T> handle_;
 };
 
 
-template <typename T, typename U>
-class InternalFieldsCallbackData : public internal::CallbackData {
- public:
-  typedef void (*Callback)(const InternalFieldsCallbackData<T, U>& data);
-
-  InternalFieldsCallbackData(Isolate* isolate, T* internalField1,
-                             U* internalField2)
-      : internal::CallbackData(isolate),
-        internal_field1_(internalField1),
-        internal_field2_(internalField2) {}
-
-  V8_INLINE T* GetInternalField1() const { return internal_field1_; }
-  V8_INLINE U* GetInternalField2() const { return internal_field2_; }
-
- private:
-  T* internal_field1_;
-  U* internal_field2_;
-};
-
-
 /**
  * An object reference that is independent of any handle scope.  Where
  * a Local handle only lives as long as the HandleScope in which it was
@@ -562,13 +550,17 @@ template <class T> class PersistentBase {
   // specify a parameter for the callback or the location of two internal
   // fields in the dying object.
   template <typename P>
-  V8_INLINE void SetPhantom(P* parameter,
-                            typename PhantomCallbackData<P>::Callback callback);
-
+  V8_INLINE void SetPhantom(
+      P* parameter,
+      typename PhantomCallbackData<P, void, void>::Callback callback);
   template <typename P, typename Q>
   V8_INLINE void SetPhantom(
-      void (*callback)(const InternalFieldsCallbackData<P, Q>&),
-      int internal_field_index1, int internal_field_index2);
+      P* parameter, int internal_field_index1,
+      typename PhantomCallbackData<P, Q, void>::Callback callback);
+  template <typename P, typename Q, typename R>
+  V8_INLINE void SetPhantom(
+      P* parameter, int internal_field_index1, int internal_field_index2,
+      typename PhantomCallbackData<P, Q, R>::Callback callback);
 
   template<typename P>
   V8_INLINE P* ClearWeak();
@@ -5595,13 +5587,13 @@ class V8_EXPORT V8 {
   typedef WeakCallbackData<Value, void>::Callback WeakCallback;
   static void MakeWeak(internal::Object** global_handle, void* data,
                        WeakCallback weak_callback);
-  static void MakePhantom(internal::Object** global_handle, void* data,
-                          PhantomCallbackData<void>::Callback weak_callback);
   static void MakePhantom(
-      internal::Object** global_handle,
-      InternalFieldsCallbackData<void, void>::Callback weak_callback,
+      internal::Object** global_handle, void* data,
+      // Must be 0 or kNoInternalFieldIndex.
       int internal_field_index1,
-      int internal_field_index2 = Object::kNoInternalFieldIndex);
+      // Must be 1 or kNoInternalFieldIndex.
+      int internal_field_index2,
+      PhantomCallbackData<void, void, void>::Callback weak_callback);
   static void* ClearWeak(internal::Object** global_handle);
   static void Eternalize(Isolate* isolate,
                          Value* handle,
@@ -6489,22 +6481,36 @@ void PersistentBase<T>::SetWeak(
 template <class T>
 template <typename P>
 void PersistentBase<T>::SetPhantom(
-    P* parameter, typename PhantomCallbackData<P>::Callback callback) {
-  typedef typename PhantomCallbackData<void>::Callback Callback;
+    P* parameter,
+    typename PhantomCallbackData<P, void, void>::Callback callback) {
+  typedef typename PhantomCallbackData<void, void, void>::Callback Callback;
+  V8::MakePhantom(reinterpret_cast<internal::Object**>(this->val_), parameter,
+                  Object::kNoInternalFieldIndex, Object::kNoInternalFieldIndex,
+                  reinterpret_cast<Callback>(callback));
+}
+
+
+template <class T>
+template <typename P, typename Q>
+void PersistentBase<T>::SetPhantom(
+    P* parameter, int internal_field_index1,
+    typename PhantomCallbackData<P, Q, void>::Callback callback) {
+  typedef typename PhantomCallbackData<void, void, void>::Callback Callback;
   V8::MakePhantom(reinterpret_cast<internal::Object**>(this->val_), parameter,
+                  internal_field_index1, Object::kNoInternalFieldIndex,
                   reinterpret_cast<Callback>(callback));
 }
 
 
 template <class T>
-template <typename U, typename V>
+template <typename P, typename Q, typename R>
 void PersistentBase<T>::SetPhantom(
-    void (*callback)(const InternalFieldsCallbackData<U, V>&),
-    int internal_field_index1, int internal_field_index2) {
-  typedef typename InternalFieldsCallbackData<void, void>::Callback Callback;
-  V8::MakePhantom(reinterpret_cast<internal::Object**>(this->val_),
-                  reinterpret_cast<Callback>(callback), internal_field_index1,
-                  internal_field_index2);
+    P* parameter, int internal_field_index1, int internal_field_index2,
+    typename PhantomCallbackData<P, Q, R>::Callback callback) {
+  typedef typename PhantomCallbackData<void, void, void>::Callback Callback;
+  V8::MakePhantom(reinterpret_cast<internal::Object**>(this->val_), parameter,
+                  internal_field_index1, internal_field_index2,
+                  reinterpret_cast<Callback>(callback));
 }
 
 
index fc528b6..51cd6c8 100644 (file)
@@ -408,18 +408,22 @@ void V8::MakeWeak(i::Object** object, void* parameter,
 }
 
 
-void V8::MakePhantom(i::Object** object, void* parameter,
-                     PhantomCallbackData<void>::Callback weak_callback) {
-  i::GlobalHandles::MakePhantom(object, parameter, weak_callback);
-}
-
-
 void V8::MakePhantom(
-    i::Object** object,
-    InternalFieldsCallbackData<void, void>::Callback weak_callback,
-    int internal_field_index1, int internal_field_index2) {
-  i::GlobalHandles::MakePhantom(object, weak_callback, internal_field_index1,
-                                internal_field_index2);
+    i::Object** object, void* parameter, int internal_field_index1,
+    int internal_field_index2,
+    PhantomCallbackData<void, void, void>::Callback weak_callback) {
+  if (internal_field_index1 == 0) {
+    if (internal_field_index2 == 1) {
+      i::GlobalHandles::MakePhantom(object, parameter, 2, weak_callback);
+    } else {
+      DCHECK_EQ(internal_field_index2, Object::kNoInternalFieldIndex);
+      i::GlobalHandles::MakePhantom(object, parameter, 1, weak_callback);
+    }
+  } else {
+    DCHECK_EQ(internal_field_index1, Object::kNoInternalFieldIndex);
+    DCHECK_EQ(internal_field_index2, Object::kNoInternalFieldIndex);
+    i::GlobalHandles::MakePhantom(object, parameter, 0, weak_callback);
+  }
 }
 
 
index 93ef1cf..e3cadda 100644 (file)
@@ -716,7 +716,7 @@ DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
   debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info));
   typedef PhantomCallbackData<void>::Callback Callback;
   GlobalHandles::MakePhantom(
-      reinterpret_cast<Object**>(debug_info_.location()), this,
+      reinterpret_cast<Object**>(debug_info_.location()), this, 0,
       reinterpret_cast<Callback>(Debug::HandlePhantomDebugInfo));
 }
 
index 4f744d6..d717c48 100644 (file)
@@ -203,7 +203,6 @@ class GlobalHandles::Node {
   // Callback parameter accessors.
   void set_parameter(void* parameter) {
     DCHECK(IsInUse());
-    DCHECK(weakness_type() == NORMAL_WEAK || weakness_type() == PHANTOM_WEAK);
     parameter_or_next_free_.parameter = parameter;
   }
   void* parameter() const {
@@ -211,30 +210,6 @@ class GlobalHandles::Node {
     return parameter_or_next_free_.parameter;
   }
 
-  void set_internal_fields(int internal_field_index1,
-                           int internal_field_index2) {
-    DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK);
-    // These are stored in an int16_t.
-    DCHECK(internal_field_index1 < 1 << 16);
-    DCHECK(internal_field_index1 >= -(1 << 16));
-    DCHECK(internal_field_index2 < 1 << 16);
-    DCHECK(internal_field_index2 >= -(1 << 16));
-    parameter_or_next_free_.internal_field_indeces.internal_field1 =
-        static_cast<int16_t>(internal_field_index1);
-    parameter_or_next_free_.internal_field_indeces.internal_field2 =
-        static_cast<int16_t>(internal_field_index2);
-  }
-
-  int internal_field1() const {
-    DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK);
-    return parameter_or_next_free_.internal_field_indeces.internal_field1;
-  }
-
-  int internal_field2() const {
-    DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK);
-    return parameter_or_next_free_.internal_field_indeces.internal_field2;
-  }
-
   // Accessors for next free node in the free list.
   Node* next_free() {
     DCHECK(state() == FREE);
@@ -255,23 +230,22 @@ class GlobalHandles::Node {
     weak_callback_ = weak_callback;
   }
 
-  void MakePhantom(void* parameter,
-                   PhantomCallbackData<void>::Callback phantom_callback,
-                   int16_t internal_field_index1,
-                   int16_t internal_field_index2) {
+  void MakePhantom(void* parameter, int number_of_internal_fields,
+                   PhantomCallbackData<void>::Callback phantom_callback) {
+    DCHECK(number_of_internal_fields >= 0);
+    DCHECK(number_of_internal_fields <= 2);
     DCHECK(phantom_callback != NULL);
     DCHECK(IsInUse());
     CHECK(object_ != NULL);
     set_state(WEAK);
-    if (parameter == NULL) {
-      set_weakness_type(INTERNAL_FIELDS_WEAK);
-      set_internal_fields(internal_field_index1, internal_field_index2);
+    if (number_of_internal_fields == 0) {
+      set_weakness_type(PHANTOM_WEAK_0_INTERNAL_FIELDS);
+    } else if (number_of_internal_fields == 1) {
+      set_weakness_type(PHANTOM_WEAK_1_INTERNAL_FIELDS);
     } else {
-      DCHECK(internal_field_index1 == v8::Object::kNoInternalFieldIndex);
-      DCHECK(internal_field_index2 == v8::Object::kNoInternalFieldIndex);
-      set_weakness_type(PHANTOM_WEAK);
-      set_parameter(parameter);
+      set_weakness_type(PHANTOM_WEAK_2_INTERNAL_FIELDS);
     }
+    set_parameter(parameter);
     weak_callback_ = reinterpret_cast<WeakCallback>(phantom_callback);
   }
 
@@ -284,63 +258,51 @@ class GlobalHandles::Node {
   }
 
   void CollectPhantomCallbackData(
-      Isolate* isolate, List<PendingPhantomCallback>* pending_phantom_callbacks,
-      List<PendingInternalFieldsCallback>* pending_internal_fields_callbacks) {
-    if (state() != Node::PENDING) return;
-    bool do_release = true;
+      Isolate* isolate,
+      List<PendingPhantomCallback>* pending_phantom_callbacks) {
+    if (state() != PENDING) return;
     if (weak_callback_ != NULL) {
       if (weakness_type() == NORMAL_WEAK) return;
 
       v8::Isolate* api_isolate = reinterpret_cast<v8::Isolate*>(isolate);
 
-      if (weakness_type() == PHANTOM_WEAK) {
-        // Phantom weak pointer case. Zap with harmless value.
-        DCHECK(*location() == Smi::FromInt(0));
-        typedef PhantomCallbackData<void> Data;
+      DCHECK(weakness_type() == PHANTOM_WEAK_0_INTERNAL_FIELDS ||
+             weakness_type() == PHANTOM_WEAK_1_INTERNAL_FIELDS ||
+             weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS);
 
-        Data data(api_isolate, parameter());
-        Data::Callback callback =
-            reinterpret_cast<Data::Callback>(weak_callback_);
-
-        pending_phantom_callbacks->Add(
-            PendingPhantomCallback(this, data, callback));
-
-        // Postpone the release of the handle. The embedder can't use the
-        // handle (it's zapped), but it may be using the location, and we
-        // don't want to confuse things by reusing that.
-        do_release = false;
-      } else {
-        DCHECK(weakness_type() == INTERNAL_FIELDS_WEAK);
-        typedef InternalFieldsCallbackData<void, void> Data;
-
-        // Phantom weak pointer case, passing internal fields instead of
-        // parameter. Don't use a handle here during GC, because it will
-        // create a handle pointing to a dying object, which can confuse
-        // the next GC.
+      Object* internal_field0 = nullptr;
+      Object* internal_field1 = nullptr;
+      if (weakness_type() != PHANTOM_WEAK_0_INTERNAL_FIELDS) {
         JSObject* jsobject = reinterpret_cast<JSObject*>(object());
         DCHECK(jsobject->IsJSObject());
-        Data data(api_isolate, jsobject->GetInternalField(internal_field1()),
-                  jsobject->GetInternalField(internal_field2()));
-        Data::Callback callback =
-            reinterpret_cast<Data::Callback>(weak_callback_);
-
-        // In the future, we want to delay the callback. In that case we will
-        // zap when we queue up, to stop the C++ side accessing the dead V8
-        // object, but we will call Release only after the callback (allowing
-        // the node to be reused).
-        pending_internal_fields_callbacks->Add(
-            PendingInternalFieldsCallback(data, callback));
+        DCHECK(jsobject->GetInternalFieldCount() >= 1);
+        internal_field0 = jsobject->GetInternalField(0);
+        if (weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS) {
+          DCHECK(jsobject->GetInternalFieldCount() >= 2);
+          internal_field1 = jsobject->GetInternalField(1);
+        }
       }
+
+      // Zap with harmless value.
+      *location() = Smi::FromInt(0);
+      typedef PhantomCallbackData<void, void, void> Data;
+
+      if (!internal_field0->IsSmi()) internal_field0 = nullptr;
+      if (!internal_field1->IsSmi()) internal_field1 = nullptr;
+
+      Data data(api_isolate, parameter(), internal_field0, internal_field1);
+      Data::Callback callback =
+          reinterpret_cast<Data::Callback>(weak_callback_);
+
+      pending_phantom_callbacks->Add(
+          PendingPhantomCallback(this, data, callback));
+      DCHECK(IsInUse());
+      set_state(NEAR_DEATH);
     }
-    // TODO(erikcorry): At the moment the callbacks are not postponed much,
-    // but if we really postpone them until after the mutator has run, we
-    // need to divide things up, so that an early callback clears the handle,
-    // while a later one destroys the objects involved, possibley triggering
-    // some work when decremented ref counts hit zero.
-    if (do_release) Release();
   }
 
   bool PostGarbageCollectionProcessing(Isolate* isolate) {
+    // Handles only weak handles (not phantom) that are dying.
     if (state() != Node::PENDING) return false;
     if (weak_callback_ == NULL) {
       Release();
@@ -354,11 +316,11 @@ class GlobalHandles::Node {
            ExternalOneByteString::cast(object_)->resource() != NULL);
     DCHECK(!object_->IsExternalTwoByteString() ||
            ExternalTwoByteString::cast(object_)->resource() != NULL);
+    if (weakness_type() != NORMAL_WEAK) return false;
+
     // Leaving V8.
     VMState<EXTERNAL> vmstate(isolate);
     HandleScope handle_scope(isolate);
-    if (weakness_type() == PHANTOM_WEAK) return false;
-    DCHECK(weakness_type() == NORMAL_WEAK);
     Object** object = location();
     Handle<Object> handle(*object, isolate);
     v8::WeakCallbackData<v8::Value, void> data(
@@ -410,10 +372,6 @@ class GlobalHandles::Node {
   // the free list link.
   union {
     void* parameter;
-    struct {
-      int16_t internal_field1;
-      int16_t internal_field2;
-    } internal_field_indeces;
     Node* next_free;
   } parameter_or_next_free_;
 
@@ -604,32 +562,21 @@ void GlobalHandles::MakeWeak(Object** location, void* parameter,
 }
 
 
-typedef PhantomCallbackData<void>::Callback GenericCallback;
-
-
-void GlobalHandles::MakePhantom(
-    Object** location,
-    v8::InternalFieldsCallbackData<void, void>::Callback phantom_callback,
-    int16_t internal_field_index1, int16_t internal_field_index2) {
-  Node::FromLocation(location)
-      ->MakePhantom(NULL, reinterpret_cast<GenericCallback>(phantom_callback),
-                    internal_field_index1, internal_field_index2);
-}
+typedef PhantomCallbackData<void, void, void>::Callback GenericCallback;
 
 
 void GlobalHandles::MakePhantom(Object** location, void* parameter,
+                                int number_of_internal_fields,
                                 GenericCallback phantom_callback) {
-  Node::FromLocation(location)->MakePhantom(parameter, phantom_callback,
-                                            v8::Object::kNoInternalFieldIndex,
-                                            v8::Object::kNoInternalFieldIndex);
+  Node::FromLocation(location)
+      ->MakePhantom(parameter, number_of_internal_fields, phantom_callback);
 }
 
 
 void GlobalHandles::CollectPhantomCallbackData() {
   for (NodeIterator it(this); !it.done(); it.Advance()) {
     Node* node = it.node();
-    node->CollectPhantomCallbackData(isolate(), &pending_phantom_callbacks_,
-                                     &pending_internal_fields_callbacks_);
+    node->CollectPhantomCallbackData(isolate(), &pending_phantom_callbacks_);
   }
 }
 
@@ -668,22 +615,22 @@ void GlobalHandles::IterateWeakRoots(ObjectVisitor* v) {
   for (NodeIterator it(this); !it.done(); it.Advance()) {
     Node* node = it.node();
     if (node->IsWeakRetainer()) {
-      // Weakness type can be normal, phantom or internal fields.
-      // For normal weakness we mark through the handle so that
-      // the object and things reachable from it are available
-      // to the callback.
-      // In the case of phantom we can zap the object handle now
-      // and we won't need it, so we don't need to mark through it.
+      // Weakness type can be normal or phantom, with or without internal
+      // fields).  For normal weakness we mark through the handle so that the
+      // object and things reachable from it are available to the callback.
+      //
+      // In the case of phantom with no internal fields, we can zap the object
+      // handle now and we won't need it, so we don't need to mark through it.
       // In the internal fields case we will need the internal
-      // fields, so we can't zap the handle, but we don't need to
-      // mark through it, because it will die in this GC round.
+      // fields, so we can't zap the handle.
       if (node->state() == Node::PENDING) {
-        if (node->weakness_type() == PHANTOM_WEAK) {
+        if (node->weakness_type() == PHANTOM_WEAK_0_INTERNAL_FIELDS) {
           *(node->location()) = Smi::FromInt(0);
         } else if (node->weakness_type() == NORMAL_WEAK) {
           v->VisitPointer(node->location());
         } else {
-          DCHECK(node->weakness_type() == INTERNAL_FIELDS_WEAK);
+          DCHECK(node->weakness_type() == PHANTOM_WEAK_1_INTERNAL_FIELDS ||
+                 node->weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS);
         }
       } else {
         // Node is not pending, so that means the object survived.  We still
@@ -736,12 +683,13 @@ void GlobalHandles::IterateNewSpaceWeakIndependentRoots(ObjectVisitor* v) {
     DCHECK(node->is_in_new_space_list());
     if ((node->is_independent() || node->is_partially_dependent()) &&
         node->IsWeakRetainer()) {
-      if (node->weakness_type() == PHANTOM_WEAK) {
+      if (node->weakness_type() == PHANTOM_WEAK_0_INTERNAL_FIELDS) {
         *(node->location()) = Smi::FromInt(0);
       } else if (node->weakness_type() == NORMAL_WEAK) {
         v->VisitPointer(node->location());
       } else {
-        DCHECK(node->weakness_type() == INTERNAL_FIELDS_WEAK);
+        DCHECK(node->weakness_type() == PHANTOM_WEAK_1_INTERNAL_FIELDS ||
+               node->weakness_type() == PHANTOM_WEAK_2_INTERNAL_FIELDS);
         // For this case we only need to trace if it's alive: The tracing of
         // something that is already alive is just to get the pointer updated
         // to the new location of the object).
@@ -886,13 +834,9 @@ int GlobalHandles::DispatchPendingPhantomCallbacks() {
   int freed_nodes = 0;
   while (pending_phantom_callbacks_.length() != 0) {
     PendingPhantomCallback callback = pending_phantom_callbacks_.RemoveLast();
+    DCHECK(callback.node()->IsInUse());
     callback.invoke();
-    freed_nodes++;
-  }
-  while (pending_internal_fields_callbacks_.length() != 0) {
-    PendingInternalFieldsCallback callback =
-        pending_internal_fields_callbacks_.RemoveLast();
-    callback.invoke();
+    DCHECK(!callback.node()->IsInUse());
     freed_nodes++;
   }
   return freed_nodes;
index b3756d0..fe9ed5a 100644 (file)
@@ -98,9 +98,15 @@ struct ObjectGroupRetainerInfo {
 
 
 enum WeaknessType {
-  NORMAL_WEAK,          // Embedder gets a handle to the dying object.
-  PHANTOM_WEAK,         // Embedder gets the parameter they passed in earlier.
-  INTERNAL_FIELDS_WEAK  // Embedder gets 2 internal fields from dying object.
+  NORMAL_WEAK,  // Embedder gets a handle to the dying object.
+  // In the following cases, the embedder gets the parameter they passed in
+  // earlier, and the 0, 1 or 2 first internal fields. Note that the internal
+  // fields must contain aligned non-V8 pointers.  Getting pointers to V8
+  // objects through this interface would be GC unsafe so in that case the
+  // embedder gets a null pointer instead.
+  PHANTOM_WEAK_0_INTERNAL_FIELDS,
+  PHANTOM_WEAK_1_INTERNAL_FIELDS,
+  PHANTOM_WEAK_2_INTERNAL_FIELDS
 };
 
 
@@ -139,14 +145,9 @@ class GlobalHandles {
 
   // It would be nice to template this one, but it's really hard to get
   // the template instantiator to work right if you do.
-  static void MakePhantom(Object** location, void* parameter,
-                          PhantomCallbackData<void>::Callback weak_callback);
-
   static void MakePhantom(
-      Object** location,
-      v8::InternalFieldsCallbackData<void, void>::Callback weak_callback,
-      int16_t internal_field_index1,
-      int16_t internal_field_index2 = v8::Object::kNoInternalFieldIndex);
+      Object** location, void* parameter, int number_of_internal_fields,
+      PhantomCallbackData<void, void, void>::Callback weak_callback);
 
   void RecordStats(HeapStats* stats);
 
@@ -302,7 +303,6 @@ class GlobalHandles {
   class NodeBlock;
   class NodeIterator;
   class PendingPhantomCallback;
-  class PendingInternalFieldsCallback;
 
   Isolate* isolate_;
 
@@ -336,7 +336,6 @@ class GlobalHandles {
   List<ObjectGroupConnection> implicit_ref_connections_;
 
   List<PendingPhantomCallback> pending_phantom_callbacks_;
-  List<PendingInternalFieldsCallback> pending_internal_fields_callbacks_;
 
   friend class Isolate;
 
@@ -346,7 +345,7 @@ class GlobalHandles {
 
 class GlobalHandles::PendingPhantomCallback {
  public:
-  typedef PhantomCallbackData<void> Data;
+  typedef PhantomCallbackData<void, void, void> Data;
   PendingPhantomCallback(Node* node, Data data, Data::Callback callback)
       : node_(node), data_(data), callback_(callback) {}
 
@@ -361,20 +360,6 @@ class GlobalHandles::PendingPhantomCallback {
 };
 
 
-class GlobalHandles::PendingInternalFieldsCallback {
- public:
-  typedef InternalFieldsCallbackData<void, void> Data;
-  PendingInternalFieldsCallback(Data data, Data::Callback callback)
-      : data_(data), callback_(callback) {}
-
-  void invoke() { callback_(data_); }
-
- private:
-  Data data_;
-  Data::Callback callback_;
-};
-
-
 class EternalHandles {
  public:
   enum SingletonHandle {
index d18059c..e62b0ed 100644 (file)
@@ -7796,8 +7796,10 @@ class Trivial2 {
 };
 
 
-void CheckInternalFields(
-    const v8::InternalFieldsCallbackData<Trivial, Trivial2>& data) {
+void CheckInternalFields(const v8::PhantomCallbackData<
+    v8::Persistent<v8::Object>, Trivial, Trivial2>& data) {
+  v8::Persistent<v8::Object>* handle = data.GetParameter();
+  handle->Reset();
   Trivial* t1 = data.GetInternalField1();
   Trivial2* t2 = data.GetInternalField2();
   CHECK_EQ(42, t1->x());
@@ -7835,7 +7837,8 @@ void InternalFieldCallback(bool global_gc) {
         reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
     CHECK_EQ(103, t2->x());
 
-    handle.SetPhantom(CheckInternalFields, 0, 1);
+    handle.SetPhantom<v8::Persistent<v8::Object>, Trivial, Trivial2>(
+        &handle, 0, 1, CheckInternalFields);
     if (!global_gc) {
       handle.MarkIndependent();
     }