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