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