The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / test / cctest / test-lockers.cc @ f230a1cf

History | View | Annotate | Download (21.5 KB)

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 "v8.h"
31

    
32
#include "api.h"
33
#include "isolate.h"
34
#include "compilation-cache.h"
35
#include "execution.h"
36
#include "smart-pointers.h"
37
#include "snapshot.h"
38
#include "platform.h"
39
#include "utils.h"
40
#include "cctest.h"
41
#include "parser.h"
42
#include "unicode-inl.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:
61
  KangarooThread(v8::Isolate* isolate, v8::Handle<v8::Context> context)
62
      : Thread("KangarooThread"),
63
        isolate_(isolate),
64
        context_(isolate, context) {}
65

    
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
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

    
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:
130
  explicit JoinableThread(const char* name)
131
    : name_(name),
132
      semaphore_(0),
133
      thread_(this) {
134
  }
135

    
136
  virtual ~JoinableThread() {}
137

    
138
  void Start() {
139
    thread_.Start();
140
  }
141

    
142
  void Join() {
143
    semaphore_.Wait();
144
  }
145

    
146
  virtual void Run() = 0;
147

    
148
 private:
149
  class ThreadWithSemaphore : public i::Thread {
150
   public:
151
    explicit ThreadWithSemaphore(JoinableThread* joinable_thread)
152
      : Thread(joinable_thread->name_),
153
        joinable_thread_(joinable_thread) {
154
    }
155

    
156
    virtual void Run() {
157
      joinable_thread_->Run();
158
      joinable_thread_->semaphore_.Signal();
159
    }
160

    
161
   private:
162
    JoinableThread* joinable_thread_;
163
  };
164

    
165
  const char* name_;
166
  i::Semaphore semaphore_;
167
  ThreadWithSemaphore thread_;
168

    
169
  friend class ThreadWithSemaphore;
170

    
171
  DISALLOW_COPY_AND_ASSIGN(JoinableThread);
172
};
173

    
174

    
175
class IsolateLockingThreadWithLocalContext : public JoinableThread {
176
 public:
177
  explicit IsolateLockingThreadWithLocalContext(v8::Isolate* isolate)
178
    : JoinableThread("IsolateLockingThread"),
179
      isolate_(isolate) {
180
  }
181

    
182
  virtual void Run() {
183
    v8::Locker locker(isolate_);
184
    v8::Isolate::Scope isolate_scope(isolate_);
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

    
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
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:
226
  explicit IsolateNonlockingThread()
227
    : JoinableThread("IsolateNonlockingThread") {
228
  }
229

    
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
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:
263
  explicit IsolateNestedLockingThread(v8::Isolate* isolate)
264
    : JoinableThread("IsolateNestedLocking"), isolate_(isolate) {
265
  }
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
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:
304
  SeparateIsolatesLocksNonexclusiveThread(v8::Isolate* isolate1,
305
                                          v8::Isolate* isolate2)
306
    : JoinableThread("SeparateIsolatesLocksNonexclusiveThread"),
307
      isolate1_(isolate1), isolate2_(isolate2) {
308
  }
309

    
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
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:
348
  explicit LockIsolateAndCalculateFibSharedContextThread(
349
      v8::Isolate* isolate, v8::Handle<v8::Context> context)
350
    : JoinableThread("LockIsolateAndCalculateFibThread"),
351
      isolate_(isolate),
352
      context_(isolate, context) {
353
  }
354

    
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:
371
  explicit LockerUnlockerThread(v8::Isolate* isolate)
372
    : JoinableThread("LockerUnlockerThread"),
373
      isolate_(isolate) {
374
  }
375

    
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.
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:
422
  explicit LockTwiceAndUnlockThread(v8::Isolate* isolate)
423
    : JoinableThread("LockTwiceAndUnlockThread"),
424
      isolate_(isolate) {
425
  }
426

    
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.
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:
476
  LockAndUnlockDifferentIsolatesThread(v8::Isolate* isolate1,
477
                                       v8::Isolate* isolate2)
478
    : JoinableThread("LockAndUnlockDifferentIsolatesThread"),
479
      isolate1_(isolate1),
480
      isolate2_(isolate2) {
481
  }
482

    
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.
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:
539
  LockUnlockLockThread(v8::Isolate* isolate, v8::Handle<v8::Context> context)
540
    : JoinableThread("LockUnlockLockThread"),
541
      isolate_(isolate),
542
      context_(isolate, context) {
543
  }
544

    
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.
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:
606
  explicit LockUnlockLockDefaultIsolateThread(v8::Handle<v8::Context> context)
607
      : JoinableThread("LockUnlockLockDefaultIsolateThread"),
608
        context_(CcTest::isolate(), context) {}
609

    
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.
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

    
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::New("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:
687
  IsolateGenesisThread(int count, const char* extension_names[])
688
    : JoinableThread("IsolateGenesisThread"),
689
      count_(count),
690
      extension_names_(extension_names)
691
  {}
692

    
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
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
}