diff options
Diffstat (limited to 'deps/v8/test/cctest/test-api.cc')
-rw-r--r-- | deps/v8/test/cctest/test-api.cc | 472 |
1 files changed, 379 insertions, 93 deletions
diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index f9f08a6641..167c4cd155 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -80,6 +80,11 @@ static void ExpectString(const char* code, const char* expected) { 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 @@ THREADED_TEST(ScriptUsingStringResource) { 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 @@ THREADED_TEST(ScriptUsingAsciiStringResource) { 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 @@ THREADED_TEST(ScriptMakingExternalString) { 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 @@ THREADED_TEST(ScriptMakingExternalAsciiString) { 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 @@ THREADED_TEST(UsingExternalString) { 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 @@ THREADED_TEST(UsingExternalAsciiString) { 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 @@ TEST(ExternalStringWithDisposeHandling) { 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 @@ TEST(ExternalStringWithDisposeHandling) { 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 @@ THREADED_TEST(StringConcat) { 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,6 +1301,197 @@ static v8::Handle<Value> EchoNamedProperty(Local<String> name, 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; @@ -1666,12 +1864,12 @@ THREADED_TEST(InternalFieldsNativePointers) { // 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 @@ THREADED_TEST(InternalFieldsNativePointersAndExternal) { 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 @@ THREADED_TEST(IdentityHash) { // 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 @@ THREADED_TEST(IdentityHash) { // 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 @@ THREADED_TEST(HiddenProperties) { 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 @@ THREADED_TEST(HiddenProperties) { 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 @@ THREADED_TEST(HiddenProperties) { 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,13 +1999,41 @@ THREADED_TEST(HiddenProperties) { 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()); } +THREADED_TEST(Regress97784) { + // Regression test for crbug.com/97784 + // Messing with the Object.prototype should not have effect on + // hidden properties. + v8::HandleScope scope; + LocalContext env; + + v8::Local<v8::Object> obj = v8::Object::New(); + v8::Local<v8::String> key = v8_str("hidden"); + + CompileRun( + "set_called = false;" + "Object.defineProperty(" + " Object.prototype," + " 'hidden'," + " {get: function() { return 45; }," + " set: function() { set_called = true; }})"); + + CHECK(obj->GetHiddenValue(key).IsEmpty()); + // Make sure that the getter and setter from Object.prototype is not invoked. + // If it did we would have full access to the hidden properties in + // the accessor. + CHECK(obj->SetHiddenValue(key, v8::Integer::New(42))); + ExpectFalse("set_called"); + CHECK_EQ(42, obj->GetHiddenValue(key)->Int32Value()); +} + + static bool interceptor_for_hidden_properties_called; static v8::Handle<Value> InterceptorForHiddenProperties( Local<String> name, const AccessorInfo& info) { @@ -1880,19 +2106,30 @@ THREADED_TEST(GlobalHandle) { } -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; @@ -1900,21 +2137,23 @@ THREADED_TEST(ApiObjectGroups) { 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. @@ -1933,14 +2172,15 @@ THREADED_TEST(ApiObjectGroups) { 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(); @@ -1958,17 +2198,17 @@ THREADED_TEST(ApiObjectGroups) { 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()); } @@ -1976,7 +2216,7 @@ THREADED_TEST(ApiObjectGroupsCycle) { HandleScope scope; LocalContext env; - NumberOfWeakCalls = 0; + WeakCallCounter counter(1234); Persistent<Object> g1s1; Persistent<Object> g1s2; @@ -1989,18 +2229,18 @@ THREADED_TEST(ApiObjectGroupsCycle) { 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. @@ -2022,14 +2262,14 @@ THREADED_TEST(ApiObjectGroupsCycle) { 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. { @@ -2047,10 +2287,10 @@ THREADED_TEST(ApiObjectGroupsCycle) { 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()); } @@ -4277,6 +4517,47 @@ THREADED_TEST(SimpleExtensions) { } +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;" @@ -4777,7 +5058,7 @@ static void InvokeScavenge() { static void InvokeMarkSweep() { - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -4870,7 +5151,7 @@ static v8::Handle<Value> ArgumentsTestCallback(const v8::Arguments& args) { 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(); } @@ -7855,7 +8136,7 @@ static v8::Handle<Value> InterceptorHasOwnPropertyGetterGC( Local<String> name, const AccessorInfo& info) { ApiTestFuzzer::Fuzz(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); return v8::Handle<Value>(); } @@ -8585,7 +8866,7 @@ static v8::Handle<Value> InterceptorCallICFastApi(Local<String> name, 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>(); } @@ -9936,6 +10217,7 @@ THREADED_TEST(LockUnlockLock) { 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()) @@ -9950,9 +10232,8 @@ static void CheckSurvivingGlobalObjectsCount(int expected) { // 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(); @@ -10021,7 +10302,7 @@ THREADED_TEST(NewPersistentHandleFromWeakCallback) { // 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); } @@ -10029,7 +10310,7 @@ v8::Persistent<v8::Object> to_be_disposed; void DisposeAndForceGcCallback(v8::Persistent<v8::Value> handle, void*) { to_be_disposed.Dispose(); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); handle.Dispose(); } @@ -10045,7 +10326,7 @@ THREADED_TEST(DoNotUseDeletedNodesInSecondLevelGc) { } handle1.MakeWeak(NULL, DisposeAndForceGcCallback); to_be_disposed = handle2; - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } void DisposingCallback(v8::Persistent<v8::Value> handle, void*) { @@ -10071,7 +10352,7 @@ THREADED_TEST(NoGlobalHandlesOrphaningDueToWeakCallback) { } handle2.MakeWeak(NULL, DisposingCallback); handle3.MakeWeak(NULL, HandleCreatingCallback); - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -10887,7 +11168,7 @@ class RegExpInterruptTest { { 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); @@ -11009,7 +11290,7 @@ class ApplyInterruptTest { while (gc_during_apply_ < kRequiredGCs) { { v8::Locker lock; - HEAP->CollectAllGarbage(false); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); gc_count_++; } i::OS::Sleep(1); @@ -11725,13 +12006,15 @@ THREADED_TEST(PixelArray) { 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]); @@ -12207,11 +12490,13 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, 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))); @@ -12329,7 +12614,8 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type, " }" "}" "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. @@ -13309,7 +13595,7 @@ TEST(Regress528) { 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); @@ -13331,7 +13617,7 @@ TEST(Regress528) { 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); @@ -13358,7 +13644,7 @@ TEST(Regress528) { 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); @@ -13576,26 +13862,26 @@ TEST(GCCallbacks) { 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); @@ -13812,7 +14098,7 @@ THREADED_TEST(TwoByteStringInAsciiCons) { void FailedAccessCheckCallbackGC(Local<v8::Object> target, v8::AccessType type, Local<v8::Value> data) { - HEAP->CollectAllGarbage(true); + HEAP->CollectAllGarbage(i::Heap::kNoGCFlags); } @@ -14386,7 +14672,7 @@ TEST(DontDeleteCellLoadIC) { "})()", "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"); } |