abstract eternal into class
authordcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 26 Aug 2013 09:41:22 +0000 (09:41 +0000)
committerdcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 26 Aug 2013 09:41:22 +0000 (09:41 +0000)
R=rossberg@chromium.org, svenpanne@chromium.org
BUG=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16316 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

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

index 93b55dd..7de714f 100644 (file)
@@ -120,6 +120,7 @@ class Utils;
 class Value;
 template <class T> class Handle;
 template <class T> class Local;
+template <class T> class Eternal;
 template <class T> class Persistent;
 class FunctionTemplate;
 class ObjectTemplate;
@@ -370,11 +371,6 @@ template <class T> class Handle {
 };
 
 
-// A value which will never be returned by Local::Eternalize
-// Useful for static initialization
-const int kUninitializedEternalIndex = -1;
-
-
 /**
  * A light-weight stack-allocated object handle.  All operations
  * that return objects from within v8 return them in local handles.  They
@@ -420,11 +416,6 @@ template <class T> class Local : public Handle<T> {
     return Local<S>::Cast(*this);
   }
 
-  // Keep this Local alive for the lifetime of the Isolate.
-  // It remains retrievable via the returned index,
-  V8_INLINE(int Eternalize(Isolate* isolate));
-  V8_INLINE(static Local<T> GetEternal(Isolate* isolate, int index));
-
   /**
    * Create a local handle for the content of another handle.
    * The referee is kept alive by the local handle even when
@@ -445,6 +436,7 @@ template <class T> class Local : public Handle<T> {
 
  private:
   friend class Utils;
+  template<class F> friend class Eternal;
   template<class F> friend class Persistent;
   template<class F> friend class Handle;
   friend class Arguments;
@@ -460,6 +452,28 @@ template <class T> class Local : public Handle<T> {
   V8_INLINE(static Local<T> New(Isolate* isolate, T* that));
 };
 
+
+// Eternal handles are set-once handles that live for the life of the isolate.
+template <class T> class Eternal {
+ public:
+  V8_INLINE(Eternal()) : index_(kInitialValue) { }
+  template<class S>
+  V8_INLINE(Eternal(Isolate* isolate, Local<S> handle))
+      : index_(kInitialValue) {
+    Set(isolate, handle);
+  }
+  // Can only be safely called if already set.
+  V8_INLINE(Local<T> Get(Isolate* isolate));
+  V8_INLINE(bool IsEmpty()) { return index_ != kInitialValue; }
+  template<class S>
+  V8_INLINE(void Set(Isolate* isolate, Local<S> handle));
+
+ private:
+  static const int kInitialValue = -1;
+  int index_;
+};
+
+
 /**
  * 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
@@ -4788,12 +4802,14 @@ class V8_EXPORT V8 {
                        void* data,
                        RevivableCallback weak_reference_callback);
   static void ClearWeak(internal::Object** global_handle);
-  static int Eternalize(internal::Isolate* isolate,
-                        internal::Object** handle);
-  static internal::Object** GetEternal(internal::Isolate* isolate, int index);
+  static void Eternalize(Isolate* isolate,
+                         Value* handle,
+                         int* index);
+  static Local<Value> GetEternal(Isolate* isolate, int index);
 
   template <class T> friend class Handle;
   template <class T> friend class Local;
+  template <class T> friend class Eternal;
   template <class T> friend class Persistent;
   friend class Context;
 };
@@ -5655,17 +5671,16 @@ Local<T> Local<T>::New(Isolate* isolate, T* that) {
 
 
 template<class T>
-int Local<T>::Eternalize(Isolate* isolate) {
-  return V8::Eternalize(reinterpret_cast<internal::Isolate*>(isolate),
-                        reinterpret_cast<internal::Object**>(this->val_));
+template<class S>
+void Eternal<T>::Set(Isolate* isolate, Local<S> handle) {
+  TYPE_CHECK(T, S);
+  V8::Eternalize(isolate, Value::Cast(*handle), &this->index_);
 }
 
 
 template<class T>
-Local<T> Local<T>::GetEternal(Isolate* isolate, int index) {
-  internal::Object** handle =
-      V8::GetEternal(reinterpret_cast<internal::Isolate*>(isolate), index);
-  return Local<T>(T::Cast(reinterpret_cast<Value*>(handle)));
+Local<T> Eternal<T>::Get(Isolate* isolate) {
+  return Local<T>::Cast(V8::GetEternal(isolate, index_));
 }
 
 
index 0eb139f..d027d7a 100644 (file)
@@ -653,13 +653,16 @@ void V8::DisposeGlobal(i::Object** obj) {
 }
 
 
-int V8::Eternalize(i::Isolate* isolate, i::Object** handle) {
-  return isolate->eternal_handles()->Create(isolate, *handle);
+void V8::Eternalize(Isolate* v8_isolate, Value* value, int* index) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+  i::Object* object = *Utils::OpenHandle(value);
+  isolate->eternal_handles()->Create(isolate, object, index);
 }
 
 
-i::Object** V8::GetEternal(i::Isolate* isolate, int index) {
-  return isolate->eternal_handles()->Get(index).location();
+Local<Value> V8::GetEternal(Isolate* v8_isolate, int index) {
+  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
+  return Utils::ToLocal(isolate->eternal_handles()->Get(index));
 }
 
 
index 5df9dd4..5632c7c 100644 (file)
@@ -1020,7 +1020,6 @@ void GlobalHandles::ComputeObjectGroupsAndImplicitReferences() {
 
 
 EternalHandles::EternalHandles() : size_(0) {
-  STATIC_ASSERT(v8::kUninitializedEternalIndex == kInvalidIndex);
   for (unsigned i = 0; i < ARRAY_SIZE(singleton_handles_); i++) {
     singleton_handles_[i] = kInvalidIndex;
   }
@@ -1062,8 +1061,9 @@ void EternalHandles::PostGarbageCollectionProcessing(Heap* heap) {
 }
 
 
-int EternalHandles::Create(Isolate* isolate, Object* object) {
-  if (object == NULL) return kInvalidIndex;
+void EternalHandles::Create(Isolate* isolate, Object* object, int* index) {
+  ASSERT_EQ(kInvalidIndex, *index);
+  if (object == NULL) return;
   ASSERT_NE(isolate->heap()->the_hole_value(), object);
   int block = size_ >> kShift;
   int offset = size_ & kMask;
@@ -1079,7 +1079,7 @@ int EternalHandles::Create(Isolate* isolate, Object* object) {
   if (isolate->heap()->InNewSpace(object)) {
     new_space_indices_.Add(size_);
   }
-  return size_++;
+  *index = size_++;
 }
 
 
index 5a4ad13..57cf70e 100644 (file)
@@ -346,8 +346,8 @@ class EternalHandles {
 
   int NumberOfHandles() { return size_; }
 
-  // Create an EternalHandle, returning the index.
-  int Create(Isolate* isolate, Object* object);
+  // Create an EternalHandle, overwriting the index.
+  void Create(Isolate* isolate, Object* object, int* index);
 
   // Grab the handle for an existing EternalHandle.
   inline Handle<Object> Get(int index) {
@@ -369,8 +369,7 @@ class EternalHandles {
   Handle<Object> CreateSingleton(Isolate* isolate,
                                  Object* object,
                                  SingletonHandle singleton) {
-    ASSERT(singleton_handles_[singleton] == kInvalidIndex);
-    singleton_handles_[singleton] = Create(isolate, object);
+    Create(isolate, object, &singleton_handles_[singleton]);
     return Get(singleton_handles_[singleton]);
   }
 
index 0b652db..c2e5ae7 100644 (file)
@@ -321,24 +321,25 @@ TEST(EternalHandles) {
   CcTest::InitializeVM();
   Isolate* isolate = Isolate::Current();
   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
-  EternalHandles* eternals = isolate->eternal_handles();
+  EternalHandles* eternal_handles = isolate->eternal_handles();
 
   // Create a number of handles that will not be on a block boundary
   const int kArrayLength = 2048-1;
   int indices[kArrayLength];
+  v8::Eternal<v8::Value> eternals[kArrayLength];
 
-  CHECK_EQ(0, eternals->NumberOfHandles());
+  CHECK_EQ(0, eternal_handles->NumberOfHandles());
   for (int i = 0; i < kArrayLength; i++) {
     HandleScope scope(isolate);
     v8::Local<v8::Object> object = v8::Object::New();
     object->Set(i, v8::Integer::New(i, v8_isolate));
-    if (i % 2 == 0) {
-      // Create with internal api
-      indices[i] = eternals->Create(isolate, *v8::Utils::OpenHandle(*object));
-    } else {
-      // Create with external api
-      indices[i] = object.Eternalize(v8_isolate);
-    }
+    // Create with internal api
+    eternal_handles->Create(
+        isolate, *v8::Utils::OpenHandle(*object), &indices[i]);
+    // Create with external api
+    CHECK(!eternals[i].IsEmpty());
+    eternals[i].Set(v8_isolate, object);
+    CHECK(eternals[i].IsEmpty());
   }
 
   isolate->heap()->CollectAllAvailableGarbage();
@@ -346,21 +347,31 @@ TEST(EternalHandles) {
   for (int i = 0; i < kArrayLength; i++) {
     for (int j = 0; j < 2; j++) {
       HandleScope scope(isolate);
-      v8::Local<v8::Object> object;
+      v8::Local<v8::Value> local;
       if (j == 0) {
         // Test internal api
-        v8::Local<v8::Value> local =
-            v8::Utils::ToLocal(eternals->Get(indices[i]));
-        object = v8::Handle<v8::Object>::Cast(local);
+        local = v8::Utils::ToLocal(eternal_handles->Get(indices[i]));
       } else {
         // Test external api
-        object = v8::Local<v8::Object>::GetEternal(v8_isolate, indices[i]);
+        local = eternals[i].Get(v8_isolate);
       }
+      v8::Local<v8::Object> object = v8::Handle<v8::Object>::Cast(local);
       v8::Local<v8::Value> value = object->Get(i);
       CHECK(value->IsInt32());
       CHECK_EQ(i, value->Int32Value());
     }
   }
 
-  CHECK_EQ(kArrayLength, eternals->NumberOfHandles());
+  CHECK_EQ(2*kArrayLength, eternal_handles->NumberOfHandles());
+
+  // Create an eternal via the constructor
+  {
+    HandleScope scope(isolate);
+    v8::Local<v8::Object> object = v8::Object::New();
+    v8::Eternal<v8::Object> eternal(v8_isolate, object);
+    CHECK(eternal.IsEmpty());
+    CHECK(object == eternal.Get(v8_isolate));
+  }
+
+  CHECK_EQ(2*kArrayLength + 1, eternal_handles->NumberOfHandles());
 }