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 { ...@@ -712,6 +712,7 @@ template <class T, class M> class Persistent {
V8_INLINE T* operator*() const { return val_; } V8_INLINE T* operator*() const { return val_; }
private: private:
friend class Isolate;
friend class Utils; friend class Utils;
template<class F> friend class Handle; template<class F> friend class Handle;
template<class F> friend class Local; template<class F> friend class Local;
...@@ -4066,7 +4067,7 @@ class V8_EXPORT Isolate { ...@@ -4066,7 +4067,7 @@ class V8_EXPORT Isolate {
* garbage collection types it is sufficient to provide object groups * garbage collection types it is sufficient to provide object groups
* for partially dependent handles only. * for partially dependent handles only.
*/ */
void SetObjectGroupId(const Persistent<Value>& object, template<typename T> void SetObjectGroupId(const Persistent<T>& object,
UniqueId id); UniqueId id);
/** /**
...@@ -4076,8 +4077,8 @@ class V8_EXPORT Isolate { ...@@ -4076,8 +4077,8 @@ class V8_EXPORT Isolate {
* are removed. It is intended to be used in the before-garbage-collection * are removed. It is intended to be used in the before-garbage-collection
* callback function. * callback function.
*/ */
void SetReferenceFromGroup(UniqueId id, template<typename T> void SetReferenceFromGroup(UniqueId id,
const Persistent<Value>& child); const Persistent<T>& child);
/** /**
* Allows the host application to declare implicit references from an object * Allows the host application to declare implicit references from an object
...@@ -4085,8 +4086,8 @@ class V8_EXPORT Isolate { ...@@ -4085,8 +4086,8 @@ class V8_EXPORT Isolate {
* too. After each garbage collection, all implicit references are removed. It * too. After each garbage collection, all implicit references are removed. It
* is intended to be used in the before-garbage-collection callback function. * is intended to be used in the before-garbage-collection callback function.
*/ */
void SetReference(const Persistent<Object>& parent, template<typename T, typename S>
const Persistent<Value>& child); void SetReference(const Persistent<T>& parent, const Persistent<S>& child);
typedef void (*GCPrologueCallback)(Isolate* isolate, typedef void (*GCPrologueCallback)(Isolate* isolate,
GCType type, GCType type,
...@@ -4140,8 +4141,11 @@ class V8_EXPORT Isolate { ...@@ -4140,8 +4141,11 @@ class V8_EXPORT Isolate {
Isolate& operator=(const Isolate&); Isolate& operator=(const Isolate&);
void* operator new(size_t size); void* operator new(size_t size);
void operator delete(void*, size_t); 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 { class V8_EXPORT StartupData {
public: public:
...@@ -6420,6 +6424,33 @@ void* Isolate::GetData() { ...@@ -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) { Local<Value> Context::GetEmbedderData(int index) {
#ifndef V8_ENABLE_CHECKS #ifndef V8_ENABLE_CHECKS
typedef internal::Object O; typedef internal::Object O;
......
...@@ -6350,31 +6350,32 @@ v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) { ...@@ -6350,31 +6350,32 @@ v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
} }
void Isolate::SetObjectGroupId(const Persistent<Value>& object, void Isolate::SetObjectGroupId(internal::Object** object, UniqueId id) {
UniqueId id) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this); i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
internal_isolate->global_handles()->SetObjectGroupId( internal_isolate->global_handles()->SetObjectGroupId(
Utils::OpenPersistent(object).location(), v8::internal::Handle<v8::internal::Object>(object).location(),
id); id);
internal_isolate->global_handles()->SetObjectGroupId(object, id);
} }
void Isolate::SetReferenceFromGroup(UniqueId id, void Isolate::SetReferenceFromGroup(UniqueId id, internal::Object** object) {
const Persistent<Value>& object) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this); i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
internal_isolate->global_handles()->SetReferenceFromGroup( internal_isolate->global_handles()->SetReferenceFromGroup(
id, 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, void Isolate::SetReference(internal::Object** parent,
const Persistent<Value>& child) { internal::Object** child) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this); 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( internal_isolate->global_handles()->SetReference(
reinterpret_cast<i::HeapObject**>(parent_location), reinterpret_cast<i::HeapObject**>(parent_location),
Utils::OpenPersistent(child).location()); v8::internal::Handle<v8::internal::Object>(child).location());
} }
......
...@@ -3318,8 +3318,9 @@ class WeakCallCounter { ...@@ -3318,8 +3318,9 @@ class WeakCallCounter {
}; };
template<typename T>
static void WeakPointerCallback(v8::Isolate* isolate, static void WeakPointerCallback(v8::Isolate* isolate,
Persistent<Value>* handle, Persistent<T>* handle,
WeakCallCounter* counter) { WeakCallCounter* counter) {
CHECK_EQ(1234, counter->id()); CHECK_EQ(1234, counter->id());
counter->increment(); counter->increment();
...@@ -3327,7 +3328,8 @@ static void WeakPointerCallback(v8::Isolate* isolate, ...@@ -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))); return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
} }
...@@ -3425,6 +3427,97 @@ THREADED_TEST(ApiObjectGroups) { ...@@ -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) { THREADED_TEST(ApiObjectGroupsCycle) {
LocalContext env; LocalContext env;
v8::Isolate* iso = env->GetIsolate(); 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