Revision: 7735
Author:   [email protected]
Date:     Fri Apr 29 15:16:45 2011
Log: Revert "This implements per-isolate locking and unlocking, including tests"

This reverts commit 76c78febb70e75b18214f5fe45de95c7fb515386.

This change has broken test-thread-termination/TerminateMultipleV8Threads

TBR=vitalyr

Review URL: http://codereview.chromium.org/6903154
http://code.google.com/p/v8/source/detail?r=7735

Deleted:
 /branches/bleeding_edge/test/cctest/test-lockers.cc
Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/api.h
 /branches/bleeding_edge/src/execution.cc
 /branches/bleeding_edge/src/isolate.cc
 /branches/bleeding_edge/src/isolate.h
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/top.cc
 /branches/bleeding_edge/src/v8threads.cc
 /branches/bleeding_edge/test/cctest/SConscript
 /branches/bleeding_edge/test/cctest/cctest.gyp
 /branches/bleeding_edge/test/cctest/test-api.cc

=======================================
--- /branches/bleeding_edge/test/cctest/test-lockers.cc Fri Apr 29 14:26:03 2011
+++ /dev/null
@@ -1,605 +0,0 @@
-// Copyright 2007-2011 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include <limits.h>
-
-#include "v8.h"
-
-#include "api.h"
-#include "isolate.h"
-#include "compilation-cache.h"
-#include "execution.h"
-#include "snapshot.h"
-#include "platform.h"
-#include "utils.h"
-#include "cctest.h"
-#include "parser.h"
-#include "unicode-inl.h"
-
-using ::v8::AccessorInfo;
-using ::v8::Context;
-using ::v8::Extension;
-using ::v8::Function;
-using ::v8::HandleScope;
-using ::v8::Local;
-using ::v8::Object;
-using ::v8::ObjectTemplate;
-using ::v8::Persistent;
-using ::v8::Script;
-using ::v8::String;
-using ::v8::Value;
-using ::v8::V8;
-
-namespace i = ::i;
-
-
-
-
-// Migrating an isolate
-class KangarooThread : public v8::internal::Thread {
- public:
-  KangarooThread(v8::Isolate* isolate,
-                 v8::Handle<v8::Context> context, int value)
-      : Thread(NULL, "KangarooThread"),
-        isolate_(isolate), context_(context), value_(value) {
-  }
-
-  void Run() {
-    {
-      v8::Locker locker(isolate_);
-      v8::Isolate::Scope isolate_scope(isolate_);
-      CHECK_EQ(isolate_, v8::internal::Isolate::Current());
-      v8::HandleScope scope;
-      v8::Context::Scope context_scope(context_);
-      Local<Value> v = CompileRun("getValue()");
-      CHECK(v->IsNumber());
-      CHECK_EQ(30, static_cast<int>(v->NumberValue()));
-    }
-    {
-      v8::Locker locker(isolate_);
-      v8::Isolate::Scope isolate_scope(isolate_);
-      v8::Context::Scope context_scope(context_);
-      v8::HandleScope scope;
-      Local<Value> v = CompileRun("getValue()");
-      CHECK(v->IsNumber());
-      CHECK_EQ(30, static_cast<int>(v->NumberValue()));
-    }
-    isolate_->Dispose();
-  }
-
- private:
-  v8::Isolate* isolate_;
-  Persistent<v8::Context> context_;
-  int value_;
-};
-
-// Migrates an isolate from one thread to another
-TEST(KangarooIsolates) {
-  v8::Isolate* isolate = v8::Isolate::New();
-  Persistent<v8::Context> context;
-  {
-    v8::Locker locker(isolate);
-    v8::Isolate::Scope isolate_scope(isolate);
-    v8::HandleScope handle_scope;
-    context = v8::Context::New();
-    v8::Context::Scope context_scope(context);
-    CHECK_EQ(isolate, v8::internal::Isolate::Current());
-    CompileRun("function getValue() { return 30; }");
-  }
-  KangarooThread thread1(isolate, context, 1);
-  thread1.Start();
-  thread1.Join();
-}
-
-static void CalcFibAndCheck() {
-  Local<Value> v = CompileRun("function fib(n) {"
-                              "  if (n <= 2) return 1;"
-                              "  return fib(n-1) + fib(n-2);"
-                              "}"
-                              "fib(10)");
-  CHECK(v->IsNumber());
-  CHECK_EQ(55, static_cast<int>(v->NumberValue()));
-}
-
-class JoinableThread {
- public:
-  explicit JoinableThread(const char* name)
-    : name_(name),
-      semaphore_(i::OS::CreateSemaphore(0)),
-      thread_(this) {
-  }
-
-  virtual ~JoinableThread() {
-    delete semaphore_;
-  }
-
-  void Start() {
-    thread_.Start();
-  }
-
-  void Join() {
-    semaphore_->Wait();
-  }
-
-  virtual void Run() = 0;
- private:
-  class ThreadWithSemaphore : public i::Thread {
-   public:
-    explicit ThreadWithSemaphore(JoinableThread* joinable_thread)
-      : Thread(NULL, joinable_thread->name_),
-        joinable_thread_(joinable_thread) {
-    }
-
-    virtual void Run() {
-      joinable_thread_->Run();
-      joinable_thread_->semaphore_->Signal();
-    }
-
-   private:
-    JoinableThread* joinable_thread_;
-  };
-
-  const char* name_;
-  i::Semaphore* semaphore_;
-  ThreadWithSemaphore thread_;
-
-  friend class ThreadWithSemaphore;
-
-  DISALLOW_COPY_AND_ASSIGN(JoinableThread);
-};
-
-
-class IsolateLockingThreadWithLocalContext : public JoinableThread {
- public:
-  explicit IsolateLockingThreadWithLocalContext(v8::Isolate* isolate)
-    : JoinableThread("IsolateLockingThread"),
-      isolate_(isolate) {
-  }
-
-  virtual void Run() {
-    v8::Locker locker(isolate_);
-    v8::Isolate::Scope isolate_scope(isolate_);
-    v8::HandleScope handle_scope;
-    LocalContext local_context;
-    CHECK_EQ(isolate_, v8::internal::Isolate::Current());
-    CalcFibAndCheck();
-  }
- private:
-  v8::Isolate* isolate_;
-};
-
-static void StartJoinAndDeleteThreads(const i::List<JoinableThread*>& threads) {
-  for (int i = 0; i < threads.length(); i++) {
-    threads[i]->Start();
-  }
-  for (int i = 0; i < threads.length(); i++) {
-    threads[i]->Join();
-  }
-  for (int i = 0; i < threads.length(); i++) {
-    delete threads[i];
-  }
-}
-
-
-// Run many threads all locking on the same isolate
-TEST(IsolateLockingStress) {
-  const int kNThreads = 100;
-  i::List<JoinableThread*> threads(kNThreads);
-  v8::Isolate* isolate = v8::Isolate::New();
-  for (int i = 0; i < kNThreads; i++) {
-    threads.Add(new IsolateLockingThreadWithLocalContext(isolate));
-  }
-  StartJoinAndDeleteThreads(threads);
-  isolate->Dispose();
-}
-
-class IsolateNonlockingThread : public JoinableThread {
- public:
-  explicit IsolateNonlockingThread()
-    : JoinableThread("IsolateNonlockingThread") {
-  }
-
-  virtual void Run() {
-    v8::Isolate* isolate = v8::Isolate::New();
-    {
-      v8::Isolate::Scope isolate_scope(isolate);
-      v8::HandleScope handle_scope;
-      v8::Handle<v8::Context> context = v8::Context::New();
-      v8::Context::Scope context_scope(context);
-      CHECK_EQ(isolate, v8::internal::Isolate::Current());
-      CalcFibAndCheck();
-    }
-    isolate->Dispose();
-  }
- private:
-};
-
-// Run many threads each accessing its own isolate without locking
-TEST(MultithreadedParallelIsolates) {
-  const int kNThreads = 50;
-  i::List<JoinableThread*> threads(kNThreads);
-  for (int i = 0; i < kNThreads; i++) {
-    threads.Add(new IsolateNonlockingThread());
-  }
-  StartJoinAndDeleteThreads(threads);
-}
-
-
-class IsolateNestedLockingThread : public JoinableThread {
- public:
-  explicit IsolateNestedLockingThread(v8::Isolate* isolate)
-    : JoinableThread("IsolateNestedLocking"), isolate_(isolate) {
-  }
-  virtual void Run() {
-    v8::Locker lock(isolate_);
-    v8::Isolate::Scope isolate_scope(isolate_);
-    v8::HandleScope handle_scope;
-    LocalContext local_context;
-    {
-      v8::Locker another_lock(isolate_);
-      CalcFibAndCheck();
-    }
-    {
-      v8::Locker another_lock(isolate_);
-      CalcFibAndCheck();
-    }
-  }
- private:
-  v8::Isolate* isolate_;
-};
-
-// Run  many threads with nested locks
-TEST(IsolateNestedLocking) {
-  const int kNThreads = 100;
-  v8::Isolate* isolate = v8::Isolate::New();
-  i::List<JoinableThread*> threads(kNThreads);
-  for (int i = 0; i < kNThreads; i++) {
-    threads.Add(new IsolateNestedLockingThread(isolate));
-  }
-  StartJoinAndDeleteThreads(threads);
-}
-
-
-class SeparateIsolatesLocksNonexclusiveThread : public JoinableThread {
- public:
-  SeparateIsolatesLocksNonexclusiveThread(v8::Isolate* isolate1,
-                                          v8::Isolate* isolate2)
-    : JoinableThread("SeparateIsolatesLocksNonexclusiveThread"),
-      isolate1_(isolate1), isolate2_(isolate2) {
-  }
-
-  virtual void Run() {
-    v8::Locker lock(isolate1_);
-    v8::Isolate::Scope isolate_scope(isolate1_);
-    v8::HandleScope handle_scope;
-    LocalContext local_context;
-
-    IsolateLockingThreadWithLocalContext threadB(isolate2_);
-    threadB.Start();
-    CalcFibAndCheck();
-    threadB.Join();
-  }
- private:
-  v8::Isolate* isolate1_;
-  v8::Isolate* isolate2_;
-};
-
-// Run parallel threads that lock and access different isolates in parallel
-TEST(SeparateIsolatesLocksNonexclusive) {
-  const int kNThreads = 100;
-  v8::Isolate* isolate1 = v8::Isolate::New();
-  v8::Isolate* isolate2 = v8::Isolate::New();
-  i::List<JoinableThread*> threads(kNThreads);
-  for (int i = 0; i < kNThreads; i++) {
-    threads.Add(new SeparateIsolatesLocksNonexclusiveThread(isolate1,
-                                                             isolate2));
-  }
-  StartJoinAndDeleteThreads(threads);
-  isolate2->Dispose();
-  isolate1->Dispose();
-}
-
-class LockIsolateAndCalculateFibSharedContextThread : public JoinableThread {
- public:
-  explicit LockIsolateAndCalculateFibSharedContextThread(
-      v8::Isolate* isolate, v8::Handle<v8::Context> context)
-    : JoinableThread("LockIsolateAndCalculateFibThread"),
-      isolate_(isolate),
-      context_(context) {
-  }
-
-  virtual void Run() {
-    v8::Locker lock(isolate_);
-    v8::Isolate::Scope isolate_scope(isolate_);
-    HandleScope handle_scope;
-    v8::Context::Scope context_scope(context_);
-    CalcFibAndCheck();
-  }
- private:
-  v8::Isolate* isolate_;
-  Persistent<v8::Context> context_;
-};
-
-class LockerUnlockerThread : public JoinableThread {
- public:
-  explicit LockerUnlockerThread(v8::Isolate* isolate)
-    : JoinableThread("LockerUnlockerThread"),
-      isolate_(isolate) {
-  }
-
-  virtual void Run() {
-    v8::Locker lock(isolate_);
-    v8::Isolate::Scope isolate_scope(isolate_);
-    v8::HandleScope handle_scope;
-    v8::Handle<v8::Context> context = v8::Context::New();
-    {
-      v8::Context::Scope context_scope(context);
-      CalcFibAndCheck();
-    }
-    {
-      isolate_->Exit();
-      v8::Unlocker unlocker(isolate_);
- LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context);
-      thread.Start();
-      thread.Join();
-    }
-    isolate_->Enter();
-    {
-      v8::Context::Scope context_scope(context);
-      CalcFibAndCheck();
-    }
-  }
- private:
-  v8::Isolate* isolate_;
-};
-
-// Use unlocker inside of a Locker, multiple threads.
-TEST(LockerUnlocker) {
-  const int kNThreads = 100;
-  i::List<JoinableThread*> threads(kNThreads);
-  v8::Isolate* isolate = v8::Isolate::New();
-  for (int i = 0; i < kNThreads; i++) {
-    threads.Add(new LockerUnlockerThread(isolate));
-  }
-  StartJoinAndDeleteThreads(threads);
-  isolate->Dispose();
-}
-
-class LockTwiceAndUnlockThread : public JoinableThread {
- public:
-  explicit LockTwiceAndUnlockThread(v8::Isolate* isolate)
-    : JoinableThread("LockTwiceAndUnlockThread"),
-      isolate_(isolate) {
-  }
-
-  virtual void Run() {
-    v8::Locker lock(isolate_);
-    v8::Isolate::Scope isolate_scope(isolate_);
-    v8::HandleScope handle_scope;
-    v8::Handle<v8::Context> context = v8::Context::New();
-    {
-      v8::Context::Scope context_scope(context);
-      CalcFibAndCheck();
-    }
-    {
-      v8::Locker second_lock(isolate_);
-      {
-        isolate_->Exit();
-        v8::Unlocker unlocker(isolate_);
- LockIsolateAndCalculateFibSharedContextThread thread(isolate_, context);
-        thread.Start();
-        thread.Join();
-      }
-    }
-    isolate_->Enter();
-    {
-      v8::Context::Scope context_scope(context);
-      CalcFibAndCheck();
-    }
-  }
- private:
-  v8::Isolate* isolate_;
-};
-
-// Use Unlocker inside two Lockers.
-TEST(LockTwiceAndUnlock) {
-  const int kNThreads = 100;
-  i::List<JoinableThread*> threads(kNThreads);
-  v8::Isolate* isolate = v8::Isolate::New();
-  for (int i = 0; i < kNThreads; i++) {
-    threads.Add(new LockTwiceAndUnlockThread(isolate));
-  }
-  StartJoinAndDeleteThreads(threads);
-  isolate->Dispose();
-}
-
-class LockAndUnlockDifferentIsolatesThread : public JoinableThread {
- public:
-  LockAndUnlockDifferentIsolatesThread(v8::Isolate* isolate1,
-                                       v8::Isolate* isolate2)
-    : JoinableThread("LockAndUnlockDifferentIsolatesThread"),
-      isolate1_(isolate1),
-      isolate2_(isolate2) {
-  }
-
-  virtual void Run() {
-    Persistent<v8::Context> context1;
-    Persistent<v8::Context> context2;
-    v8::Locker lock1(isolate1_);
-    CHECK(v8::Locker::IsLocked(isolate1_));
-    CHECK(!v8::Locker::IsLocked(isolate2_));
-    {
-      v8::Isolate::Scope isolate_scope(isolate1_);
-      v8::HandleScope handle_scope;
-      context1 = v8::Context::New();
-      {
-        v8::Context::Scope context_scope(context1);
-        CalcFibAndCheck();
-      }
-    }
-    v8::Locker lock2(isolate2_);
-    CHECK(v8::Locker::IsLocked(isolate1_));
-    CHECK(v8::Locker::IsLocked(isolate2_));
-    {
-      v8::Isolate::Scope isolate_scope(isolate2_);
-      v8::HandleScope handle_scope;
-      context2 = v8::Context::New();
-      {
-        v8::Context::Scope context_scope(context2);
-        CalcFibAndCheck();
-      }
-    }
-    {
-      v8::Unlocker unlock1(isolate1_);
-      CHECK(!v8::Locker::IsLocked(isolate1_));
-      CHECK(v8::Locker::IsLocked(isolate2_));
-      v8::Isolate::Scope isolate_scope(isolate2_);
-      v8::HandleScope handle_scope;
-      v8::Context::Scope context_scope(context2);
- LockIsolateAndCalculateFibSharedContextThread thread(isolate1_, context1);
-      thread.Start();
-      CalcFibAndCheck();
-      thread.Join();
-    }
-  }
- private:
-  v8::Isolate* isolate1_;
-  v8::Isolate* isolate2_;
-};
-
-// Lock two isolates and unlock one of them.
-TEST(LockAndUnlockDifferentIsolates) {
-  v8::Isolate* isolate1 = v8::Isolate::New();
-  v8::Isolate* isolate2 = v8::Isolate::New();
-  LockAndUnlockDifferentIsolatesThread thread(isolate1, isolate2);
-  thread.Start();
-  thread.Join();
-  isolate2->Dispose();
-  isolate1->Dispose();
-}
-
-class LockUnlockLockThread : public JoinableThread {
- public:
- LockUnlockLockThread(v8::Isolate* isolate, v8::Handle<v8::Context> context)
-    : JoinableThread("LockUnlockLockThread"),
-      isolate_(isolate),
-      context_(context) {
-  }
-
-  virtual void Run() {
-    v8::Locker lock1(isolate_);
-    CHECK(v8::Locker::IsLocked(isolate_));
-    CHECK(!v8::Locker::IsLocked());
-    {
-      v8::Isolate::Scope isolate_scope(isolate_);
-      v8::HandleScope handle_scope;
-      v8::Context::Scope context_scope(context_);
-      CalcFibAndCheck();
-    }
-    {
-      v8::Unlocker unlock1(isolate_);
-      CHECK(!v8::Locker::IsLocked(isolate_));
-      CHECK(!v8::Locker::IsLocked());
-      {
-        v8::Locker lock2(isolate_);
-        v8::Isolate::Scope isolate_scope(isolate_);
-        v8::HandleScope handle_scope;
-        CHECK(v8::Locker::IsLocked(isolate_));
-        CHECK(!v8::Locker::IsLocked());
-        v8::Context::Scope context_scope(context_);
-        CalcFibAndCheck();
-      }
-    }
-  }
-
- private:
-  v8::Isolate* isolate_;
-  v8::Persistent<v8::Context> context_;
-};
-
-// Locker inside an Unlocker inside a Locker.
-TEST(LockUnlockLockMultithreaded) {
-  const int kNThreads = 100;
-  v8::Isolate* isolate = v8::Isolate::New();
-  Persistent<v8::Context> context;
-  {
-    v8::Locker locker_(isolate);
-    v8::Isolate::Scope isolate_scope(isolate);
-    v8::HandleScope handle_scope;
-    context = v8::Context::New();
-  }
-  i::List<JoinableThread*> threads(kNThreads);
-  for (int i = 0; i < kNThreads; i++) {
-    threads.Add(new LockUnlockLockThread(isolate, context));
-  }
-  StartJoinAndDeleteThreads(threads);
-}
-
-class LockUnlockLockDefaultIsolateThread : public JoinableThread {
- public:
-  LockUnlockLockDefaultIsolateThread(v8::Handle<v8::Context> context)
-    : JoinableThread("LockUnlockLockDefaultIsolateThread"),
-      context_(context) {
-  }
-
-  virtual void Run() {
-    v8::Locker lock1;
-    {
-      v8::HandleScope handle_scope;
-      v8::Context::Scope context_scope(context_);
-      CalcFibAndCheck();
-    }
-    {
-      v8::Unlocker unlock1;
-      {
-        v8::Locker lock2;
-        v8::HandleScope handle_scope;
-        v8::Context::Scope context_scope(context_);
-        CalcFibAndCheck();
-      }
-    }
-  }
-
- private:
-  v8::Persistent<v8::Context> context_;
-};
-
-// Locker inside an Unlocker inside a Locker for default isolate.
-TEST(LockUnlockLockDefaultIsolateMultithreaded) {
-  const int kNThreads = 100;
-  Persistent<v8::Context> context;
-  {
-    v8::Locker locker_;
-    v8::HandleScope handle_scope;
-    context = v8::Context::New();
-  }
-  i::List<JoinableThread*> threads(kNThreads);
-  for (int i = 0; i < kNThreads; i++) {
-    threads.Add(new LockUnlockLockDefaultIsolateThread(context));
-  }
-  StartJoinAndDeleteThreads(threads);
-}
=======================================
--- /branches/bleeding_edge/include/v8.h        Fri Apr 29 14:26:03 2011
+++ /branches/bleeding_edge/include/v8.h        Fri Apr 29 15:16:45 2011
@@ -3355,20 +3355,26 @@
  * to the user of V8 to ensure (perhaps with locking) that this
  * constraint is not violated.
  *
- * v8::Locker is a scoped lock object. While it's
- * active (i.e. between its construction and destruction) the current thread is - * allowed to use the locked isolate. V8 guarantees that an isolate can be locked - * by at most one thread at any time. In other words, the scope of a v8::Locker is
- * a critical section.
+ * More then one thread and multiple V8 isolates can be used
+ * without any locking if each isolate is created and accessed
+ * by a single thread only. For example, one thread can use
+ * multiple isolates or multiple threads can each create and run
+ * their own isolate.
  *
- * Sample usage:
-* \code
+ * If you wish to start using V8 isolate in more then one thread
+ * you can do this by constructing a v8::Locker object to guard
+ * access to the isolate. After the code using V8 has completed
+ * for the current thread you can call the destructor.  This can
+ * be combined with C++ scope-based construction as follows
+ * (assumes the default isolate that is used if not specified as
+ * a parameter for the Locker):
+ *
+ * \code
  * ...
  * {
- *   v8::Locker locker(isolate);
- *   v8::Isolate::Scope isolate_scope(isolate);
+ *   v8::Locker locker;
  *   ...
- *   // Code using V8 and isolate goes here.
+ *   // Code using V8 goes here.
  *   ...
  * } // Destructor called here
  * \endcode
@@ -3379,13 +3385,11 @@
  *
  * \code
  * {
- *   isolate->Exit();
- *   v8::Unlocker unlocker(isolate);
+ *   v8::Unlocker unlocker;
  *   ...
  *   // Code not using V8 goes here while V8 can run in another thread.
  *   ...
  * } // Destructor called here.
- * isolate->Enter();
  * \endcode
  *
  * The Unlocker object is intended for use in a long-running callback
@@ -3405,45 +3409,32 @@
  * \code
  * // V8 not locked.
  * {
- *   v8::Locker locker(isolate);
- *   Isolate::Scope isolate_scope(isolate);
+ *   v8::Locker locker;
  *   // V8 locked.
  *   {
- *     v8::Locker another_locker(isolate);
+ *     v8::Locker another_locker;
  *     // V8 still locked (2 levels).
  *     {
- *       isolate->Exit();
- *       v8::Unlocker unlocker(isolate);
+ *       v8::Unlocker unlocker;
  *       // V8 not locked.
  *     }
- *     isolate->Enter();
  *     // V8 locked again (2 levels).
  *   }
  *   // V8 still locked (1 level).
  * }
  * // V8 Now no longer locked.
  * \endcode
- *
- *
  */
 class V8EXPORT Unlocker {
  public:
-  /**
-   * Initialize Unlocker for a given Isolate. NULL means default isolate.
-   */
-  explicit Unlocker(Isolate* isolate = NULL);
+  Unlocker();
   ~Unlocker();
- private:
-  internal::Isolate* isolate_;
 };


 class V8EXPORT Locker {
  public:
-  /**
-   * Initialize Locker for a given Isolate. NULL means default isolate.
-   */
-  explicit Locker(Isolate* isolate = NULL);
+  Locker();
   ~Locker();

   /**
@@ -3461,10 +3452,9 @@
   static void StopPreemption();

   /**
- * Returns whether or not the locker for a given isolate, or default isolate if NULL is given,
-   * is locked by the current thread.
+   * Returns whether or not the locker is locked by the current thread.
    */
-  static bool IsLocked(Isolate* isolate = NULL);
+  static bool IsLocked();

   /**
    * Returns whether v8::Locker is being used by this V8 instance.
@@ -3474,7 +3464,6 @@
  private:
   bool has_lock_;
   bool top_level_;
-  internal::Isolate* isolate_;

   static bool active_;

=======================================
--- /branches/bleeding_edge/src/api.cc  Fri Apr 29 14:26:03 2011
+++ /branches/bleeding_edge/src/api.cc  Fri Apr 29 15:16:45 2011
@@ -53,6 +53,7 @@

 #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))

+// TODO(isolates): avoid repeated TLS reads in function prologues.
 #ifdef ENABLE_VMSTATE_TRACKING
 #define ENTER_V8(isolate)                                        \
   ASSERT((isolate)->IsInitialized());                           \
@@ -289,7 +290,6 @@
   if (isolate != NULL) {
     if (isolate->IsInitialized()) return true;
   }
-  ASSERT(isolate == i::Isolate::Current());
   return ApiCheck(InitializeHelper(), location, "Error initializing V8");
 }

@@ -5687,8 +5687,9 @@


 char* HandleScopeImplementer::ArchiveThread(char* storage) {
+  Isolate* isolate = Isolate::Current();
   v8::ImplementationUtilities::HandleScopeData* current =
-      isolate_->handle_scope_data();
+      isolate->handle_scope_data();
   handle_scope_data_ = *current;
   memcpy(storage, this, sizeof(*this));

@@ -5706,7 +5707,7 @@

 char* HandleScopeImplementer::RestoreThread(char* storage) {
   memcpy(this, storage, sizeof(*this));
-  *isolate_->handle_scope_data() = handle_scope_data_;
+  *Isolate::Current()->handle_scope_data() = handle_scope_data_;
   return storage + ArchiveSpacePerThread();
 }

@@ -5732,7 +5733,7 @@

 void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
   v8::ImplementationUtilities::HandleScopeData* current =
-      isolate_->handle_scope_data();
+      Isolate::Current()->handle_scope_data();
   handle_scope_data_ = *current;
   IterateThis(v);
 }
=======================================
--- /branches/bleeding_edge/src/api.h   Fri Apr 29 14:26:03 2011
+++ /branches/bleeding_edge/src/api.h   Fri Apr 29 15:16:45 2011
@@ -399,9 +399,8 @@
 ISOLATED_CLASS HandleScopeImplementer {
  public:

-  explicit HandleScopeImplementer(Isolate* isolate)
-      : isolate_(isolate),
-        blocks_(0),
+  HandleScopeImplementer()
+      : blocks_(0),
         entered_contexts_(0),
         saved_contexts_(0),
         spare_(NULL),
@@ -467,7 +466,6 @@
     ASSERT(call_depth_ == 0);
   }

-  Isolate* isolate_;
   List<internal::Object**> blocks_;
   // Used as a stack to keep track of entered contexts.
   List<Handle<Object> > entered_contexts_;
=======================================
--- /branches/bleeding_edge/src/execution.cc    Fri Apr 29 14:26:03 2011
+++ /branches/bleeding_edge/src/execution.cc    Fri Apr 29 15:16:45 2011
@@ -457,9 +457,8 @@

 void StackGuard::InitThread(const ExecutionAccess& lock) {
   if (thread_local_.Initialize()) isolate_->heap()->SetStackLimits();
-  Isolate::PerIsolateThreadData* per_thread =
-      isolate_->FindOrAllocatePerThreadDataForThisThread();
-  uintptr_t stored_limit = per_thread->stack_limit();
+  uintptr_t stored_limit =
+      Isolate::CurrentPerIsolateThreadData()->stack_limit();
   // You should hold the ExecutionAccess lock when you call this.
   if (stored_limit != 0) {
     StackGuard::SetStackLimit(stored_limit);
=======================================
--- /branches/bleeding_edge/src/isolate.cc      Fri Apr 29 14:26:03 2011
+++ /branches/bleeding_edge/src/isolate.cc      Fri Apr 29 15:16:45 2011
@@ -309,17 +309,6 @@
   }
   return per_thread;
 }
-
-
-Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() {
-  ThreadId thread_id = ThreadId::Current();
-  PerIsolateThreadData* per_thread = NULL;
-  {
-    ScopedLock lock(process_wide_mutex_);
-    per_thread = thread_data_table_->Lookup(this, thread_id);
-  }
-  return per_thread;
-}


 void Isolate::EnsureDefaultIsolate() {
@@ -333,9 +322,7 @@
   }
   // Can't use SetIsolateThreadLocals(default_isolate_, NULL) here
   // becase a non-null thread data may be already set.
-  if (Thread::GetThreadLocal(isolate_key_) == NULL) {
-    Thread::SetThreadLocal(isolate_key_, default_isolate_);
-  }
+  Thread::SetThreadLocal(isolate_key_, default_isolate_);
   CHECK(default_isolate_->PreInit());
 }

@@ -471,11 +458,6 @@
   zone_.isolate_ = this;
   stack_guard_.isolate_ = this;

-  // ThreadManager is initialized early to support locking an isolate
-  // before it is entered.
-  thread_manager_ = new ThreadManager();
-  thread_manager_->isolate_ = this;
-
 #if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
     defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
   simulator_initialized_ = false;
@@ -661,6 +643,7 @@
   TRACE_ISOLATE(preinit);

   ASSERT(Isolate::Current() == this);
+
 #ifdef ENABLE_DEBUGGER_SUPPORT
   debug_ = new Debug(this);
   debugger_ = new Debugger();
@@ -688,6 +671,8 @@

   string_tracker_ = new StringTracker();
   string_tracker_->isolate_ = this;
+  thread_manager_ = new ThreadManager();
+  thread_manager_->isolate_ = this;
   compilation_cache_ = new CompilationCache(this);
   transcendental_cache_ = new TranscendentalCache();
   keyed_lookup_cache_ = new KeyedLookupCache();
@@ -698,7 +683,7 @@
   write_input_buffer_ = new StringInputBuffer();
   global_handles_ = new GlobalHandles(this);
   bootstrapper_ = new Bootstrapper();
-  handle_scope_implementer_ = new HandleScopeImplementer(this);
+  handle_scope_implementer_ = new HandleScopeImplementer();
   stub_cache_ = new StubCache(this);
   ast_sentinels_ = new AstSentinels();
   regexp_stack_ = new RegExpStack();
@@ -715,7 +700,6 @@


 void Isolate::InitializeThreadLocal() {
-  thread_local_top_.isolate_ = this;
   thread_local_top_.Initialize();
   clear_pending_exception();
   clear_pending_message();
=======================================
--- /branches/bleeding_edge/src/isolate.h       Fri Apr 29 14:26:03 2011
+++ /branches/bleeding_edge/src/isolate.h       Fri Apr 29 15:16:45 2011
@@ -224,7 +224,6 @@
     ASSERT(try_catch_handler_address_ == NULL);
   }

-  Isolate* isolate_;
// The context where the current execution method is created and for variable
   // lookups.
   Context* context_;
@@ -487,10 +486,6 @@
   // Safe to call multiple times.
   static void EnsureDefaultIsolate();

-  // Find the PerThread for this particular (isolate, thread) combination
-  // If one does not yet exist, return null.
-  PerIsolateThreadData* FindPerThreadDataForThisThread();
-
 #ifdef ENABLE_DEBUGGER_SUPPORT
   // Get the debugger from the default isolate. Preinitializes the
   // default isolate if needed.
@@ -1070,7 +1065,7 @@
   // If one does not yet exist, allocate a new one.
   PerIsolateThreadData* FindOrAllocatePerThreadDataForThisThread();

-// PreInits and returns a default isolate. Needed when a new thread tries
+  // PreInits and returns a default isolate. Needed when a new thread tries
// to create a Locker for the first time (the lock itself is in the isolate).
   static Isolate* GetDefaultIsolateForLocking();

@@ -1202,12 +1197,9 @@

   friend class ExecutionAccess;
   friend class IsolateInitializer;
-  friend class ThreadManager;
-  friend class StackGuard;
   friend class ThreadId;
   friend class v8::Isolate;
   friend class v8::Locker;
-  friend class v8::Unlocker;

   DISALLOW_COPY_AND_ASSIGN(Isolate);
 };
=======================================
--- /branches/bleeding_edge/src/objects.cc      Fri Apr 29 14:26:03 2011
+++ /branches/bleeding_edge/src/objects.cc      Fri Apr 29 15:16:45 2011
@@ -4958,7 +4958,8 @@


 // Archive statics that are thread local.
-char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
+char* Relocatable::ArchiveState(char* to) {
+  Isolate* isolate = Isolate::Current();
   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
   isolate->set_relocatable_top(NULL);
   return to + ArchiveSpacePerThread();
@@ -4966,7 +4967,8 @@


 // Restore statics that are thread local.
-char* Relocatable::RestoreState(Isolate* isolate, char* from) {
+char* Relocatable::RestoreState(char* from) {
+  Isolate* isolate = Isolate::Current();
   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
   return from + ArchiveSpacePerThread();
 }
=======================================
--- /branches/bleeding_edge/src/objects.h       Fri Apr 29 14:26:03 2011
+++ /branches/bleeding_edge/src/objects.h       Fri Apr 29 15:16:45 2011
@@ -5924,8 +5924,8 @@

   static void PostGarbageCollectionProcessing();
   static int ArchiveSpacePerThread();
-  static char* ArchiveState(Isolate* isolate, char* to);
-  static char* RestoreState(Isolate* isolate, char* from);
+  static char* ArchiveState(char* to);
+  static char* RestoreState(char* from);
   static void Iterate(ObjectVisitor* v);
   static void Iterate(ObjectVisitor* v, Relocatable* top);
   static char* Iterate(ObjectVisitor* v, char* t);
=======================================
--- /branches/bleeding_edge/src/top.cc  Fri Apr 29 14:26:03 2011
+++ /branches/bleeding_edge/src/top.cc  Fri Apr 29 15:16:45 2011
@@ -77,9 +77,9 @@
   InitializeInternal();
 #ifdef USE_SIMULATOR
 #ifdef V8_TARGET_ARCH_ARM
-  simulator_ = Simulator::current(isolate_);
+  simulator_ = Simulator::current(Isolate::Current());
 #elif V8_TARGET_ARCH_MIPS
-  simulator_ = Simulator::current(isolate_);
+  simulator_ = Simulator::current(Isolate::Current());
 #endif
 #endif
   thread_id_ = ThreadId::Current();
=======================================
--- /branches/bleeding_edge/src/v8threads.cc    Fri Apr 29 14:26:03 2011
+++ /branches/bleeding_edge/src/v8threads.cc    Fri Apr 29 15:16:45 2011
@@ -43,85 +43,90 @@


 // Constructor for the Locker object.  Once the Locker is constructed the
-// current thread will be guaranteed to have the lock for a given isolate.
-Locker::Locker(v8::Isolate* isolate)
-  : has_lock_(false),
-    top_level_(false),
-    isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
-  if (isolate_ == NULL) {
-    isolate_ = i::Isolate::GetDefaultIsolateForLocking();
-  }
+// current thread will be guaranteed to have the big V8 lock.
+Locker::Locker() : has_lock_(false), top_level_(true) {
+ // TODO(isolates): When Locker has Isolate parameter and it is provided, grab
+  // that one instead of using the current one.
+  // We pull default isolate for Locker constructor w/o p[arameter.
+  // A thread should not enter an isolate before acquiring a lock,
+  // in cases which mandate using Lockers.
+  // So getting a lock is the first thing threads do in a scenario where
+  // multple threads share an isolate. Hence, we need to access
+  // 'locking isolate' before we can actually enter into default isolate.
+ internal::Isolate* isolate = internal::Isolate::GetDefaultIsolateForLocking();
+  ASSERT(isolate != NULL);
+
   // Record that the Locker has been used at least once.
   active_ = true;
   // Get the big lock if necessary.
-  if (!isolate_->thread_manager()->IsLockedByCurrentThread()) {
-    isolate_->thread_manager()->Lock();
+  if (!isolate->thread_manager()->IsLockedByCurrentThread()) {
+    isolate->thread_manager()->Lock();
     has_lock_ = true;

+    if (isolate->IsDefaultIsolate()) {
+      // This only enters if not yet entered.
+      internal::Isolate::EnterDefaultIsolate();
+    }
+
+    ASSERT(internal::Thread::HasThreadLocal(
+        internal::Isolate::thread_id_key()));
+
     // Make sure that V8 is initialized.  Archiving of threads interferes
     // with deserialization by adding additional root pointers, so we must
     // initialize here, before anyone can call ~Locker() or Unlocker().
-    if (isolate_->IsDefaultIsolate()) {
-      // This only enters if not yet entered.
-      internal::Isolate::EnterDefaultIsolate();
-    } else if (!isolate_->IsInitialized()) {
-      isolate_->Enter();
+    if (!isolate->IsInitialized()) {
       V8::Initialize();
-      isolate_->Exit();
-    }
-
+    }
     // This may be a locker within an unlocker in which case we have to
     // get the saved state for this thread and restore it.
-    if (isolate_->thread_manager()->RestoreThread()) {
+    if (isolate->thread_manager()->RestoreThread()) {
       top_level_ = false;
     } else {
-      internal::ExecutionAccess access(isolate_);
-      isolate_->stack_guard()->ClearThread(access);
-      isolate_->stack_guard()->InitThread(access);
+      internal::ExecutionAccess access(isolate);
+      isolate->stack_guard()->ClearThread(access);
+      isolate->stack_guard()->InitThread(access);
     }
   }
-  ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
+  ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
 }


-bool Locker::IsLocked(v8::Isolate* isolate) {
-  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
-  if (internal_isolate == NULL) {
-    internal_isolate = i::Isolate::GetDefaultIsolateForLocking();
-  }
-  return internal_isolate->thread_manager()->IsLockedByCurrentThread();
+bool Locker::IsLocked() {
+  return internal::Isolate::Current()->thread_manager()->
+      IsLockedByCurrentThread();
 }


 Locker::~Locker() {
-  ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
+  // TODO(isolate): this should use a field storing the isolate it
+  // locked instead.
+  internal::Isolate* isolate = internal::Isolate::Current();
+  ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
   if (has_lock_) {
     if (top_level_) {
-      isolate_->thread_manager()->FreeThreadResources();
+      isolate->thread_manager()->FreeThreadResources();
     } else {
-      isolate_->thread_manager()->ArchiveThread();
-    }
-    isolate_->thread_manager()->Unlock();
+      isolate->thread_manager()->ArchiveThread();
+    }
+    isolate->thread_manager()->Unlock();
   }
 }


-Unlocker::Unlocker(v8::Isolate* isolate)
-  : isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
-  if (isolate_ == NULL) {
-    isolate_ = i::Isolate::GetDefaultIsolateForLocking();
-  }
-
-  ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
-  isolate_->thread_manager()->ArchiveThread();
-  isolate_->thread_manager()->Unlock();
+Unlocker::Unlocker() {
+  internal::Isolate* isolate = internal::Isolate::Current();
+  ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
+  isolate->thread_manager()->ArchiveThread();
+  isolate->thread_manager()->Unlock();
 }


 Unlocker::~Unlocker() {
-  ASSERT(!isolate_->thread_manager()->IsLockedByCurrentThread());
-  isolate_->thread_manager()->Lock();
-  isolate_->thread_manager()->RestoreThread();
+  // TODO(isolates): check it's the isolate we unlocked.
+  internal::Isolate* isolate = internal::Isolate::Current();
+  ASSERT(!isolate->thread_manager()->IsLockedByCurrentThread());
+  isolate->thread_manager()->Lock();
+  isolate->thread_manager()->RestoreThread();
 }


@@ -139,20 +144,17 @@


 bool ThreadManager::RestoreThread() {
-  ASSERT(IsLockedByCurrentThread());
   // First check whether the current thread has been 'lazily archived', ie
   // not archived at all.  If that is the case we put the state storage we
   // had prepared back in the free list, since we didn't need it after all.
   if (lazily_archived_thread_.Equals(ThreadId::Current())) {
     lazily_archived_thread_ = ThreadId::Invalid();
-    Isolate::PerIsolateThreadData* per_thread =
-        isolate_->FindPerThreadDataForThisThread();
-    ASSERT(per_thread != NULL);
-    ASSERT(per_thread->thread_state() == lazily_archived_thread_state_);
+    ASSERT(Isolate::CurrentPerIsolateThreadData()->thread_state() ==
+           lazily_archived_thread_state_);
     lazily_archived_thread_state_->set_id(ThreadId::Invalid());
     lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
     lazily_archived_thread_state_ = NULL;
-    per_thread->set_thread_state(NULL);
+    Isolate::CurrentPerIsolateThreadData()->set_thread_state(NULL);
     return true;
   }

@@ -166,7 +168,7 @@
     EagerlyArchiveThread();
   }
   Isolate::PerIsolateThreadData* per_thread =
-      isolate_->FindPerThreadDataForThisThread();
+      Isolate::CurrentPerIsolateThreadData();
   if (per_thread == NULL || per_thread->thread_state() == NULL) {
     // This is a new thread.
     isolate_->stack_guard()->InitThread(access);
@@ -176,7 +178,7 @@
   char* from = state->data();
   from = isolate_->handle_scope_implementer()->RestoreThread(from);
   from = isolate_->RestoreThread(from);
-  from = Relocatable::RestoreState(isolate_, from);
+  from = Relocatable::RestoreState(from);
 #ifdef ENABLE_DEBUGGER_SUPPORT
   from = isolate_->debug()->RestoreDebug(from);
 #endif
@@ -298,12 +300,9 @@
 void ThreadManager::ArchiveThread() {
   ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid()));
   ASSERT(!IsArchived());
-  ASSERT(IsLockedByCurrentThread());
   ThreadState* state = GetFreeThreadState();
   state->Unlink();
-  Isolate::PerIsolateThreadData* per_thread =
-      isolate_->FindOrAllocatePerThreadDataForThisThread();
-  per_thread->set_thread_state(state);
+  Isolate::CurrentPerIsolateThreadData()->set_thread_state(state);
   lazily_archived_thread_ = ThreadId::Current();
   lazily_archived_thread_state_ = state;
   ASSERT(state->id().Equals(ThreadId::Invalid()));
@@ -313,7 +312,6 @@


 void ThreadManager::EagerlyArchiveThread() {
-  ASSERT(IsLockedByCurrentThread());
   ThreadState* state = lazily_archived_thread_state_;
   state->LinkInto(ThreadState::IN_USE_LIST);
   char* to = state->data();
@@ -321,7 +319,7 @@
   // in ThreadManager::Iterate(ObjectVisitor*).
   to = isolate_->handle_scope_implementer()->ArchiveThread(to);
   to = isolate_->ArchiveThread(to);
-  to = Relocatable::ArchiveState(isolate_, to);
+  to = Relocatable::ArchiveState(to);
 #ifdef ENABLE_DEBUGGER_SUPPORT
   to = isolate_->debug()->ArchiveDebug(to);
 #endif
@@ -346,10 +344,10 @@


 bool ThreadManager::IsArchived() {
-  Isolate::PerIsolateThreadData* data =
-      isolate_->FindPerThreadDataForThisThread();
+ Isolate::PerIsolateThreadData* data = Isolate::CurrentPerIsolateThreadData();
   return data != NULL && data->thread_state() != NULL;
 }
+

 void ThreadManager::Iterate(ObjectVisitor* v) {
   // Expecting no threads during serialization/deserialization
=======================================
--- /branches/bleeding_edge/test/cctest/SConscript      Fri Apr 29 14:26:03 2011
+++ /branches/bleeding_edge/test/cctest/SConscript      Fri Apr 29 15:16:45 2011
@@ -64,7 +64,6 @@
     'test-list.cc',
     'test-liveedit.cc',
     'test-lock.cc',
-    'test-lockers.cc',
     'test-log-utils.cc',
     'test-log.cc',
     'test-mark-compact.cc',
=======================================
--- /branches/bleeding_edge/test/cctest/cctest.gyp      Fri Apr 29 14:26:03 2011
+++ /branches/bleeding_edge/test/cctest/cctest.gyp      Fri Apr 29 15:16:45 2011
@@ -93,7 +93,6 @@
         'test-list.cc',
         'test-liveedit.cc',
         'test-lock.cc',
-        'test-lockers.cc',
         'test-log.cc',
         'test-log-utils.cc',
         'test-mark-compact.cc',
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc     Fri Apr 29 14:26:03 2011
+++ /branches/bleeding_edge/test/cctest/test-api.cc     Fri Apr 29 15:16:45 2011
@@ -30,7 +30,6 @@
 #include "v8.h"

 #include "api.h"
-#include "isolate.h"
 #include "compilation-cache.h"
 #include "execution.h"
 #include "snapshot.h"
@@ -13387,28 +13386,6 @@
   isolate2->Dispose();
 }

-TEST(IsolateDifferentContexts) {
-  v8::Isolate* isolate = v8::Isolate::New();
-  Persistent<v8::Context> context;
-  {
-    v8::Isolate::Scope isolate_scope(isolate);
-    v8::HandleScope handle_scope;
-    context = v8::Context::New();
-    v8::Context::Scope context_scope(context);
-    Local<Value> v = CompileRun("2");
-    CHECK(v->IsNumber());
-    CHECK_EQ(2, static_cast<int>(v->NumberValue()));
-  }
-  {
-    v8::Isolate::Scope isolate_scope(isolate);
-    v8::HandleScope handle_scope;
-    context = v8::Context::New();
-    v8::Context::Scope context_scope(context);
-    Local<Value> v = CompileRun("22");
-    CHECK(v->IsNumber());
-    CHECK_EQ(22, static_cast<int>(v->NumberValue()));
-  }
-}

 class InitDefaultIsolateThread : public v8::internal::Thread {
  public:

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to