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
This commit is contained in:
antonm@chromium.org 2009-11-17 13:50:07 +00:00
parent 41749529dd
commit 9a545949a4
2 changed files with 29 additions and 0 deletions

View File

@ -165,6 +165,9 @@ class GlobalHandles::Node : public Malloced {
// 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.
set_first_free(NULL);
if (first_deallocated()) {
first_deallocated()->set_next(head());
}
// Leaving V8.
VMState state(EXTERNAL);
func(object, par);
@ -270,6 +273,7 @@ Handle<Object> GlobalHandles::Create(Object* value) {
// Next try deallocated list
result = first_deallocated();
set_first_deallocated(result->next_free());
ASSERT(result->next() == head());
set_head(result);
} else {
// Allocate a new node.

View File

@ -6226,6 +6226,31 @@ THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) {
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) {
v8::V8::Initialize();