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;
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_));
}
......
......@@ -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));
}
......
......@@ -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_++;
}
......
......@@ -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]);
}
......
......@@ -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());
}
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