Index: test/cctest/test-lockers.cc |
diff --git a/test/cctest/test-lockers.cc b/test/cctest/test-lockers.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..3499f7134338f37fac6e09152728292994fa5e77 |
--- /dev/null |
+++ b/test/cctest/test-lockers.cc |
@@ -0,0 +1,602 @@ |
+// Copyright 2007-2009 the V8 project authors. All rights reserved. |
Vitaly Repeshko
2011/04/15 00:29:39
2011
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+// Redistribution and use in source and binary forms, with or without |
+// modification, are permitted provided that the following conditions are |
+// met: |
+// |
+// * Redistributions of source code must retain the above copyright |
+// notice, this list of conditions and the following disclaimer. |
+// * Redistributions in binary form must reproduce the above |
+// copyright notice, this list of conditions and the following |
+// disclaimer in the documentation and/or other materials provided |
+// with the distribution. |
+// * Neither the name of Google Inc. nor the names of its |
+// contributors may be used to endorse or promote products derived |
+// from this software without specific prior written permission. |
+// |
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+ |
+#include <limits.h> |
+#include <vector> |
+ |
+#include "v8.h" |
+ |
+#include "api.h" |
+#include "isolate.h" |
+#include "compilation-cache.h" |
+#include "execution.h" |
+#include "snapshot.h" |
+#include "platform.h" |
+#include "utils.h" |
+#include "cctest.h" |
+#include "parser.h" |
+#include "unicode-inl.h" |
+ |
+using ::v8::AccessorInfo; |
+using ::v8::Context; |
+using ::v8::Extension; |
+using ::v8::Function; |
+using ::v8::HandleScope; |
+using ::v8::Local; |
+using ::v8::Object; |
+using ::v8::ObjectTemplate; |
+using ::v8::Persistent; |
+using ::v8::Script; |
+using ::v8::String; |
+using ::v8::Value; |
+using ::v8::V8; |
+ |
+namespace i = ::i; |
+ |
+ |
+ |
+ |
+// Migrating an isolate |
+class KangarooThread : public v8::internal::Thread { |
+ public: |
+ explicit KangarooThread(v8::Isolate* isolate, |
Vitaly Repeshko
2011/04/15 00:29:39
nit: explicit not required.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ v8::Handle<v8::Context> context, int value) |
Vitaly Repeshko
2011/04/15 00:29:39
nit: Weird indentation.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ : Thread(NULL, "KangarooThread1"), |
Vitaly Repeshko
2011/04/15 00:29:39
Why 1? There doesn't seem to be a second one.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ isolate_(isolate), context_(context), value_(value) { |
+ } |
+ |
+ void Run() { |
+ { |
+ v8::Locker locker(isolate_); |
+ v8::Isolate::Scope isolate_scope(isolate_); |
+ CHECK_EQ(isolate_, v8::internal::Isolate::Current()); |
+ v8::HandleScope scope; |
+ context_->Enter(); |
Vitaly Repeshko
2011/04/15 00:29:39
Please use Context::Scope where possible.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ Local<Value> v = CompileRun("getValue()"); |
+ CHECK(v->IsNumber()); |
+ CHECK_EQ(30, static_cast<int>(v->NumberValue())); |
+ context_->Exit(); |
+ } |
+ { |
+ v8::Locker locker(isolate_); |
+ v8::Isolate::Scope isolate_scope(isolate_); |
+ context_->Enter(); |
+ v8::HandleScope scope; |
+ Local<Value> v = CompileRun("getValue()"); |
+ CHECK(v->IsNumber()); |
+ CHECK_EQ(30, static_cast<int>(v->NumberValue())); |
+ context_->Exit(); |
+ } |
+ isolate_->Dispose(); |
+ } |
+ |
+ private: |
+ v8::Isolate* isolate_; |
+ Persistent<v8::Context> context_; |
+ int value_; |
+}; |
+ |
+ |
+TEST(KangarooIsolates) { |
Vitaly Repeshko
2011/04/15 00:29:39
Please describe what a test does for non-trivial t
|
+ v8::Isolate* isolate = v8::Isolate::New(); |
+ Persistent<v8::Context> context; |
+ { |
+ v8::Locker locker_(isolate); |
Vitaly Repeshko
2011/04/15 00:29:39
nit: Why _ ?
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ v8::Isolate::Scope isolate_scope(isolate); |
+ v8::HandleScope handle_scope; |
+ context = v8::Context::New(); |
+ context->Enter(); |
+ CHECK_EQ(isolate, v8::internal::Isolate::Current()); |
+ CompileRun("function getValue() { return 30; }"); |
Vitaly Repeshko
2011/04/15 00:29:39
It'd be useful for this script to have some state,
Dmitry Lomov
2011/04/19 01:50:47
It has a state of sorts - note that KangarooThread
|
+ context->Exit(); |
+ } |
+ KangarooThread thread1(isolate, context, 1); |
+ thread1.Start(); |
+ thread1.Join(); |
+} |
+ |
+static void CalcFibAndCheck() { |
+ Local<Value> v = CompileRun("function fib(n) {" |
+ " if (n <= 2) return 1;" |
+ " return fib(n-1) + fib(n-2);" |
+ "}" |
+ "fib(10)"); |
+ CHECK(v->IsNumber()); |
+ CHECK_EQ(55, static_cast<int>(v->NumberValue())); |
+} |
+ |
+class JoinableThread : public i::Thread { |
Vitaly Repeshko
2011/04/15 00:29:39
To make this a bit more readable make JoinableThre
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ public: |
+ explicit JoinableThread(i::Isolate* isolate, const char* name) |
+ : Thread(isolate, name), |
+ semaphore_(NULL) { |
+ } |
+ |
+ void StartWithSignal(i::Semaphore* semaphore) { |
+ semaphore_ = semaphore; |
+ Start(); |
+ } |
+ |
+ void Run() { |
Vitaly Repeshko
2011/04/15 00:29:39
nit: Keep "virtual" when overriding.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ DoRun(); |
+ if (semaphore_ != NULL) |
+ semaphore_->Signal(); |
+ } |
+ virtual void DoRun() = 0; |
+ private: |
+ i::Semaphore* semaphore_; |
+}; |
+ |
+ |
+class IsolateLockingThreadWithLocalContext : public JoinableThread { |
+ public: |
+ explicit IsolateLockingThreadWithLocalContext(v8::Isolate* isolate) |
+ : JoinableThread(NULL, "IsolateLockingThread"), |
+ isolate_(isolate) { |
+ } |
+ |
+ void DoRun() { |
+ v8::Locker locker(isolate_); |
+ v8::Isolate::Scope isolate_scope(isolate_); |
+ v8::HandleScope handle_scope; |
+ LocalContext local_context; |
+ CHECK_EQ(isolate_, v8::internal::Isolate::Current()); |
+ CalcFibAndCheck(); |
+ } |
+ private: |
+ v8::Isolate* isolate_; |
+}; |
+ |
+static void StartJoinAndDeleteThreads(const i::List<JoinableThread*>& threads) { |
+ i::Semaphore* semaphore = i::OS::CreateSemaphore(0); |
+ for (int i = 0; i < threads.length(); i++) { |
+ threads[i]->StartWithSignal(semaphore); |
+ } |
+ for (int i = 0; i < threads.length(); i++) { |
+ semaphore->Wait(); |
+ } |
+ for (int i = 0; i < threads.length(); i++) { |
+ delete threads[i]; |
+ } |
+ delete semaphore; |
+} |
+ |
+TEST(IsolateLockingStress) { |
+ const int kNThreads = 100; |
+ i::List<JoinableThread*> threads(kNThreads); |
+ v8::Isolate* isolate = v8::Isolate::New(); |
+ for (int i = 0; i < kNThreads; i++) { |
+ threads.Add(new IsolateLockingThreadWithLocalContext(isolate)); |
+ } |
+ StartJoinAndDeleteThreads(threads); |
+ isolate->Dispose(); |
+} |
+ |
+class IsolateNonlockingThread : public JoinableThread { |
+ public: |
+ explicit IsolateNonlockingThread() |
+ : JoinableThread(NULL, "IsolateNonlockingThread") { |
+ } |
+ |
+ void DoRun() { |
+ v8::Isolate* isolate = v8::Isolate::New(); |
+ { |
+ v8::Isolate::Scope isolate_scope(isolate); |
+ v8::HandleScope handle_scope; |
+ v8::Handle<v8::Context> context = v8::Context::New(); |
+ context->Enter(); |
+ CHECK_EQ(isolate, v8::internal::Isolate::Current()); |
+ CalcFibAndCheck(); |
+ context->Exit(); |
Vitaly Repeshko
2011/04/15 00:29:39
nit: Fix indentation.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ } |
+ isolate->Dispose(); |
+ } |
+ private: |
+}; |
+ |
+TEST(MultithreadedParallelIsolates) { |
+ const int kNThreads = 50; |
+ i::List<JoinableThread*> threads(kNThreads); |
+ for (int i = 0; i < kNThreads; i++) { |
+ threads.Add(new IsolateNonlockingThread()); |
+ } |
+ StartJoinAndDeleteThreads(threads); |
+} |
+ |
+ |
+class IsolateLockingTwiceThread : public JoinableThread { |
Vitaly Repeshko
2011/04/15 00:29:39
LockingTwice -> NestedLocking
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ public: |
+ explicit IsolateLockingTwiceThread(v8::Isolate* isolate) |
+ : JoinableThread(NULL, "IsolateLockingTwice"), isolate_(isolate) { |
+ } |
+ void DoRun() { |
+ v8::Locker lock(isolate_); |
+ v8::Isolate::Scope isolate_scope(isolate_); |
+ v8::HandleScope handle_scope; |
+ LocalContext local_context; |
+ { |
+ v8::Locker another_lock(isolate_); |
+ CalcFibAndCheck(); |
+ } |
+ { |
+ v8::Locker another_lock(isolate_); |
+ CalcFibAndCheck(); |
+ } |
+ } |
+ private: |
+ v8::Isolate* isolate_; |
+}; |
+ |
+TEST(IsolateLockingTwice) { |
+ const int kNThreads = 100; |
+ v8::Isolate* isolate = v8::Isolate::New(); |
+ i::List<JoinableThread*> threads(kNThreads); |
+ for (int i = 0; i < kNThreads; i++) { |
+ threads.Add(new IsolateLockingTwiceThread(isolate)); |
+ } |
+ StartJoinAndDeleteThreads(threads); |
+} |
+ |
+class LockIsolateAndCalculateFibThread : public JoinableThread { |
Vitaly Repeshko
2011/04/15 00:29:39
Isn't this the same as IsolateLockingThreadWithLoc
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ public: |
+ explicit LockIsolateAndCalculateFibThread(v8::Isolate* isolate) |
+ : JoinableThread(NULL, "LockIsolateAndCalculateFibThread"), |
+ isolate_(isolate) { |
+ } |
+ |
+ void DoRun() { |
+ v8::Locker lock(isolate_); |
+ v8::Isolate::Scope isolate_scope(isolate_); |
+ LocalContext local_context; |
+ HandleScope handle_scope; |
+ CalcFibAndCheck(); |
+ } |
+ private: |
+ v8::Isolate* isolate_; |
+}; |
+ |
+class SeparateIsolatesLocksNonexclusiveThreadA : public JoinableThread { |
+ public: |
+ explicit SeparateIsolatesLocksNonexclusiveThreadA(v8::Isolate* isolate1, |
Vitaly Repeshko
2011/04/15 00:29:39
nit: explicit not required.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ v8::Isolate* isolate2) |
+ : JoinableThread(NULL, "ASeparateIsolatesLocksNonexclusiveThreadA"), |
Vitaly Repeshko
2011/04/15 00:29:39
Why "A"? There doesn't seem to be a "B" variant of
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ isolate1_(isolate1), isolate2_(isolate2) { |
+ } |
+ |
+ void DoRun() { |
+ v8::Locker lock(isolate1_); |
+ v8::Isolate::Scope isolate_scope(isolate1_); |
+ v8::HandleScope handle_scope; |
+ LocalContext local_context; |
+ |
+ LockIsolateAndCalculateFibThread threadB(isolate2_); |
+ i::Semaphore* semaphore = i::OS::CreateSemaphore(0); |
+ threadB.StartWithSignal(semaphore); |
+ CalcFibAndCheck(); |
+ semaphore->Wait(); |
+ delete semaphore; |
+ } |
+ private: |
+ v8::Isolate* isolate1_; |
+ v8::Isolate* isolate2_; |
+}; |
+ |
+TEST(SeparateIsolatesLocksNonexclusive) { |
+ const int kNThreads = 100; |
+ v8::Isolate* isolate1 = v8::Isolate::New(); |
+ v8::Isolate* isolate2 = v8::Isolate::New(); |
+ i::List<JoinableThread*> threads(kNThreads); |
+ for (int i = 0; i < kNThreads; i++) { |
+ threads.Add(new SeparateIsolatesLocksNonexclusiveThreadA(isolate1, |
+ isolate2)); |
+ } |
+ StartJoinAndDeleteThreads(threads); |
+ isolate2->Dispose(); |
+ isolate1->Dispose(); |
+} |
+ |
+class LockIsolateAndCalculateFibSharedContextThread : public JoinableThread { |
+ public: |
+ explicit LockIsolateAndCalculateFibSharedContextThread( |
+ v8::Isolate* isolate, v8::Handle<v8::Context> context) |
+ : JoinableThread(NULL, "LockIsolateAndCalculateFibThread"), |
+ isolate_(isolate), |
+ context_(context) { |
+ } |
+ |
+ void DoRun() { |
+ v8::Locker lock(isolate_); |
+ v8::Isolate::Scope isolate_scope(isolate_); |
+ HandleScope handle_scope; |
+ context_->Enter(); |
+ CalcFibAndCheck(); |
+ context_->Exit(); |
+ } |
+ private: |
+ v8::Isolate* isolate_; |
+ Persistent<v8::Context> context_; |
+}; |
+ |
+class LockerUnlockerThread : public JoinableThread { |
+ public: |
+ explicit LockerUnlockerThread(v8::Isolate* isolate) |
+ : JoinableThread(NULL, "LockerUnlockerThread"), |
+ isolate_(isolate) { |
+ } |
+ |
+ void DoRun() { |
+ v8::Locker lock(isolate_); |
+ v8::Isolate::Scope isolate_scope(isolate_); |
+ v8::HandleScope handle_scope; |
+ v8::Handle<v8::Context> context = v8::Context::New(); |
+ context->Enter(); |
+ CalcFibAndCheck(); |
+ { |
+ context->Exit(); |
Vitaly Repeshko
2011/04/15 00:29:39
Do we have to exit the context here?
Dmitry Lomov
2011/04/19 01:50:47
Yes because we exit the isolate - in the next line
|
+ isolate_->Exit(); |
+ v8::Unlocker unlocker(isolate_); |
Vitaly Repeshko
2011/04/15 00:29:39
Hmm, do we really want to be able to unlock some a
Dmitry Lomov
2011/04/19 01:50:47
Here is what I think on the subject:
1. I do not h
|
+ LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context); |
+ i::Semaphore* semaphore = i::OS::CreateSemaphore(0); |
+ thread.StartWithSignal(semaphore); |
+ semaphore->Wait(); |
+ delete semaphore; |
+ } |
+ isolate_->Enter(); |
+ context->Enter(); |
+ CalcFibAndCheck(); |
Vitaly Repeshko
2011/04/15 00:29:39
context->Exit()?
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ } |
+ private: |
+ v8::Isolate* isolate_; |
+}; |
+ |
+TEST(LockerUnlocker) { |
+ const int kNThreads = 100; |
+ i::List<JoinableThread*> threads(kNThreads); |
+ v8::Isolate* isolate = v8::Isolate::New(); |
+ for (int i = 0; i < kNThreads; i++) { |
+ threads.Add(new LockerUnlockerThread(isolate)); |
+ } |
+ StartJoinAndDeleteThreads(threads); |
+ isolate->Dispose(); |
+} |
+ |
+class LockTwiceAndUnlockThread : public JoinableThread { |
+ public: |
+ explicit LockTwiceAndUnlockThread(v8::Isolate* isolate) |
+ : JoinableThread(NULL, "LockTwiceAndUnlockThread"), |
+ isolate_(isolate) { |
+ } |
+ |
+ void DoRun() { |
+ v8::Locker lock(isolate_); |
+ v8::Isolate::Scope isolate_scope(isolate_); |
+ v8::HandleScope handle_scope; |
+ v8::Handle<v8::Context> context = v8::Context::New(); |
+ context->Enter(); |
+ CalcFibAndCheck(); |
+ { |
+ v8::Locker second_lock(isolate_); |
+ { |
+ context->Exit(); |
+ isolate_->Exit(); |
+ v8::Unlocker unlocker(isolate_); |
+ LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context); |
+ i::Semaphore* semaphore = i::OS::CreateSemaphore(0); |
+ thread.StartWithSignal(semaphore); |
+ semaphore->Wait(); |
+ delete semaphore; |
+ } |
+ } |
+ isolate_->Enter(); |
+ context->Enter(); |
+ CalcFibAndCheck(); |
+ } |
Vitaly Repeshko
2011/04/15 00:29:39
context->Exit()?
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
+ private: |
+ v8::Isolate* isolate_; |
+}; |
+ |
+TEST(LockTwiceAndUnlock) { |
+ const int kNThreads = 100; |
+ i::List<JoinableThread*> threads(kNThreads); |
+ v8::Isolate* isolate = v8::Isolate::New(); |
+ for (int i = 0; i < kNThreads; i++) { |
+ threads.Add(new LockTwiceAndUnlockThread(isolate)); |
+ } |
+ StartJoinAndDeleteThreads(threads); |
+ isolate->Dispose(); |
+} |
+ |
+class LockAndUnlockDifferentIsolatesThread : public JoinableThread { |
+ public: |
+ LockAndUnlockDifferentIsolatesThread(v8::Isolate* isolate1, |
+ v8::Isolate* isolate2) |
+ : JoinableThread(NULL, "LockAndUnlockDifferentIsolatesThread"), |
+ isolate1_(isolate1), |
+ isolate2_(isolate2) { |
+ } |
+ |
+ void DoRun() { |
+ Persistent<v8::Context> context1; |
+ Persistent<v8::Context> context2; |
+ v8::Locker lock1(isolate1_); |
+ CHECK(v8::Locker::IsLocked(isolate1_)); |
+ CHECK(!v8::Locker::IsLocked(isolate2_)); |
+ { |
+ v8::Isolate::Scope isolate_scope(isolate1_); |
+ v8::HandleScope handle_scope; |
+ context1 = v8::Context::New(); |
+ context1->Enter(); |
+ CalcFibAndCheck(); |
+ context1->Exit(); |
+ } |
+ v8::Locker lock2(isolate2_); |
+ CHECK(v8::Locker::IsLocked(isolate1_)); |
+ CHECK(v8::Locker::IsLocked(isolate2_)); |
+ { |
+ v8::Isolate::Scope isolate_scope(isolate2_); |
+ v8::HandleScope handle_scope; |
+ context2 = v8::Context::New(); |
+ context2->Enter(); |
+ CalcFibAndCheck(); |
+ context2->Exit(); |
+ } |
+ { |
+ v8::Unlocker unlock1(isolate1_); |
+ CHECK(!v8::Locker::IsLocked(isolate1_)); |
+ CHECK(v8::Locker::IsLocked(isolate2_)); |
+ v8::Isolate::Scope isolate_scope(isolate2_); |
+ v8::HandleScope handle_scope; |
+ context2->Enter(); |
+ i::Semaphore* semaphore = i::OS::CreateSemaphore(0); |
+ LockIsolateAndCalculateFibSharedContextThread thread(isolate1_, context1); |
+ thread.StartWithSignal(semaphore); |
+ CalcFibAndCheck(); |
+ semaphore->Wait(); |
+ delete semaphore; |
+ context2->Exit(); |
+ } |
+ } |
+ private: |
+ v8::Isolate* isolate1_; |
+ v8::Isolate* isolate2_; |
+}; |
+ |
+TEST(LockAndUnlockDifferentIsolates) { |
+ v8::Isolate* isolate1 = v8::Isolate::New(); |
+ v8::Isolate* isolate2 = v8::Isolate::New(); |
+ LockAndUnlockDifferentIsolatesThread thread(isolate1, isolate2); |
+ i::Semaphore* semaphore = i::OS::CreateSemaphore(0); |
+ thread.StartWithSignal(semaphore); |
+ semaphore->Wait(); |
+ delete semaphore; |
+ isolate2->Dispose(); |
+ isolate1->Dispose(); |
+} |
+ |
+class LockUnlockLockThread : public JoinableThread { |
+ public: |
+ LockUnlockLockThread(v8::Isolate* isolate, v8::Handle<v8::Context> context) |
+ : JoinableThread(NULL, "LockUnlockLockThread"), |
+ isolate_(isolate), |
+ context_(context) { |
+ } |
+ |
+ void DoRun() { |
+ v8::Locker lock1(isolate_); |
+ CHECK(v8::Locker::IsLocked(isolate_)); |
+ CHECK(!v8::Locker::IsLocked()); |
+ { |
+ v8::Isolate::Scope isolate_scope(isolate_); |
+ v8::HandleScope handle_scope; |
+ context_->Enter(); |
+ CalcFibAndCheck(); |
+ context_->Exit(); |
+ } |
+ { |
+ v8::Unlocker unlock1(isolate_); |
+ CHECK(!v8::Locker::IsLocked(isolate_)); |
+ CHECK(!v8::Locker::IsLocked()); |
+ { |
+ v8::Locker lock2(isolate_); |
+ v8::Isolate::Scope isolate_scope(isolate_); |
+ v8::HandleScope handle_scope; |
+ CHECK(v8::Locker::IsLocked(isolate_)); |
+ CHECK(!v8::Locker::IsLocked()); |
+ context_->Enter(); |
+ CalcFibAndCheck(); |
+ context_->Exit(); |
+ } |
+ } |
+ } |
+ |
+ private: |
+ v8::Isolate* isolate_; |
+ v8::Persistent<v8::Context> context_; |
+}; |
+ |
+TEST(LockUnlockLockMultithreaded) { |
+ const int kNThreads = 100; |
+ v8::Isolate* isolate = v8::Isolate::New(); |
+ Persistent<v8::Context> context; |
+ { |
+ v8::Locker locker_(isolate); |
+ v8::Isolate::Scope isolate_scope(isolate); |
+ v8::HandleScope handle_scope; |
+ context = v8::Context::New(); |
+ } |
+ i::List<JoinableThread*> threads(kNThreads); |
+ for (int i = 0; i < kNThreads; i++) { |
+ threads.Add(new LockUnlockLockThread(isolate, context)); |
+ } |
+ StartJoinAndDeleteThreads(threads); |
+} |
+ |
+class LockUnlockLockDefaultIsolateThread : public JoinableThread { |
+ public: |
+ LockUnlockLockDefaultIsolateThread(v8::Handle<v8::Context> context) |
+ : JoinableThread(NULL, "LockUnlockLockDefaultIsolateThread"), |
+ context_(context) { |
+ } |
+ |
+ void DoRun() { |
+ v8::Locker lock1; |
+ { |
+ v8::HandleScope handle_scope; |
+ context_->Enter(); |
+ CalcFibAndCheck(); |
+ context_->Exit(); |
+ } |
+ { |
+ v8::Unlocker unlock1; |
+ { |
+ v8::Locker lock2; |
+ v8::HandleScope handle_scope; |
+ context_->Enter(); |
+ CalcFibAndCheck(); |
+ context_->Exit(); |
+ } |
+ } |
+ } |
+ |
+ private: |
+ v8::Persistent<v8::Context> context_; |
+}; |
+ |
+TEST(LockUnlockLockDefaultIsolateMultithreaded) { |
+ const int kNThreads = 100; |
+ Persistent<v8::Context> context; |
+ { |
+ v8::Locker locker_; |
+ v8::HandleScope handle_scope; |
+ context = v8::Context::New(); |
+ } |
+ i::List<JoinableThread*> threads(kNThreads); |
+ for (int i = 0; i < kNThreads; i++) { |
+ threads.Add(new LockUnlockLockDefaultIsolateThread(context)); |
+ } |
+ StartJoinAndDeleteThreads(threads); |
+} |