Commit 63f03357 authored by danno@chromium.org's avatar danno@chromium.org

Fix performance regressions due to lazy initialization.

This CL:
- Adds a new trait parameter to LazyInstance to let it initialize the instance
  without paying the cost of atomic operations (which are expensive on Mac).
  This only works for users who don't care about thread-safety and this is now
the default initialization trait used by LazyInstance in v8.

- Reverts the changes that were made in r11010 in isolate.{cc,h}. That lets
  Isolate's accessors be as cheap as they were before (but adds one static initializer).

- Adds OS::PostSetup() used to initialize the math functions which depend on CPU features.
That lets the math functions get rid of CallOnce().

BUG=118686

Review URL: https://chromiumcodereview.appspot.com/9873023
Patch from Philippe Liard <pliard@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11198 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b063b2d7
......@@ -4180,7 +4180,7 @@ void v8::Object::SetPointerInInternalField(int index, void* value) {
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<Number> v8::Number::New(double value) {
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 @@ bool V8::IsExecutionTerminating(Isolate* isolate) {
Isolate* Isolate::GetCurrent() {
i::Isolate* isolate = i::Isolate::Current();
i::Isolate* isolate = i::Isolate::UncheckedCurrent();
return reinterpret_cast<Isolate*>(isolate);
}
......
......@@ -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::AllocateThreadId() {
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;
}
......@@ -339,16 +312,23 @@ void Isolate::PreallocatedStorageDelete(void* p) {
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 @@ Isolate::PerIsolateThreadData*
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 @@ Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() {
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 @@ void Isolate::TearDown() {
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::Deinit() {
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);
}
......
......@@ -430,25 +430,19 @@ class Isolate {
// 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 @@ class Isolate {
// 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 @@ class Isolate {
// 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 @@ class Isolate {
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,
......
......@@ -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 DefaultCreateTrait {
};
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 @@ struct LazyInstanceImpl {
}
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),
reinterpret_cast<void*>(&storage_));
}
public:
......@@ -187,28 +215,32 @@ struct LazyInstanceImpl {
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
......
......@@ -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::SetUp() {
}
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.
}
......
......@@ -54,6 +54,7 @@
#include "v8.h"
#include "v8threads.h"
#include "platform-posix.h"
#include "platform.h"
#include "vm-state-inl.h"
......@@ -91,6 +92,13 @@ void OS::SetUp() {
}
void OS::PostSetUp() {
// Math functions depend on CPU features therefore they are initialized after
// CPU.
MathSetup();
}
void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
__asm__ __volatile__("" : : : "memory");
*ptr = value;
......
......@@ -57,6 +57,7 @@
#include "v8.h"
#include "platform-posix.h"
#include "platform.h"
#include "v8threads.h"
#include "vm-state-inl.h"
......@@ -105,6 +106,13 @@ void OS::SetUp() {
}
void OS::PostSetUp() {
// Math functions depend on CPU features therefore they are initialized after
// CPU.
MathSetup();
}
uint64_t OS::CpuFeaturesImpliedByPlatform() {
return 0; // Linux runs on anything.
}
......
......@@ -58,6 +58,7 @@
#include "v8.h"
#include "platform-posix.h"
#include "platform.h"
#include "vm-state-inl.h"
......@@ -101,6 +102,13 @@ void OS::SetUp() {
}
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
// determining that pointers are outside the heap (used mostly in assertions
// and verification). The estimate is conservative, i.e., not all addresses in
......
......@@ -86,6 +86,11 @@ void OS::SetUp() {
}
void OS::PostSetUp() {
UNIMPLEMENTED();
}
// Returns the accumulated user time for thread.
int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) {
UNIMPLEMENTED();
......
......@@ -51,6 +51,7 @@
#include "v8.h"
#include "platform-posix.h"
#include "platform.h"
#include "v8threads.h"
#include "vm-state-inl.h"
......@@ -107,6 +108,13 @@ void OS::SetUp() {
}
void OS::PostSetUp() {
// Math functions depend on CPU features therefore they are initialized after
// CPU.
MathSetup();
}
uint64_t OS::CpuFeaturesImpliedByPlatform() {
return 0;
}
......
......@@ -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 @@ double modulo(double x, double y) {
#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 @@ UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction())
#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;
......
// 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_
......@@ -52,6 +52,7 @@
#include "v8.h"
#include "platform-posix.h"
#include "platform.h"
#include "v8threads.h"
#include "vm-state-inl.h"
......@@ -102,6 +103,13 @@ void OS::SetUp() {
}
void OS::PostSetUp() {
// Math functions depend on CPU features therefore they are initialized after
// CPU.
MathSetup();
}
uint64_t OS::CpuFeaturesImpliedByPlatform() {
return 0; // Solaris runs on a lot of things.
}
......
......@@ -167,7 +167,6 @@ void OS::MemCopy(void* dest, const void* src, size_t size) {
#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 @@ void init_modulo_function() {
}
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 @@ double modulo(double x, double y) {
#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,16 @@ UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction())
#undef MATH_FUNCTION
void MathSetup() {
init_modulo_function();
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
......@@ -568,6 +573,13 @@ void OS::SetUp() {
}
void OS::PostSetUp() {
// Math functions depend on CPU features therefore they are initialized after
// CPU.
MathSetup();
}
// Returns the accumulated user time for thread.
int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) {
FILETIME dummy;
......
......@@ -119,6 +119,10 @@ class OS {
// 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 @@ struct CreateMutexTrait {
// // 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 @@ struct CreateSemaphoreTrait {
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
......
......@@ -260,6 +260,8 @@ void V8::InitializeOncePerProcessImpl() {
use_crankshaft_ = false;
}
OS::PostSetUp();
RuntimeProfiler::GlobalSetup();
ElementsAccessor::InitializeOncePerProcess();
......
......@@ -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"
......
......@@ -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',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment