Commit 9a545949 authored by antonm@chromium.org's avatar antonm@chromium.org

Restore invariant (next of first deallocated must point to the head) before calling into weak

callbacks.

Otherwise if callback allocates a new handle, it could orphan some global handles (with disastorous
consequences if those global handles are cached).

Review URL: http://codereview.chromium.org/395024

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3318 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 41749529
...@@ -165,6 +165,9 @@ class GlobalHandles::Node : public Malloced { ...@@ -165,6 +165,9 @@ class GlobalHandles::Node : public Malloced {
// It's fine though to reuse nodes that were destroyed in weak callback // It's fine though to reuse nodes that were destroyed in weak callback
// as those cannot be deallocated until we are back from the callback. // as those cannot be deallocated until we are back from the callback.
set_first_free(NULL); set_first_free(NULL);
if (first_deallocated()) {
first_deallocated()->set_next(head());
}
// Leaving V8. // Leaving V8.
VMState state(EXTERNAL); VMState state(EXTERNAL);
func(object, par); func(object, par);
...@@ -270,6 +273,7 @@ Handle<Object> GlobalHandles::Create(Object* value) { ...@@ -270,6 +273,7 @@ Handle<Object> GlobalHandles::Create(Object* value) {
// Next try deallocated list // Next try deallocated list
result = first_deallocated(); result = first_deallocated();
set_first_deallocated(result->next_free()); set_first_deallocated(result->next_free());
ASSERT(result->next() == head());
set_head(result); set_head(result);
} else { } else {
// Allocate a new node. // Allocate a new node.
......
...@@ -6226,6 +6226,31 @@ THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) { ...@@ -6226,6 +6226,31 @@ THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
i::Heap::CollectAllGarbage(false); i::Heap::CollectAllGarbage(false);
} }
void DisposingCallback(v8::Persistent<v8::Value> handle, void*) {
handle.Dispose();
}
void HandleCreatingCallback(v8::Persistent<v8::Value> handle, void*) {
v8::HandleScope scope;
v8::Persistent<v8::Object>::New(v8::Object::New());
}
THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) {
LocalContext context;
v8::Persistent<v8::Object> handle1, handle2, handle3;
{
v8::HandleScope scope;
handle3 = v8::Persistent<v8::Object>::New(v8::Object::New());
handle2 = v8::Persistent<v8::Object>::New(v8::Object::New());
handle1 = v8::Persistent<v8::Object>::New(v8::Object::New());
}
handle2.MakeWeak(NULL, DisposingCallback);
handle3.MakeWeak(NULL, HandleCreatingCallback);
i::Heap::CollectAllGarbage(false);
}
THREADED_TEST(CheckForCrossContextObjectLiterals) { THREADED_TEST(CheckForCrossContextObjectLiterals) {
v8::V8::Initialize(); v8::V8::Initialize();
......
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