OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2007-2009 the V8 project authors. All rights reserved. | |
Vitaly Repeshko
2011/04/15 00:29:39
2011
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
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> | |
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 explicit KangarooThread(v8::Isolate* isolate, | |
Vitaly Repeshko
2011/04/15 00:29:39
nit: explicit not required.
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
67 v8::Handle<v8::Context> context, int value) | |
Vitaly Repeshko
2011/04/15 00:29:39
nit: Weird indentation.
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
68 : Thread(NULL, "KangarooThread1"), | |
Vitaly Repeshko
2011/04/15 00:29:39
Why 1? There doesn't seem to be a second one.
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
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 context_->Enter(); | |
Vitaly Repeshko
2011/04/15 00:29:39
Please use Context::Scope where possible.
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
79 Local<Value> v = CompileRun("getValue()"); | |
80 CHECK(v->IsNumber()); | |
81 CHECK_EQ(30, static_cast<int>(v->NumberValue())); | |
82 context_->Exit(); | |
83 } | |
84 { | |
85 v8::Locker locker(isolate_); | |
86 v8::Isolate::Scope isolate_scope(isolate_); | |
87 context_->Enter(); | |
88 v8::HandleScope scope; | |
89 Local<Value> v = CompileRun("getValue()"); | |
90 CHECK(v->IsNumber()); | |
91 CHECK_EQ(30, static_cast<int>(v->NumberValue())); | |
92 context_->Exit(); | |
93 } | |
94 isolate_->Dispose(); | |
95 } | |
96 | |
97 private: | |
98 v8::Isolate* isolate_; | |
99 Persistent<v8::Context> context_; | |
100 int value_; | |
101 }; | |
102 | |
103 | |
104 TEST(KangarooIsolates) { | |
Vitaly Repeshko
2011/04/15 00:29:39
Please describe what a test does for non-trivial t
| |
105 v8::Isolate* isolate = v8::Isolate::New(); | |
106 Persistent<v8::Context> context; | |
107 { | |
108 v8::Locker locker_(isolate); | |
Vitaly Repeshko
2011/04/15 00:29:39
nit: Why _ ?
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
109 v8::Isolate::Scope isolate_scope(isolate); | |
110 v8::HandleScope handle_scope; | |
111 context = v8::Context::New(); | |
112 context->Enter(); | |
113 CHECK_EQ(isolate, v8::internal::Isolate::Current()); | |
114 CompileRun("function getValue() { return 30; }"); | |
Vitaly Repeshko
2011/04/15 00:29:39
It'd be useful for this script to have some state,
Dmitry Lomov
2011/04/19 01:50:47
It has a state of sorts - note that KangarooThread
| |
115 context->Exit(); | |
116 } | |
117 KangarooThread thread1(isolate, context, 1); | |
118 thread1.Start(); | |
119 thread1.Join(); | |
120 } | |
121 | |
122 static void CalcFibAndCheck() { | |
123 Local<Value> v = CompileRun("function fib(n) {" | |
124 " if (n <= 2) return 1;" | |
125 " return fib(n-1) + fib(n-2);" | |
126 "}" | |
127 "fib(10)"); | |
128 CHECK(v->IsNumber()); | |
129 CHECK_EQ(55, static_cast<int>(v->NumberValue())); | |
130 } | |
131 | |
132 class JoinableThread : public i::Thread { | |
Vitaly Repeshko
2011/04/15 00:29:39
To make this a bit more readable make JoinableThre
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
133 public: | |
134 explicit JoinableThread(i::Isolate* isolate, const char* name) | |
135 : Thread(isolate, name), | |
136 semaphore_(NULL) { | |
137 } | |
138 | |
139 void StartWithSignal(i::Semaphore* semaphore) { | |
140 semaphore_ = semaphore; | |
141 Start(); | |
142 } | |
143 | |
144 void Run() { | |
Vitaly Repeshko
2011/04/15 00:29:39
nit: Keep "virtual" when overriding.
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
145 DoRun(); | |
146 if (semaphore_ != NULL) | |
147 semaphore_->Signal(); | |
148 } | |
149 virtual void DoRun() = 0; | |
150 private: | |
151 i::Semaphore* semaphore_; | |
152 }; | |
153 | |
154 | |
155 class IsolateLockingThreadWithLocalContext : public JoinableThread { | |
156 public: | |
157 explicit IsolateLockingThreadWithLocalContext(v8::Isolate* isolate) | |
158 : JoinableThread(NULL, "IsolateLockingThread"), | |
159 isolate_(isolate) { | |
160 } | |
161 | |
162 void DoRun() { | |
163 v8::Locker locker(isolate_); | |
164 v8::Isolate::Scope isolate_scope(isolate_); | |
165 v8::HandleScope handle_scope; | |
166 LocalContext local_context; | |
167 CHECK_EQ(isolate_, v8::internal::Isolate::Current()); | |
168 CalcFibAndCheck(); | |
169 } | |
170 private: | |
171 v8::Isolate* isolate_; | |
172 }; | |
173 | |
174 static void StartJoinAndDeleteThreads(const i::List<JoinableThread*>& threads) { | |
175 i::Semaphore* semaphore = i::OS::CreateSemaphore(0); | |
176 for (int i = 0; i < threads.length(); i++) { | |
177 threads[i]->StartWithSignal(semaphore); | |
178 } | |
179 for (int i = 0; i < threads.length(); i++) { | |
180 semaphore->Wait(); | |
181 } | |
182 for (int i = 0; i < threads.length(); i++) { | |
183 delete threads[i]; | |
184 } | |
185 delete semaphore; | |
186 } | |
187 | |
188 TEST(IsolateLockingStress) { | |
189 const int kNThreads = 100; | |
190 i::List<JoinableThread*> threads(kNThreads); | |
191 v8::Isolate* isolate = v8::Isolate::New(); | |
192 for (int i = 0; i < kNThreads; i++) { | |
193 threads.Add(new IsolateLockingThreadWithLocalContext(isolate)); | |
194 } | |
195 StartJoinAndDeleteThreads(threads); | |
196 isolate->Dispose(); | |
197 } | |
198 | |
199 class IsolateNonlockingThread : public JoinableThread { | |
200 public: | |
201 explicit IsolateNonlockingThread() | |
202 : JoinableThread(NULL, "IsolateNonlockingThread") { | |
203 } | |
204 | |
205 void DoRun() { | |
206 v8::Isolate* isolate = v8::Isolate::New(); | |
207 { | |
208 v8::Isolate::Scope isolate_scope(isolate); | |
209 v8::HandleScope handle_scope; | |
210 v8::Handle<v8::Context> context = v8::Context::New(); | |
211 context->Enter(); | |
212 CHECK_EQ(isolate, v8::internal::Isolate::Current()); | |
213 CalcFibAndCheck(); | |
214 context->Exit(); | |
Vitaly Repeshko
2011/04/15 00:29:39
nit: Fix indentation.
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
215 } | |
216 isolate->Dispose(); | |
217 } | |
218 private: | |
219 }; | |
220 | |
221 TEST(MultithreadedParallelIsolates) { | |
222 const int kNThreads = 50; | |
223 i::List<JoinableThread*> threads(kNThreads); | |
224 for (int i = 0; i < kNThreads; i++) { | |
225 threads.Add(new IsolateNonlockingThread()); | |
226 } | |
227 StartJoinAndDeleteThreads(threads); | |
228 } | |
229 | |
230 | |
231 class IsolateLockingTwiceThread : public JoinableThread { | |
Vitaly Repeshko
2011/04/15 00:29:39
LockingTwice -> NestedLocking
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
232 public: | |
233 explicit IsolateLockingTwiceThread(v8::Isolate* isolate) | |
234 : JoinableThread(NULL, "IsolateLockingTwice"), isolate_(isolate) { | |
235 } | |
236 void DoRun() { | |
237 v8::Locker lock(isolate_); | |
238 v8::Isolate::Scope isolate_scope(isolate_); | |
239 v8::HandleScope handle_scope; | |
240 LocalContext local_context; | |
241 { | |
242 v8::Locker another_lock(isolate_); | |
243 CalcFibAndCheck(); | |
244 } | |
245 { | |
246 v8::Locker another_lock(isolate_); | |
247 CalcFibAndCheck(); | |
248 } | |
249 } | |
250 private: | |
251 v8::Isolate* isolate_; | |
252 }; | |
253 | |
254 TEST(IsolateLockingTwice) { | |
255 const int kNThreads = 100; | |
256 v8::Isolate* isolate = v8::Isolate::New(); | |
257 i::List<JoinableThread*> threads(kNThreads); | |
258 for (int i = 0; i < kNThreads; i++) { | |
259 threads.Add(new IsolateLockingTwiceThread(isolate)); | |
260 } | |
261 StartJoinAndDeleteThreads(threads); | |
262 } | |
263 | |
264 class LockIsolateAndCalculateFibThread : public JoinableThread { | |
Vitaly Repeshko
2011/04/15 00:29:39
Isn't this the same as IsolateLockingThreadWithLoc
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
265 public: | |
266 explicit LockIsolateAndCalculateFibThread(v8::Isolate* isolate) | |
267 : JoinableThread(NULL, "LockIsolateAndCalculateFibThread"), | |
268 isolate_(isolate) { | |
269 } | |
270 | |
271 void DoRun() { | |
272 v8::Locker lock(isolate_); | |
273 v8::Isolate::Scope isolate_scope(isolate_); | |
274 LocalContext local_context; | |
275 HandleScope handle_scope; | |
276 CalcFibAndCheck(); | |
277 } | |
278 private: | |
279 v8::Isolate* isolate_; | |
280 }; | |
281 | |
282 class SeparateIsolatesLocksNonexclusiveThreadA : public JoinableThread { | |
283 public: | |
284 explicit SeparateIsolatesLocksNonexclusiveThreadA(v8::Isolate* isolate1, | |
Vitaly Repeshko
2011/04/15 00:29:39
nit: explicit not required.
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
285 v8::Isolate* isolate2) | |
286 : JoinableThread(NULL, "ASeparateIsolatesLocksNonexclusiveThreadA"), | |
Vitaly Repeshko
2011/04/15 00:29:39
Why "A"? There doesn't seem to be a "B" variant of
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
287 isolate1_(isolate1), isolate2_(isolate2) { | |
288 } | |
289 | |
290 void DoRun() { | |
291 v8::Locker lock(isolate1_); | |
292 v8::Isolate::Scope isolate_scope(isolate1_); | |
293 v8::HandleScope handle_scope; | |
294 LocalContext local_context; | |
295 | |
296 LockIsolateAndCalculateFibThread threadB(isolate2_); | |
297 i::Semaphore* semaphore = i::OS::CreateSemaphore(0); | |
298 threadB.StartWithSignal(semaphore); | |
299 CalcFibAndCheck(); | |
300 semaphore->Wait(); | |
301 delete semaphore; | |
302 } | |
303 private: | |
304 v8::Isolate* isolate1_; | |
305 v8::Isolate* isolate2_; | |
306 }; | |
307 | |
308 TEST(SeparateIsolatesLocksNonexclusive) { | |
309 const int kNThreads = 100; | |
310 v8::Isolate* isolate1 = v8::Isolate::New(); | |
311 v8::Isolate* isolate2 = v8::Isolate::New(); | |
312 i::List<JoinableThread*> threads(kNThreads); | |
313 for (int i = 0; i < kNThreads; i++) { | |
314 threads.Add(new SeparateIsolatesLocksNonexclusiveThreadA(isolate1, | |
315 isolate2)); | |
316 } | |
317 StartJoinAndDeleteThreads(threads); | |
318 isolate2->Dispose(); | |
319 isolate1->Dispose(); | |
320 } | |
321 | |
322 class LockIsolateAndCalculateFibSharedContextThread : public JoinableThread { | |
323 public: | |
324 explicit LockIsolateAndCalculateFibSharedContextThread( | |
325 v8::Isolate* isolate, v8::Handle<v8::Context> context) | |
326 : JoinableThread(NULL, "LockIsolateAndCalculateFibThread"), | |
327 isolate_(isolate), | |
328 context_(context) { | |
329 } | |
330 | |
331 void DoRun() { | |
332 v8::Locker lock(isolate_); | |
333 v8::Isolate::Scope isolate_scope(isolate_); | |
334 HandleScope handle_scope; | |
335 context_->Enter(); | |
336 CalcFibAndCheck(); | |
337 context_->Exit(); | |
338 } | |
339 private: | |
340 v8::Isolate* isolate_; | |
341 Persistent<v8::Context> context_; | |
342 }; | |
343 | |
344 class LockerUnlockerThread : public JoinableThread { | |
345 public: | |
346 explicit LockerUnlockerThread(v8::Isolate* isolate) | |
347 : JoinableThread(NULL, "LockerUnlockerThread"), | |
348 isolate_(isolate) { | |
349 } | |
350 | |
351 void DoRun() { | |
352 v8::Locker lock(isolate_); | |
353 v8::Isolate::Scope isolate_scope(isolate_); | |
354 v8::HandleScope handle_scope; | |
355 v8::Handle<v8::Context> context = v8::Context::New(); | |
356 context->Enter(); | |
357 CalcFibAndCheck(); | |
358 { | |
359 context->Exit(); | |
Vitaly Repeshko
2011/04/15 00:29:39
Do we have to exit the context here?
Dmitry Lomov
2011/04/19 01:50:47
Yes because we exit the isolate - in the next line
| |
360 isolate_->Exit(); | |
361 v8::Unlocker unlocker(isolate_); | |
Vitaly Repeshko
2011/04/15 00:29:39
Hmm, do we really want to be able to unlock some a
Dmitry Lomov
2011/04/19 01:50:47
Here is what I think on the subject:
1. I do not h
| |
362 LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context); | |
363 i::Semaphore* semaphore = i::OS::CreateSemaphore(0); | |
364 thread.StartWithSignal(semaphore); | |
365 semaphore->Wait(); | |
366 delete semaphore; | |
367 } | |
368 isolate_->Enter(); | |
369 context->Enter(); | |
370 CalcFibAndCheck(); | |
Vitaly Repeshko
2011/04/15 00:29:39
context->Exit()?
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
371 } | |
372 private: | |
373 v8::Isolate* isolate_; | |
374 }; | |
375 | |
376 TEST(LockerUnlocker) { | |
377 const int kNThreads = 100; | |
378 i::List<JoinableThread*> threads(kNThreads); | |
379 v8::Isolate* isolate = v8::Isolate::New(); | |
380 for (int i = 0; i < kNThreads; i++) { | |
381 threads.Add(new LockerUnlockerThread(isolate)); | |
382 } | |
383 StartJoinAndDeleteThreads(threads); | |
384 isolate->Dispose(); | |
385 } | |
386 | |
387 class LockTwiceAndUnlockThread : public JoinableThread { | |
388 public: | |
389 explicit LockTwiceAndUnlockThread(v8::Isolate* isolate) | |
390 : JoinableThread(NULL, "LockTwiceAndUnlockThread"), | |
391 isolate_(isolate) { | |
392 } | |
393 | |
394 void DoRun() { | |
395 v8::Locker lock(isolate_); | |
396 v8::Isolate::Scope isolate_scope(isolate_); | |
397 v8::HandleScope handle_scope; | |
398 v8::Handle<v8::Context> context = v8::Context::New(); | |
399 context->Enter(); | |
400 CalcFibAndCheck(); | |
401 { | |
402 v8::Locker second_lock(isolate_); | |
403 { | |
404 context->Exit(); | |
405 isolate_->Exit(); | |
406 v8::Unlocker unlocker(isolate_); | |
407 LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context); | |
408 i::Semaphore* semaphore = i::OS::CreateSemaphore(0); | |
409 thread.StartWithSignal(semaphore); | |
410 semaphore->Wait(); | |
411 delete semaphore; | |
412 } | |
413 } | |
414 isolate_->Enter(); | |
415 context->Enter(); | |
416 CalcFibAndCheck(); | |
417 } | |
Vitaly Repeshko
2011/04/15 00:29:39
context->Exit()?
Dmitry Lomov
2011/04/19 01:50:47
Done.
| |
418 private: | |
419 v8::Isolate* isolate_; | |
420 }; | |
421 | |
422 TEST(LockTwiceAndUnlock) { | |
423 const int kNThreads = 100; | |
424 i::List<JoinableThread*> threads(kNThreads); | |
425 v8::Isolate* isolate = v8::Isolate::New(); | |
426 for (int i = 0; i < kNThreads; i++) { | |
427 threads.Add(new LockTwiceAndUnlockThread(isolate)); | |
428 } | |
429 StartJoinAndDeleteThreads(threads); | |
430 isolate->Dispose(); | |
431 } | |
432 | |
433 class LockAndUnlockDifferentIsolatesThread : public JoinableThread { | |
434 public: | |
435 LockAndUnlockDifferentIsolatesThread(v8::Isolate* isolate1, | |
436 v8::Isolate* isolate2) | |
437 : JoinableThread(NULL, "LockAndUnlockDifferentIsolatesThread"), | |
438 isolate1_(isolate1), | |
439 isolate2_(isolate2) { | |
440 } | |
441 | |
442 void DoRun() { | |
443 Persistent<v8::Context> context1; | |
444 Persistent<v8::Context> context2; | |
445 v8::Locker lock1(isolate1_); | |
446 CHECK(v8::Locker::IsLocked(isolate1_)); | |
447 CHECK(!v8::Locker::IsLocked(isolate2_)); | |
448 { | |
449 v8::Isolate::Scope isolate_scope(isolate1_); | |
450 v8::HandleScope handle_scope; | |
451 context1 = v8::Context::New(); | |
452 context1->Enter(); | |
453 CalcFibAndCheck(); | |
454 context1->Exit(); | |
455 } | |
456 v8::Locker lock2(isolate2_); | |
457 CHECK(v8::Locker::IsLocked(isolate1_)); | |
458 CHECK(v8::Locker::IsLocked(isolate2_)); | |
459 { | |
460 v8::Isolate::Scope isolate_scope(isolate2_); | |
461 v8::HandleScope handle_scope; | |
462 context2 = v8::Context::New(); | |
463 context2->Enter(); | |
464 CalcFibAndCheck(); | |
465 context2->Exit(); | |
466 } | |
467 { | |
468 v8::Unlocker unlock1(isolate1_); | |
469 CHECK(!v8::Locker::IsLocked(isolate1_)); | |
470 CHECK(v8::Locker::IsLocked(isolate2_)); | |
471 v8::Isolate::Scope isolate_scope(isolate2_); | |
472 v8::HandleScope handle_scope; | |
473 context2->Enter(); | |
474 i::Semaphore* semaphore = i::OS::CreateSemaphore(0); | |
475 LockIsolateAndCalculateFibSharedContextThread thread(isolate1_, context1); | |
476 thread.StartWithSignal(semaphore); | |
477 CalcFibAndCheck(); | |
478 semaphore->Wait(); | |
479 delete semaphore; | |
480 context2->Exit(); | |
481 } | |
482 } | |
483 private: | |
484 v8::Isolate* isolate1_; | |
485 v8::Isolate* isolate2_; | |
486 }; | |
487 | |
488 TEST(LockAndUnlockDifferentIsolates) { | |
489 v8::Isolate* isolate1 = v8::Isolate::New(); | |
490 v8::Isolate* isolate2 = v8::Isolate::New(); | |
491 LockAndUnlockDifferentIsolatesThread thread(isolate1, isolate2); | |
492 i::Semaphore* semaphore = i::OS::CreateSemaphore(0); | |
493 thread.StartWithSignal(semaphore); | |
494 semaphore->Wait(); | |
495 delete semaphore; | |
496 isolate2->Dispose(); | |
497 isolate1->Dispose(); | |
498 } | |
499 | |
500 class LockUnlockLockThread : public JoinableThread { | |
501 public: | |
502 LockUnlockLockThread(v8::Isolate* isolate, v8::Handle<v8::Context> context) | |
503 : JoinableThread(NULL, "LockUnlockLockThread"), | |
504 isolate_(isolate), | |
505 context_(context) { | |
506 } | |
507 | |
508 void DoRun() { | |
509 v8::Locker lock1(isolate_); | |
510 CHECK(v8::Locker::IsLocked(isolate_)); | |
511 CHECK(!v8::Locker::IsLocked()); | |
512 { | |
513 v8::Isolate::Scope isolate_scope(isolate_); | |
514 v8::HandleScope handle_scope; | |
515 context_->Enter(); | |
516 CalcFibAndCheck(); | |
517 context_->Exit(); | |
518 } | |
519 { | |
520 v8::Unlocker unlock1(isolate_); | |
521 CHECK(!v8::Locker::IsLocked(isolate_)); | |
522 CHECK(!v8::Locker::IsLocked()); | |
523 { | |
524 v8::Locker lock2(isolate_); | |
525 v8::Isolate::Scope isolate_scope(isolate_); | |
526 v8::HandleScope handle_scope; | |
527 CHECK(v8::Locker::IsLocked(isolate_)); | |
528 CHECK(!v8::Locker::IsLocked()); | |
529 context_->Enter(); | |
530 CalcFibAndCheck(); | |
531 context_->Exit(); | |
532 } | |
533 } | |
534 } | |
535 | |
536 private: | |
537 v8::Isolate* isolate_; | |
538 v8::Persistent<v8::Context> context_; | |
539 }; | |
540 | |
541 TEST(LockUnlockLockMultithreaded) { | |
542 const int kNThreads = 100; | |
543 v8::Isolate* isolate = v8::Isolate::New(); | |
544 Persistent<v8::Context> context; | |
545 { | |
546 v8::Locker locker_(isolate); | |
547 v8::Isolate::Scope isolate_scope(isolate); | |
548 v8::HandleScope handle_scope; | |
549 context = v8::Context::New(); | |
550 } | |
551 i::List<JoinableThread*> threads(kNThreads); | |
552 for (int i = 0; i < kNThreads; i++) { | |
553 threads.Add(new LockUnlockLockThread(isolate, context)); | |
554 } | |
555 StartJoinAndDeleteThreads(threads); | |
556 } | |
557 | |
558 class LockUnlockLockDefaultIsolateThread : public JoinableThread { | |
559 public: | |
560 LockUnlockLockDefaultIsolateThread(v8::Handle<v8::Context> context) | |
561 : JoinableThread(NULL, "LockUnlockLockDefaultIsolateThread"), | |
562 context_(context) { | |
563 } | |
564 | |
565 void DoRun() { | |
566 v8::Locker lock1; | |
567 { | |
568 v8::HandleScope handle_scope; | |
569 context_->Enter(); | |
570 CalcFibAndCheck(); | |
571 context_->Exit(); | |
572 } | |
573 { | |
574 v8::Unlocker unlock1; | |
575 { | |
576 v8::Locker lock2; | |
577 v8::HandleScope handle_scope; | |
578 context_->Enter(); | |
579 CalcFibAndCheck(); | |
580 context_->Exit(); | |
581 } | |
582 } | |
583 } | |
584 | |
585 private: | |
586 v8::Persistent<v8::Context> context_; | |
587 }; | |
588 | |
589 TEST(LockUnlockLockDefaultIsolateMultithreaded) { | |
590 const int kNThreads = 100; | |
591 Persistent<v8::Context> context; | |
592 { | |
593 v8::Locker locker_; | |
594 v8::HandleScope handle_scope; | |
595 context = v8::Context::New(); | |
596 } | |
597 i::List<JoinableThread*> threads(kNThreads); | |
598 for (int i = 0; i < kNThreads; i++) { | |
599 threads.Add(new LockUnlockLockDefaultIsolateThread(context)); | |
600 } | |
601 StartJoinAndDeleteThreads(threads); | |
602 } | |
OLD | NEW |