blob: ca0f0731332a2c42a195e3a27063a1aabfb8e2f5 [file] [log] [blame]
lrn@chromium.org0040ca92011-05-09 10:42:56 +00001// Copyright 2007-2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <limits.h>
29
ulan@chromium.org57ff8812013-05-10 08:16:55 +000030// TODO(dcarney): remove
31#define V8_ALLOW_ACCESS_TO_PERSISTENT_IMPLICIT
32
lrn@chromium.org0040ca92011-05-09 10:42:56 +000033#include "v8.h"
34
35#include "api.h"
36#include "isolate.h"
37#include "compilation-cache.h"
38#include "execution.h"
danno@chromium.orgca29dd82013-04-26 11:59:48 +000039#include "smart-pointers.h"
lrn@chromium.org0040ca92011-05-09 10:42:56 +000040#include "snapshot.h"
41#include "platform.h"
42#include "utils.h"
43#include "cctest.h"
44#include "parser.h"
45#include "unicode-inl.h"
46
47using ::v8::AccessorInfo;
48using ::v8::Context;
49using ::v8::Extension;
50using ::v8::Function;
51using ::v8::HandleScope;
52using ::v8::Local;
53using ::v8::Object;
54using ::v8::ObjectTemplate;
55using ::v8::Persistent;
56using ::v8::Script;
57using ::v8::String;
58using ::v8::Value;
59using ::v8::V8;
60
lrn@chromium.org0040ca92011-05-09 10:42:56 +000061
62// Migrating an isolate
63class KangarooThread : public v8::internal::Thread {
64 public:
danno@chromium.orgca29dd82013-04-26 11:59:48 +000065 KangarooThread(v8::Isolate* isolate, v8::Handle<v8::Context> context)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +000066 : Thread("KangarooThread"),
danno@chromium.orgca29dd82013-04-26 11:59:48 +000067 isolate_(isolate),
68 context_(isolate, context) {}
lrn@chromium.org0040ca92011-05-09 10:42:56 +000069
70 void Run() {
71 {
72 v8::Locker locker(isolate_);
73 v8::Isolate::Scope isolate_scope(isolate_);
74 CHECK_EQ(isolate_, v8::internal::Isolate::Current());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000075 v8::HandleScope scope(isolate_);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000076 v8::Context::Scope context_scope(isolate_, context_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +000077 Local<Value> v = CompileRun("getValue()");
78 CHECK(v->IsNumber());
79 CHECK_EQ(30, static_cast<int>(v->NumberValue()));
80 }
81 {
82 v8::Locker locker(isolate_);
83 v8::Isolate::Scope isolate_scope(isolate_);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +000084 v8::HandleScope scope(isolate_);
ulan@chromium.org57ff8812013-05-10 08:16:55 +000085 v8::Context::Scope context_scope(isolate_, context_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +000086 Local<Value> v = CompileRun("getValue()");
87 CHECK(v->IsNumber());
88 CHECK_EQ(30, static_cast<int>(v->NumberValue()));
89 }
90 isolate_->Dispose();
91 }
92
93 private:
94 v8::Isolate* isolate_;
95 Persistent<v8::Context> context_;
lrn@chromium.org0040ca92011-05-09 10:42:56 +000096};
97
98// Migrates an isolate from one thread to another
99TEST(KangarooIsolates) {
100 v8::Isolate* isolate = v8::Isolate::New();
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000101 i::SmartPointer<KangarooThread> thread1;
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000102 {
103 v8::Locker locker(isolate);
104 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000105 v8::HandleScope handle_scope(isolate);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000106 v8::Local<v8::Context> context = v8::Context::New(isolate);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000107 v8::Context::Scope context_scope(context);
108 CHECK_EQ(isolate, v8::internal::Isolate::Current());
109 CompileRun("function getValue() { return 30; }");
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000110 thread1.Reset(new KangarooThread(isolate, context));
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000111 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000112 thread1->Start();
113 thread1->Join();
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000114}
115
116static void CalcFibAndCheck() {
117 Local<Value> v = CompileRun("function fib(n) {"
118 " if (n <= 2) return 1;"
119 " return fib(n-1) + fib(n-2);"
120 "}"
121 "fib(10)");
122 CHECK(v->IsNumber());
123 CHECK_EQ(55, static_cast<int>(v->NumberValue()));
124}
125
126class JoinableThread {
127 public:
128 explicit JoinableThread(const char* name)
129 : name_(name),
130 semaphore_(i::OS::CreateSemaphore(0)),
131 thread_(this) {
132 }
133
134 virtual ~JoinableThread() {
135 delete semaphore_;
136 }
137
138 void Start() {
139 thread_.Start();
140 }
141
142 void Join() {
143 semaphore_->Wait();
144 }
145
146 virtual void Run() = 0;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000147
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000148 private:
149 class ThreadWithSemaphore : public i::Thread {
150 public:
151 explicit ThreadWithSemaphore(JoinableThread* joinable_thread)
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000152 : Thread(joinable_thread->name_),
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000153 joinable_thread_(joinable_thread) {
154 }
155
156 virtual void Run() {
157 joinable_thread_->Run();
158 joinable_thread_->semaphore_->Signal();
159 }
160
161 private:
162 JoinableThread* joinable_thread_;
163 };
164
165 const char* name_;
166 i::Semaphore* semaphore_;
167 ThreadWithSemaphore thread_;
168
169 friend class ThreadWithSemaphore;
170
171 DISALLOW_COPY_AND_ASSIGN(JoinableThread);
172};
173
174
175class IsolateLockingThreadWithLocalContext : public JoinableThread {
176 public:
177 explicit IsolateLockingThreadWithLocalContext(v8::Isolate* isolate)
178 : JoinableThread("IsolateLockingThread"),
179 isolate_(isolate) {
180 }
181
182 virtual void Run() {
183 v8::Locker locker(isolate_);
184 v8::Isolate::Scope isolate_scope(isolate_);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000185 v8::HandleScope handle_scope(isolate_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000186 LocalContext local_context;
187 CHECK_EQ(isolate_, v8::internal::Isolate::Current());
188 CalcFibAndCheck();
189 }
190 private:
191 v8::Isolate* isolate_;
192};
193
194static void StartJoinAndDeleteThreads(const i::List<JoinableThread*>& threads) {
195 for (int i = 0; i < threads.length(); i++) {
196 threads[i]->Start();
197 }
198 for (int i = 0; i < threads.length(); i++) {
199 threads[i]->Join();
200 }
201 for (int i = 0; i < threads.length(); i++) {
202 delete threads[i];
203 }
204}
205
206
207// Run many threads all locking on the same isolate
208TEST(IsolateLockingStress) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000209#ifdef V8_TARGET_ARCH_MIPS
210 const int kNThreads = 50;
211#else
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000212 const int kNThreads = 100;
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000213#endif
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000214 i::List<JoinableThread*> threads(kNThreads);
215 v8::Isolate* isolate = v8::Isolate::New();
216 for (int i = 0; i < kNThreads; i++) {
217 threads.Add(new IsolateLockingThreadWithLocalContext(isolate));
218 }
219 StartJoinAndDeleteThreads(threads);
220 isolate->Dispose();
221}
222
223class IsolateNonlockingThread : public JoinableThread {
224 public:
225 explicit IsolateNonlockingThread()
226 : JoinableThread("IsolateNonlockingThread") {
227 }
228
229 virtual void Run() {
230 v8::Isolate* isolate = v8::Isolate::New();
231 {
232 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000233 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000234 v8::Handle<v8::Context> context = v8::Context::New(isolate);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000235 v8::Context::Scope context_scope(context);
236 CHECK_EQ(isolate, v8::internal::Isolate::Current());
237 CalcFibAndCheck();
238 }
239 isolate->Dispose();
240 }
241 private:
242};
243
244// Run many threads each accessing its own isolate without locking
245TEST(MultithreadedParallelIsolates) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000246#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000247 const int kNThreads = 10;
248#else
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000249 const int kNThreads = 50;
vegorov@chromium.org7304bca2011-05-16 12:14:13 +0000250#endif
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000251 i::List<JoinableThread*> threads(kNThreads);
252 for (int i = 0; i < kNThreads; i++) {
253 threads.Add(new IsolateNonlockingThread());
254 }
255 StartJoinAndDeleteThreads(threads);
256}
257
258
259class IsolateNestedLockingThread : public JoinableThread {
260 public:
261 explicit IsolateNestedLockingThread(v8::Isolate* isolate)
262 : JoinableThread("IsolateNestedLocking"), isolate_(isolate) {
263 }
264 virtual void Run() {
265 v8::Locker lock(isolate_);
266 v8::Isolate::Scope isolate_scope(isolate_);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000267 v8::HandleScope handle_scope(isolate_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000268 LocalContext local_context;
269 {
270 v8::Locker another_lock(isolate_);
271 CalcFibAndCheck();
272 }
273 {
274 v8::Locker another_lock(isolate_);
275 CalcFibAndCheck();
276 }
277 }
278 private:
279 v8::Isolate* isolate_;
280};
281
282// Run many threads with nested locks
283TEST(IsolateNestedLocking) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000284#ifdef V8_TARGET_ARCH_MIPS
285 const int kNThreads = 50;
286#else
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000287 const int kNThreads = 100;
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000288#endif
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000289 v8::Isolate* isolate = v8::Isolate::New();
290 i::List<JoinableThread*> threads(kNThreads);
291 for (int i = 0; i < kNThreads; i++) {
292 threads.Add(new IsolateNestedLockingThread(isolate));
293 }
294 StartJoinAndDeleteThreads(threads);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000295 isolate->Dispose();
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000296}
297
298
299class SeparateIsolatesLocksNonexclusiveThread : public JoinableThread {
300 public:
301 SeparateIsolatesLocksNonexclusiveThread(v8::Isolate* isolate1,
302 v8::Isolate* isolate2)
303 : JoinableThread("SeparateIsolatesLocksNonexclusiveThread"),
304 isolate1_(isolate1), isolate2_(isolate2) {
305 }
306
307 virtual void Run() {
308 v8::Locker lock(isolate1_);
309 v8::Isolate::Scope isolate_scope(isolate1_);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000310 v8::HandleScope handle_scope(isolate1_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000311 LocalContext local_context;
312
313 IsolateLockingThreadWithLocalContext threadB(isolate2_);
314 threadB.Start();
315 CalcFibAndCheck();
316 threadB.Join();
317 }
318 private:
319 v8::Isolate* isolate1_;
320 v8::Isolate* isolate2_;
321};
322
323// Run parallel threads that lock and access different isolates in parallel
324TEST(SeparateIsolatesLocksNonexclusive) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000325#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000326 const int kNThreads = 50;
327#else
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000328 const int kNThreads = 100;
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000329#endif
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000330 v8::Isolate* isolate1 = v8::Isolate::New();
331 v8::Isolate* isolate2 = v8::Isolate::New();
332 i::List<JoinableThread*> threads(kNThreads);
333 for (int i = 0; i < kNThreads; i++) {
334 threads.Add(new SeparateIsolatesLocksNonexclusiveThread(isolate1,
335 isolate2));
336 }
337 StartJoinAndDeleteThreads(threads);
338 isolate2->Dispose();
339 isolate1->Dispose();
340}
341
342class LockIsolateAndCalculateFibSharedContextThread : public JoinableThread {
343 public:
344 explicit LockIsolateAndCalculateFibSharedContextThread(
345 v8::Isolate* isolate, v8::Handle<v8::Context> context)
346 : JoinableThread("LockIsolateAndCalculateFibThread"),
347 isolate_(isolate),
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000348 context_(isolate, context) {
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000349 }
350
351 virtual void Run() {
352 v8::Locker lock(isolate_);
353 v8::Isolate::Scope isolate_scope(isolate_);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000354 HandleScope handle_scope(isolate_);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000355 v8::Context::Scope context_scope(isolate_, context_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000356 CalcFibAndCheck();
357 }
358 private:
359 v8::Isolate* isolate_;
360 Persistent<v8::Context> context_;
361};
362
363class LockerUnlockerThread : public JoinableThread {
364 public:
365 explicit LockerUnlockerThread(v8::Isolate* isolate)
366 : JoinableThread("LockerUnlockerThread"),
367 isolate_(isolate) {
368 }
369
370 virtual void Run() {
371 v8::Locker lock(isolate_);
372 v8::Isolate::Scope isolate_scope(isolate_);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000373 v8::HandleScope handle_scope(isolate_);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000374 v8::Local<v8::Context> context = v8::Context::New(isolate_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000375 {
376 v8::Context::Scope context_scope(context);
377 CalcFibAndCheck();
378 }
379 {
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000380 LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000381 isolate_->Exit();
382 v8::Unlocker unlocker(isolate_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000383 thread.Start();
384 thread.Join();
385 }
386 isolate_->Enter();
387 {
388 v8::Context::Scope context_scope(context);
389 CalcFibAndCheck();
390 }
391 }
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000392
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000393 private:
394 v8::Isolate* isolate_;
395};
396
397// Use unlocker inside of a Locker, multiple threads.
398TEST(LockerUnlocker) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000399#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000400 const int kNThreads = 50;
401#else
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000402 const int kNThreads = 100;
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000403#endif
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000404 i::List<JoinableThread*> threads(kNThreads);
405 v8::Isolate* isolate = v8::Isolate::New();
406 for (int i = 0; i < kNThreads; i++) {
407 threads.Add(new LockerUnlockerThread(isolate));
408 }
409 StartJoinAndDeleteThreads(threads);
410 isolate->Dispose();
411}
412
413class LockTwiceAndUnlockThread : public JoinableThread {
414 public:
415 explicit LockTwiceAndUnlockThread(v8::Isolate* isolate)
416 : JoinableThread("LockTwiceAndUnlockThread"),
417 isolate_(isolate) {
418 }
419
420 virtual void Run() {
421 v8::Locker lock(isolate_);
422 v8::Isolate::Scope isolate_scope(isolate_);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000423 v8::HandleScope handle_scope(isolate_);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000424 v8::Local<v8::Context> context = v8::Context::New(isolate_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000425 {
426 v8::Context::Scope context_scope(context);
427 CalcFibAndCheck();
428 }
429 {
430 v8::Locker second_lock(isolate_);
431 {
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000432 LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000433 isolate_->Exit();
434 v8::Unlocker unlocker(isolate_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000435 thread.Start();
436 thread.Join();
437 }
438 }
439 isolate_->Enter();
440 {
441 v8::Context::Scope context_scope(context);
442 CalcFibAndCheck();
443 }
444 }
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000445
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000446 private:
447 v8::Isolate* isolate_;
448};
449
450// Use Unlocker inside two Lockers.
451TEST(LockTwiceAndUnlock) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000452#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000453 const int kNThreads = 50;
454#else
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000455 const int kNThreads = 100;
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000456#endif
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000457 i::List<JoinableThread*> threads(kNThreads);
458 v8::Isolate* isolate = v8::Isolate::New();
459 for (int i = 0; i < kNThreads; i++) {
460 threads.Add(new LockTwiceAndUnlockThread(isolate));
461 }
462 StartJoinAndDeleteThreads(threads);
463 isolate->Dispose();
464}
465
466class LockAndUnlockDifferentIsolatesThread : public JoinableThread {
467 public:
468 LockAndUnlockDifferentIsolatesThread(v8::Isolate* isolate1,
469 v8::Isolate* isolate2)
470 : JoinableThread("LockAndUnlockDifferentIsolatesThread"),
471 isolate1_(isolate1),
472 isolate2_(isolate2) {
473 }
474
475 virtual void Run() {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000476 i::SmartPointer<LockIsolateAndCalculateFibSharedContextThread> thread;
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000477 v8::Locker lock1(isolate1_);
478 CHECK(v8::Locker::IsLocked(isolate1_));
479 CHECK(!v8::Locker::IsLocked(isolate2_));
480 {
481 v8::Isolate::Scope isolate_scope(isolate1_);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000482 v8::HandleScope handle_scope(isolate1_);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000483 v8::Handle<v8::Context> context1 = v8::Context::New(isolate1_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000484 {
485 v8::Context::Scope context_scope(context1);
486 CalcFibAndCheck();
487 }
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000488 thread.Reset(new LockIsolateAndCalculateFibSharedContextThread(
489 isolate1_, context1));
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000490 }
491 v8::Locker lock2(isolate2_);
492 CHECK(v8::Locker::IsLocked(isolate1_));
493 CHECK(v8::Locker::IsLocked(isolate2_));
494 {
495 v8::Isolate::Scope isolate_scope(isolate2_);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000496 v8::HandleScope handle_scope(isolate2_);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000497 v8::Handle<v8::Context> context2 = v8::Context::New(isolate2_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000498 {
499 v8::Context::Scope context_scope(context2);
500 CalcFibAndCheck();
501 }
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000502 v8::Unlocker unlock1(isolate1_);
503 CHECK(!v8::Locker::IsLocked(isolate1_));
504 CHECK(v8::Locker::IsLocked(isolate2_));
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000505 v8::Context::Scope context_scope(context2);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000506 thread->Start();
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000507 CalcFibAndCheck();
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000508 thread->Join();
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000509 }
510 }
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000511
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000512 private:
513 v8::Isolate* isolate1_;
514 v8::Isolate* isolate2_;
515};
516
517// Lock two isolates and unlock one of them.
518TEST(LockAndUnlockDifferentIsolates) {
519 v8::Isolate* isolate1 = v8::Isolate::New();
520 v8::Isolate* isolate2 = v8::Isolate::New();
521 LockAndUnlockDifferentIsolatesThread thread(isolate1, isolate2);
522 thread.Start();
523 thread.Join();
524 isolate2->Dispose();
525 isolate1->Dispose();
526}
527
528class LockUnlockLockThread : public JoinableThread {
529 public:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000530 LockUnlockLockThread(v8::Isolate* isolate, v8::Handle<v8::Context> context)
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000531 : JoinableThread("LockUnlockLockThread"),
532 isolate_(isolate),
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000533 context_(isolate, context) {
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000534 }
535
536 virtual void Run() {
537 v8::Locker lock1(isolate_);
538 CHECK(v8::Locker::IsLocked(isolate_));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000539 CHECK(!v8::Locker::IsLocked(CcTest::default_isolate()));
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000540 {
541 v8::Isolate::Scope isolate_scope(isolate_);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000542 v8::HandleScope handle_scope(isolate_);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000543 v8::Context::Scope context_scope(isolate_, context_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000544 CalcFibAndCheck();
545 }
546 {
547 v8::Unlocker unlock1(isolate_);
548 CHECK(!v8::Locker::IsLocked(isolate_));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000549 CHECK(!v8::Locker::IsLocked(CcTest::default_isolate()));
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000550 {
551 v8::Locker lock2(isolate_);
552 v8::Isolate::Scope isolate_scope(isolate_);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000553 v8::HandleScope handle_scope(isolate_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000554 CHECK(v8::Locker::IsLocked(isolate_));
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000555 CHECK(!v8::Locker::IsLocked(CcTest::default_isolate()));
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000556 v8::Context::Scope context_scope(isolate_, context_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000557 CalcFibAndCheck();
558 }
559 }
560 }
561
562 private:
563 v8::Isolate* isolate_;
564 v8::Persistent<v8::Context> context_;
565};
566
567// Locker inside an Unlocker inside a Locker.
568TEST(LockUnlockLockMultithreaded) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000569#ifdef V8_TARGET_ARCH_MIPS
570 const int kNThreads = 50;
571#else
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000572 const int kNThreads = 100;
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000573#endif
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000574 v8::Isolate* isolate = v8::Isolate::New();
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000575 i::List<JoinableThread*> threads(kNThreads);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000576 {
577 v8::Locker locker_(isolate);
578 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000579 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000580 v8::Handle<v8::Context> context = v8::Context::New(isolate);
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000581 for (int i = 0; i < kNThreads; i++) {
582 threads.Add(new LockUnlockLockThread(
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000583 isolate, context));
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000584 }
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000585 }
586 StartJoinAndDeleteThreads(threads);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000587 isolate->Dispose();
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000588}
589
590class LockUnlockLockDefaultIsolateThread : public JoinableThread {
591 public:
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000592 explicit LockUnlockLockDefaultIsolateThread(v8::Handle<v8::Context> context)
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000593 : JoinableThread("LockUnlockLockDefaultIsolateThread"),
594 context_(CcTest::default_isolate(), context) {}
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000595
596 virtual void Run() {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000597 v8::Locker lock1(CcTest::default_isolate());
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000598 {
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000599 v8::HandleScope handle_scope(CcTest::default_isolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000600 v8::Context::Scope context_scope(CcTest::default_isolate(), context_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000601 CalcFibAndCheck();
602 }
603 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000604 v8::Unlocker unlock1(CcTest::default_isolate());
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000605 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000606 v8::Locker lock2(CcTest::default_isolate());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000607 v8::HandleScope handle_scope(CcTest::default_isolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000608 v8::Context::Scope context_scope(CcTest::default_isolate(), context_);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000609 CalcFibAndCheck();
610 }
611 }
612 }
613
614 private:
615 v8::Persistent<v8::Context> context_;
616};
617
618// Locker inside an Unlocker inside a Locker for default isolate.
619TEST(LockUnlockLockDefaultIsolateMultithreaded) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000620#ifdef V8_TARGET_ARCH_MIPS
621 const int kNThreads = 50;
622#else
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000623 const int kNThreads = 100;
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000624#endif
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000625 Local<v8::Context> context;
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000626 i::List<JoinableThread*> threads(kNThreads);
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000627 {
yangguo@chromium.org46a2a512013-01-18 16:29:40 +0000628 v8::Locker locker_(CcTest::default_isolate());
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000629 v8::HandleScope handle_scope(CcTest::default_isolate());
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000630 context = v8::Context::New(CcTest::default_isolate());
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000631 for (int i = 0; i < kNThreads; i++) {
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000632 threads.Add(new LockUnlockLockDefaultIsolateThread(context));
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000633 }
lrn@chromium.org0040ca92011-05-09 10:42:56 +0000634 }
635 StartJoinAndDeleteThreads(threads);
636}
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000637
638
639TEST(Regress1433) {
640 for (int i = 0; i < 10; i++) {
641 v8::Isolate* isolate = v8::Isolate::New();
642 {
643 v8::Locker lock(isolate);
644 v8::Isolate::Scope isolate_scope(isolate);
svenpanne@chromium.org2bda5432013-03-15 12:39:50 +0000645 v8::HandleScope handle_scope(isolate);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000646 v8::Handle<Context> context = v8::Context::New(isolate);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000647 v8::Context::Scope context_scope(context);
648 v8::Handle<String> source = v8::String::New("1+1");
649 v8::Handle<Script> script = v8::Script::Compile(source);
650 v8::Handle<Value> result = script->Run();
651 v8::String::AsciiValue ascii(result);
jkummerow@chromium.orge297f592011-06-08 10:05:15 +0000652 }
653 isolate->Dispose();
654 }
655}
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000656
657
658static const char* kSimpleExtensionSource =
659 "(function Foo() {"
660 " return 4;"
661 "})() ";
662
663class IsolateGenesisThread : public JoinableThread {
664 public:
665 IsolateGenesisThread(int count, const char* extension_names[])
666 : JoinableThread("IsolateGenesisThread"),
667 count_(count),
668 extension_names_(extension_names)
669 {}
670
671 virtual void Run() {
672 v8::Isolate* isolate = v8::Isolate::New();
673 {
674 v8::Isolate::Scope isolate_scope(isolate);
675 CHECK(!i::Isolate::Current()->has_installed_extensions());
676 v8::ExtensionConfiguration extensions(count_, extension_names_);
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000677 v8::HandleScope handle_scope(isolate);
678 v8::Context::New(isolate, &extensions);
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000679 CHECK(i::Isolate::Current()->has_installed_extensions());
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000680 }
681 isolate->Dispose();
682 }
683 private:
684 int count_;
685 const char** extension_names_;
686};
687
688// Test installing extensions in separate isolates concurrently.
689// http://code.google.com/p/v8/issues/detail?id=1821
690TEST(ExtensionsRegistration) {
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000691#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
692 const int kNThreads = 10;
693#else
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000694 const int kNThreads = 40;
mstarzinger@chromium.orgf8c6bd52011-11-23 12:13:52 +0000695#endif
ricow@chromium.org27bf2882011-11-17 08:34:43 +0000696 v8::RegisterExtension(new v8::Extension("test0",
697 kSimpleExtensionSource));
698 v8::RegisterExtension(new v8::Extension("test1",
699 kSimpleExtensionSource));
700 v8::RegisterExtension(new v8::Extension("test2",
701 kSimpleExtensionSource));
702 v8::RegisterExtension(new v8::Extension("test3",
703 kSimpleExtensionSource));
704 v8::RegisterExtension(new v8::Extension("test4",
705 kSimpleExtensionSource));
706 v8::RegisterExtension(new v8::Extension("test5",
707 kSimpleExtensionSource));
708 v8::RegisterExtension(new v8::Extension("test6",
709 kSimpleExtensionSource));
710 v8::RegisterExtension(new v8::Extension("test7",
711 kSimpleExtensionSource));
712 const char* extension_names[] = { "test0", "test1",
713 "test2", "test3", "test4",
714 "test5", "test6", "test7" };
715 i::List<JoinableThread*> threads(kNThreads);
716 for (int i = 0; i < kNThreads; i++) {
717 threads.Add(new IsolateGenesisThread(8, extension_names));
718 }
719 StartJoinAndDeleteThreads(threads);
720}