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