Index: test/cctest/test-api.cc |
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc |
index cf84538d830120829bcee127a9e2be3a8998e0b0..e9d77eca86c63f2ac99a53cb2adf5aa3328836b9 100644 |
--- a/test/cctest/test-api.cc |
+++ b/test/cctest/test-api.cc |
@@ -4432,55 +4432,116 @@ THREADED_TEST(WeakReference) { |
} |
-static bool in_scavenge = false; |
-static int last = -1; |
- |
-static void ForceScavenge(v8::Persistent<v8::Value> obj, void* data) { |
- CHECK_EQ(-1, last); |
- last = 0; |
+static void DisposeAndSetFlag(v8::Persistent<v8::Value> obj, void* data) { |
obj.Dispose(); |
obj.Clear(); |
- in_scavenge = true; |
- HEAP->PerformScavenge(); |
- in_scavenge = false; |
*(reinterpret_cast<bool*>(data)) = true; |
} |
-static void CheckIsNotInvokedInScavenge(v8::Persistent<v8::Value> obj, |
- void* data) { |
- CHECK_EQ(0, last); |
- last = 1; |
- *(reinterpret_cast<bool*>(data)) = in_scavenge; |
- obj.Dispose(); |
- obj.Clear(); |
-} |
-THREADED_TEST(NoWeakRefCallbacksInScavenge) { |
- // Test verifies that scavenge cannot invoke WeakReferenceCallbacks. |
- // Calling callbacks from scavenges is unsafe as objects held by those |
- // handlers might have become strongly reachable, but scavenge doesn't |
- // check that. |
+THREADED_TEST(IndependentWeakHandle) { |
v8::Persistent<Context> context = Context::New(); |
Context::Scope context_scope(context); |
v8::Persistent<v8::Object> object_a; |
- v8::Persistent<v8::Object> object_b; |
{ |
v8::HandleScope handle_scope; |
- object_b = v8::Persistent<v8::Object>::New(v8::Object::New()); |
object_a = v8::Persistent<v8::Object>::New(v8::Object::New()); |
} |
bool object_a_disposed = false; |
- object_a.MakeWeak(&object_a_disposed, &ForceScavenge); |
- bool released_in_scavenge = false; |
- object_b.MakeWeak(&released_in_scavenge, &CheckIsNotInvokedInScavenge); |
+ object_a.MakeWeak(&object_a_disposed, &DisposeAndSetFlag); |
+ object_a.MarkIndependent(); |
+ HEAP->PerformScavenge(); |
+ CHECK(object_a_disposed); |
+} |
- while (!object_a_disposed) { |
- HEAP->CollectAllGarbage(false); |
+ |
+static void InvokeScavenge() { |
+ HEAP->PerformScavenge(); |
+} |
+ |
+ |
+static void InvokeMarkSweep() { |
+ HEAP->CollectAllGarbage(false); |
+} |
+ |
+ |
+static void ForceScavenge(v8::Persistent<v8::Value> obj, void* data) { |
+ obj.Dispose(); |
+ obj.Clear(); |
+ *(reinterpret_cast<bool*>(data)) = true; |
+ InvokeScavenge(); |
+} |
+ |
+ |
+static void ForceMarkSweep(v8::Persistent<v8::Value> obj, void* data) { |
+ obj.Dispose(); |
+ obj.Clear(); |
+ *(reinterpret_cast<bool*>(data)) = true; |
+ InvokeMarkSweep(); |
+} |
+ |
+ |
+THREADED_TEST(GCFromWeakCallbacks) { |
+ v8::Persistent<Context> context = Context::New(); |
+ Context::Scope context_scope(context); |
+ |
+ static const int kNumberOfGCTypes = 2; |
+ v8::WeakReferenceCallback gc_forcing_callback[kNumberOfGCTypes] = |
+ {&ForceScavenge, &ForceMarkSweep}; |
+ |
+ typedef void (*GCInvoker)(); |
+ GCInvoker invoke_gc[kNumberOfGCTypes] = {&InvokeScavenge, &InvokeMarkSweep}; |
+ |
+ for (int outer_gc = 0; outer_gc < kNumberOfGCTypes; outer_gc++) { |
+ for (int inner_gc = 0; inner_gc < kNumberOfGCTypes; inner_gc++) { |
+ v8::Persistent<v8::Object> object; |
+ { |
+ v8::HandleScope handle_scope; |
+ object = v8::Persistent<v8::Object>::New(v8::Object::New()); |
+ } |
+ bool disposed = false; |
+ object.MakeWeak(&disposed, gc_forcing_callback[inner_gc]); |
+ object.MarkIndependent(); |
+ invoke_gc[outer_gc](); |
+ CHECK(disposed); |
+ } |
+ } |
+} |
+ |
+ |
+static void RevivingCallback(v8::Persistent<v8::Value> obj, void* data) { |
+ obj.ClearWeak(); |
+ *(reinterpret_cast<bool*>(data)) = true; |
+} |
+ |
+ |
+THREADED_TEST(IndependentHandleRevival) { |
+ v8::Persistent<Context> context = Context::New(); |
+ Context::Scope context_scope(context); |
+ |
+ v8::Persistent<v8::Object> object; |
+ { |
+ v8::HandleScope handle_scope; |
+ object = v8::Persistent<v8::Object>::New(v8::Object::New()); |
+ object->Set(v8_str("x"), v8::Integer::New(1)); |
+ v8::Local<String> y_str = v8_str("y"); |
+ object->Set(y_str, y_str); |
+ } |
+ bool revived = false; |
+ object.MakeWeak(&revived, &RevivingCallback); |
+ object.MarkIndependent(); |
+ HEAP->PerformScavenge(); |
+ CHECK(revived); |
+ HEAP->CollectAllGarbage(true); |
+ { |
+ v8::HandleScope handle_scope; |
+ v8::Local<String> y_str = v8_str("y"); |
+ CHECK_EQ(v8::Integer::New(1), object->Get(v8_str("x"))); |
+ CHECK(object->Get(y_str)->Equals(y_str)); |
} |
- CHECK(!released_in_scavenge); |
} |