Commit f039f334 authored by marja@chromium.org's avatar marja@chromium.org

Enable calling the SetReference* & SetObjectGroupId functions with a Persistent<SubclassOfValue>.

This is needed for https://codereview.chromium.org/26792002/

BUG=
R=svenpanne@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17253 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 8ef4b0ca
......@@ -712,6 +712,7 @@ template <class T, class M> class Persistent {
V8_INLINE T* operator*() const { return val_; }
private:
friend class Isolate;
friend class Utils;
template<class F> friend class Handle;
template<class F> friend class Local;
......@@ -4066,7 +4067,7 @@ class V8_EXPORT Isolate {
* garbage collection types it is sufficient to provide object groups
* for partially dependent handles only.
*/
void SetObjectGroupId(const Persistent<Value>& object,
template<typename T> void SetObjectGroupId(const Persistent<T>& object,
UniqueId id);
/**
......@@ -4076,8 +4077,8 @@ class V8_EXPORT Isolate {
* are removed. It is intended to be used in the before-garbage-collection
* callback function.
*/
void SetReferenceFromGroup(UniqueId id,
const Persistent<Value>& child);
template<typename T> void SetReferenceFromGroup(UniqueId id,
const Persistent<T>& child);
/**
* Allows the host application to declare implicit references from an object
......@@ -4085,8 +4086,8 @@ class V8_EXPORT Isolate {
* too. After each garbage collection, all implicit references are removed. It
* is intended to be used in the before-garbage-collection callback function.
*/
void SetReference(const Persistent<Object>& parent,
const Persistent<Value>& child);
template<typename T, typename S>
void SetReference(const Persistent<T>& parent, const Persistent<S>& child);
typedef void (*GCPrologueCallback)(Isolate* isolate,
GCType type,
......@@ -4140,8 +4141,11 @@ class V8_EXPORT Isolate {
Isolate& operator=(const Isolate&);
void* operator new(size_t size);
void operator delete(void*, size_t);
};
void SetObjectGroupId(internal::Object** object, UniqueId id);
void SetReferenceFromGroup(UniqueId id, internal::Object** object);
void SetReference(internal::Object** parent, internal::Object** child);
};
class V8_EXPORT StartupData {
public:
......@@ -6420,6 +6424,33 @@ void* Isolate::GetData() {
}
template<typename T>
void Isolate::SetObjectGroupId(const Persistent<T>& object,
UniqueId id) {
TYPE_CHECK(Value, T);
SetObjectGroupId(reinterpret_cast<v8::internal::Object**>(object.val_), id);
}
template<typename T>
void Isolate::SetReferenceFromGroup(UniqueId id,
const Persistent<T>& object) {
TYPE_CHECK(Value, T);
SetReferenceFromGroup(id,
reinterpret_cast<v8::internal::Object**>(object.val_));
}
template<typename T, typename S>
void Isolate::SetReference(const Persistent<T>& parent,
const Persistent<S>& child) {
TYPE_CHECK(Object, T);
TYPE_CHECK(Value, S);
SetReference(reinterpret_cast<v8::internal::Object**>(parent.val_),
reinterpret_cast<v8::internal::Object**>(child.val_));
}
Local<Value> Context::GetEmbedderData(int index) {
#ifndef V8_ENABLE_CHECKS
typedef internal::Object O;
......
......@@ -6350,31 +6350,32 @@ v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
}
void Isolate::SetObjectGroupId(const Persistent<Value>& object,
UniqueId id) {
void Isolate::SetObjectGroupId(internal::Object** object, UniqueId id) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
internal_isolate->global_handles()->SetObjectGroupId(
Utils::OpenPersistent(object).location(),
v8::internal::Handle<v8::internal::Object>(object).location(),
id);
internal_isolate->global_handles()->SetObjectGroupId(object, id);
}
void Isolate::SetReferenceFromGroup(UniqueId id,
const Persistent<Value>& object) {
void Isolate::SetReferenceFromGroup(UniqueId id, internal::Object** object) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
internal_isolate->global_handles()->SetReferenceFromGroup(
id,
Utils::OpenPersistent(object).location());
v8::internal::Handle<v8::internal::Object>(object).location());
internal_isolate->global_handles()->SetReferenceFromGroup(id, object);
}
void Isolate::SetReference(const Persistent<Object>& parent,
const Persistent<Value>& child) {
void Isolate::SetReference(internal::Object** parent,
internal::Object** child) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
i::Object** parent_location = Utils::OpenPersistent(parent).location();
i::Object** parent_location =
v8::internal::Handle<v8::internal::Object>(parent).location();
internal_isolate->global_handles()->SetReference(
reinterpret_cast<i::HeapObject**>(parent_location),
Utils::OpenPersistent(child).location());
v8::internal::Handle<v8::internal::Object>(child).location());
}
......
......@@ -3318,8 +3318,9 @@ class WeakCallCounter {
};
template<typename T>
static void WeakPointerCallback(v8::Isolate* isolate,
Persistent<Value>* handle,
Persistent<T>* handle,
WeakCallCounter* counter) {
CHECK_EQ(1234, counter->id());
counter->increment();
......@@ -3327,7 +3328,8 @@ static void WeakPointerCallback(v8::Isolate* isolate,
}
static UniqueId MakeUniqueId(const Persistent<Value>& p) {
template<typename T>
static UniqueId MakeUniqueId(const Persistent<T>& p) {
return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
}
......@@ -3425,6 +3427,97 @@ THREADED_TEST(ApiObjectGroups) {
}
THREADED_TEST(ApiObjectGroupsForSubtypes) {
LocalContext env;
v8::Isolate* iso = env->GetIsolate();
HandleScope scope(iso);
Persistent<Object> g1s1;
Persistent<String> g1s2;
Persistent<String> g1c1;
Persistent<Object> g2s1;
Persistent<String> g2s2;
Persistent<String> g2c1;
WeakCallCounter counter(1234);
{
HandleScope scope(iso);
g1s1.Reset(iso, Object::New());
g1s2.Reset(iso, String::New("foo1"));
g1c1.Reset(iso, String::New("foo2"));
g1s1.MakeWeak(&counter, &WeakPointerCallback);
g1s2.MakeWeak(&counter, &WeakPointerCallback);
g1c1.MakeWeak(&counter, &WeakPointerCallback);
g2s1.Reset(iso, Object::New());
g2s2.Reset(iso, String::New("foo3"));
g2c1.Reset(iso, String::New("foo4"));
g2s1.MakeWeak(&counter, &WeakPointerCallback);
g2s2.MakeWeak(&counter, &WeakPointerCallback);
g2c1.MakeWeak(&counter, &WeakPointerCallback);
}
Persistent<Value> root(iso, g1s1); // make a root.
// Connect group 1 and 2, make a cycle.
{
HandleScope scope(iso);
CHECK(Local<Object>::New(iso, g1s1)->Set(0, Local<Object>::New(iso, g2s1)));
CHECK(Local<Object>::New(iso, g2s1)->Set(0, Local<Object>::New(iso, g1s1)));
}
{
UniqueId id1 = MakeUniqueId(g1s1);
UniqueId id2 = MakeUniqueId(g2s2);
iso->SetObjectGroupId(g1s1, id1);
iso->SetObjectGroupId(g1s2, id1);
iso->SetReference(g1s1, g1c1);
iso->SetObjectGroupId(g2s1, id2);
iso->SetObjectGroupId(g2s2, id2);
iso->SetReferenceFromGroup(id2, g2c1);
}
// Do a single full GC, ensure incremental marking is stopped.
v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
iso)->heap();
heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
// All object should be alive.
CHECK_EQ(0, counter.NumberOfWeakCalls());
// Weaken the root.
root.MakeWeak(&counter, &WeakPointerCallback);
// But make children strong roots---all the objects (except for children)
// should be collectable now.
g1c1.ClearWeak();
g2c1.ClearWeak();
// Groups are deleted, rebuild groups.
{
UniqueId id1 = MakeUniqueId(g1s1);
UniqueId id2 = MakeUniqueId(g2s2);
iso->SetObjectGroupId(g1s1, id1);
iso->SetObjectGroupId(g1s2, id1);
iso->SetReference(g1s1, g1c1);
iso->SetObjectGroupId(g2s1, id2);
iso->SetObjectGroupId(g2s2, id2);
iso->SetReferenceFromGroup(id2, g2c1);
}
heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
// All objects should be gone. 5 global handles in total.
CHECK_EQ(5, counter.NumberOfWeakCalls());
// And now make children weak again and collect them.
g1c1.MakeWeak(&counter, &WeakPointerCallback);
g2c1.MakeWeak(&counter, &WeakPointerCallback);
heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
CHECK_EQ(7, counter.NumberOfWeakCalls());
}
THREADED_TEST(ApiObjectGroupsCycle) {
LocalContext env;
v8::Isolate* iso = env->GetIsolate();
......
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