summaryrefslogtreecommitdiff
path: root/deps/v8/test/cctest/test-api.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/cctest/test-api.cc')
-rw-r--r--deps/v8/test/cctest/test-api.cc472
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");
}