From: dcarney@chromium.org Date: Mon, 26 Aug 2013 09:41:22 +0000 (+0000) Subject: abstract eternal into class X-Git-Tag: upstream/4.7.83~12844 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b1bc71a51030c26f4ab1e3d6d5aee3975647c47b;p=platform%2Fupstream%2Fv8.git abstract eternal into class 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 --- diff --git a/include/v8.h b/include/v8.h index 93b55dd..7de714f 100644 --- a/include/v8.h +++ b/include/v8.h @@ -120,6 +120,7 @@ class Utils; class Value; template class Handle; template class Local; +template class Eternal; template class Persistent; class FunctionTemplate; class ObjectTemplate; @@ -370,11 +371,6 @@ template 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 Local : public Handle { return Local::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 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 Local : public Handle { private: friend class Utils; + template friend class Eternal; template friend class Persistent; template friend class Handle; friend class Arguments; @@ -460,6 +452,28 @@ template class Local : public Handle { V8_INLINE(static Local New(Isolate* isolate, T* that)); }; + +// Eternal handles are set-once handles that live for the life of the isolate. +template class Eternal { + public: + V8_INLINE(Eternal()) : index_(kInitialValue) { } + template + V8_INLINE(Eternal(Isolate* isolate, Local handle)) + : index_(kInitialValue) { + Set(isolate, handle); + } + // Can only be safely called if already set. + V8_INLINE(Local Get(Isolate* isolate)); + V8_INLINE(bool IsEmpty()) { return index_ != kInitialValue; } + template + V8_INLINE(void Set(Isolate* isolate, Local 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 GetEternal(Isolate* isolate, int index); template friend class Handle; template friend class Local; + template friend class Eternal; template friend class Persistent; friend class Context; }; @@ -5655,17 +5671,16 @@ Local Local::New(Isolate* isolate, T* that) { template -int Local::Eternalize(Isolate* isolate) { - return V8::Eternalize(reinterpret_cast(isolate), - reinterpret_cast(this->val_)); +template +void Eternal::Set(Isolate* isolate, Local handle) { + TYPE_CHECK(T, S); + V8::Eternalize(isolate, Value::Cast(*handle), &this->index_); } template -Local Local::GetEternal(Isolate* isolate, int index) { - internal::Object** handle = - V8::GetEternal(reinterpret_cast(isolate), index); - return Local(T::Cast(reinterpret_cast(handle))); +Local Eternal::Get(Isolate* isolate) { + return Local::Cast(V8::GetEternal(isolate, index_)); } diff --git a/src/api.cc b/src/api.cc index 0eb139f..d027d7a 100644 --- a/src/api.cc +++ b/src/api.cc @@ -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(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 V8::GetEternal(Isolate* v8_isolate, int index) { + i::Isolate* isolate = reinterpret_cast(v8_isolate); + return Utils::ToLocal(isolate->eternal_handles()->Get(index)); } diff --git a/src/global-handles.cc b/src/global-handles.cc index 5df9dd4..5632c7c 100644 --- a/src/global-handles.cc +++ b/src/global-handles.cc @@ -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_++; } diff --git a/src/global-handles.h b/src/global-handles.h index 5a4ad13..57cf70e 100644 --- a/src/global-handles.h +++ b/src/global-handles.h @@ -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 Get(int index) { @@ -369,8 +369,7 @@ class EternalHandles { Handle 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]); } diff --git a/test/cctest/test-global-handles.cc b/test/cctest/test-global-handles.cc index 0b652db..c2e5ae7 100644 --- a/test/cctest/test-global-handles.cc +++ b/test/cctest/test-global-handles.cc @@ -321,24 +321,25 @@ TEST(EternalHandles) { CcTest::InitializeVM(); Isolate* isolate = Isolate::Current(); v8::Isolate* v8_isolate = reinterpret_cast(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 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 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 object; + v8::Local local; if (j == 0) { // Test internal api - v8::Local local = - v8::Utils::ToLocal(eternals->Get(indices[i])); - object = v8::Handle::Cast(local); + local = v8::Utils::ToLocal(eternal_handles->Get(indices[i])); } else { // Test external api - object = v8::Local::GetEternal(v8_isolate, indices[i]); + local = eternals[i].Get(v8_isolate); } + v8::Local object = v8::Handle::Cast(local); v8::Local 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 object = v8::Object::New(); + v8::Eternal eternal(v8_isolate, object); + CHECK(eternal.IsEmpty()); + CHECK(object == eternal.Get(v8_isolate)); + } + + CHECK_EQ(2*kArrayLength + 1, eternal_handles->NumberOfHandles()); }