Chromium Code Reviews| 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 |