Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: test/cctest/test-lockers.cc

Issue 6788023: Per-isolate v8::Locker and v8::Unlocker (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Code review feedback Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« src/v8threads.cc ('K') | « test/cctest/test-api.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 #include <vector>
Vitaly Repeshko 2011/04/21 21:15:27 Remove unnecessary includes.
30
31 #include "v8.h"
32
33 #include "api.h"
34 #include "isolate.h"
35 #include "compilation-cache.h"
36 #include "execution.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::AccessorInfo;
45 using ::v8::Context;
46 using ::v8::Extension;
47 using ::v8::Function;
48 using ::v8::HandleScope;
49 using ::v8::Local;
50 using ::v8::Object;
51 using ::v8::ObjectTemplate;
52 using ::v8::Persistent;
53 using ::v8::Script;
54 using ::v8::String;
55 using ::v8::Value;
56 using ::v8::V8;
57
58 namespace i = ::i;
59
60
61
62
63 // Migrating an isolate
64 class KangarooThread : public v8::internal::Thread {
65 public:
66 KangarooThread(v8::Isolate* isolate,
67 v8::Handle<v8::Context> context, int value)
68 : Thread(NULL, "KangarooThread"),
69 isolate_(isolate), context_(context), value_(value) {
70 }
71
72 void Run() {
73 {
74 v8::Locker locker(isolate_);
75 v8::Isolate::Scope isolate_scope(isolate_);
76 CHECK_EQ(isolate_, v8::internal::Isolate::Current());
77 v8::HandleScope scope;
78 v8::Context::Scope context_scope(context_);
79 Local<Value> v = CompileRun("getValue()");
80 CHECK(v->IsNumber());
81 CHECK_EQ(30, static_cast<int>(v->NumberValue()));
82 }
83 {
84 v8::Locker locker(isolate_);
85 v8::Isolate::Scope isolate_scope(isolate_);
86 v8::Context::Scope context_scope(context_);
87 v8::HandleScope scope;
88 Local<Value> v = CompileRun("getValue()");
89 CHECK(v->IsNumber());
90 CHECK_EQ(30, static_cast<int>(v->NumberValue()));
91 }
92 isolate_->Dispose();
93 }
94
95 private:
96 v8::Isolate* isolate_;
97 Persistent<v8::Context> context_;
98 int value_;
99 };
100
101 // Migrates an isolate from one thread to another
102 TEST(KangarooIsolates) {
103 v8::Isolate* isolate = v8::Isolate::New();
104 Persistent<v8::Context> context;
105 {
106 v8::Locker locker(isolate);
107 v8::Isolate::Scope isolate_scope(isolate);
108 v8::HandleScope handle_scope;
109 context = v8::Context::New();
110 v8::Context::Scope context_scope(context);
111 CHECK_EQ(isolate, v8::internal::Isolate::Current());
112 CompileRun("function getValue() { return 30; }");
113 }
114 KangarooThread thread1(isolate, context, 1);
115 thread1.Start();
116 thread1.Join();
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_(i::OS::CreateSemaphore(0)),
134 thread_(this) {
135 }
136
137 virtual ~JoinableThread() {
138 delete semaphore_;
139 }
140
141 void Start() {
142 thread_.Start();
143 }
144
145 void Join() {
146 semaphore_->Wait();
147 }
148
149 virtual void Run() = 0;
150 private:
151 class ThreadWithSemaphore : public i::Thread {
152 public:
153 explicit ThreadWithSemaphore(JoinableThread* joinable_thread)
154 : Thread(NULL, joinable_thread->name_),
155 joinable_thread_(joinable_thread) {
156 }
157
158 virtual void Run() {
159 joinable_thread_->Run();
160 joinable_thread_->semaphore_->Signal();
161 }
162
163 private:
164 JoinableThread* joinable_thread_;
165 };
166
167 const char* name_;
168 i::Semaphore* semaphore_;
169 ThreadWithSemaphore thread_;
170
171 friend class ThreadWithSemaphore;
172
173 DISALLOW_COPY_AND_ASSIGN(JoinableThread);
174 };
175
176
177 class IsolateLockingThreadWithLocalContext : public JoinableThread {
178 public:
179 explicit IsolateLockingThreadWithLocalContext(v8::Isolate* isolate)
180 : JoinableThread("IsolateLockingThread"),
181 isolate_(isolate) {
182 }
183
184 virtual void Run() {
185 v8::Locker locker(isolate_);
186 v8::Isolate::Scope isolate_scope(isolate_);
187 v8::HandleScope handle_scope;
188 LocalContext local_context;
189 CHECK_EQ(isolate_, v8::internal::Isolate::Current());
190 CalcFibAndCheck();
191 }
192 private:
193 v8::Isolate* isolate_;
194 };
195
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
210 TEST(IsolateLockingStress) {
211 const int kNThreads = 100;
212 i::List<JoinableThread*> threads(kNThreads);
213 v8::Isolate* isolate = v8::Isolate::New();
214 for (int i = 0; i < kNThreads; i++) {
215 threads.Add(new IsolateLockingThreadWithLocalContext(isolate));
216 }
217 StartJoinAndDeleteThreads(threads);
218 isolate->Dispose();
219 }
220
221 class IsolateNonlockingThread : public JoinableThread {
222 public:
223 explicit IsolateNonlockingThread()
224 : JoinableThread("IsolateNonlockingThread") {
225 }
226
227 virtual void Run() {
228 v8::Isolate* isolate = v8::Isolate::New();
229 {
230 v8::Isolate::Scope isolate_scope(isolate);
231 v8::HandleScope handle_scope;
232 v8::Handle<v8::Context> context = v8::Context::New();
233 v8::Context::Scope context_scope(context);
234 CHECK_EQ(isolate, v8::internal::Isolate::Current());
235 CalcFibAndCheck();
236 }
237 isolate->Dispose();
238 }
239 private:
240 };
241
242 // Run many threads each accessing its own isolate without locking
243 TEST(MultithreadedParallelIsolates) {
244 const int kNThreads = 50;
245 i::List<JoinableThread*> threads(kNThreads);
246 for (int i = 0; i < kNThreads; i++) {
247 threads.Add(new IsolateNonlockingThread());
248 }
249 StartJoinAndDeleteThreads(threads);
250 }
251
252
253 class IsolateNestedLockingThread : public JoinableThread {
254 public:
255 explicit IsolateNestedLockingThread(v8::Isolate* isolate)
256 : JoinableThread("IsolateNestedLocking"), isolate_(isolate) {
257 }
258 virtual void Run() {
259 v8::Locker lock(isolate_);
260 v8::Isolate::Scope isolate_scope(isolate_);
261 v8::HandleScope handle_scope;
262 LocalContext local_context;
263 {
264 v8::Locker another_lock(isolate_);
265 CalcFibAndCheck();
266 }
267 {
268 v8::Locker another_lock(isolate_);
269 CalcFibAndCheck();
270 }
271 }
272 private:
273 v8::Isolate* isolate_;
274 };
275
276 // Run many threads with nested locks
277 TEST(IsolateNestedLocking) {
278 const int kNThreads = 100;
279 v8::Isolate* isolate = v8::Isolate::New();
280 i::List<JoinableThread*> threads(kNThreads);
281 for (int i = 0; i < kNThreads; i++) {
282 threads.Add(new IsolateNestedLockingThread(isolate));
283 }
284 StartJoinAndDeleteThreads(threads);
285 }
286
287
288 class SeparateIsolatesLocksNonexclusiveThread : public JoinableThread {
289 public:
290 SeparateIsolatesLocksNonexclusiveThread(v8::Isolate* isolate1,
291 v8::Isolate* isolate2)
292 : JoinableThread("SeparateIsolatesLocksNonexclusiveThread"),
293 isolate1_(isolate1), isolate2_(isolate2) {
294 }
295
296 virtual void Run() {
297 v8::Locker lock(isolate1_);
298 v8::Isolate::Scope isolate_scope(isolate1_);
299 v8::HandleScope handle_scope;
300 LocalContext local_context;
301
302 IsolateLockingThreadWithLocalContext threadB(isolate2_);
303 threadB.Start();
304 CalcFibAndCheck();
305 threadB.Join();
306 }
307 private:
308 v8::Isolate* isolate1_;
309 v8::Isolate* isolate2_;
310 };
311
312 // Run parallel threads that lock and access different isolates in parallel
313 TEST(SeparateIsolatesLocksNonexclusive) {
314 const int kNThreads = 100;
315 v8::Isolate* isolate1 = v8::Isolate::New();
316 v8::Isolate* isolate2 = v8::Isolate::New();
317 i::List<JoinableThread*> threads(kNThreads);
318 for (int i = 0; i < kNThreads; i++) {
319 threads.Add(new SeparateIsolatesLocksNonexclusiveThread(isolate1,
320 isolate2));
321 }
322 StartJoinAndDeleteThreads(threads);
323 isolate2->Dispose();
324 isolate1->Dispose();
325 }
326
327 class LockIsolateAndCalculateFibSharedContextThread : public JoinableThread {
328 public:
329 explicit LockIsolateAndCalculateFibSharedContextThread(
330 v8::Isolate* isolate, v8::Handle<v8::Context> context)
331 : JoinableThread("LockIsolateAndCalculateFibThread"),
332 isolate_(isolate),
333 context_(context) {
334 }
335
336 virtual void Run() {
337 v8::Locker lock(isolate_);
338 v8::Isolate::Scope isolate_scope(isolate_);
339 HandleScope handle_scope;
340 v8::Context::Scope context_scope(context_);
341 CalcFibAndCheck();
342 }
343 private:
344 v8::Isolate* isolate_;
345 Persistent<v8::Context> context_;
346 };
347
348 class LockerUnlockerThread : public JoinableThread {
349 public:
350 explicit LockerUnlockerThread(v8::Isolate* isolate)
351 : JoinableThread("LockerUnlockerThread"),
352 isolate_(isolate) {
353 }
354
355 virtual void Run() {
356 v8::Locker lock(isolate_);
357 v8::Isolate::Scope isolate_scope(isolate_);
358 v8::HandleScope handle_scope;
359 v8::Handle<v8::Context> context = v8::Context::New();
360 {
361 v8::Context::Scope context_scope(context);
362 CalcFibAndCheck();
363 }
364 {
365 isolate_->Exit();
366 v8::Unlocker unlocker(isolate_);
367 LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context);
368 thread.Start();
369 thread.Join();
370 }
371 isolate_->Enter();
372 {
373 v8::Context::Scope context_scope(context);
374 CalcFibAndCheck();
375 }
376 }
377 private:
378 v8::Isolate* isolate_;
379 };
380
381 // Use unlocker inside of a Locker, multiple threads.
382 TEST(LockerUnlocker) {
383 const int kNThreads = 100;
384 i::List<JoinableThread*> threads(kNThreads);
385 v8::Isolate* isolate = v8::Isolate::New();
386 for (int i = 0; i < kNThreads; i++) {
387 threads.Add(new LockerUnlockerThread(isolate));
388 }
389 StartJoinAndDeleteThreads(threads);
390 isolate->Dispose();
391 }
392
393 class LockTwiceAndUnlockThread : public JoinableThread {
394 public:
395 explicit LockTwiceAndUnlockThread(v8::Isolate* isolate)
396 : JoinableThread("LockTwiceAndUnlockThread"),
397 isolate_(isolate) {
398 }
399
400 virtual void Run() {
401 v8::Locker lock(isolate_);
402 v8::Isolate::Scope isolate_scope(isolate_);
403 v8::HandleScope handle_scope;
404 v8::Handle<v8::Context> context = v8::Context::New();
405 {
406 v8::Context::Scope context_scope(context);
407 CalcFibAndCheck();
408 }
409 {
410 v8::Locker second_lock(isolate_);
411 {
412 isolate_->Exit();
413 v8::Unlocker unlocker(isolate_);
414 LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context);
415 thread.Start();
416 thread.Join();
417 }
418 }
419 isolate_->Enter();
420 {
421 v8::Context::Scope context_scope(context);
422 CalcFibAndCheck();
423 }
424 }
425 private:
426 v8::Isolate* isolate_;
427 };
428
429 // Use Unlocker inside two Lockers.
430 TEST(LockTwiceAndUnlock) {
431 const int kNThreads = 100;
432 i::List<JoinableThread*> threads(kNThreads);
433 v8::Isolate* isolate = v8::Isolate::New();
434 for (int i = 0; i < kNThreads; i++) {
435 threads.Add(new LockTwiceAndUnlockThread(isolate));
436 }
437 StartJoinAndDeleteThreads(threads);
438 isolate->Dispose();
439 }
440
441 class LockAndUnlockDifferentIsolatesThread : public JoinableThread {
442 public:
443 LockAndUnlockDifferentIsolatesThread(v8::Isolate* isolate1,
444 v8::Isolate* isolate2)
445 : JoinableThread("LockAndUnlockDifferentIsolatesThread"),
446 isolate1_(isolate1),
447 isolate2_(isolate2) {
448 }
449
450 virtual void Run() {
451 Persistent<v8::Context> context1;
452 Persistent<v8::Context> context2;
453 v8::Locker lock1(isolate1_);
454 CHECK(v8::Locker::IsLocked(isolate1_));
455 CHECK(!v8::Locker::IsLocked(isolate2_));
456 {
457 v8::Isolate::Scope isolate_scope(isolate1_);
458 v8::HandleScope handle_scope;
459 context1 = v8::Context::New();
460 {
461 v8::Context::Scope context_scope(context1);
462 CalcFibAndCheck();
463 }
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;
471 context2 = v8::Context::New();
472 {
473 v8::Context::Scope context_scope(context2);
474 CalcFibAndCheck();
475 }
476 }
477 {
478 v8::Unlocker unlock1(isolate1_);
479 CHECK(!v8::Locker::IsLocked(isolate1_));
480 CHECK(v8::Locker::IsLocked(isolate2_));
481 v8::Isolate::Scope isolate_scope(isolate2_);
482 v8::HandleScope handle_scope;
483 v8::Context::Scope context_scope(context2);
484 LockIsolateAndCalculateFibSharedContextThread thread(isolate1_, context1);
485 thread.Start();
486 CalcFibAndCheck();
487 thread.Join();
488 }
489 }
490 private:
491 v8::Isolate* isolate1_;
492 v8::Isolate* isolate2_;
493 };
494
495 // Lock two isolates and unlock one of them.
496 TEST(LockAndUnlockDifferentIsolates) {
497 v8::Isolate* isolate1 = v8::Isolate::New();
498 v8::Isolate* isolate2 = v8::Isolate::New();
499 LockAndUnlockDifferentIsolatesThread thread(isolate1, isolate2);
500 thread.Start();
501 thread.Join();
502 isolate2->Dispose();
503 isolate1->Dispose();
504 }
505
506 class LockUnlockLockThread : public JoinableThread {
507 public:
508 LockUnlockLockThread(v8::Isolate* isolate, v8::Handle<v8::Context> context)
509 : JoinableThread("LockUnlockLockThread"),
510 isolate_(isolate),
511 context_(context) {
512 }
513
514 virtual void Run() {
515 v8::Locker lock1(isolate_);
516 CHECK(v8::Locker::IsLocked(isolate_));
517 CHECK(!v8::Locker::IsLocked());
518 {
519 v8::Isolate::Scope isolate_scope(isolate_);
520 v8::HandleScope handle_scope;
521 v8::Context::Scope context_scope(context_);
522 CalcFibAndCheck();
523 }
524 {
525 v8::Unlocker unlock1(isolate_);
526 CHECK(!v8::Locker::IsLocked(isolate_));
527 CHECK(!v8::Locker::IsLocked());
528 {
529 v8::Locker lock2(isolate_);
530 v8::Isolate::Scope isolate_scope(isolate_);
531 v8::HandleScope handle_scope;
532 CHECK(v8::Locker::IsLocked(isolate_));
533 CHECK(!v8::Locker::IsLocked());
534 v8::Context::Scope context_scope(context_);
535 CalcFibAndCheck();
536 }
537 }
538 }
539
540 private:
541 v8::Isolate* isolate_;
542 v8::Persistent<v8::Context> context_;
543 };
544
545 // Locker inside an Unlocker inside a Locker.
546 TEST(LockUnlockLockMultithreaded) {
547 const int kNThreads = 100;
548 v8::Isolate* isolate = v8::Isolate::New();
549 Persistent<v8::Context> context;
550 {
551 v8::Locker locker_(isolate);
552 v8::Isolate::Scope isolate_scope(isolate);
553 v8::HandleScope handle_scope;
554 context = v8::Context::New();
555 }
556 i::List<JoinableThread*> threads(kNThreads);
557 for (int i = 0; i < kNThreads; i++) {
558 threads.Add(new LockUnlockLockThread(isolate, context));
559 }
560 StartJoinAndDeleteThreads(threads);
561 }
562
563 class LockUnlockLockDefaultIsolateThread : public JoinableThread {
564 public:
565 LockUnlockLockDefaultIsolateThread(v8::Handle<v8::Context> context)
566 : JoinableThread("LockUnlockLockDefaultIsolateThread"),
567 context_(context) {
568 }
569
570 virtual void Run() {
571 v8::Locker lock1;
572 {
573 v8::HandleScope handle_scope;
574 v8::Context::Scope context_scope(context_);
575 CalcFibAndCheck();
576 }
577 {
578 v8::Unlocker unlock1;
579 {
580 v8::Locker lock2;
581 v8::HandleScope handle_scope;
582 v8::Context::Scope context_scope(context_);
583 CalcFibAndCheck();
584 }
585 }
586 }
587
588 private:
589 v8::Persistent<v8::Context> context_;
590 };
591
592 // Locker inside an Unlocker inside a Locker for default isolate.
593 TEST(LockUnlockLockDefaultIsolateMultithreaded) {
594 const int kNThreads = 100;
595 Persistent<v8::Context> context;
596 {
597 v8::Locker locker_;
598 v8::HandleScope handle_scope;
599 context = v8::Context::New();
600 }
601 i::List<JoinableThread*> threads(kNThreads);
602 for (int i = 0; i < kNThreads; i++) {
603 threads.Add(new LockUnlockLockDefaultIsolateThread(context));
604 }
605 StartJoinAndDeleteThreads(threads);
606 }
OLDNEW
« src/v8threads.cc ('K') | « test/cctest/test-api.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698