• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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 
30 #include "src/v8.h"
31 
32 #include "src/api.h"
33 #include "src/compilation-cache.h"
34 #include "src/execution.h"
35 #include "src/isolate.h"
36 #include "src/parser.h"
37 #include "src/platform.h"
38 #include "src/smart-pointers.h"
39 #include "src/snapshot.h"
40 #include "src/unicode-inl.h"
41 #include "src/utils.h"
42 #include "test/cctest/cctest.h"
43 
44 using ::v8::Context;
45 using ::v8::Extension;
46 using ::v8::Function;
47 using ::v8::HandleScope;
48 using ::v8::Local;
49 using ::v8::Object;
50 using ::v8::ObjectTemplate;
51 using ::v8::Persistent;
52 using ::v8::Script;
53 using ::v8::String;
54 using ::v8::Value;
55 using ::v8::V8;
56 
57 
58 // Migrating an isolate
59 class KangarooThread : public v8::internal::Thread {
60  public:
KangarooThread(v8::Isolate * isolate,v8::Handle<v8::Context> context)61   KangarooThread(v8::Isolate* isolate, v8::Handle<v8::Context> context)
62       : Thread("KangarooThread"),
63         isolate_(isolate),
64         context_(isolate, context) {}
65 
Run()66   void Run() {
67     {
68       v8::Locker locker(isolate_);
69       v8::Isolate::Scope isolate_scope(isolate_);
70       CHECK_EQ(isolate_, v8::internal::Isolate::Current());
71       v8::HandleScope scope(isolate_);
72       v8::Local<v8::Context> context =
73           v8::Local<v8::Context>::New(isolate_, context_);
74       v8::Context::Scope context_scope(context);
75       Local<Value> v = CompileRun("getValue()");
76       CHECK(v->IsNumber());
77       CHECK_EQ(30, static_cast<int>(v->NumberValue()));
78     }
79     {
80       v8::Locker locker(isolate_);
81       v8::Isolate::Scope isolate_scope(isolate_);
82       v8::HandleScope scope(isolate_);
83       v8::Local<v8::Context> context =
84           v8::Local<v8::Context>::New(isolate_, context_);
85       v8::Context::Scope context_scope(context);
86       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_;
96 };
97 
98 
99 // Migrates an isolate from one thread to another
TEST(KangarooIsolates)100 TEST(KangarooIsolates) {
101   v8::Isolate* isolate = v8::Isolate::New();
102   i::SmartPointer<KangarooThread> thread1;
103   {
104     v8::Locker locker(isolate);
105     v8::Isolate::Scope isolate_scope(isolate);
106     v8::HandleScope handle_scope(isolate);
107     v8::Local<v8::Context> context = v8::Context::New(isolate);
108     v8::Context::Scope context_scope(context);
109     CHECK_EQ(isolate, v8::internal::Isolate::Current());
110     CompileRun("function getValue() { return 30; }");
111     thread1.Reset(new KangarooThread(isolate, context));
112   }
113   thread1->Start();
114   thread1->Join();
115 }
116 
117 
CalcFibAndCheck()118 static void CalcFibAndCheck() {
119   Local<Value> v = CompileRun("function fib(n) {"
120                               "  if (n <= 2) return 1;"
121                               "  return fib(n-1) + fib(n-2);"
122                               "}"
123                               "fib(10)");
124   CHECK(v->IsNumber());
125   CHECK_EQ(55, static_cast<int>(v->NumberValue()));
126 }
127 
128 class JoinableThread {
129  public:
JoinableThread(const char * name)130   explicit JoinableThread(const char* name)
131     : name_(name),
132       semaphore_(0),
133       thread_(this) {
134   }
135 
~JoinableThread()136   virtual ~JoinableThread() {}
137 
Start()138   void Start() {
139     thread_.Start();
140   }
141 
Join()142   void Join() {
143     semaphore_.Wait();
144   }
145 
146   virtual void Run() = 0;
147 
148  private:
149   class ThreadWithSemaphore : public i::Thread {
150    public:
ThreadWithSemaphore(JoinableThread * joinable_thread)151     explicit ThreadWithSemaphore(JoinableThread* joinable_thread)
152       : Thread(joinable_thread->name_),
153         joinable_thread_(joinable_thread) {
154     }
155 
Run()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 
175 class IsolateLockingThreadWithLocalContext : public JoinableThread {
176  public:
IsolateLockingThreadWithLocalContext(v8::Isolate * isolate)177   explicit IsolateLockingThreadWithLocalContext(v8::Isolate* isolate)
178     : JoinableThread("IsolateLockingThread"),
179       isolate_(isolate) {
180   }
181 
Run()182   virtual void Run() {
183     v8::Locker locker(isolate_);
184     v8::Isolate::Scope isolate_scope(isolate_);
185     v8::HandleScope handle_scope(isolate_);
186     LocalContext local_context(isolate_);
187     CHECK_EQ(isolate_, v8::internal::Isolate::Current());
188     CalcFibAndCheck();
189   }
190  private:
191   v8::Isolate* isolate_;
192 };
193 
194 
StartJoinAndDeleteThreads(const i::List<JoinableThread * > & threads)195 static void StartJoinAndDeleteThreads(const i::List<JoinableThread*>& threads) {
196   for (int i = 0; i < threads.length(); i++) {
197     threads[i]->Start();
198   }
199   for (int i = 0; i < threads.length(); i++) {
200     threads[i]->Join();
201   }
202   for (int i = 0; i < threads.length(); i++) {
203     delete threads[i];
204   }
205 }
206 
207 
208 // Run many threads all locking on the same isolate
TEST(IsolateLockingStress)209 TEST(IsolateLockingStress) {
210 #if V8_TARGET_ARCH_MIPS
211   const int kNThreads = 50;
212 #else
213   const int kNThreads = 100;
214 #endif
215   i::List<JoinableThread*> threads(kNThreads);
216   v8::Isolate* isolate = v8::Isolate::New();
217   for (int i = 0; i < kNThreads; i++) {
218     threads.Add(new IsolateLockingThreadWithLocalContext(isolate));
219   }
220   StartJoinAndDeleteThreads(threads);
221   isolate->Dispose();
222 }
223 
224 class IsolateNonlockingThread : public JoinableThread {
225  public:
IsolateNonlockingThread()226   explicit IsolateNonlockingThread()
227     : JoinableThread("IsolateNonlockingThread") {
228   }
229 
Run()230   virtual void Run() {
231     v8::Isolate* isolate = v8::Isolate::New();
232     {
233       v8::Isolate::Scope isolate_scope(isolate);
234       v8::HandleScope handle_scope(isolate);
235       v8::Handle<v8::Context> context = v8::Context::New(isolate);
236       v8::Context::Scope context_scope(context);
237       CHECK_EQ(isolate, v8::internal::Isolate::Current());
238       CalcFibAndCheck();
239     }
240     isolate->Dispose();
241   }
242  private:
243 };
244 
245 
246 // Run many threads each accessing its own isolate without locking
TEST(MultithreadedParallelIsolates)247 TEST(MultithreadedParallelIsolates) {
248 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
249   const int kNThreads = 10;
250 #else
251   const int kNThreads = 50;
252 #endif
253   i::List<JoinableThread*> threads(kNThreads);
254   for (int i = 0; i < kNThreads; i++) {
255     threads.Add(new IsolateNonlockingThread());
256   }
257   StartJoinAndDeleteThreads(threads);
258 }
259 
260 
261 class IsolateNestedLockingThread : public JoinableThread {
262  public:
IsolateNestedLockingThread(v8::Isolate * isolate)263   explicit IsolateNestedLockingThread(v8::Isolate* isolate)
264     : JoinableThread("IsolateNestedLocking"), isolate_(isolate) {
265   }
Run()266   virtual void Run() {
267     v8::Locker lock(isolate_);
268     v8::Isolate::Scope isolate_scope(isolate_);
269     v8::HandleScope handle_scope(isolate_);
270     LocalContext local_context(isolate_);
271     {
272       v8::Locker another_lock(isolate_);
273       CalcFibAndCheck();
274     }
275     {
276       v8::Locker another_lock(isolate_);
277       CalcFibAndCheck();
278     }
279   }
280  private:
281   v8::Isolate* isolate_;
282 };
283 
284 
285 // Run  many threads with nested locks
TEST(IsolateNestedLocking)286 TEST(IsolateNestedLocking) {
287 #if V8_TARGET_ARCH_MIPS
288   const int kNThreads = 50;
289 #else
290   const int kNThreads = 100;
291 #endif
292   v8::Isolate* isolate = v8::Isolate::New();
293   i::List<JoinableThread*> threads(kNThreads);
294   for (int i = 0; i < kNThreads; i++) {
295     threads.Add(new IsolateNestedLockingThread(isolate));
296   }
297   StartJoinAndDeleteThreads(threads);
298   isolate->Dispose();
299 }
300 
301 
302 class SeparateIsolatesLocksNonexclusiveThread : public JoinableThread {
303  public:
SeparateIsolatesLocksNonexclusiveThread(v8::Isolate * isolate1,v8::Isolate * isolate2)304   SeparateIsolatesLocksNonexclusiveThread(v8::Isolate* isolate1,
305                                           v8::Isolate* isolate2)
306     : JoinableThread("SeparateIsolatesLocksNonexclusiveThread"),
307       isolate1_(isolate1), isolate2_(isolate2) {
308   }
309 
Run()310   virtual void Run() {
311     v8::Locker lock(isolate1_);
312     v8::Isolate::Scope isolate_scope(isolate1_);
313     v8::HandleScope handle_scope(isolate1_);
314     LocalContext local_context(isolate1_);
315 
316     IsolateLockingThreadWithLocalContext threadB(isolate2_);
317     threadB.Start();
318     CalcFibAndCheck();
319     threadB.Join();
320   }
321  private:
322   v8::Isolate* isolate1_;
323   v8::Isolate* isolate2_;
324 };
325 
326 
327 // Run parallel threads that lock and access different isolates in parallel
TEST(SeparateIsolatesLocksNonexclusive)328 TEST(SeparateIsolatesLocksNonexclusive) {
329 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
330   const int kNThreads = 50;
331 #else
332   const int kNThreads = 100;
333 #endif
334   v8::Isolate* isolate1 = v8::Isolate::New();
335   v8::Isolate* isolate2 = v8::Isolate::New();
336   i::List<JoinableThread*> threads(kNThreads);
337   for (int i = 0; i < kNThreads; i++) {
338     threads.Add(new SeparateIsolatesLocksNonexclusiveThread(isolate1,
339                                                              isolate2));
340   }
341   StartJoinAndDeleteThreads(threads);
342   isolate2->Dispose();
343   isolate1->Dispose();
344 }
345 
346 class LockIsolateAndCalculateFibSharedContextThread : public JoinableThread {
347  public:
LockIsolateAndCalculateFibSharedContextThread(v8::Isolate * isolate,v8::Handle<v8::Context> context)348   explicit LockIsolateAndCalculateFibSharedContextThread(
349       v8::Isolate* isolate, v8::Handle<v8::Context> context)
350     : JoinableThread("LockIsolateAndCalculateFibThread"),
351       isolate_(isolate),
352       context_(isolate, context) {
353   }
354 
Run()355   virtual void Run() {
356     v8::Locker lock(isolate_);
357     v8::Isolate::Scope isolate_scope(isolate_);
358     HandleScope handle_scope(isolate_);
359     v8::Local<v8::Context> context =
360         v8::Local<v8::Context>::New(isolate_, context_);
361     v8::Context::Scope context_scope(context);
362     CalcFibAndCheck();
363   }
364  private:
365   v8::Isolate* isolate_;
366   Persistent<v8::Context> context_;
367 };
368 
369 class LockerUnlockerThread : public JoinableThread {
370  public:
LockerUnlockerThread(v8::Isolate * isolate)371   explicit LockerUnlockerThread(v8::Isolate* isolate)
372     : JoinableThread("LockerUnlockerThread"),
373       isolate_(isolate) {
374   }
375 
Run()376   virtual void Run() {
377     v8::Locker lock(isolate_);
378     v8::Isolate::Scope isolate_scope(isolate_);
379     v8::HandleScope handle_scope(isolate_);
380     v8::Local<v8::Context> context = v8::Context::New(isolate_);
381     {
382       v8::Context::Scope context_scope(context);
383       CalcFibAndCheck();
384     }
385     {
386       LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context);
387       isolate_->Exit();
388       v8::Unlocker unlocker(isolate_);
389       thread.Start();
390       thread.Join();
391     }
392     isolate_->Enter();
393     {
394       v8::Context::Scope context_scope(context);
395       CalcFibAndCheck();
396     }
397   }
398 
399  private:
400   v8::Isolate* isolate_;
401 };
402 
403 
404 // Use unlocker inside of a Locker, multiple threads.
TEST(LockerUnlocker)405 TEST(LockerUnlocker) {
406 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
407   const int kNThreads = 50;
408 #else
409   const int kNThreads = 100;
410 #endif
411   i::List<JoinableThread*> threads(kNThreads);
412   v8::Isolate* isolate = v8::Isolate::New();
413   for (int i = 0; i < kNThreads; i++) {
414     threads.Add(new LockerUnlockerThread(isolate));
415   }
416   StartJoinAndDeleteThreads(threads);
417   isolate->Dispose();
418 }
419 
420 class LockTwiceAndUnlockThread : public JoinableThread {
421  public:
LockTwiceAndUnlockThread(v8::Isolate * isolate)422   explicit LockTwiceAndUnlockThread(v8::Isolate* isolate)
423     : JoinableThread("LockTwiceAndUnlockThread"),
424       isolate_(isolate) {
425   }
426 
Run()427   virtual void Run() {
428     v8::Locker lock(isolate_);
429     v8::Isolate::Scope isolate_scope(isolate_);
430     v8::HandleScope handle_scope(isolate_);
431     v8::Local<v8::Context> context = v8::Context::New(isolate_);
432     {
433       v8::Context::Scope context_scope(context);
434       CalcFibAndCheck();
435     }
436     {
437       v8::Locker second_lock(isolate_);
438       {
439         LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context);
440         isolate_->Exit();
441         v8::Unlocker unlocker(isolate_);
442         thread.Start();
443         thread.Join();
444       }
445     }
446     isolate_->Enter();
447     {
448       v8::Context::Scope context_scope(context);
449       CalcFibAndCheck();
450     }
451   }
452 
453  private:
454   v8::Isolate* isolate_;
455 };
456 
457 
458 // Use Unlocker inside two Lockers.
TEST(LockTwiceAndUnlock)459 TEST(LockTwiceAndUnlock) {
460 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
461   const int kNThreads = 50;
462 #else
463   const int kNThreads = 100;
464 #endif
465   i::List<JoinableThread*> threads(kNThreads);
466   v8::Isolate* isolate = v8::Isolate::New();
467   for (int i = 0; i < kNThreads; i++) {
468     threads.Add(new LockTwiceAndUnlockThread(isolate));
469   }
470   StartJoinAndDeleteThreads(threads);
471   isolate->Dispose();
472 }
473 
474 class LockAndUnlockDifferentIsolatesThread : public JoinableThread {
475  public:
LockAndUnlockDifferentIsolatesThread(v8::Isolate * isolate1,v8::Isolate * isolate2)476   LockAndUnlockDifferentIsolatesThread(v8::Isolate* isolate1,
477                                        v8::Isolate* isolate2)
478     : JoinableThread("LockAndUnlockDifferentIsolatesThread"),
479       isolate1_(isolate1),
480       isolate2_(isolate2) {
481   }
482 
Run()483   virtual void Run() {
484     i::SmartPointer<LockIsolateAndCalculateFibSharedContextThread> thread;
485     v8::Locker lock1(isolate1_);
486     CHECK(v8::Locker::IsLocked(isolate1_));
487     CHECK(!v8::Locker::IsLocked(isolate2_));
488     {
489       v8::Isolate::Scope isolate_scope(isolate1_);
490       v8::HandleScope handle_scope(isolate1_);
491       v8::Handle<v8::Context> context1 = v8::Context::New(isolate1_);
492       {
493         v8::Context::Scope context_scope(context1);
494         CalcFibAndCheck();
495       }
496       thread.Reset(new LockIsolateAndCalculateFibSharedContextThread(
497           isolate1_, context1));
498     }
499     v8::Locker lock2(isolate2_);
500     CHECK(v8::Locker::IsLocked(isolate1_));
501     CHECK(v8::Locker::IsLocked(isolate2_));
502     {
503       v8::Isolate::Scope isolate_scope(isolate2_);
504       v8::HandleScope handle_scope(isolate2_);
505       v8::Handle<v8::Context> context2 = v8::Context::New(isolate2_);
506       {
507         v8::Context::Scope context_scope(context2);
508         CalcFibAndCheck();
509       }
510       v8::Unlocker unlock1(isolate1_);
511       CHECK(!v8::Locker::IsLocked(isolate1_));
512       CHECK(v8::Locker::IsLocked(isolate2_));
513       v8::Context::Scope context_scope(context2);
514       thread->Start();
515       CalcFibAndCheck();
516       thread->Join();
517     }
518   }
519 
520  private:
521   v8::Isolate* isolate1_;
522   v8::Isolate* isolate2_;
523 };
524 
525 
526 // Lock two isolates and unlock one of them.
TEST(LockAndUnlockDifferentIsolates)527 TEST(LockAndUnlockDifferentIsolates) {
528   v8::Isolate* isolate1 = v8::Isolate::New();
529   v8::Isolate* isolate2 = v8::Isolate::New();
530   LockAndUnlockDifferentIsolatesThread thread(isolate1, isolate2);
531   thread.Start();
532   thread.Join();
533   isolate2->Dispose();
534   isolate1->Dispose();
535 }
536 
537 class LockUnlockLockThread : public JoinableThread {
538  public:
LockUnlockLockThread(v8::Isolate * isolate,v8::Handle<v8::Context> context)539   LockUnlockLockThread(v8::Isolate* isolate, v8::Handle<v8::Context> context)
540     : JoinableThread("LockUnlockLockThread"),
541       isolate_(isolate),
542       context_(isolate, context) {
543   }
544 
Run()545   virtual void Run() {
546     v8::Locker lock1(isolate_);
547     CHECK(v8::Locker::IsLocked(isolate_));
548     CHECK(!v8::Locker::IsLocked(CcTest::isolate()));
549     {
550       v8::Isolate::Scope isolate_scope(isolate_);
551       v8::HandleScope handle_scope(isolate_);
552       v8::Local<v8::Context> context =
553           v8::Local<v8::Context>::New(isolate_, context_);
554       v8::Context::Scope context_scope(context);
555       CalcFibAndCheck();
556     }
557     {
558       v8::Unlocker unlock1(isolate_);
559       CHECK(!v8::Locker::IsLocked(isolate_));
560       CHECK(!v8::Locker::IsLocked(CcTest::isolate()));
561       {
562         v8::Locker lock2(isolate_);
563         v8::Isolate::Scope isolate_scope(isolate_);
564         v8::HandleScope handle_scope(isolate_);
565         CHECK(v8::Locker::IsLocked(isolate_));
566         CHECK(!v8::Locker::IsLocked(CcTest::isolate()));
567         v8::Local<v8::Context> context =
568             v8::Local<v8::Context>::New(isolate_, context_);
569         v8::Context::Scope context_scope(context);
570         CalcFibAndCheck();
571       }
572     }
573   }
574 
575  private:
576   v8::Isolate* isolate_;
577   v8::Persistent<v8::Context> context_;
578 };
579 
580 
581 // Locker inside an Unlocker inside a Locker.
TEST(LockUnlockLockMultithreaded)582 TEST(LockUnlockLockMultithreaded) {
583 #if V8_TARGET_ARCH_MIPS
584   const int kNThreads = 50;
585 #else
586   const int kNThreads = 100;
587 #endif
588   v8::Isolate* isolate = v8::Isolate::New();
589   i::List<JoinableThread*> threads(kNThreads);
590   {
591     v8::Locker locker_(isolate);
592     v8::Isolate::Scope isolate_scope(isolate);
593     v8::HandleScope handle_scope(isolate);
594     v8::Handle<v8::Context> context = v8::Context::New(isolate);
595     for (int i = 0; i < kNThreads; i++) {
596       threads.Add(new LockUnlockLockThread(
597           isolate, context));
598     }
599   }
600   StartJoinAndDeleteThreads(threads);
601   isolate->Dispose();
602 }
603 
604 class LockUnlockLockDefaultIsolateThread : public JoinableThread {
605  public:
LockUnlockLockDefaultIsolateThread(v8::Handle<v8::Context> context)606   explicit LockUnlockLockDefaultIsolateThread(v8::Handle<v8::Context> context)
607       : JoinableThread("LockUnlockLockDefaultIsolateThread"),
608         context_(CcTest::isolate(), context) {}
609 
Run()610   virtual void Run() {
611     v8::Locker lock1(CcTest::isolate());
612     {
613       v8::Isolate::Scope isolate_scope(CcTest::isolate());
614       v8::HandleScope handle_scope(CcTest::isolate());
615       v8::Local<v8::Context> context =
616           v8::Local<v8::Context>::New(CcTest::isolate(), context_);
617       v8::Context::Scope context_scope(context);
618       CalcFibAndCheck();
619     }
620     {
621       v8::Unlocker unlock1(CcTest::isolate());
622       {
623         v8::Locker lock2(CcTest::isolate());
624         v8::Isolate::Scope isolate_scope(CcTest::isolate());
625         v8::HandleScope handle_scope(CcTest::isolate());
626         v8::Local<v8::Context> context =
627             v8::Local<v8::Context>::New(CcTest::isolate(), context_);
628         v8::Context::Scope context_scope(context);
629         CalcFibAndCheck();
630       }
631     }
632   }
633 
634  private:
635   v8::Persistent<v8::Context> context_;
636 };
637 
638 
639 // Locker inside an Unlocker inside a Locker for default isolate.
TEST(LockUnlockLockDefaultIsolateMultithreaded)640 TEST(LockUnlockLockDefaultIsolateMultithreaded) {
641 #if V8_TARGET_ARCH_MIPS
642   const int kNThreads = 50;
643 #else
644   const int kNThreads = 100;
645 #endif
646   Local<v8::Context> context;
647   i::List<JoinableThread*> threads(kNThreads);
648   {
649     v8::Locker locker_(CcTest::isolate());
650     v8::Isolate::Scope isolate_scope(CcTest::isolate());
651     v8::HandleScope handle_scope(CcTest::isolate());
652     context = v8::Context::New(CcTest::isolate());
653     for (int i = 0; i < kNThreads; i++) {
654       threads.Add(new LockUnlockLockDefaultIsolateThread(context));
655     }
656   }
657   StartJoinAndDeleteThreads(threads);
658 }
659 
660 
TEST(Regress1433)661 TEST(Regress1433) {
662   for (int i = 0; i < 10; i++) {
663     v8::Isolate* isolate = v8::Isolate::New();
664     {
665       v8::Locker lock(isolate);
666       v8::Isolate::Scope isolate_scope(isolate);
667       v8::HandleScope handle_scope(isolate);
668       v8::Handle<Context> context = v8::Context::New(isolate);
669       v8::Context::Scope context_scope(context);
670       v8::Handle<String> source = v8::String::NewFromUtf8(isolate, "1+1");
671       v8::Handle<Script> script = v8::Script::Compile(source);
672       v8::Handle<Value> result = script->Run();
673       v8::String::Utf8Value utf8(result);
674     }
675     isolate->Dispose();
676   }
677 }
678 
679 
680 static const char* kSimpleExtensionSource =
681   "(function Foo() {"
682   "  return 4;"
683   "})() ";
684 
685 class IsolateGenesisThread : public JoinableThread {
686  public:
IsolateGenesisThread(int count,const char * extension_names[])687   IsolateGenesisThread(int count, const char* extension_names[])
688     : JoinableThread("IsolateGenesisThread"),
689       count_(count),
690       extension_names_(extension_names)
691   {}
692 
Run()693   virtual void Run() {
694     v8::Isolate* isolate = v8::Isolate::New();
695     {
696       v8::Isolate::Scope isolate_scope(isolate);
697       CHECK(!i::Isolate::Current()->has_installed_extensions());
698       v8::ExtensionConfiguration extensions(count_, extension_names_);
699       v8::HandleScope handle_scope(isolate);
700       v8::Context::New(isolate, &extensions);
701       CHECK(i::Isolate::Current()->has_installed_extensions());
702     }
703     isolate->Dispose();
704   }
705  private:
706   int count_;
707   const char** extension_names_;
708 };
709 
710 
711 // Test installing extensions in separate isolates concurrently.
712 // http://code.google.com/p/v8/issues/detail?id=1821
TEST(ExtensionsRegistration)713 TEST(ExtensionsRegistration) {
714 #if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
715   const int kNThreads = 10;
716 #else
717   const int kNThreads = 40;
718 #endif
719   v8::RegisterExtension(new v8::Extension("test0",
720                                           kSimpleExtensionSource));
721   v8::RegisterExtension(new v8::Extension("test1",
722                                           kSimpleExtensionSource));
723   v8::RegisterExtension(new v8::Extension("test2",
724                                           kSimpleExtensionSource));
725   v8::RegisterExtension(new v8::Extension("test3",
726                                           kSimpleExtensionSource));
727   v8::RegisterExtension(new v8::Extension("test4",
728                                           kSimpleExtensionSource));
729   v8::RegisterExtension(new v8::Extension("test5",
730                                           kSimpleExtensionSource));
731   v8::RegisterExtension(new v8::Extension("test6",
732                                           kSimpleExtensionSource));
733   v8::RegisterExtension(new v8::Extension("test7",
734                                           kSimpleExtensionSource));
735   const char* extension_names[] = { "test0", "test1",
736                                     "test2", "test3", "test4",
737                                     "test5", "test6", "test7" };
738   i::List<JoinableThread*> threads(kNThreads);
739   for (int i = 0; i < kNThreads; i++) {
740     threads.Add(new IsolateGenesisThread(8, extension_names));
741   }
742   StartJoinAndDeleteThreads(threads);
743 }
744