Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(817)

Unified Diff: test/cctest/test-api.cc

Issue 39973003: Merge bleeding_edge. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: again Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « test/cctest/cctest.status ('k') | test/cctest/test-assembler-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/cctest/test-api.cc
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 22e207785888f2857db01f6e20486a8a64c216d4..d5e838ebe09618a6dbc3dcdd567d5d0136482cc2 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -3318,8 +3318,9 @@ class WeakCallCounter {
};
+template<typename T>
static void WeakPointerCallback(v8::Isolate* isolate,
- Persistent<Value>* handle,
+ Persistent<T>* handle,
WeakCallCounter* counter) {
CHECK_EQ(1234, counter->id());
counter->increment();
@@ -3327,7 +3328,8 @@ static void WeakPointerCallback(v8::Isolate* isolate,
}
-static UniqueId MakeUniqueId(const Persistent<Value>& p) {
+template<typename T>
+static UniqueId MakeUniqueId(const Persistent<T>& p) {
return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p)));
}
@@ -3425,6 +3427,97 @@ THREADED_TEST(ApiObjectGroups) {
}
+THREADED_TEST(ApiObjectGroupsForSubtypes) {
+ LocalContext env;
+ v8::Isolate* iso = env->GetIsolate();
+ HandleScope scope(iso);
+
+ Persistent<Object> g1s1;
+ Persistent<String> g1s2;
+ Persistent<String> g1c1;
+ Persistent<Object> g2s1;
+ Persistent<String> g2s2;
+ Persistent<String> g2c1;
+
+ WeakCallCounter counter(1234);
+
+ {
+ HandleScope scope(iso);
+ g1s1.Reset(iso, Object::New());
+ g1s2.Reset(iso, String::New("foo1"));
+ g1c1.Reset(iso, String::New("foo2"));
+ g1s1.MakeWeak(&counter, &WeakPointerCallback);
+ g1s2.MakeWeak(&counter, &WeakPointerCallback);
+ g1c1.MakeWeak(&counter, &WeakPointerCallback);
+
+ g2s1.Reset(iso, Object::New());
+ g2s2.Reset(iso, String::New("foo3"));
+ g2c1.Reset(iso, String::New("foo4"));
+ g2s1.MakeWeak(&counter, &WeakPointerCallback);
+ g2s2.MakeWeak(&counter, &WeakPointerCallback);
+ g2c1.MakeWeak(&counter, &WeakPointerCallback);
+ }
+
+ Persistent<Value> root(iso, g1s1); // make a root.
+
+ // Connect group 1 and 2, make a cycle.
+ {
+ HandleScope scope(iso);
+ CHECK(Local<Object>::New(iso, g1s1)->Set(0, Local<Object>::New(iso, g2s1)));
+ CHECK(Local<Object>::New(iso, g2s1)->Set(0, Local<Object>::New(iso, g1s1)));
+ }
+
+ {
+ UniqueId id1 = MakeUniqueId(g1s1);
+ UniqueId id2 = MakeUniqueId(g2s2);
+ iso->SetObjectGroupId(g1s1, id1);
+ iso->SetObjectGroupId(g1s2, id1);
+ iso->SetReference(g1s1, g1c1);
+ iso->SetObjectGroupId(g2s1, id2);
+ iso->SetObjectGroupId(g2s2, id2);
+ iso->SetReferenceFromGroup(id2, g2c1);
+ }
+ // Do a single full GC, ensure incremental marking is stopped.
+ v8::internal::Heap* heap = reinterpret_cast<v8::internal::Isolate*>(
+ iso)->heap();
+ heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+
+ // All object should be alive.
+ CHECK_EQ(0, counter.NumberOfWeakCalls());
+
+ // Weaken the root.
+ root.MakeWeak(&counter, &WeakPointerCallback);
+ // But make children strong roots---all the objects (except for children)
+ // should be collectable now.
+ g1c1.ClearWeak();
+ g2c1.ClearWeak();
+
+ // Groups are deleted, rebuild groups.
+ {
+ UniqueId id1 = MakeUniqueId(g1s1);
+ UniqueId id2 = MakeUniqueId(g2s2);
+ iso->SetObjectGroupId(g1s1, id1);
+ iso->SetObjectGroupId(g1s2, id1);
+ iso->SetReference(g1s1, g1c1);
+ iso->SetObjectGroupId(g2s1, id2);
+ iso->SetObjectGroupId(g2s2, id2);
+ iso->SetReferenceFromGroup(id2, g2c1);
+ }
+
+ heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+
+ // All objects should be gone. 5 global handles in total.
+ CHECK_EQ(5, counter.NumberOfWeakCalls());
+
+ // And now make children weak again and collect them.
+ g1c1.MakeWeak(&counter, &WeakPointerCallback);
+ g2c1.MakeWeak(&counter, &WeakPointerCallback);
+
+ heap->CollectAllGarbage(i::Heap::kAbortIncrementalMarkingMask);
+ CHECK_EQ(7, counter.NumberOfWeakCalls());
+}
+
+
THREADED_TEST(ApiObjectGroupsCycle) {
LocalContext env;
v8::Isolate* iso = env->GetIsolate();
@@ -14323,129 +14416,6 @@ THREADED_TEST(CrossContextNew) {
}
-class RegExpInterruptTest {
- public:
- RegExpInterruptTest() : block_(0) {}
- ~RegExpInterruptTest() {}
- void RunTest() {
- gc_count_ = 0;
- gc_during_regexp_ = 0;
- regexp_success_ = false;
- gc_success_ = false;
- GCThread gc_thread(this);
- gc_thread.Start();
- v8::Isolate* isolate = CcTest::isolate();
- v8::Locker::StartPreemption(isolate, 1);
-
- LongRunningRegExp();
- {
- v8::Unlocker unlock(isolate);
- gc_thread.Join();
- }
- v8::Locker::StopPreemption(isolate);
- CHECK(regexp_success_);
- CHECK(gc_success_);
- }
-
- private:
- // Number of garbage collections required.
- static const int kRequiredGCs = 5;
-
- class GCThread : public i::Thread {
- public:
- explicit GCThread(RegExpInterruptTest* test)
- : Thread("GCThread"), test_(test) {}
- virtual void Run() {
- test_->CollectGarbage();
- }
- private:
- RegExpInterruptTest* test_;
- };
-
- void CollectGarbage() {
- block_.Wait();
- while (gc_during_regexp_ < kRequiredGCs) {
- {
- v8::Locker lock(CcTest::isolate());
- v8::Isolate::Scope isolate_scope(CcTest::isolate());
- // TODO(lrn): Perhaps create some garbage before collecting.
- CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
- gc_count_++;
- }
- i::OS::Sleep(1);
- }
- gc_success_ = true;
- }
-
- void LongRunningRegExp() {
- block_.Signal(); // Enable garbage collection thread on next preemption.
- int rounds = 0;
- while (gc_during_regexp_ < kRequiredGCs) {
- int gc_before = gc_count_;
- {
- // Match 15-30 "a"'s against 14 and a "b".
- const char* c_source =
- "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
- ".exec('aaaaaaaaaaaaaaab') === null";
- Local<String> source = String::New(c_source);
- Local<Script> script = Script::Compile(source);
- Local<Value> result = script->Run();
- if (!result->BooleanValue()) {
- gc_during_regexp_ = kRequiredGCs; // Allow gc thread to exit.
- return;
- }
- }
- {
- // Match 15-30 "a"'s against 15 and a "b".
- const char* c_source =
- "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
- ".exec('aaaaaaaaaaaaaaaab')[0] === 'aaaaaaaaaaaaaaaa'";
- Local<String> source = String::New(c_source);
- Local<Script> script = Script::Compile(source);
- Local<Value> result = script->Run();
- if (!result->BooleanValue()) {
- gc_during_regexp_ = kRequiredGCs;
- return;
- }
- }
- int gc_after = gc_count_;
- gc_during_regexp_ += gc_after - gc_before;
- rounds++;
- i::OS::Sleep(1);
- }
- regexp_success_ = true;
- }
-
- i::Semaphore block_;
- int gc_count_;
- int gc_during_regexp_;
- bool regexp_success_;
- bool gc_success_;
-};
-
-
-// Test that a regular expression execution can be interrupted and
-// survive a garbage collection.
-TEST(RegExpInterruption) {
- v8::Locker lock(CcTest::isolate());
- v8::HandleScope scope(CcTest::isolate());
- Local<Context> local_env;
- {
- LocalContext env;
- local_env = env.local();
- }
-
- // Local context should still be live.
- CHECK(!local_env.IsEmpty());
- local_env->Enter();
-
- // Should complete without problems.
- RegExpInterruptTest().RunTest();
-
- local_env->Exit();
-}
-
-
class ApplyInterruptTest {
public:
ApplyInterruptTest() : block_(0) {}
@@ -14735,144 +14705,79 @@ TEST(CompileExternalTwoByteSource) {
}
-class RegExpStringModificationTest {
- public:
- RegExpStringModificationTest()
- : block_(0),
- morphs_(0),
- morphs_during_regexp_(0),
- ascii_resource_(i::Vector<const char>("aaaaaaaaaaaaaab", 15)),
- uc16_resource_(i::Vector<const uint16_t>(two_byte_content_, 15)) {}
- ~RegExpStringModificationTest() {}
- void RunTest() {
- v8::Isolate* isolate = CcTest::isolate();
- i::Factory* factory = CcTest::i_isolate()->factory();
+#ifndef V8_INTERPRETED_REGEXP
- regexp_success_ = false;
- morph_success_ = false;
+struct RegExpInterruptionData {
+ int loop_count;
+ UC16VectorResource* string_resource;
+ v8::Persistent<v8::String> string;
+} regexp_interruption_data;
- // Initialize the contents of two_byte_content_ to be a uc16 representation
- // of "aaaaaaaaaaaaaab".
- for (int i = 0; i < 14; i++) {
- two_byte_content_[i] = 'a';
- }
- two_byte_content_[14] = 'b';
-
- // Create the input string for the regexp - the one we are going to change
- // properties of.
- input_ = factory->NewExternalStringFromAscii(&ascii_resource_);
-
- // Inject the input as a global variable.
- i::Handle<i::String> input_name =
- factory->NewStringFromAscii(i::Vector<const char>("input", 5));
- i::JSReceiver::SetProperty(
- i::handle(CcTest::i_isolate()->native_context()->global_object()),
- input_name,
- input_,
- NONE,
- i::kNonStrictMode);
-
- MorphThread morph_thread(this);
- morph_thread.Start();
- v8::Locker::StartPreemption(isolate, 1);
- LongRunningRegExp();
- {
- v8::Unlocker unlock(isolate);
- morph_thread.Join();
+
+class RegExpInterruptionThread : public i::Thread {
+ public:
+ explicit RegExpInterruptionThread(v8::Isolate* isolate)
+ : Thread("TimeoutThread"), isolate_(isolate) {}
+
+ virtual void Run() {
+ for (regexp_interruption_data.loop_count = 0;
+ regexp_interruption_data.loop_count < 7;
+ regexp_interruption_data.loop_count++) {
+ i::OS::Sleep(50); // Wait a bit before requesting GC.
+ reinterpret_cast<i::Isolate*>(isolate_)->stack_guard()->RequestGC();
}
- v8::Locker::StopPreemption(isolate);
- CHECK(regexp_success_);
- CHECK(morph_success_);
+ i::OS::Sleep(50); // Wait a bit before terminating.
+ v8::V8::TerminateExecution(isolate_);
}
private:
- // Number of string modifications required.
- static const int kRequiredModifications = 5;
- static const int kMaxModifications = 100;
+ v8::Isolate* isolate_;
+};
- class MorphThread : public i::Thread {
- public:
- explicit MorphThread(RegExpStringModificationTest* test)
- : Thread("MorphThread"), test_(test) {}
- virtual void Run() {
- test_->MorphString();
- }
- private:
- RegExpStringModificationTest* test_;
- };
- void MorphString() {
- block_.Wait();
- while (morphs_during_regexp_ < kRequiredModifications &&
- morphs_ < kMaxModifications) {
- {
- v8::Locker lock(CcTest::isolate());
- v8::Isolate::Scope isolate_scope(CcTest::isolate());
- // Swap string between ascii and two-byte representation.
- i::String* string = *input_;
- MorphAString(string, &ascii_resource_, &uc16_resource_);
- morphs_++;
- }
- i::OS::Sleep(1);
- }
- morph_success_ = true;
- }
+void RunBeforeGC(v8::GCType type, v8::GCCallbackFlags flags) {
+ if (regexp_interruption_data.loop_count != 2) return;
+ v8::HandleScope scope(CcTest::isolate());
+ v8::Local<v8::String> string = v8::Local<v8::String>::New(
+ CcTest::isolate(), regexp_interruption_data.string);
+ string->MakeExternal(regexp_interruption_data.string_resource);
+}
- void LongRunningRegExp() {
- block_.Signal(); // Enable morphing thread on next preemption.
- while (morphs_during_regexp_ < kRequiredModifications &&
- morphs_ < kMaxModifications) {
- int morphs_before = morphs_;
- {
- v8::HandleScope scope(CcTest::isolate());
- // Match 15-30 "a"'s against 14 and a "b".
- const char* c_source =
- "/a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaa/"
- ".exec(input) === null";
- Local<String> source = String::New(c_source);
- Local<Script> script = Script::Compile(source);
- Local<Value> result = script->Run();
- CHECK(result->IsTrue());
- }
- int morphs_after = morphs_;
- morphs_during_regexp_ += morphs_after - morphs_before;
- }
- regexp_success_ = true;
- }
- i::uc16 two_byte_content_[15];
- i::Semaphore block_;
- int morphs_;
- int morphs_during_regexp_;
- bool regexp_success_;
- bool morph_success_;
- i::Handle<i::String> input_;
- AsciiVectorResource ascii_resource_;
- UC16VectorResource uc16_resource_;
-};
+// Test that RegExp execution can be interrupted. Specifically, we test
+// * interrupting with GC
+// * turn the subject string from one-byte internal to two-byte external string
+// * force termination
+TEST(RegExpInterruption) {
+ v8::HandleScope scope(CcTest::isolate());
+ LocalContext env;
+ RegExpInterruptionThread timeout_thread(CcTest::isolate());
-// Test that a regular expression execution can be interrupted and
-// the string changed without failing.
-TEST(RegExpStringModification) {
- v8::Locker lock(CcTest::isolate());
- v8::HandleScope scope(CcTest::isolate());
- Local<Context> local_env;
- {
- LocalContext env;
- local_env = env.local();
- }
+ v8::V8::AddGCPrologueCallback(RunBeforeGC);
+ static const char* ascii_content = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ i::uc16* uc16_content = AsciiToTwoByteString(ascii_content);
+ v8::Local<v8::String> string = v8_str(ascii_content);
- // Local context should still be live.
- CHECK(!local_env.IsEmpty());
- local_env->Enter();
+ CcTest::global()->Set(v8_str("a"), string);
+ regexp_interruption_data.string.Reset(CcTest::isolate(), string);
+ regexp_interruption_data.string_resource = new UC16VectorResource(
+ i::Vector<const i::uc16>(uc16_content, i::StrLength(ascii_content)));
- // Should complete without problems.
- RegExpStringModificationTest().RunTest();
+ v8::TryCatch try_catch;
+ timeout_thread.Start();
- local_env->Exit();
+ CompileRun("/((a*)*)*b/.exec(a)");
+ CHECK(try_catch.HasTerminated());
+
+ timeout_thread.Join();
+
+ delete regexp_interruption_data.string_resource;
+ regexp_interruption_data.string.Dispose();
}
+#endif // V8_INTERPRETED_REGEXP
+
// Test that we cannot set a property on the global object if there
// is a read-only property in the prototype chain.
@@ -17599,6 +17504,70 @@ THREADED_TEST(FunctionGetInferredName) {
}
+THREADED_TEST(FunctionGetDisplayName) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ const char* code = "var error = false;"
+ "function a() { this.x = 1; };"
+ "a.displayName = 'display_a';"
+ "var b = (function() {"
+ " var f = function() { this.x = 2; };"
+ " f.displayName = 'display_b';"
+ " return f;"
+ "})();"
+ "var c = function() {};"
+ "c.__defineGetter__('displayName', function() {"
+ " error = true;"
+ " throw new Error();"
+ "});"
+ "function d() {};"
+ "d.__defineGetter__('displayName', function() {"
+ " error = true;"
+ " return 'wrong_display_name';"
+ "});"
+ "function e() {};"
+ "e.displayName = 'wrong_display_name';"
+ "e.__defineSetter__('displayName', function() {"
+ " error = true;"
+ " throw new Error();"
+ "});"
+ "function f() {};"
+ "f.displayName = { 'foo': 6, toString: function() {"
+ " error = true;"
+ " return 'wrong_display_name';"
+ "}};"
+ "var g = function() {"
+ " arguments.callee.displayName = 'set_in_runtime';"
+ "}; g();"
+ ;
+ v8::ScriptOrigin origin = v8::ScriptOrigin(v8::String::New("test"));
+ v8::Script::Compile(v8::String::New(code), &origin)->Run();
+ v8::Local<v8::Value> error = env->Global()->Get(v8::String::New("error"));
+ v8::Local<v8::Function> a = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("a")));
+ v8::Local<v8::Function> b = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("b")));
+ v8::Local<v8::Function> c = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("c")));
+ v8::Local<v8::Function> d = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("d")));
+ v8::Local<v8::Function> e = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("e")));
+ v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("f")));
+ v8::Local<v8::Function> g = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("g")));
+ CHECK_EQ(false, error->BooleanValue());
+ CHECK_EQ("display_a", *v8::String::Utf8Value(a->GetDisplayName()));
+ CHECK_EQ("display_b", *v8::String::Utf8Value(b->GetDisplayName()));
+ CHECK(c->GetDisplayName()->IsUndefined());
+ CHECK(d->GetDisplayName()->IsUndefined());
+ CHECK(e->GetDisplayName()->IsUndefined());
+ CHECK(f->GetDisplayName()->IsUndefined());
+ CHECK_EQ("set_in_runtime", *v8::String::Utf8Value(g->GetDisplayName()));
+}
+
+
THREADED_TEST(ScriptLineNumber) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -17632,6 +17601,23 @@ THREADED_TEST(ScriptColumnNumber) {
}
+THREADED_TEST(FunctionIsBuiltin) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+ v8::Local<v8::Function> f;
+ f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor"));
+ CHECK(f->IsBuiltin());
+ f = v8::Local<v8::Function>::Cast(CompileRun("Object"));
+ CHECK(f->IsBuiltin());
+ f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__"));
+ CHECK(f->IsBuiltin());
+ f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString"));
+ CHECK(f->IsBuiltin());
+ f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;"));
+ CHECK(!f->IsBuiltin());
+}
+
+
THREADED_TEST(FunctionGetScriptId) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
« no previous file with comments | « test/cctest/cctest.status ('k') | test/cctest/test-assembler-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698