Revision: 11215
Author:   [email protected]
Date:     Tue Apr  3 01:37:53 2012
Log:      Merged r11194, r11198, r11201, r11214 into trunk branch.

Ensure that arguments object is materialized when deoptimizing from inlined function.

Fix performance regressions due to lazy initialization.

Fix broken build on Windows due to r11198.

Properly support shrinking arrays in CopyDictionaryToObjectElements.

BUG=v8:2045,chromium:118686,chromium:121407

[email protected]

Review URL: https://chromiumcodereview.appspot.com/9959093
http://code.google.com/p/v8/source/detail?r=11215

Added:
 /trunk/src/platform-posix.h
 /trunk/test/mjsunit/regress/regress-121407.js
 /trunk/test/mjsunit/regress/regress-2045.js
Modified:
 /trunk/src/api.cc
 /trunk/src/arm/lithium-arm.cc
 /trunk/src/elements.cc
 /trunk/src/hydrogen-instructions.h
 /trunk/src/hydrogen.cc
 /trunk/src/ia32/lithium-ia32.cc
 /trunk/src/isolate.cc
 /trunk/src/isolate.h
 /trunk/src/lazy-instance.h
 /trunk/src/mips/lithium-mips.cc
 /trunk/src/platform-cygwin.cc
 /trunk/src/platform-freebsd.cc
 /trunk/src/platform-linux.cc
 /trunk/src/platform-macos.cc
 /trunk/src/platform-nullos.cc
 /trunk/src/platform-openbsd.cc
 /trunk/src/platform-posix.cc
 /trunk/src/platform-solaris.cc
 /trunk/src/platform-win32.cc
 /trunk/src/platform.h
 /trunk/src/v8.cc
 /trunk/src/version.cc
 /trunk/src/x64/lithium-x64.cc
 /trunk/tools/check-static-initializers.sh
 /trunk/tools/gyp/v8.gyp

=======================================
--- /dev/null
+++ /trunk/src/platform-posix.h Tue Apr  3 01:37:53 2012
@@ -0,0 +1,40 @@
+// Copyright 2012 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.
+
+#ifndef V8_PLATFORM_POSIX_H_
+#define V8_PLATFORM_POSIX_H_
+
+namespace v8 {
+namespace internal {
+
+// Used by platform implementation files during OS::PostSetUp() to initialize
+// the math functions.
+void MathSetup();
+
+} }  // namespace v8::internal
+
+#endif  // V8_PLATFORM_POSIX_H_
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-121407.js       Tue Apr  3 01:37:53 2012
@@ -0,0 +1,40 @@
+// Copyright 2012 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.
+
+var a = [0,1,2,3];
+a[2000000] = 2000000;
+a.length=2000;
+for (var i = 0; i <= 256; i++) {
+    a[i] = new Object();
+}
+
+a = [0.5,1.5,2.5,3.5,4.5,5.5];
+a[2000000] = 2000000;
+a.length=2000;
+for (var i = 0; i <= 256; i++) {
+    a[i] = new Object();
+}
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-2045.js Tue Apr  3 01:37:53 2012
@@ -0,0 +1,49 @@
+// Copyright 2012 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.
+
+// Flags: --allow-natives-syntax
+
+function foo() {
+  assertEquals(2, arguments.length);
+}
+
+function bar() {
+  G.x;
+  return foo.apply(this, arguments);
+}
+
+function baz() {
+  return bar(1, 2);
+}
+
+G = {x: 0};
+baz();
+baz();
+%OptimizeFunctionOnNextCall(baz);
+baz();
+delete G.x;
+baz();
=======================================
--- /trunk/src/api.cc   Fri Mar 30 01:38:13 2012
+++ /trunk/src/api.cc   Tue Apr  3 01:37:53 2012
@@ -4180,7 +4180,7 @@


 bool v8::V8::Initialize() {
-  i::Isolate* isolate = i::Isolate::Current();
+  i::Isolate* isolate = i::Isolate::UncheckedCurrent();
   if (isolate != NULL && isolate->IsInitialized()) {
     return true;
   }
@@ -5073,7 +5073,7 @@


 Local<Integer> v8::Integer::New(int32_t value) {
-  i::Isolate* isolate = i::Isolate::Current();
+  i::Isolate* isolate = i::Isolate::UncheckedCurrent();
   EnsureInitializedForIsolate(isolate, "v8::Integer::New()");
   if (i::Smi::IsValid(value)) {
return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value),
@@ -5351,7 +5351,7 @@


 Isolate* Isolate::GetCurrent() {
-  i::Isolate* isolate = i::Isolate::Current();
+  i::Isolate* isolate = i::Isolate::UncheckedCurrent();
   return reinterpret_cast<Isolate*>(isolate);
 }

=======================================
--- /trunk/src/arm/lithium-arm.cc       Fri Mar 30 01:38:13 2012
+++ /trunk/src/arm/lithium-arm.cc       Tue Apr  3 01:37:53 2012
@@ -2271,6 +2271,9 @@
                                                undefined,
                                                instr->call_kind(),
                                                instr->is_construct());
+  if (instr->arguments() != NULL) {
+    inner->Bind(instr->arguments(), graph()->GetArgumentsObject());
+  }
   current_block_->UpdateEnvironment(inner);
   chunk_->AddInlinedClosure(instr->closure());
   return NULL;
=======================================
--- /trunk/src/elements.cc      Fri Mar 30 01:38:13 2012
+++ /trunk/src/elements.cc      Tue Apr  3 01:37:53 2012
@@ -199,10 +199,13 @@
     }
 #endif
   }
-  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length());
   ASSERT(to != from);
   ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS);
   if (copy_size == 0) return;
+  uint32_t to_length = to->length();
+  if (to_start + copy_size > to_length) {
+    copy_size = to_length - to_start;
+  }
   for (int i = 0; i < copy_size; i++) {
     int entry = from->FindEntry(i + from_start);
     if (entry != SeededNumberDictionary::kNotFound) {
@@ -356,8 +359,11 @@
       }
     }
   }
-  ASSERT(copy_size + static_cast<int>(to_start) <= to->length());
   if (copy_size == 0) return;
+  uint32_t to_length = to->length();
+  if (to_start + copy_size > to_length) {
+    copy_size = to_length - to_start;
+  }
   for (int i = 0; i < copy_size; i++) {
     int entry = from->FindEntry(i + from_start);
     if (entry != SeededNumberDictionary::kNotFound) {
=======================================
--- /trunk/src/hydrogen-instructions.h  Fri Mar 30 01:38:13 2012
+++ /trunk/src/hydrogen-instructions.h  Tue Apr  3 01:37:53 2012
@@ -1353,12 +1353,14 @@
                 int arguments_count,
                 FunctionLiteral* function,
                 CallKind call_kind,
-                bool is_construct)
+                bool is_construct,
+                Variable* arguments)
       : closure_(closure),
         arguments_count_(arguments_count),
         function_(function),
         call_kind_(call_kind),
-        is_construct_(is_construct) {
+        is_construct_(is_construct),
+        arguments_(arguments) {
   }

   virtual void PrintDataTo(StringStream* stream);
@@ -1372,6 +1374,8 @@
   virtual Representation RequiredInputRepresentation(int index) {
     return Representation::None();
   }
+
+  Variable* arguments() { return arguments_; }

   DECLARE_CONCRETE_INSTRUCTION(EnterInlined)

@@ -1381,6 +1385,7 @@
   FunctionLiteral* function_;
   CallKind call_kind_;
   bool is_construct_;
+  Variable* arguments_;
 };


=======================================
--- /trunk/src/hydrogen.cc      Fri Mar 30 01:38:13 2012
+++ /trunk/src/hydrogen.cc      Tue Apr  3 01:37:53 2012
@@ -5425,7 +5425,8 @@
                                            arguments->length(),
                                            function,
                                            call_kind,
- function_state()->is_construct())); + function_state()->is_construct(), + function->scope()->arguments()));
   // If the function uses arguments object create and bind one.
   if (function->scope()->arguments() != NULL) {
     ASSERT(function->scope()->arguments()->IsStackAllocated());
=======================================
--- /trunk/src/ia32/lithium-ia32.cc     Fri Mar 30 01:38:13 2012
+++ /trunk/src/ia32/lithium-ia32.cc     Tue Apr  3 01:37:53 2012
@@ -2380,6 +2380,9 @@
                                                undefined,
                                                instr->call_kind(),
                                                instr->is_construct());
+  if (instr->arguments() != NULL) {
+    inner->Bind(instr->arguments(), graph()->GetArgumentsObject());
+  }
   current_block_->UpdateEnvironment(inner);
   chunk_->AddInlinedClosure(instr->closure());
   return NULL;
=======================================
--- /trunk/src/isolate.cc       Fri Mar 30 01:38:13 2012
+++ /trunk/src/isolate.cc       Tue Apr  3 01:37:53 2012
@@ -38,7 +38,6 @@
 #include "heap-profiler.h"
 #include "hydrogen.h"
 #include "isolate.h"
-#include "lazy-instance.h"
 #include "lithium-allocator.h"
 #include "log.h"
 #include "messages.h"
@@ -57,31 +56,6 @@
 namespace v8 {
 namespace internal {

-struct GlobalState {
-  Thread::LocalStorageKey per_isolate_thread_data_key;
-  Thread::LocalStorageKey isolate_key;
-  Thread::LocalStorageKey thread_id_key;
-  Isolate* default_isolate;
-  Isolate::ThreadDataTable* thread_data_table;
-  Mutex* mutex;
-};
-
-struct InitializeGlobalState {
-  static void Construct(GlobalState* state) {
-    state->isolate_key = Thread::CreateThreadLocalKey();
-    state->thread_id_key = Thread::CreateThreadLocalKey();
-    state->per_isolate_thread_data_key = Thread::CreateThreadLocalKey();
-    state->thread_data_table = new Isolate::ThreadDataTable();
-    state->default_isolate = new Isolate();
-    state->mutex = OS::CreateMutex();
-    // Can't use SetIsolateThreadLocals(default_isolate_, NULL) here
-    // because a non-null thread data may be already set.
-    Thread::SetThreadLocal(state->isolate_key, state->default_isolate);
-  }
-};
-
-static LazyInstance<GlobalState, InitializeGlobalState>::type global_state;
-
 Atomic32 ThreadId::highest_thread_id_ = 0;

 int ThreadId::AllocateThreadId() {
@@ -91,11 +65,10 @@


 int ThreadId::GetCurrentThreadId() {
-  const GlobalState& global = global_state.Get();
-  int thread_id = Thread::GetThreadLocalInt(global.thread_id_key);
+  int thread_id = Thread::GetThreadLocalInt(Isolate::thread_id_key_);
   if (thread_id == 0) {
     thread_id = AllocateThreadId();
-    Thread::SetThreadLocalInt(global.thread_id_key, thread_id);
+    Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id);
   }
   return thread_id;
 }
@@ -338,17 +311,24 @@
   storage->Unlink();
   storage->LinkTo(&free_list_);
 }
+
+Isolate* Isolate::default_isolate_ = NULL;
+Thread::LocalStorageKey Isolate::isolate_key_;
+Thread::LocalStorageKey Isolate::thread_id_key_;
+Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
+Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex();
+Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
+

 Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData(
     ThreadId thread_id) {
   ASSERT(!thread_id.Equals(ThreadId::Invalid()));
PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id);
   {
-    GlobalState* const global = global_state.Pointer();
-    ScopedLock lock(global->mutex);
-    ASSERT(global->thread_data_table->Lookup(this, thread_id) == NULL);
-    global->thread_data_table->Insert(per_thread);
- ASSERT(global->thread_data_table->Lookup(this, thread_id) == per_thread);
+    ScopedLock lock(process_wide_mutex_);
+    ASSERT(thread_data_table_->Lookup(this, thread_id) == NULL);
+    thread_data_table_->Insert(per_thread);
+    ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread);
   }
   return per_thread;
 }
@@ -359,9 +339,8 @@
   ThreadId thread_id = ThreadId::Current();
   PerIsolateThreadData* per_thread = NULL;
   {
-    GlobalState* const global = global_state.Pointer();
-    ScopedLock lock(global->mutex);
-    per_thread = global->thread_data_table->Lookup(this, thread_id);
+    ScopedLock lock(process_wide_mutex_);
+    per_thread = thread_data_table_->Lookup(this, thread_id);
     if (per_thread == NULL) {
       per_thread = AllocatePerIsolateThreadData(thread_id);
     }
@@ -374,74 +353,64 @@
   ThreadId thread_id = ThreadId::Current();
   PerIsolateThreadData* per_thread = NULL;
   {
-    GlobalState* const global = global_state.Pointer();
-    ScopedLock lock(global->mutex);
-    per_thread = global->thread_data_table->Lookup(this, thread_id);
+    ScopedLock lock(process_wide_mutex_);
+    per_thread = thread_data_table_->Lookup(this, thread_id);
   }
   return per_thread;
 }
-
-
-bool Isolate::IsDefaultIsolate() const {
-  return this == global_state.Get().default_isolate;
-}


 void Isolate::EnsureDefaultIsolate() {
-  GlobalState* const global = global_state.Pointer();
+  ScopedLock lock(process_wide_mutex_);
+  if (default_isolate_ == NULL) {
+    isolate_key_ = Thread::CreateThreadLocalKey();
+    thread_id_key_ = Thread::CreateThreadLocalKey();
+    per_isolate_thread_data_key_ = Thread::CreateThreadLocalKey();
+    thread_data_table_ = new Isolate::ThreadDataTable();
+    default_isolate_ = new Isolate();
+  }
   // Can't use SetIsolateThreadLocals(default_isolate_, NULL) here
   // because a non-null thread data may be already set.
-  if (Thread::GetThreadLocal(global->isolate_key) == NULL) {
-    Thread::SetThreadLocal(global->isolate_key, global->default_isolate);
+  if (Thread::GetThreadLocal(isolate_key_) == NULL) {
+    Thread::SetThreadLocal(isolate_key_, default_isolate_);
   }
 }

+struct StaticInitializer {
+  StaticInitializer() {
+    Isolate::EnsureDefaultIsolate();
+  }
+} static_initializer;

 #ifdef ENABLE_DEBUGGER_SUPPORT
 Debugger* Isolate::GetDefaultIsolateDebugger() {
   EnsureDefaultIsolate();
-  return global_state.Pointer()->default_isolate->debugger();
+  return default_isolate_->debugger();
 }
 #endif


 StackGuard* Isolate::GetDefaultIsolateStackGuard() {
   EnsureDefaultIsolate();
-  return global_state.Pointer()->default_isolate->stack_guard();
-}
-
-
-Thread::LocalStorageKey Isolate::isolate_key() {
-  return global_state.Get().isolate_key;
-}
-
-
-Thread::LocalStorageKey Isolate::thread_id_key() {
-  return global_state.Get().thread_id_key;
-}
-
-
-Thread::LocalStorageKey Isolate::per_isolate_thread_data_key() {
-  return global_state.Get().per_isolate_thread_data_key;
+  return default_isolate_->stack_guard();
 }


 void Isolate::EnterDefaultIsolate() {
   EnsureDefaultIsolate();
-  Isolate* const default_isolate = global_state.Pointer()->default_isolate;
-  ASSERT(default_isolate != NULL);
+  ASSERT(default_isolate_ != NULL);

   PerIsolateThreadData* data = CurrentPerIsolateThreadData();
   // If not yet in default isolate - enter it.
-  if (data == NULL || data->isolate() != default_isolate) {
-    default_isolate->Enter();
+  if (data == NULL || data->isolate() != default_isolate_) {
+    default_isolate_->Enter();
   }
 }


 Isolate* Isolate::GetDefaultIsolateForLocking() {
   EnsureDefaultIsolate();
-  return global_state.Pointer()->default_isolate;
+  return default_isolate_;
 }


@@ -1564,8 +1533,8 @@

   Deinit();

-  { ScopedLock lock(global_state.Pointer()->mutex);
-    global_state.Pointer()->thread_data_table->RemoveAllThreads(this);
+  { ScopedLock lock(process_wide_mutex_);
+    thread_data_table_->RemoveAllThreads(this);
   }

   if (!IsDefaultIsolate()) {
@@ -1618,9 +1587,8 @@

 void Isolate::SetIsolateThreadLocals(Isolate* isolate,
                                      PerIsolateThreadData* data) {
-  const GlobalState& global = global_state.Get();
-  Thread::SetThreadLocal(global.isolate_key, isolate);
-  Thread::SetThreadLocal(global.per_isolate_thread_data_key, data);
+  Thread::SetThreadLocal(isolate_key_, isolate);
+  Thread::SetThreadLocal(per_isolate_thread_data_key_, data);
 }


=======================================
--- /trunk/src/isolate.h        Fri Mar 30 01:38:13 2012
+++ /trunk/src/isolate.h        Tue Apr  3 01:37:53 2012
@@ -430,25 +430,19 @@
   // not currently set).
   static PerIsolateThreadData* CurrentPerIsolateThreadData() {
     return reinterpret_cast<PerIsolateThreadData*>(
-        Thread::GetThreadLocal(per_isolate_thread_data_key()));
+        Thread::GetThreadLocal(per_isolate_thread_data_key_));
   }

   // Returns the isolate inside which the current thread is running.
   INLINE(static Isolate* Current()) {
-    const Thread::LocalStorageKey key = isolate_key();
     Isolate* isolate = reinterpret_cast<Isolate*>(
-        Thread::GetExistingThreadLocal(key));
-    if (!isolate) {
-      EnsureDefaultIsolate();
-      isolate = reinterpret_cast<Isolate*>(
-          Thread::GetExistingThreadLocal(key));
-    }
+        Thread::GetExistingThreadLocal(isolate_key_));
     ASSERT(isolate != NULL);
     return isolate;
   }

   INLINE(static Isolate* UncheckedCurrent()) {
- return reinterpret_cast<Isolate*>(Thread::GetThreadLocal(isolate_key())); + return reinterpret_cast<Isolate*>(Thread::GetThreadLocal(isolate_key_));
   }

   // Usually called by Init(), but can be called early e.g. to allow
@@ -470,7 +464,7 @@
   // for legacy API reasons.
   void TearDown();

-  bool IsDefaultIsolate() const;
+  bool IsDefaultIsolate() const { return this == default_isolate_; }

   // Ensures that process-wide resources and the default isolate have been
   // allocated. It is only necessary to call this method in rare cases, for
@@ -495,10 +489,14 @@
   // Returns the key used to store the pointer to the current isolate.
// Used internally for V8 threads that do not execute JavaScript but still
   // are part of the domain of an isolate (like the context switcher).
-  static Thread::LocalStorageKey isolate_key();
+  static Thread::LocalStorageKey isolate_key() {
+    return isolate_key_;
+  }

   // Returns the key used to store process-wide thread IDs.
-  static Thread::LocalStorageKey thread_id_key();
+  static Thread::LocalStorageKey thread_id_key() {
+    return thread_id_key_;
+  }

   static Thread::LocalStorageKey per_isolate_thread_data_key();

@@ -1082,6 +1080,16 @@
     DISALLOW_COPY_AND_ASSIGN(EntryStackItem);
   };

+  // This mutex protects highest_thread_id_, thread_data_table_ and
+  // default_isolate_.
+  static Mutex* process_wide_mutex_;
+
+  static Thread::LocalStorageKey per_isolate_thread_data_key_;
+  static Thread::LocalStorageKey isolate_key_;
+  static Thread::LocalStorageKey thread_id_key_;
+  static Isolate* default_isolate_;
+  static ThreadDataTable* thread_data_table_;
+
   void Deinit();

   static void SetIsolateThreadLocals(Isolate* isolate,
=======================================
--- /trunk/src/lazy-instance.h  Fri Mar 30 01:38:13 2012
+++ /trunk/src/lazy-instance.h  Tue Apr  3 01:37:53 2012
@@ -65,6 +65,9 @@
 //   static LazyInstance<MyClass, MyCreateTrait>::type my_instance =
 //      LAZY_INSTANCE_INITIALIZER;
 //
+// WARNING: This implementation of LazyInstance is NOT thread-safe by default.
+// See ThreadSafeInitOnceTrait declared below for that.
+//
 // Notes for advanced users:
 // LazyInstance can actually be used in two different ways:
 //
@@ -151,9 +154,29 @@
 };


+struct ThreadSafeInitOnceTrait {
+  template <typename Function, typename Storage>
+  static void Init(OnceType* once, Function function, Storage storage) {
+    CallOnce(once, function, storage);
+  }
+};
+
+
+// Initialization trait for users who don't care about thread-safety.
+struct SingleThreadInitOnceTrait {
+  template <typename Function, typename Storage>
+  static void Init(OnceType* once, Function function, Storage storage) {
+    if (*once == ONCE_STATE_UNINITIALIZED) {
+      function(storage);
+      *once = ONCE_STATE_DONE;
+    }
+  }
+};
+
+
 // TODO(pliard): Handle instances destruction (using global destructors).
 template <typename T, typename AllocationTrait, typename CreateTrait,
-          typename DestroyTrait  /* not used yet. */ >
+ typename InitOnceTrait, typename DestroyTrait /* not used yet. */>
 struct LazyInstanceImpl {
  public:
   typedef typename AllocationTrait::StorageType StorageType;
@@ -164,7 +187,12 @@
   }

   void Init() const {
-    CallOnce(&once_, &InitInstance, &storage_);
+    InitOnceTrait::Init(
+        &once_,
+        // Casts to void* are needed here to avoid breaking strict aliasing
+        // rules.
+        reinterpret_cast<void(*)(void*)>(&InitInstance),  // NOLINT
+        reinterpret_cast<void*>(&storage_));
   }

  public:
@@ -187,28 +215,32 @@

 template <typename T,
           typename CreateTrait = DefaultConstructTrait<T>,
+          typename InitOnceTrait = SingleThreadInitOnceTrait,
           typename DestroyTrait = LeakyInstanceTrait<T> >
 struct LazyStaticInstance {
- typedef LazyInstanceImpl<T, StaticallyAllocatedInstanceTrait<T>, CreateTrait,
-      DestroyTrait> type;
+  typedef LazyInstanceImpl<T, StaticallyAllocatedInstanceTrait<T>,
+      CreateTrait, InitOnceTrait, DestroyTrait> type;
 };


 template <typename T,
           typename CreateTrait = DefaultConstructTrait<T>,
+          typename InitOnceTrait = SingleThreadInitOnceTrait,
           typename DestroyTrait = LeakyInstanceTrait<T> >
 struct LazyInstance {
   // A LazyInstance is a LazyStaticInstance.
- typedef typename LazyStaticInstance<T, CreateTrait, DestroyTrait>::type type;
+  typedef typename LazyStaticInstance<T, CreateTrait, InitOnceTrait,
+      DestroyTrait>::type type;
 };


 template <typename T,
           typename CreateTrait = DefaultConstructTrait<T>,
+          typename InitOnceTrait = SingleThreadInitOnceTrait,
           typename DestroyTrait = LeakyInstanceTrait<T> >
 struct LazyDynamicInstance {
- typedef LazyInstanceImpl<T, DynamicallyAllocatedInstanceTrait<T>, CreateTrait,
-      DestroyTrait> type;
+  typedef LazyInstanceImpl<T, DynamicallyAllocatedInstanceTrait<T>,
+      CreateTrait, InitOnceTrait, DestroyTrait> type;
 };

 } }  // namespace v8::internal
=======================================
--- /trunk/src/mips/lithium-mips.cc     Fri Mar 30 01:38:13 2012
+++ /trunk/src/mips/lithium-mips.cc     Tue Apr  3 01:37:53 2012
@@ -2277,6 +2277,9 @@
                                                undefined,
                                                instr->call_kind(),
                                                instr->is_construct());
+  if (instr->arguments() != NULL) {
+    inner->Bind(instr->arguments(), graph()->GetArgumentsObject());
+  }
   current_block_->UpdateEnvironment(inner);
   chunk_->AddInlinedClosure(instr->closure());
   return NULL;
=======================================
--- /trunk/src/platform-cygwin.cc       Fri Mar 30 01:38:13 2012
+++ /trunk/src/platform-cygwin.cc       Tue Apr  3 01:37:53 2012
@@ -41,6 +41,7 @@

 #include "v8.h"

+#include "platform-posix.h"
 #include "platform.h"
 #include "v8threads.h"
 #include "vm-state-inl.h"
@@ -73,6 +74,12 @@
 }


+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized after
+  // CPU.
+  MathSetup();
+}
+
 uint64_t OS::CpuFeaturesImpliedByPlatform() {
   return 0;  // Nothing special about Cygwin.
 }
=======================================
--- /trunk/src/platform-freebsd.cc      Fri Mar 30 01:38:13 2012
+++ /trunk/src/platform-freebsd.cc      Tue Apr  3 01:37:53 2012
@@ -54,6 +54,7 @@
 #include "v8.h"
 #include "v8threads.h"

+#include "platform-posix.h"
 #include "platform.h"
 #include "vm-state-inl.h"

@@ -89,6 +90,13 @@
   srandom(static_cast<unsigned int>(seed));
   limit_mutex = CreateMutex();
 }
+
+
+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized after
+  // CPU.
+  MathSetup();
+}


 void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
=======================================
--- /trunk/src/platform-linux.cc        Fri Mar 30 01:38:13 2012
+++ /trunk/src/platform-linux.cc        Tue Apr  3 01:37:53 2012
@@ -57,6 +57,7 @@

 #include "v8.h"

+#include "platform-posix.h"
 #include "platform.h"
 #include "v8threads.h"
 #include "vm-state-inl.h"
@@ -103,6 +104,13 @@
   }
 #endif
 }
+
+
+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized after
+  // CPU.
+  MathSetup();
+}


 uint64_t OS::CpuFeaturesImpliedByPlatform() {
=======================================
--- /trunk/src/platform-macos.cc        Fri Mar 30 01:38:13 2012
+++ /trunk/src/platform-macos.cc        Tue Apr  3 01:37:53 2012
@@ -58,6 +58,7 @@

 #include "v8.h"

+#include "platform-posix.h"
 #include "platform.h"
 #include "vm-state-inl.h"

@@ -99,6 +100,13 @@
   srandom(static_cast<unsigned int>(seed));
   limit_mutex = CreateMutex();
 }
+
+
+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized after
+  // CPU.
+  MathSetup();
+}


 // We keep the lowest and highest addresses mapped as a quick way of
=======================================
--- /trunk/src/platform-nullos.cc       Tue Mar  6 00:42:24 2012
+++ /trunk/src/platform-nullos.cc       Tue Apr  3 01:37:53 2012
@@ -84,6 +84,11 @@
   // Seed the random number generator.
   UNIMPLEMENTED();
 }
+
+
+void OS::PostSetUp() {
+  UNIMPLEMENTED();
+}


 // Returns the accumulated user time for thread.
=======================================
--- /trunk/src/platform-openbsd.cc      Fri Mar 30 01:38:13 2012
+++ /trunk/src/platform-openbsd.cc      Tue Apr  3 01:37:53 2012
@@ -51,6 +51,7 @@

 #include "v8.h"

+#include "platform-posix.h"
 #include "platform.h"
 #include "v8threads.h"
 #include "vm-state-inl.h"
@@ -105,6 +106,13 @@
   srandom(static_cast<unsigned int>(seed));
   limit_mutex = CreateMutex();
 }
+
+
+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized after
+  // CPU.
+  MathSetup();
+}


 uint64_t OS::CpuFeaturesImpliedByPlatform() {
=======================================
--- /trunk/src/platform-posix.cc        Fri Mar 30 01:38:13 2012
+++ /trunk/src/platform-posix.cc        Tue Apr  3 01:37:53 2012
@@ -29,6 +29,8 @@
// own but contains the parts which are the same across POSIX platforms Linux,
 // Mac OS, FreeBSD and OpenBSD.

+#include "platform-posix.h"
+
 #include <unistd.h>
 #include <errno.h>
 #include <time.h>
@@ -129,13 +131,10 @@

 #define UNARY_MATH_FUNCTION(name, generator)             \
 static UnaryMathFunction fast_##name##_function = NULL;  \
-V8_DECLARE_ONCE(fast_##name##_init_once);                \
 void init_fast_##name##_function() {                     \
   fast_##name##_function = generator;                    \
 }                                                        \
 double fast_##name(double x) {                           \
-  CallOnce(&fast_##name##_init_once,                     \
-           &init_fast_##name##_function);                \
   return (*fast_##name##_function)(x);                   \
 }

@@ -148,6 +147,15 @@
 #undef MATH_FUNCTION


+void MathSetup() {
+  init_fast_sin_function();
+  init_fast_cos_function();
+  init_fast_tan_function();
+  init_fast_log_function();
+  init_fast_sqrt_function();
+}
+
+
 double OS::nan_value() {
   // NAN from math.h is defined in C99 and not in POSIX.
   return NAN;
=======================================
--- /trunk/src/platform-solaris.cc      Fri Mar 30 01:38:13 2012
+++ /trunk/src/platform-solaris.cc      Tue Apr  3 01:37:53 2012
@@ -52,6 +52,7 @@

 #include "v8.h"

+#include "platform-posix.h"
 #include "platform.h"
 #include "v8threads.h"
 #include "vm-state-inl.h"
@@ -100,6 +101,13 @@
   srandom(static_cast<unsigned int>(seed));
   limit_mutex = CreateMutex();
 }
+
+
+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized after
+  // CPU.
+  MathSetup();
+}


 uint64_t OS::CpuFeaturesImpliedByPlatform() {
=======================================
--- /trunk/src/platform-win32.cc        Fri Mar 30 01:38:13 2012
+++ /trunk/src/platform-win32.cc        Tue Apr  3 01:37:53 2012
@@ -167,7 +167,6 @@
 #ifdef _WIN64
 typedef double (*ModuloFunction)(double, double);
 static ModuloFunction modulo_function = NULL;
-V8_DECLARE_ONCE(modulo_function_init_once);
 // Defined in codegen-x64.cc.
 ModuloFunction CreateModuloFunction();

@@ -176,7 +175,6 @@
 }

 double modulo(double x, double y) {
-  CallOnce(&modulo_function_init_once, &init_modulo_function);
   // Note: here we rely on dependent reads being ordered. This is true
   // on all architectures we currently support.
   return (*modulo_function)(x, y);
@@ -199,13 +197,10 @@

 #define UNARY_MATH_FUNCTION(name, generator)             \
 static UnaryMathFunction fast_##name##_function = NULL;  \
-V8_DECLARE_ONCE(fast_##name##_init_once);                \
 void init_fast_##name##_function() {                     \
   fast_##name##_function = generator;                    \
 }                                                        \
 double fast_##name(double x) {                           \
-  CallOnce(&fast_##name##_init_once,                     \
-           &init_fast_##name##_function);                \
   return (*fast_##name##_function)(x);                   \
 }

@@ -218,6 +213,18 @@
 #undef MATH_FUNCTION


+void MathSetup() {
+#ifdef _WIN64
+  init_modulo_function();
+#endif
+  init_fast_sin_function();
+  init_fast_cos_function();
+  init_fast_tan_function();
+  init_fast_log_function();
+  init_fast_sqrt_function();
+}
+
+
// ----------------------------------------------------------------------------
 // The Time class represents time on win32. A timestamp is represented as
// a 64-bit integer in 100 nanoseconds since January 1, 1601 (UTC). JavaScript
@@ -566,6 +573,13 @@
   srand(static_cast<unsigned int>(seed));
   limit_mutex = CreateMutex();
 }
+
+
+void OS::PostSetUp() {
+ // Math functions depend on CPU features therefore they are initialized after
+  // CPU.
+  MathSetup();
+}


 // Returns the accumulated user time for thread.
=======================================
--- /trunk/src/platform.h       Fri Mar 30 01:38:13 2012
+++ /trunk/src/platform.h       Tue Apr  3 01:37:53 2012
@@ -119,6 +119,10 @@
   // Initializes the platform OS support. Called once at VM startup.
   static void SetUp();

+ // Initializes the platform OS support that depend on CPU features. This is
+  // called after CPU initialization.
+  static void PostSetUp();
+
   // Returns the accumulated user time for thread. This routine
   // can be used for profiling. The implementation should
   // strive for high-precision timer resolution, preferable
@@ -545,7 +549,8 @@
 //     // Do something.
 //   }
 //
-typedef LazyDynamicInstance<Mutex, CreateMutexTrait>::type LazyMutex;
+typedef LazyDynamicInstance<
+    Mutex, CreateMutexTrait, ThreadSafeInitOnceTrait>::type LazyMutex;

 #define LAZY_MUTEX_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER

@@ -616,7 +621,8 @@
 template <int InitialValue>
 struct LazySemaphore {
   typedef typename LazyDynamicInstance<
-      Semaphore, CreateSemaphoreTrait<InitialValue> >::type type;
+      Semaphore, CreateSemaphoreTrait<InitialValue>,
+      ThreadSafeInitOnceTrait>::type type;
 };

 #define LAZY_SEMAPHORE_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
=======================================
--- /trunk/src/v8.cc    Fri Mar 30 01:38:13 2012
+++ /trunk/src/v8.cc    Tue Apr  3 01:37:53 2012
@@ -259,6 +259,8 @@
   if (!CPU::SupportsCrankshaft()) {
     use_crankshaft_ = false;
   }
+
+  OS::PostSetUp();

   RuntimeProfiler::GlobalSetup();

=======================================
--- /trunk/src/version.cc       Mon Apr  2 07:52:24 2012
+++ /trunk/src/version.cc       Tue Apr  3 01:37:53 2012
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     10
 #define BUILD_NUMBER      0
-#define PATCH_LEVEL       2
+#define PATCH_LEVEL       3
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
=======================================
--- /trunk/src/x64/lithium-x64.cc       Fri Mar 30 01:38:13 2012
+++ /trunk/src/x64/lithium-x64.cc       Tue Apr  3 01:37:53 2012
@@ -2270,6 +2270,9 @@
                                                undefined,
                                                instr->call_kind(),
                                                instr->is_construct());
+  if (instr->arguments() != NULL) {
+    inner->Bind(instr->arguments(), graph()->GetArgumentsObject());
+  }
   current_block_->UpdateEnvironment(inner);
   chunk_->AddInlinedClosure(instr->closure());
   return NULL;
=======================================
--- /trunk/tools/check-static-initializers.sh   Fri Mar 30 01:38:13 2012
+++ /trunk/tools/check-static-initializers.sh   Tue Apr  3 01:37:53 2012
@@ -31,9 +31,10 @@
# Note that the project must be built with SCons before running this script.

 # Allow:
-#  - _GLOBAL__I__ZN2v88internal32AtomicOps_Internalx86CPUFeaturesE
 #  - _GLOBAL__I__ZN2v810LineEditor6first_E
-expected_static_init_count=2
+#  - _GLOBAL__I__ZN2v88internal32AtomicOps_Internalx86CPUFeaturesE
+#  - _GLOBAL__I__ZN2v88internal8ThreadId18highest_thread_id_E
+expected_static_init_count=3

 v8_root=$(readlink -f $(dirname $BASH_SOURCE)/../)
 d8="${v8_root}/d8"
=======================================
--- /trunk/tools/gyp/v8.gyp     Fri Mar 30 01:38:13 2012
+++ /trunk/tools/gyp/v8.gyp     Tue Apr  3 01:37:53 2012
@@ -395,6 +395,7 @@
             '../../src/once.h',
             '../../src/parser.cc',
             '../../src/parser.h',
+            '../../src/platform-posix.h',
             '../../src/platform-tls-mac.h',
             '../../src/platform-tls-win32.h',
             '../../src/platform-tls.h',

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

Reply via email to