| Index: test/cctest/test-api.cc
|
| ===================================================================
|
| --- test/cctest/test-api.cc (revision 9531)
|
| +++ test/cctest/test-api.cc (working copy)
|
| @@ -80,6 +80,11 @@
|
| CHECK_EQ(expected, *ascii);
|
| }
|
|
|
| +static void ExpectInt32(const char* code, int expected) {
|
| + Local<Value> result = CompileRun(code);
|
| + CHECK(result->IsInt32());
|
| + CHECK_EQ(expected, result->Int32Value());
|
| +}
|
|
|
| static void ExpectBoolean(const char* code, bool expected) {
|
| Local<Value> result = CompileRun(code);
|
| @@ -393,11 +398,11 @@
|
| CHECK(source->IsExternal());
|
| CHECK_EQ(resource,
|
| static_cast<TestResource*>(source->GetExternalStringResource()));
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(0, dispose_count);
|
| }
|
| v8::internal::Isolate::Current()->compilation_cache()->Clear();
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllAvailableGarbage();
|
| CHECK_EQ(1, dispose_count);
|
| }
|
|
|
| @@ -415,11 +420,11 @@
|
| Local<Value> value = script->Run();
|
| CHECK(value->IsNumber());
|
| CHECK_EQ(7, value->Int32Value());
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(0, dispose_count);
|
| }
|
| i::Isolate::Current()->compilation_cache()->Clear();
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllAvailableGarbage();
|
| CHECK_EQ(1, dispose_count);
|
| }
|
|
|
| @@ -441,11 +446,12 @@
|
| Local<Value> value = script->Run();
|
| CHECK(value->IsNumber());
|
| CHECK_EQ(7, value->Int32Value());
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(0, dispose_count);
|
| }
|
| i::Isolate::Current()->compilation_cache()->Clear();
|
| - HEAP->CollectAllGarbage(false);
|
| + // TODO(1608): This should use kAbortIncrementalMarking.
|
| + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
|
| CHECK_EQ(1, dispose_count);
|
| }
|
|
|
| @@ -467,11 +473,12 @@
|
| Local<Value> value = script->Run();
|
| CHECK(value->IsNumber());
|
| CHECK_EQ(7, value->Int32Value());
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(0, dispose_count);
|
| }
|
| i::Isolate::Current()->compilation_cache()->Clear();
|
| - HEAP->CollectAllGarbage(false);
|
| + // TODO(1608): This should use kAbortIncrementalMarking.
|
| + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
|
| CHECK_EQ(1, dispose_count);
|
| }
|
|
|
| @@ -572,8 +579,8 @@
|
| i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring);
|
| CHECK(isymbol->IsSymbol());
|
| }
|
| - HEAP->CollectAllGarbage(false);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| }
|
|
|
|
|
| @@ -590,8 +597,8 @@
|
| i::Handle<i::String> isymbol = FACTORY->SymbolFromString(istring);
|
| CHECK(isymbol->IsSymbol());
|
| }
|
| - HEAP->CollectAllGarbage(false);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| }
|
|
|
|
|
| @@ -672,11 +679,11 @@
|
| Local<Value> value = script->Run();
|
| CHECK(value->IsNumber());
|
| CHECK_EQ(7, value->Int32Value());
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllAvailableGarbage();
|
| CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
|
| }
|
| i::Isolate::Current()->compilation_cache()->Clear();
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllAvailableGarbage();
|
| CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
|
| CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
|
|
|
| @@ -693,11 +700,11 @@
|
| Local<Value> value = script->Run();
|
| CHECK(value->IsNumber());
|
| CHECK_EQ(7, value->Int32Value());
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllAvailableGarbage();
|
| CHECK_EQ(0, TestAsciiResourceWithDisposeControl::dispose_count);
|
| }
|
| i::Isolate::Current()->compilation_cache()->Clear();
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllAvailableGarbage();
|
| CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_calls);
|
| CHECK_EQ(1, TestAsciiResourceWithDisposeControl::dispose_count);
|
| }
|
| @@ -744,8 +751,8 @@
|
| CHECK_EQ(68, value->Int32Value());
|
| }
|
| i::Isolate::Current()->compilation_cache()->Clear();
|
| - HEAP->CollectAllGarbage(false);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| }
|
|
|
|
|
| @@ -1294,7 +1301,198 @@
|
| return name;
|
| }
|
|
|
| +// Helper functions for Interceptor/Accessor interaction tests
|
|
|
| +Handle<Value> SimpleAccessorGetter(Local<String> name,
|
| + const AccessorInfo& info) {
|
| + Handle<Object> self = info.This();
|
| + return self->Get(String::Concat(v8_str("accessor_"), name));
|
| +}
|
| +
|
| +void SimpleAccessorSetter(Local<String> name, Local<Value> value,
|
| + const AccessorInfo& info) {
|
| + Handle<Object> self = info.This();
|
| + self->Set(String::Concat(v8_str("accessor_"), name), value);
|
| +}
|
| +
|
| +Handle<Value> EmptyInterceptorGetter(Local<String> name,
|
| + const AccessorInfo& info) {
|
| + return Handle<Value>();
|
| +}
|
| +
|
| +Handle<Value> EmptyInterceptorSetter(Local<String> name,
|
| + Local<Value> value,
|
| + const AccessorInfo& info) {
|
| + return Handle<Value>();
|
| +}
|
| +
|
| +Handle<Value> InterceptorGetter(Local<String> name,
|
| + const AccessorInfo& info) {
|
| + // Intercept names that start with 'interceptor_'.
|
| + String::AsciiValue ascii(name);
|
| + char* name_str = *ascii;
|
| + char prefix[] = "interceptor_";
|
| + int i;
|
| + for (i = 0; name_str[i] && prefix[i]; ++i) {
|
| + if (name_str[i] != prefix[i]) return Handle<Value>();
|
| + }
|
| + Handle<Object> self = info.This();
|
| + return self->GetHiddenValue(v8_str(name_str + i));
|
| +}
|
| +
|
| +Handle<Value> InterceptorSetter(Local<String> name,
|
| + Local<Value> value,
|
| + const AccessorInfo& info) {
|
| + // Intercept accesses that set certain integer values.
|
| + if (value->IsInt32() && value->Int32Value() < 10000) {
|
| + Handle<Object> self = info.This();
|
| + self->SetHiddenValue(name, value);
|
| + return value;
|
| + }
|
| + return Handle<Value>();
|
| +}
|
| +
|
| +void AddAccessor(Handle<FunctionTemplate> templ,
|
| + Handle<String> name,
|
| + v8::AccessorGetter getter,
|
| + v8::AccessorSetter setter) {
|
| + templ->PrototypeTemplate()->SetAccessor(name, getter, setter);
|
| +}
|
| +
|
| +void AddInterceptor(Handle<FunctionTemplate> templ,
|
| + v8::NamedPropertyGetter getter,
|
| + v8::NamedPropertySetter setter) {
|
| + templ->InstanceTemplate()->SetNamedPropertyHandler(getter, setter);
|
| +}
|
| +
|
| +THREADED_TEST(EmptyInterceptorDoesNotShadowAccessors) {
|
| + v8::HandleScope scope;
|
| + Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| + Handle<FunctionTemplate> child = FunctionTemplate::New();
|
| + child->Inherit(parent);
|
| + AddAccessor(parent, v8_str("age"),
|
| + SimpleAccessorGetter, SimpleAccessorSetter);
|
| + AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("Child"), child->GetFunction());
|
| + CompileRun("var child = new Child;"
|
| + "child.age = 10;");
|
| + ExpectBoolean("child.hasOwnProperty('age')", false);
|
| + ExpectInt32("child.age", 10);
|
| + ExpectInt32("child.accessor_age", 10);
|
| +}
|
| +
|
| +THREADED_TEST(EmptyInterceptorDoesNotShadowJSAccessors) {
|
| + v8::HandleScope scope;
|
| + Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| + Handle<FunctionTemplate> child = FunctionTemplate::New();
|
| + child->Inherit(parent);
|
| + AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("Child"), child->GetFunction());
|
| + CompileRun("var child = new Child;"
|
| + "var parent = child.__proto__;"
|
| + "Object.defineProperty(parent, 'age', "
|
| + " {get: function(){ return this.accessor_age; }, "
|
| + " set: function(v){ this.accessor_age = v; }, "
|
| + " enumerable: true, configurable: true});"
|
| + "child.age = 10;");
|
| + ExpectBoolean("child.hasOwnProperty('age')", false);
|
| + ExpectInt32("child.age", 10);
|
| + ExpectInt32("child.accessor_age", 10);
|
| +}
|
| +
|
| +THREADED_TEST(EmptyInterceptorDoesNotAffectJSProperties) {
|
| + v8::HandleScope scope;
|
| + Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| + Handle<FunctionTemplate> child = FunctionTemplate::New();
|
| + child->Inherit(parent);
|
| + AddInterceptor(child, EmptyInterceptorGetter, EmptyInterceptorSetter);
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("Child"), child->GetFunction());
|
| + CompileRun("var child = new Child;"
|
| + "var parent = child.__proto__;"
|
| + "parent.name = 'Alice';");
|
| + ExpectBoolean("child.hasOwnProperty('name')", false);
|
| + ExpectString("child.name", "Alice");
|
| + CompileRun("child.name = 'Bob';");
|
| + ExpectString("child.name", "Bob");
|
| + ExpectBoolean("child.hasOwnProperty('name')", true);
|
| + ExpectString("parent.name", "Alice");
|
| +}
|
| +
|
| +THREADED_TEST(SwitchFromInterceptorToAccessor) {
|
| + v8::HandleScope scope;
|
| + Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| + Handle<FunctionTemplate> child = FunctionTemplate::New();
|
| + child->Inherit(parent);
|
| + AddAccessor(parent, v8_str("age"),
|
| + SimpleAccessorGetter, SimpleAccessorSetter);
|
| + AddInterceptor(child, InterceptorGetter, InterceptorSetter);
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("Child"), child->GetFunction());
|
| + CompileRun("var child = new Child;"
|
| + "function setAge(i){ child.age = i; };"
|
| + "for(var i = 0; i <= 10000; i++) setAge(i);");
|
| + // All i < 10000 go to the interceptor.
|
| + ExpectInt32("child.interceptor_age", 9999);
|
| + // The last i goes to the accessor.
|
| + ExpectInt32("child.accessor_age", 10000);
|
| +}
|
| +
|
| +THREADED_TEST(SwitchFromAccessorToInterceptor) {
|
| + v8::HandleScope scope;
|
| + Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| + Handle<FunctionTemplate> child = FunctionTemplate::New();
|
| + child->Inherit(parent);
|
| + AddAccessor(parent, v8_str("age"),
|
| + SimpleAccessorGetter, SimpleAccessorSetter);
|
| + AddInterceptor(child, InterceptorGetter, InterceptorSetter);
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("Child"), child->GetFunction());
|
| + CompileRun("var child = new Child;"
|
| + "function setAge(i){ child.age = i; };"
|
| + "for(var i = 20000; i >= 9999; i--) setAge(i);");
|
| + // All i >= 10000 go to the accessor.
|
| + ExpectInt32("child.accessor_age", 10000);
|
| + // The last i goes to the interceptor.
|
| + ExpectInt32("child.interceptor_age", 9999);
|
| +}
|
| +
|
| +THREADED_TEST(SwitchFromInterceptorToProperty) {
|
| + v8::HandleScope scope;
|
| + Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| + Handle<FunctionTemplate> child = FunctionTemplate::New();
|
| + child->Inherit(parent);
|
| + AddInterceptor(child, InterceptorGetter, InterceptorSetter);
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("Child"), child->GetFunction());
|
| + CompileRun("var child = new Child;"
|
| + "function setAge(i){ child.age = i; };"
|
| + "for(var i = 0; i <= 10000; i++) setAge(i);");
|
| + // All i < 10000 go to the interceptor.
|
| + ExpectInt32("child.interceptor_age", 9999);
|
| + // The last i goes to child's own property.
|
| + ExpectInt32("child.age", 10000);
|
| +}
|
| +
|
| +THREADED_TEST(SwitchFromPropertyToInterceptor) {
|
| + v8::HandleScope scope;
|
| + Handle<FunctionTemplate> parent = FunctionTemplate::New();
|
| + Handle<FunctionTemplate> child = FunctionTemplate::New();
|
| + child->Inherit(parent);
|
| + AddInterceptor(child, InterceptorGetter, InterceptorSetter);
|
| + LocalContext env;
|
| + env->Global()->Set(v8_str("Child"), child->GetFunction());
|
| + CompileRun("var child = new Child;"
|
| + "function setAge(i){ child.age = i; };"
|
| + "for(var i = 20000; i >= 9999; i--) setAge(i);");
|
| + // All i >= 10000 go to child's own property.
|
| + ExpectInt32("child.age", 10000);
|
| + // The last i goes to the interceptor.
|
| + ExpectInt32("child.interceptor_age", 9999);
|
| +}
|
| +
|
| THREADED_TEST(NamedPropertyHandlerGetter) {
|
| echo_named_call_count = 0;
|
| v8::HandleScope scope;
|
| @@ -1666,12 +1864,12 @@
|
|
|
| // Check reading and writing aligned pointers.
|
| obj->SetPointerInInternalField(0, aligned);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(aligned, obj->GetPointerFromInternalField(0));
|
|
|
| // Check reading and writing unaligned pointers.
|
| obj->SetPointerInInternalField(0, unaligned);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0));
|
|
|
| delete[] data;
|
| @@ -1697,19 +1895,19 @@
|
| CHECK_EQ(1, static_cast<int>(reinterpret_cast<uintptr_t>(unaligned) & 0x1));
|
|
|
| obj->SetPointerInInternalField(0, aligned);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(aligned, v8::External::Unwrap(obj->GetInternalField(0)));
|
|
|
| obj->SetPointerInInternalField(0, unaligned);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(unaligned, v8::External::Unwrap(obj->GetInternalField(0)));
|
|
|
| obj->SetInternalField(0, v8::External::Wrap(aligned));
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(aligned, obj->GetPointerFromInternalField(0));
|
|
|
| obj->SetInternalField(0, v8::External::Wrap(unaligned));
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(unaligned, obj->GetPointerFromInternalField(0));
|
|
|
| delete[] data;
|
| @@ -1722,7 +1920,7 @@
|
|
|
| // Ensure that the test starts with an fresh heap to test whether the hash
|
| // code is based on the address.
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| Local<v8::Object> obj = v8::Object::New();
|
| int hash = obj->GetIdentityHash();
|
| int hash1 = obj->GetIdentityHash();
|
| @@ -1732,7 +1930,7 @@
|
| // objects should not be assigned the same hash code. If the test below fails
|
| // the random number generator should be evaluated.
|
| CHECK_NE(hash, hash2);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| int hash3 = v8::Object::New()->GetIdentityHash();
|
| // Make sure that the identity hash is not based on the initial address of
|
| // the object alone. If the test below fails the random number generator
|
| @@ -1769,7 +1967,7 @@
|
| v8::Local<v8::String> empty = v8_str("");
|
| v8::Local<v8::String> prop_name = v8_str("prop_name");
|
|
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
|
|
| // Make sure delete of a non-existent hidden value works
|
| CHECK(obj->DeleteHiddenValue(key));
|
| @@ -1779,7 +1977,7 @@
|
| CHECK(obj->SetHiddenValue(key, v8::Integer::New(2002)));
|
| CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
|
|
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
|
|
| // Make sure we do not find the hidden property.
|
| CHECK(!obj->Has(empty));
|
| @@ -1790,7 +1988,7 @@
|
| CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
|
| CHECK_EQ(2003, obj->Get(empty)->Int32Value());
|
|
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
|
|
| // Add another property and delete it afterwards to force the object in
|
| // slow case.
|
| @@ -1801,7 +1999,7 @@
|
| CHECK(obj->Delete(prop_name));
|
| CHECK_EQ(2002, obj->GetHiddenValue(key)->Int32Value());
|
|
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
|
|
| CHECK(obj->DeleteHiddenValue(key));
|
| CHECK(obj->GetHiddenValue(key).IsEmpty());
|
| @@ -1908,19 +2106,30 @@
|
| }
|
|
|
|
|
| -static int NumberOfWeakCalls = 0;
|
| +class WeakCallCounter {
|
| + public:
|
| + explicit WeakCallCounter(int id) : id_(id), number_of_weak_calls_(0) { }
|
| + int id() { return id_; }
|
| + void increment() { number_of_weak_calls_++; }
|
| + int NumberOfWeakCalls() { return number_of_weak_calls_; }
|
| + private:
|
| + int id_;
|
| + int number_of_weak_calls_;
|
| +};
|
| +
|
| +
|
| static void WeakPointerCallback(Persistent<Value> handle, void* id) {
|
| - CHECK_EQ(reinterpret_cast<void*>(1234), id);
|
| - NumberOfWeakCalls++;
|
| + WeakCallCounter* counter = reinterpret_cast<WeakCallCounter*>(id);
|
| + CHECK_EQ(1234, counter->id());
|
| + counter->increment();
|
| handle.Dispose();
|
| }
|
|
|
| +
|
| THREADED_TEST(ApiObjectGroups) {
|
| HandleScope scope;
|
| LocalContext env;
|
|
|
| - NumberOfWeakCalls = 0;
|
| -
|
| Persistent<Object> g1s1;
|
| Persistent<Object> g1s2;
|
| Persistent<Object> g1c1;
|
| @@ -1928,21 +2137,23 @@
|
| Persistent<Object> g2s2;
|
| Persistent<Object> g2c1;
|
|
|
| + WeakCallCounter counter(1234);
|
| +
|
| {
|
| HandleScope scope;
|
| g1s1 = Persistent<Object>::New(Object::New());
|
| g1s2 = Persistent<Object>::New(Object::New());
|
| g1c1 = Persistent<Object>::New(Object::New());
|
| - g1s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| - g1s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| - g1c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| + g1s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
| + g1s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
| + g1c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
|
|
| g2s1 = Persistent<Object>::New(Object::New());
|
| g2s2 = Persistent<Object>::New(Object::New());
|
| g2c1 = Persistent<Object>::New(Object::New());
|
| - g2s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| - g2s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| - g2c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| + g2s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
| + g2s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
| + g2c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
| }
|
|
|
| Persistent<Object> root = Persistent<Object>::New(g1s1); // make a root.
|
| @@ -1961,14 +2172,15 @@
|
| V8::AddObjectGroup(g2_objects, 2);
|
| V8::AddImplicitReferences(g2s2, g2_children, 1);
|
| }
|
| - // Do a full GC
|
| - HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
|
| + // Do a single full GC. Use kMakeHeapIterableMask to ensure that
|
| + // incremental garbage collection is stopped.
|
| + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
|
|
|
| // All object should be alive.
|
| - CHECK_EQ(0, NumberOfWeakCalls);
|
| + CHECK_EQ(0, counter.NumberOfWeakCalls());
|
|
|
| // Weaken the root.
|
| - root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| + root.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
| // But make children strong roots---all the objects (except for children)
|
| // should be collectable now.
|
| g1c1.ClearWeak();
|
| @@ -1986,17 +2198,17 @@
|
| V8::AddImplicitReferences(g2s2, g2_children, 1);
|
| }
|
|
|
| - HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
|
| + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
|
|
|
| // All objects should be gone. 5 global handles in total.
|
| - CHECK_EQ(5, NumberOfWeakCalls);
|
| + CHECK_EQ(5, counter.NumberOfWeakCalls());
|
|
|
| // And now make children weak again and collect them.
|
| - g1c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| - g2c1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| + g1c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
| + g2c1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
|
|
| - HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
|
| - CHECK_EQ(7, NumberOfWeakCalls);
|
| + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
|
| + CHECK_EQ(7, counter.NumberOfWeakCalls());
|
| }
|
|
|
|
|
| @@ -2004,7 +2216,7 @@
|
| HandleScope scope;
|
| LocalContext env;
|
|
|
| - NumberOfWeakCalls = 0;
|
| + WeakCallCounter counter(1234);
|
|
|
| Persistent<Object> g1s1;
|
| Persistent<Object> g1s2;
|
| @@ -2017,18 +2229,18 @@
|
| HandleScope scope;
|
| g1s1 = Persistent<Object>::New(Object::New());
|
| g1s2 = Persistent<Object>::New(Object::New());
|
| - g1s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| - g1s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| + g1s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
| + g1s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
|
|
| g2s1 = Persistent<Object>::New(Object::New());
|
| g2s2 = Persistent<Object>::New(Object::New());
|
| - g2s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| - g2s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| + g2s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
| + g2s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
|
|
| g3s1 = Persistent<Object>::New(Object::New());
|
| g3s2 = Persistent<Object>::New(Object::New());
|
| - g3s1.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| - g3s2.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| + g3s1.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
| + g3s2.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
| }
|
|
|
| Persistent<Object> root = Persistent<Object>::New(g1s1); // make a root.
|
| @@ -2050,14 +2262,14 @@
|
| V8::AddObjectGroup(g3_objects, 2);
|
| V8::AddImplicitReferences(g3s1, g3_children, 1);
|
| }
|
| - // Do a full GC
|
| - HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
|
| + // Do a single full GC
|
| + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
|
|
|
| // All object should be alive.
|
| - CHECK_EQ(0, NumberOfWeakCalls);
|
| + CHECK_EQ(0, counter.NumberOfWeakCalls());
|
|
|
| // Weaken the root.
|
| - root.MakeWeak(reinterpret_cast<void*>(1234), &WeakPointerCallback);
|
| + root.MakeWeak(reinterpret_cast<void*>(&counter), &WeakPointerCallback);
|
|
|
| // Groups are deleted, rebuild groups.
|
| {
|
| @@ -2075,10 +2287,10 @@
|
| V8::AddImplicitReferences(g3s1, g3_children, 1);
|
| }
|
|
|
| - HEAP->CollectGarbage(i::OLD_POINTER_SPACE);
|
| + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
|
|
|
| // All objects should be gone. 7 global handles in total.
|
| - CHECK_EQ(7, NumberOfWeakCalls);
|
| + CHECK_EQ(7, counter.NumberOfWeakCalls());
|
| }
|
|
|
|
|
| @@ -4305,6 +4517,47 @@
|
| }
|
|
|
|
|
| +static const char* kEmbeddedExtensionSource =
|
| + "function Ret54321(){return 54321;}~~@@$"
|
| + "$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
|
| +static const int kEmbeddedExtensionSourceValidLen = 34;
|
| +
|
| +
|
| +THREADED_TEST(ExtensionMissingSourceLength) {
|
| + v8::HandleScope handle_scope;
|
| + v8::RegisterExtension(new Extension("srclentest_fail",
|
| + kEmbeddedExtensionSource));
|
| + const char* extension_names[] = { "srclentest_fail" };
|
| + v8::ExtensionConfiguration extensions(1, extension_names);
|
| + v8::Handle<Context> context = Context::New(&extensions);
|
| + CHECK_EQ(0, *context);
|
| +}
|
| +
|
| +
|
| +THREADED_TEST(ExtensionWithSourceLength) {
|
| + for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
|
| + source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
|
| + v8::HandleScope handle_scope;
|
| + i::ScopedVector<char> extension_name(32);
|
| + i::OS::SNPrintF(extension_name, "ext #%d", source_len);
|
| + v8::RegisterExtension(new Extension(extension_name.start(),
|
| + kEmbeddedExtensionSource, 0, 0,
|
| + source_len));
|
| + const char* extension_names[1] = { extension_name.start() };
|
| + v8::ExtensionConfiguration extensions(1, extension_names);
|
| + v8::Handle<Context> context = Context::New(&extensions);
|
| + if (source_len == kEmbeddedExtensionSourceValidLen) {
|
| + Context::Scope lock(context);
|
| + v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
|
| + CHECK_EQ(v8::Integer::New(54321), result);
|
| + } else {
|
| + // Anything but exactly the right length should fail to compile.
|
| + CHECK_EQ(0, *context);
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| static const char* kEvalExtensionSource1 =
|
| "function UseEval1() {"
|
| " var x = 42;"
|
| @@ -4805,7 +5058,7 @@
|
|
|
|
|
| static void InvokeMarkSweep() {
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| }
|
|
|
|
|
| @@ -4898,7 +5151,7 @@
|
| CHECK_EQ(v8::Integer::New(3), args[2]);
|
| CHECK_EQ(v8::Undefined(), args[3]);
|
| v8::HandleScope scope;
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| return v8::Undefined();
|
| }
|
|
|
| @@ -7883,7 +8136,7 @@
|
| Local<String> name,
|
| const AccessorInfo& info) {
|
| ApiTestFuzzer::Fuzz();
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| return v8::Handle<Value>();
|
| }
|
|
|
| @@ -8613,7 +8866,7 @@
|
| int* call_count = reinterpret_cast<int*>(v8::External::Unwrap(info.Data()));
|
| ++(*call_count);
|
| if ((*call_count) % 20 == 0) {
|
| - HEAP->CollectAllGarbage(true);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| }
|
| return v8::Handle<Value>();
|
| }
|
| @@ -9964,6 +10217,7 @@
|
|
|
|
|
| static int GetGlobalObjectsCount() {
|
| + i::Isolate::Current()->heap()->EnsureHeapIsIterable();
|
| int count = 0;
|
| i::HeapIterator it;
|
| for (i::HeapObject* object = it.next(); object != NULL; object = it.next())
|
| @@ -9978,9 +10232,8 @@
|
| // the first garbage collection but some of the maps have already
|
| // been marked at that point. Therefore some of the maps are not
|
| // collected until the second garbage collection.
|
| - HEAP->global_context_map();
|
| - HEAP->CollectAllGarbage(false);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| + HEAP->CollectAllGarbage(i::Heap::kMakeHeapIterableMask);
|
| int count = GetGlobalObjectsCount();
|
| #ifdef DEBUG
|
| if (count != expected) HEAP->TracePathToGlobal();
|
| @@ -10049,7 +10302,7 @@
|
| // weak callback of the first handle would be able to 'reallocate' it.
|
| handle1.MakeWeak(NULL, NewPersistentHandleCallback);
|
| handle2.Dispose();
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| }
|
|
|
|
|
| @@ -10057,7 +10310,7 @@
|
|
|
| void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) {
|
| to_be_disposed.Dispose();
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| handle.Dispose();
|
| }
|
|
|
| @@ -10073,7 +10326,7 @@
|
| }
|
| handle1.MakeWeak(NULL, DisposeAndForceGcCallback);
|
| to_be_disposed = handle2;
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| }
|
|
|
| void DisposingCallback(v8::Persistent<v8::Value> handle, void*) {
|
| @@ -10099,7 +10352,7 @@
|
| }
|
| handle2.MakeWeak(NULL, DisposingCallback);
|
| handle3.MakeWeak(NULL, HandleCreatingCallback);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| }
|
|
|
|
|
| @@ -10915,7 +11168,7 @@
|
| {
|
| v8::Locker lock;
|
| // TODO(lrn): Perhaps create some garbage before collecting.
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| gc_count_++;
|
| }
|
| i::OS::Sleep(1);
|
| @@ -11037,7 +11290,7 @@
|
| while (gc_during_apply_ < kRequiredGCs) {
|
| {
|
| v8::Locker lock;
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| gc_count_++;
|
| }
|
| i::OS::Sleep(1);
|
| @@ -11753,13 +12006,15 @@
|
| i::Handle<i::ExternalPixelArray> pixels =
|
| i::Handle<i::ExternalPixelArray>::cast(
|
| FACTORY->NewExternalArray(kElementCount,
|
| - v8::kExternalPixelArray,
|
| - pixel_data));
|
| - HEAP->CollectAllGarbage(false); // Force GC to trigger verification.
|
| + v8::kExternalPixelArray,
|
| + pixel_data));
|
| + // Force GC to trigger verification.
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| for (int i = 0; i < kElementCount; i++) {
|
| pixels->set(i, i % 256);
|
| }
|
| - HEAP->CollectAllGarbage(false); // Force GC to trigger verification.
|
| + // Force GC to trigger verification.
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| for (int i = 0; i < kElementCount; i++) {
|
| CHECK_EQ(i % 256, pixels->get_scalar(i));
|
| CHECK_EQ(i % 256, pixel_data[i]);
|
| @@ -12235,11 +12490,13 @@
|
| i::Handle<ExternalArrayClass> array =
|
| i::Handle<ExternalArrayClass>::cast(
|
| FACTORY->NewExternalArray(kElementCount, array_type, array_data));
|
| - HEAP->CollectAllGarbage(false); // Force GC to trigger verification.
|
| + // Force GC to trigger verification.
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| for (int i = 0; i < kElementCount; i++) {
|
| array->set(i, static_cast<ElementType>(i));
|
| }
|
| - HEAP->CollectAllGarbage(false); // Force GC to trigger verification.
|
| + // Force GC to trigger verification.
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| for (int i = 0; i < kElementCount; i++) {
|
| CHECK_EQ(static_cast<int64_t>(i),
|
| static_cast<int64_t>(array->get_scalar(i)));
|
| @@ -12357,7 +12614,8 @@
|
| " }"
|
| "}"
|
| "sum;");
|
| - HEAP->CollectAllGarbage(false); // Force GC to trigger verification.
|
| + // Force GC to trigger verification.
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(28, result->Int32Value());
|
|
|
| // Make sure out-of-range loads do not throw.
|
| @@ -13337,7 +13595,7 @@
|
| other_context->Enter();
|
| CompileRun(source_simple);
|
| other_context->Exit();
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| if (GetGlobalObjectsCount() == 1) break;
|
| }
|
| CHECK_GE(2, gc_count);
|
| @@ -13359,7 +13617,7 @@
|
| other_context->Enter();
|
| CompileRun(source_eval);
|
| other_context->Exit();
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| if (GetGlobalObjectsCount() == 1) break;
|
| }
|
| CHECK_GE(2, gc_count);
|
| @@ -13386,7 +13644,7 @@
|
| other_context->Enter();
|
| CompileRun(source_exception);
|
| other_context->Exit();
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| if (GetGlobalObjectsCount() == 1) break;
|
| }
|
| CHECK_GE(2, gc_count);
|
| @@ -13604,26 +13862,26 @@
|
| v8::V8::AddGCEpilogueCallback(EpilogueCallback);
|
| CHECK_EQ(0, prologue_call_count);
|
| CHECK_EQ(0, epilogue_call_count);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(1, prologue_call_count);
|
| CHECK_EQ(1, epilogue_call_count);
|
| v8::V8::AddGCPrologueCallback(PrologueCallbackSecond);
|
| v8::V8::AddGCEpilogueCallback(EpilogueCallbackSecond);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(2, prologue_call_count);
|
| CHECK_EQ(2, epilogue_call_count);
|
| CHECK_EQ(1, prologue_call_count_second);
|
| CHECK_EQ(1, epilogue_call_count_second);
|
| v8::V8::RemoveGCPrologueCallback(PrologueCallback);
|
| v8::V8::RemoveGCEpilogueCallback(EpilogueCallback);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(2, prologue_call_count);
|
| CHECK_EQ(2, epilogue_call_count);
|
| CHECK_EQ(2, prologue_call_count_second);
|
| CHECK_EQ(2, epilogue_call_count_second);
|
| v8::V8::RemoveGCPrologueCallback(PrologueCallbackSecond);
|
| v8::V8::RemoveGCEpilogueCallback(EpilogueCallbackSecond);
|
| - HEAP->CollectAllGarbage(false);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| CHECK_EQ(2, prologue_call_count);
|
| CHECK_EQ(2, epilogue_call_count);
|
| CHECK_EQ(2, prologue_call_count_second);
|
| @@ -13840,7 +14098,7 @@
|
| void FailedAccessCheckCallbackGC(Local<v8::Object> target,
|
| v8::AccessType type,
|
| Local<v8::Value> data) {
|
| - HEAP->CollectAllGarbage(true);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| }
|
|
|
|
|
| @@ -14414,7 +14672,7 @@
|
| "})()",
|
| "ReferenceError: cell is not defined");
|
| CompileRun("cell = \"new_second\";");
|
| - HEAP->CollectAllGarbage(true);
|
| + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags);
|
| ExpectString("readCell()", "new_second");
|
| ExpectString("readCell()", "new_second");
|
| }
|
|
|