| Index: test/cctest/test-api.cc
|
| ===================================================================
|
| --- test/cctest/test-api.cc (revision 3369)
|
| +++ test/cctest/test-api.cc (working copy)
|
| @@ -8495,3 +8495,107 @@
|
| v8::String::Utf8Value value(try_catch.Exception());
|
| CHECK_EQ(0, strcmp(*value, "Hey!"));
|
| }
|
| +
|
| +
|
| +static int GetGlobalObjectsCount() {
|
| + int count = 0;
|
| + v8::internal::HeapIterator it;
|
| + while (it.has_next()) {
|
| + v8::internal::HeapObject* object = it.next();
|
| + if (object->IsJSGlobalObject()) {
|
| + count++;
|
| + }
|
| + }
|
| +#ifdef DEBUG
|
| + if (count > 0) v8::internal::Heap::TracePathToGlobal();
|
| +#endif
|
| + return count;
|
| +}
|
| +
|
| +
|
| +TEST(Bug528) {
|
| + v8::V8::Initialize();
|
| +
|
| + v8::HandleScope scope;
|
| + v8::Persistent<Context> context;
|
| + int gc_count;
|
| +
|
| + // Context-dependent context data creates reference from the compilation
|
| + // cache to the global object.
|
| + context = Context::New();
|
| + {
|
| + v8::HandleScope scope;
|
| +
|
| + context->Enter();
|
| + Local<v8::Object> obj = v8::Object::New();
|
| + context->SetData(obj);
|
| + CompileRun("1");
|
| + context->Exit();
|
| + }
|
| + context.Dispose();
|
| + for (gc_count = 1; gc_count < 10; gc_count++) {
|
| + v8::internal::Heap::CollectAllGarbage(false);
|
| + if (GetGlobalObjectsCount() == 0) break;
|
| + }
|
| + CHECK_EQ(0, GetGlobalObjectsCount());
|
| +
|
| + // Compilation cache size is different for Android.
|
| +#if defined(ANDROID)
|
| + CHECK_EQ(1, gc_count);
|
| +#else
|
| + CHECK_EQ(5, gc_count);
|
| +#endif
|
| +
|
| + // Eval in a function creates reference from the compilation cache to the
|
| + // global object.
|
| + context = Context::New();
|
| + {
|
| + v8::HandleScope scope;
|
| +
|
| + context->Enter();
|
| + CompileRun("function f(){eval('1')}; f()");
|
| + context->Exit();
|
| + }
|
| + context.Dispose();
|
| + for (gc_count = 1; gc_count < 10; gc_count++) {
|
| + v8::internal::Heap::CollectAllGarbage(false);
|
| + if (GetGlobalObjectsCount() == 0) break;
|
| + }
|
| + CHECK_EQ(0, GetGlobalObjectsCount());
|
| +
|
| + // Compilation cache size is different for Android.
|
| +#if defined(ANDROID)
|
| + CHECK_EQ(1, gc_count);
|
| +#else
|
| + CHECK_EQ(2, gc_count);
|
| +#endif
|
| +
|
| + // Looking up the line number for an exception creates reference from the
|
| + // compilation cache to the global object.
|
| + context = Context::New();
|
| + {
|
| + v8::HandleScope scope;
|
| +
|
| + context->Enter();
|
| + v8::TryCatch try_catch;
|
| + CompileRun("function f(){throw 1;}; f()");
|
| + CHECK(try_catch.HasCaught());
|
| + v8::Handle<v8::Message> message = try_catch.Message();
|
| + CHECK(!message.IsEmpty());
|
| + CHECK_EQ(1, message->GetLineNumber());
|
| + context->Exit();
|
| + }
|
| + context.Dispose();
|
| + for (gc_count = 1; gc_count < 10; gc_count++) {
|
| + v8::internal::Heap::CollectAllGarbage(false);
|
| + if (GetGlobalObjectsCount() == 0) break;
|
| + }
|
| + CHECK_EQ(0, GetGlobalObjectsCount());
|
| +
|
| + // Compilation cache size is different for Android.
|
| +#if defined(ANDROID)
|
| + CHECK_EQ(2, gc_count);
|
| +#else
|
| + CHECK_EQ(5, gc_count);
|
| +#endif
|
| +}
|
|
|