Commit b1bc71a5 authored by dcarney@chromium.org's avatar dcarney@chromium.org

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
parent 5768fcf1
...@@ -120,6 +120,7 @@ class Utils; ...@@ -120,6 +120,7 @@ class Utils;
class Value; class Value;
template <class T> class Handle; template <class T> class Handle;
template <class T> class Local; template <class T> class Local;
template <class T> class Eternal;
template <class T> class Persistent; template <class T> class Persistent;
class FunctionTemplate; class FunctionTemplate;
class ObjectTemplate; class ObjectTemplate;
...@@ -370,11 +371,6 @@ template <class T> class Handle { ...@@ -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 * A light-weight stack-allocated object handle. All operations
* that return objects from within v8 return them in local handles. They * that return objects from within v8 return them in local handles. They
...@@ -420,11 +416,6 @@ template <class T> class Local : public Handle<T> { ...@@ -420,11 +416,6 @@ template <class T> class Local : public Handle<T> {
return Local<S>::Cast(*this); 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. * Create a local handle for the content of another handle.
* The referee is kept alive by the local handle even when * The referee is kept alive by the local handle even when
...@@ -445,6 +436,7 @@ template <class T> class Local : public Handle<T> { ...@@ -445,6 +436,7 @@ template <class T> class Local : public Handle<T> {
private: private:
friend class Utils; friend class Utils;
template<class F> friend class Eternal;
template<class F> friend class Persistent; template<class F> friend class Persistent;
template<class F> friend class Handle; template<class F> friend class Handle;
friend class Arguments; friend class Arguments;
...@@ -460,6 +452,28 @@ template <class T> class Local : public Handle<T> { ...@@ -460,6 +452,28 @@ template <class T> class Local : public Handle<T> {
V8_INLINE(static Local<T> New(Isolate* isolate, T* that)); 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 * 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 * a Local handle only lives as long as the HandleScope in which it was
...@@ -4788,12 +4802,14 @@ class V8_EXPORT V8 { ...@@ -4788,12 +4802,14 @@ class V8_EXPORT V8 {
void* data, void* data,
RevivableCallback weak_reference_callback); RevivableCallback weak_reference_callback);
static void ClearWeak(internal::Object** global_handle); static void ClearWeak(internal::Object** global_handle);
static int Eternalize(internal::Isolate* isolate, static void Eternalize(Isolate* isolate,
internal::Object** handle); Value* handle,
static internal::Object** GetEternal(internal::Isolate* isolate, int index); int* index);
static Local<Value> GetEternal(Isolate* isolate, int index);
template <class T> friend class Handle; template <class T> friend class Handle;
template <class T> friend class Local; template <class T> friend class Local;
template <class T> friend class Eternal;
template <class T> friend class Persistent; template <class T> friend class Persistent;
friend class Context; friend class Context;
}; };
...@@ -5655,17 +5671,16 @@ Local<T> Local<T>::New(Isolate* isolate, T* that) { ...@@ -5655,17 +5671,16 @@ Local<T> Local<T>::New(Isolate* isolate, T* that) {
template<class T> template<class T>
int Local<T>::Eternalize(Isolate* isolate) { template<class S>
return V8::Eternalize(reinterpret_cast<internal::Isolate*>(isolate), void Eternal<T>::Set(Isolate* isolate, Local<S> handle) {
reinterpret_cast<internal::Object**>(this->val_)); TYPE_CHECK(T, S);
V8::Eternalize(isolate, Value::Cast(*handle), &this->index_);
} }
template<class T> template<class T>
Local<T> Local<T>::GetEternal(Isolate* isolate, int index) { Local<T> Eternal<T>::Get(Isolate* isolate) {
internal::Object** handle = return Local<T>::Cast(V8::GetEternal(isolate, index_));
V8::GetEternal(reinterpret_cast<internal::Isolate*>(isolate), index);
return Local<T>(T::Cast(reinterpret_cast<Value*>(handle)));
} }
......
...@@ -653,13 +653,16 @@ void V8::DisposeGlobal(i::Object** obj) { ...@@ -653,13 +653,16 @@ void V8::DisposeGlobal(i::Object** obj) {
} }
int V8::Eternalize(i::Isolate* isolate, i::Object** handle) { void V8::Eternalize(Isolate* v8_isolate, Value* value, int* index) {
return isolate->eternal_handles()->Create(isolate, *handle); 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) { Local<Value> V8::GetEternal(Isolate* v8_isolate, int index) {
return isolate->eternal_handles()->Get(index).location(); i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
return Utils::ToLocal(isolate->eternal_handles()->Get(index));
} }
......
...@@ -1020,7 +1020,6 @@ void GlobalHandles::ComputeObjectGroupsAndImplicitReferences() { ...@@ -1020,7 +1020,6 @@ void GlobalHandles::ComputeObjectGroupsAndImplicitReferences() {
EternalHandles::EternalHandles() : size_(0) { EternalHandles::EternalHandles() : size_(0) {
STATIC_ASSERT(v8::kUninitializedEternalIndex == kInvalidIndex);
for (unsigned i = 0; i < ARRAY_SIZE(singleton_handles_); i++) { for (unsigned i = 0; i < ARRAY_SIZE(singleton_handles_); i++) {
singleton_handles_[i] = kInvalidIndex; singleton_handles_[i] = kInvalidIndex;
} }
...@@ -1062,8 +1061,9 @@ void EternalHandles::PostGarbageCollectionProcessing(Heap* heap) { ...@@ -1062,8 +1061,9 @@ void EternalHandles::PostGarbageCollectionProcessing(Heap* heap) {
} }
int EternalHandles::Create(Isolate* isolate, Object* object) { void EternalHandles::Create(Isolate* isolate, Object* object, int* index) {
if (object == NULL) return kInvalidIndex; ASSERT_EQ(kInvalidIndex, *index);
if (object == NULL) return;
ASSERT_NE(isolate->heap()->the_hole_value(), object); ASSERT_NE(isolate->heap()->the_hole_value(), object);
int block = size_ >> kShift; int block = size_ >> kShift;
int offset = size_ & kMask; int offset = size_ & kMask;
...@@ -1079,7 +1079,7 @@ int EternalHandles::Create(Isolate* isolate, Object* object) { ...@@ -1079,7 +1079,7 @@ int EternalHandles::Create(Isolate* isolate, Object* object) {
if (isolate->heap()->InNewSpace(object)) { if (isolate->heap()->InNewSpace(object)) {
new_space_indices_.Add(size_); new_space_indices_.Add(size_);
} }
return size_++; *index = size_++;
} }
......
...@@ -346,8 +346,8 @@ class EternalHandles { ...@@ -346,8 +346,8 @@ class EternalHandles {
int NumberOfHandles() { return size_; } int NumberOfHandles() { return size_; }
// Create an EternalHandle, returning the index. // Create an EternalHandle, overwriting the index.
int Create(Isolate* isolate, Object* object); void Create(Isolate* isolate, Object* object, int* index);
// Grab the handle for an existing EternalHandle. // Grab the handle for an existing EternalHandle.
inline Handle<Object> Get(int index) { inline Handle<Object> Get(int index) {
...@@ -369,8 +369,7 @@ class EternalHandles { ...@@ -369,8 +369,7 @@ class EternalHandles {
Handle<Object> CreateSingleton(Isolate* isolate, Handle<Object> CreateSingleton(Isolate* isolate,
Object* object, Object* object,
SingletonHandle singleton) { SingletonHandle singleton) {
ASSERT(singleton_handles_[singleton] == kInvalidIndex); Create(isolate, object, &singleton_handles_[singleton]);
singleton_handles_[singleton] = Create(isolate, object);
return Get(singleton_handles_[singleton]); return Get(singleton_handles_[singleton]);
} }
......
...@@ -321,24 +321,25 @@ TEST(EternalHandles) { ...@@ -321,24 +321,25 @@ TEST(EternalHandles) {
CcTest::InitializeVM(); CcTest::InitializeVM();
Isolate* isolate = Isolate::Current(); Isolate* isolate = Isolate::Current();
v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate); 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 // Create a number of handles that will not be on a block boundary
const int kArrayLength = 2048-1; const int kArrayLength = 2048-1;
int indices[kArrayLength]; 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++) { for (int i = 0; i < kArrayLength; i++) {
HandleScope scope(isolate); HandleScope scope(isolate);
v8::Local<v8::Object> object = v8::Object::New(); v8::Local<v8::Object> object = v8::Object::New();
object->Set(i, v8::Integer::New(i, v8_isolate)); object->Set(i, v8::Integer::New(i, v8_isolate));
if (i % 2 == 0) { // Create with internal api
// Create with internal api eternal_handles->Create(
indices[i] = eternals->Create(isolate, *v8::Utils::OpenHandle(*object)); isolate, *v8::Utils::OpenHandle(*object), &indices[i]);
} else { // Create with external api
// Create with external api CHECK(!eternals[i].IsEmpty());
indices[i] = object.Eternalize(v8_isolate); eternals[i].Set(v8_isolate, object);
} CHECK(eternals[i].IsEmpty());
} }
isolate->heap()->CollectAllAvailableGarbage(); isolate->heap()->CollectAllAvailableGarbage();
...@@ -346,21 +347,31 @@ TEST(EternalHandles) { ...@@ -346,21 +347,31 @@ TEST(EternalHandles) {
for (int i = 0; i < kArrayLength; i++) { for (int i = 0; i < kArrayLength; i++) {
for (int j = 0; j < 2; j++) { for (int j = 0; j < 2; j++) {
HandleScope scope(isolate); HandleScope scope(isolate);
v8::Local<v8::Object> object; v8::Local<v8::Value> local;
if (j == 0) { if (j == 0) {
// Test internal api // Test internal api
v8::Local<v8::Value> local = local = v8::Utils::ToLocal(eternal_handles->Get(indices[i]));
v8::Utils::ToLocal(eternals->Get(indices[i]));
object = v8::Handle<v8::Object>::Cast(local);
} else { } else {
// Test external api // 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); v8::Local<v8::Value> value = object->Get(i);
CHECK(value->IsInt32()); CHECK(value->IsInt32());
CHECK_EQ(i, value->Int32Value()); 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());
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment