diff --git a/src/assembler.cc b/src/assembler.cc index 4944202f07..40765b31d7 100644 --- a/src/assembler.cc +++ b/src/assembler.cc @@ -99,21 +99,7 @@ struct DoubleConstant BASE_EMBEDDED { double the_hole_nan; }; -struct InitializeDoubleConstants { - static void Construct(DoubleConstant* double_constants) { - double_constants->min_int = kMinInt; - double_constants->one_half = 0.5; - double_constants->minus_zero = -0.0; - double_constants->uint8_max_value = 255; - double_constants->zero = 0.0; - double_constants->canonical_non_hole_nan = OS::nan_value(); - double_constants->the_hole_nan = BitCast(kHoleNanInt64); - double_constants->negative_infinity = -V8_INFINITY; - } -}; - -static LazyInstance::type - double_constants = LAZY_INSTANCE_INITIALIZER; +static DoubleConstant double_constants; const char* const RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING"; @@ -726,6 +712,18 @@ void RelocInfo::Verify() { // ----------------------------------------------------------------------------- // Implementation of ExternalReference +void ExternalReference::SetUp() { + double_constants.min_int = kMinInt; + double_constants.one_half = 0.5; + double_constants.minus_zero = -0.0; + double_constants.uint8_max_value = 255; + double_constants.zero = 0.0; + double_constants.canonical_non_hole_nan = OS::nan_value(); + double_constants.the_hole_nan = BitCast(kHoleNanInt64); + double_constants.negative_infinity = -V8_INFINITY; +} + + ExternalReference::ExternalReference(Builtins::CFunctionId id, Isolate* isolate) : address_(Redirect(isolate, Builtins::c_function_address(id))) {} @@ -958,50 +956,47 @@ ExternalReference ExternalReference::scheduled_exception_address( ExternalReference ExternalReference::address_of_min_int() { - return ExternalReference(reinterpret_cast( - &double_constants.Pointer()->min_int)); + return ExternalReference(reinterpret_cast(&double_constants.min_int)); } ExternalReference ExternalReference::address_of_one_half() { - return ExternalReference(reinterpret_cast( - &double_constants.Pointer()->one_half)); + return ExternalReference(reinterpret_cast(&double_constants.one_half)); } ExternalReference ExternalReference::address_of_minus_zero() { - return ExternalReference(reinterpret_cast( - &double_constants.Pointer()->minus_zero)); + return ExternalReference( + reinterpret_cast(&double_constants.minus_zero)); } ExternalReference ExternalReference::address_of_zero() { - return ExternalReference(reinterpret_cast( - &double_constants.Pointer()->zero)); + return ExternalReference(reinterpret_cast(&double_constants.zero)); } ExternalReference ExternalReference::address_of_uint8_max_value() { - return ExternalReference(reinterpret_cast( - &double_constants.Pointer()->uint8_max_value)); + return ExternalReference( + reinterpret_cast(&double_constants.uint8_max_value)); } ExternalReference ExternalReference::address_of_negative_infinity() { - return ExternalReference(reinterpret_cast( - &double_constants.Pointer()->negative_infinity)); + return ExternalReference( + reinterpret_cast(&double_constants.negative_infinity)); } ExternalReference ExternalReference::address_of_canonical_non_hole_nan() { - return ExternalReference(reinterpret_cast( - &double_constants.Pointer()->canonical_non_hole_nan)); + return ExternalReference( + reinterpret_cast(&double_constants.canonical_non_hole_nan)); } ExternalReference ExternalReference::address_of_the_hole_nan() { - return ExternalReference(reinterpret_cast( - &double_constants.Pointer()->the_hole_nan)); + return ExternalReference( + reinterpret_cast(&double_constants.the_hole_nan)); } diff --git a/src/assembler.h b/src/assembler.h index 918a2a679b..6deca26276 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -535,6 +535,8 @@ class ExternalReference BASE_EMBEDDED { DIRECT_GETTER_CALL }; + static void SetUp(); + typedef void* ExternalReferenceRedirector(void* original, Type type); ExternalReference(Builtins::CFunctionId id, Isolate* isolate); diff --git a/src/frames.cc b/src/frames.cc index 0571a813f5..591128441f 100644 --- a/src/frames.cc +++ b/src/frames.cc @@ -1369,24 +1369,23 @@ int NumRegs(RegList reglist) { struct JSCallerSavedCodeData { - JSCallerSavedCodeData() { - int i = 0; - for (int r = 0; r < kNumRegs; r++) - if ((kJSCallerSaved & (1 << r)) != 0) - reg_code[i++] = r; - - ASSERT(i == kNumJSCallerSaved); - } int reg_code[kNumJSCallerSaved]; }; +JSCallerSavedCodeData caller_saved_code_data; -static LazyInstance::type caller_saved_code_data = - LAZY_INSTANCE_INITIALIZER; +void SetUpJSCallerSavedCodeData() { + int i = 0; + for (int r = 0; r < kNumRegs; r++) + if ((kJSCallerSaved & (1 << r)) != 0) + caller_saved_code_data.reg_code[i++] = r; + + ASSERT(i == kNumJSCallerSaved); +} int JSCallerSavedCode(int n) { ASSERT(0 <= n && n < kNumJSCallerSaved); - return caller_saved_code_data.Get().reg_code[n]; + return caller_saved_code_data.reg_code[n]; } diff --git a/src/frames.h b/src/frames.h index 9071555197..7178bd413a 100644 --- a/src/frames.h +++ b/src/frames.h @@ -40,6 +40,8 @@ typedef uint32_t RegList; // Get the number of registers in a given register list. int NumRegs(RegList list); +void SetUpJSCallerSavedCodeData(); + // Return the code of the n-th saved register available to JavaScript. int JSCallerSavedCode(int n); diff --git a/src/heap.cc b/src/heap.cc index 48e8b56762..6070723a5d 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -42,6 +42,7 @@ #include "natives.h" #include "objects-visiting.h" #include "objects-visiting-inl.h" +#include "once.h" #include "runtime-profiler.h" #include "scopeinfo.h" #include "snapshot.h" @@ -60,8 +61,6 @@ namespace v8 { namespace internal { -static LazyMutex gc_initializer_mutex = LAZY_MUTEX_INITIALIZER; - Heap::Heap() : isolate_(NULL), @@ -5850,6 +5849,15 @@ class HeapDebugUtils { #endif + +V8_DECLARE_ONCE(initialize_gc_once); + +static void InitializeGCOnce() { + InitializeScavengingVisitorsTables(); + NewSpaceScavenger::Initialize(); + MarkCompactCollector::Initialize(); +} + bool Heap::SetUp(bool create_heap_objects) { #ifdef DEBUG allocation_timeout_ = FLAG_gc_interval; @@ -5868,15 +5876,7 @@ bool Heap::SetUp(bool create_heap_objects) { if (!ConfigureHeapDefault()) return false; } - gc_initializer_mutex.Pointer()->Lock(); - static bool initialized_gc = false; - if (!initialized_gc) { - initialized_gc = true; - InitializeScavengingVisitorsTables(); - NewSpaceScavenger::Initialize(); - MarkCompactCollector::Initialize(); - } - gc_initializer_mutex.Pointer()->Unlock(); + CallOnce(&initialize_gc_once, &InitializeGCOnce); MarkMapPointersAsEncoded(false); diff --git a/src/lazy-instance.h b/src/lazy-instance.h index 4beb55c0a2..5bbe230fb6 100644 --- a/src/lazy-instance.h +++ b/src/lazy-instance.h @@ -65,8 +65,12 @@ // static LazyInstance::type my_instance = // LAZY_INSTANCE_INITIALIZER; // -// WARNING: This implementation of LazyInstance is NOT thread-safe by default. -// See ThreadSafeInitOnceTrait declared below for that. +// WARNINGS: +// - This implementation of LazyInstance is NOT THREAD-SAFE by default. See +// ThreadSafeInitOnceTrait declared below for that. +// - Lazy initialization comes with a cost. Make sure that you don't use it on +// critical path. Consider adding your initialization code to a function +// which is explicitly called once. // // Notes for advanced users: // LazyInstance can actually be used in two different ways: diff --git a/src/log.cc b/src/log.cc index 21d64df21c..d93a9d82b1 100644 --- a/src/log.cc +++ b/src/log.cc @@ -1730,13 +1730,20 @@ void Logger::EnableSlidingStateWindow() { } // Protects the state below. -static LazyMutex active_samplers_mutex = LAZY_MUTEX_INITIALIZER; +static Mutex* active_samplers_mutex = NULL; List* SamplerRegistry::active_samplers_ = NULL; +void SamplerRegistry::SetUp() { + if (!active_samplers_mutex) { + active_samplers_mutex = OS::CreateMutex(); + } +} + + bool SamplerRegistry::IterateActiveSamplers(VisitSampler func, void* param) { - ScopedLock lock(active_samplers_mutex.Pointer()); + ScopedLock lock(active_samplers_mutex); for (int i = 0; ActiveSamplersExist() && i < active_samplers_->length(); ++i) { @@ -1763,7 +1770,7 @@ SamplerRegistry::State SamplerRegistry::GetState() { void SamplerRegistry::AddActiveSampler(Sampler* sampler) { ASSERT(sampler->IsActive()); - ScopedLock lock(active_samplers_mutex.Pointer()); + ScopedLock lock(active_samplers_mutex); if (active_samplers_ == NULL) { active_samplers_ = new List; } else { @@ -1775,7 +1782,7 @@ void SamplerRegistry::AddActiveSampler(Sampler* sampler) { void SamplerRegistry::RemoveActiveSampler(Sampler* sampler) { ASSERT(sampler->IsActive()); - ScopedLock lock(active_samplers_mutex.Pointer()); + ScopedLock lock(active_samplers_mutex); ASSERT(active_samplers_ != NULL); bool removed = active_samplers_->RemoveElement(sampler); ASSERT(removed); diff --git a/src/log.h b/src/log.h index 129738757e..03c7b3b670 100644 --- a/src/log.h +++ b/src/log.h @@ -437,6 +437,8 @@ class SamplerRegistry : public AllStatic { HAS_CPU_PROFILING_SAMPLERS }; + static void SetUp(); + typedef void (*VisitSampler)(Sampler*, void*); static State GetState(); diff --git a/src/platform-cygwin.cc b/src/platform-cygwin.cc index dd7253ba06..8b1e38197f 100644 --- a/src/platform-cygwin.cc +++ b/src/platform-cygwin.cc @@ -62,22 +62,8 @@ double ceiling(double x) { static Mutex* limit_mutex = NULL; -void OS::SetUp() { - // Seed the random number generator. - // Convert the current time to a 64-bit integer first, before converting it - // to an unsigned. Going directly can cause an overflow and the seed to be - // set to all ones. The seed will be identical for different instances that - // call this setup code within the same millisecond. - uint64_t seed = static_cast(TimeCurrentMillis()); - srandom(static_cast(seed)); - limit_mutex = CreateMutex(); -} - - void OS::PostSetUp() { - // Math functions depend on CPU features therefore they are initialized after - // CPU. - MathSetup(); + POSIXPostSetUp(); } uint64_t OS::CpuFeaturesImpliedByPlatform() { @@ -634,8 +620,14 @@ class SamplerThread : public Thread { : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)), interval_(interval) {} + static void SetUp() { + if (!mutex_) { + mutex_ = OS::CreateMutex(); + } + } + static void AddActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::AddActiveSampler(sampler); if (instance_ == NULL) { instance_ = new SamplerThread(sampler->interval()); @@ -646,7 +638,7 @@ class SamplerThread : public Thread { } static void RemoveActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::RemoveActiveSampler(sampler); if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); @@ -732,7 +724,7 @@ class SamplerThread : public Thread { RuntimeProfilerRateLimiter rate_limiter_; // Protects the process wide state below. - static LazyMutex mutex_; + static Mutex* mutex_; static SamplerThread* instance_; private: @@ -740,10 +732,23 @@ class SamplerThread : public Thread { }; -LazyMutex SamplerThread::mutex_ = LAZY_MUTEX_INITIALIZER; +Mutex* SamplerThread::mutex_ = NULL; SamplerThread* SamplerThread::instance_ = NULL; +void OS::SetUp() { + // Seed the random number generator. + // Convert the current time to a 64-bit integer first, before converting it + // to an unsigned. Going directly can cause an overflow and the seed to be + // set to all ones. The seed will be identical for different instances that + // call this setup code within the same millisecond. + uint64_t seed = static_cast(TimeCurrentMillis()); + srandom(static_cast(seed)); + limit_mutex = CreateMutex(); + SamplerThread::SetUp(); +} + + Sampler::Sampler(Isolate* isolate, int interval) : isolate_(isolate), interval_(interval), diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc index 6a004ea7fa..6b1c987e2f 100644 --- a/src/platform-freebsd.cc +++ b/src/platform-freebsd.cc @@ -80,22 +80,8 @@ double ceiling(double x) { static Mutex* limit_mutex = NULL; -void OS::SetUp() { - // Seed the random number generator. - // Convert the current time to a 64-bit integer first, before converting it - // to an unsigned. Going directly can cause an overflow and the seed to be - // set to all ones. The seed will be identical for different instances that - // call this setup code within the same millisecond. - uint64_t seed = static_cast(TimeCurrentMillis()); - srandom(static_cast(seed)); - limit_mutex = CreateMutex(); -} - - void OS::PostSetUp() { - // Math functions depend on CPU features therefore they are initialized after - // CPU. - MathSetup(); + POSIXPostSetUp(); } @@ -730,8 +716,14 @@ class SignalSender : public Thread { : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)), interval_(interval) {} + static void SetUp() { + if (!mutex_) { + mutex_ = OS::CreateMutex(); + } + } + static void AddActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::AddActiveSampler(sampler); if (instance_ == NULL) { // Install a signal handler. @@ -751,7 +743,7 @@ class SignalSender : public Thread { } static void RemoveActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::RemoveActiveSampler(sampler); if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); @@ -844,7 +836,7 @@ class SignalSender : public Thread { RuntimeProfilerRateLimiter rate_limiter_; // Protects the process wide state below. - static LazyMutex mutex_; + static Mutex* mutex_; static SignalSender* instance_; static bool signal_handler_installed_; static struct sigaction old_signal_handler_; @@ -853,12 +845,25 @@ class SignalSender : public Thread { DISALLOW_COPY_AND_ASSIGN(SignalSender); }; -LazyMutex SignalSender::mutex_ = LAZY_MUTEX_INITIALIZER; +Mutex* SignalSender::mutex_ = NULL; SignalSender* SignalSender::instance_ = NULL; struct sigaction SignalSender::old_signal_handler_; bool SignalSender::signal_handler_installed_ = false; +void OS::SetUp() { + // Seed the random number generator. + // Convert the current time to a 64-bit integer first, before converting it + // to an unsigned. Going directly can cause an overflow and the seed to be + // set to all ones. The seed will be identical for different instances that + // call this setup code within the same millisecond. + uint64_t seed = static_cast(TimeCurrentMillis()); + srandom(static_cast(seed)); + limit_mutex = CreateMutex(); + SignalSender::SetUp(); +} + + Sampler::Sampler(Isolate* isolate, int interval) : isolate_(isolate), interval_(interval), diff --git a/src/platform-linux.cc b/src/platform-linux.cc index ca394aafce..3a44357aad 100644 --- a/src/platform-linux.cc +++ b/src/platform-linux.cc @@ -79,37 +79,8 @@ double ceiling(double x) { static Mutex* limit_mutex = NULL; -void OS::SetUp() { - // Seed the random number generator. We preserve microsecond resolution. - uint64_t seed = Ticks() ^ (getpid() << 16); - srandom(static_cast(seed)); - limit_mutex = CreateMutex(); - -#ifdef __arm__ - // When running on ARM hardware check that the EABI used by V8 and - // by the C code is the same. - bool hard_float = OS::ArmUsingHardFloat(); - if (hard_float) { -#if !USE_EABI_HARDFLOAT - PrintF("ERROR: Binary compiled with -mfloat-abi=hard but without " - "-DUSE_EABI_HARDFLOAT\n"); - exit(1); -#endif - } else { -#if USE_EABI_HARDFLOAT - PrintF("ERROR: Binary not compiled with -mfloat-abi=hard but with " - "-DUSE_EABI_HARDFLOAT\n"); - exit(1); -#endif - } -#endif -} - - void OS::PostSetUp() { - // Math functions depend on CPU features therefore they are initialized after - // CPU. - MathSetup(); + POSIXPostSetUp(); } @@ -1084,6 +1055,12 @@ class SignalSender : public Thread { vm_tgid_(getpid()), interval_(interval) {} + static void SetUp() { + if (!mutex_) { + mutex_ = OS::CreateMutex(); + } + } + static void InstallSignalHandler() { struct sigaction sa; sa.sa_sigaction = ProfilerSignalHandler; @@ -1101,7 +1078,7 @@ class SignalSender : public Thread { } static void AddActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::AddActiveSampler(sampler); if (instance_ == NULL) { // Start a thread that will send SIGPROF signal to VM threads, @@ -1114,7 +1091,7 @@ class SignalSender : public Thread { } static void RemoveActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::RemoveActiveSampler(sampler); if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); @@ -1217,7 +1194,7 @@ class SignalSender : public Thread { RuntimeProfilerRateLimiter rate_limiter_; // Protects the process wide state below. - static LazyMutex mutex_; + static Mutex* mutex_; static SignalSender* instance_; static bool signal_handler_installed_; static struct sigaction old_signal_handler_; @@ -1227,12 +1204,40 @@ class SignalSender : public Thread { }; -LazyMutex SignalSender::mutex_ = LAZY_MUTEX_INITIALIZER; +Mutex* SignalSender::mutex_ = NULL; SignalSender* SignalSender::instance_ = NULL; struct sigaction SignalSender::old_signal_handler_; bool SignalSender::signal_handler_installed_ = false; +void OS::SetUp() { + // Seed the random number generator. We preserve microsecond resolution. + uint64_t seed = Ticks() ^ (getpid() << 16); + srandom(static_cast(seed)); + limit_mutex = CreateMutex(); + +#ifdef __arm__ + // When running on ARM hardware check that the EABI used by V8 and + // by the C code is the same. + bool hard_float = OS::ArmUsingHardFloat(); + if (hard_float) { +#if !USE_EABI_HARDFLOAT + PrintF("ERROR: Binary compiled with -mfloat-abi=hard but without " + "-DUSE_EABI_HARDFLOAT\n"); + exit(1); +#endif + } else { +#if USE_EABI_HARDFLOAT + PrintF("ERROR: Binary not compiled with -mfloat-abi=hard but with " + "-DUSE_EABI_HARDFLOAT\n"); + exit(1); +#endif + } +#endif + SignalSender::SetUp(); +} + + Sampler::Sampler(Isolate* isolate, int interval) : isolate_(isolate), interval_(interval), diff --git a/src/platform-macos.cc b/src/platform-macos.cc index dbcd80e9f2..afcd80afff 100644 --- a/src/platform-macos.cc +++ b/src/platform-macos.cc @@ -94,18 +94,8 @@ double ceiling(double x) { static Mutex* limit_mutex = NULL; -void OS::SetUp() { - // Seed the random number generator. We preserve microsecond resolution. - uint64_t seed = Ticks() ^ (getpid() << 16); - srandom(static_cast(seed)); - limit_mutex = CreateMutex(); -} - - void OS::PostSetUp() { - // Math functions depend on CPU features therefore they are initialized after - // CPU. - MathSetup(); + POSIXPostSetUp(); } @@ -753,8 +743,14 @@ class SamplerThread : public Thread { : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)), interval_(interval) {} + static void SetUp() { + if (!mutex_) { + mutex_ = OS::CreateMutex(); + } + } + static void AddActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::AddActiveSampler(sampler); if (instance_ == NULL) { instance_ = new SamplerThread(sampler->interval()); @@ -765,7 +761,7 @@ class SamplerThread : public Thread { } static void RemoveActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::RemoveActiveSampler(sampler); if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); @@ -862,7 +858,7 @@ class SamplerThread : public Thread { RuntimeProfilerRateLimiter rate_limiter_; // Protects the process wide state below. - static LazyMutex mutex_; + static Mutex* mutex_; static SamplerThread* instance_; private: @@ -872,10 +868,19 @@ class SamplerThread : public Thread { #undef REGISTER_FIELD -LazyMutex SamplerThread::mutex_ = LAZY_MUTEX_INITIALIZER; +Mutex* SamplerThread::mutex_ = NULL; SamplerThread* SamplerThread::instance_ = NULL; +void OS::SetUp() { + // Seed the random number generator. We preserve microsecond resolution. + uint64_t seed = Ticks() ^ (getpid() << 16); + srandom(static_cast(seed)); + limit_mutex = CreateMutex(); + SamplerThread::SetUp(); +} + + Sampler::Sampler(Isolate* isolate, int interval) : isolate_(isolate), interval_(interval), diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc index 6a06e3e536..2b2d5308eb 100644 --- a/src/platform-openbsd.cc +++ b/src/platform-openbsd.cc @@ -100,18 +100,8 @@ static void* GetRandomMmapAddr() { } -void OS::SetUp() { - // Seed the random number generator. We preserve microsecond resolution. - uint64_t seed = Ticks() ^ (getpid() << 16); - srandom(static_cast(seed)); - limit_mutex = CreateMutex(); -} - - void OS::PostSetUp() { - // Math functions depend on CPU features therefore they are initialized after - // CPU. - MathSetup(); + POSIXPostSetUp(); } @@ -803,6 +793,12 @@ class SignalSender : public Thread { vm_tgid_(getpid()), interval_(interval) {} + static void SetUp() { + if (!mutex_) { + mutex_ = OS::CreateMutex(); + } + } + static void InstallSignalHandler() { struct sigaction sa; sa.sa_sigaction = ProfilerSignalHandler; @@ -820,7 +816,7 @@ class SignalSender : public Thread { } static void AddActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::AddActiveSampler(sampler); if (instance_ == NULL) { // Start a thread that will send SIGPROF signal to VM threads, @@ -833,7 +829,7 @@ class SignalSender : public Thread { } static void RemoveActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::RemoveActiveSampler(sampler); if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); @@ -927,7 +923,7 @@ class SignalSender : public Thread { RuntimeProfilerRateLimiter rate_limiter_; // Protects the process wide state below. - static LazyMutex mutex_; + static Mutex* mutex_; static SignalSender* instance_; static bool signal_handler_installed_; static struct sigaction old_signal_handler_; @@ -937,12 +933,21 @@ class SignalSender : public Thread { }; -LazyMutex SignalSender::mutex_ = LAZY_MUTEX_INITIALIZER; +Mutex* SignalSender::mutex_ = NULL; SignalSender* SignalSender::instance_ = NULL; struct sigaction SignalSender::old_signal_handler_; bool SignalSender::signal_handler_installed_ = false; +void OS::SetUp() { + // Seed the random number generator. We preserve microsecond resolution. + uint64_t seed = Ticks() ^ (getpid() << 16); + srandom(static_cast(seed)); + limit_mutex = CreateMutex(); + SignalSender::SetUp(); +} + + Sampler::Sampler(Isolate* isolate, int interval) : isolate_(isolate), interval_(interval), diff --git a/src/platform-posix.cc b/src/platform-posix.cc index 59066ea39e..66316594c8 100644 --- a/src/platform-posix.cc +++ b/src/platform-posix.cc @@ -147,15 +147,6 @@ 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; @@ -313,20 +304,11 @@ int OS::VSNPrintF(Vector str, #if defined(V8_TARGET_ARCH_IA32) static OS::MemCopyFunction memcopy_function = NULL; -static LazyMutex memcopy_function_mutex = LAZY_MUTEX_INITIALIZER; // Defined in codegen-ia32.cc. OS::MemCopyFunction CreateMemCopyFunction(); // Copy memory area to disjoint memory area. void OS::MemCopy(void* dest, const void* src, size_t size) { - if (memcopy_function == NULL) { - ScopedLock lock(memcopy_function_mutex.Pointer()); - if (memcopy_function == NULL) { - OS::MemCopyFunction temp = CreateMemCopyFunction(); - MemoryBarrier(); - memcopy_function = temp; - } - } // Note: here we rely on dependent reads being ordered. This is true // on all architectures we currently support. (*memcopy_function)(dest, src, size); @@ -336,6 +318,18 @@ void OS::MemCopy(void* dest, const void* src, size_t size) { } #endif // V8_TARGET_ARCH_IA32 + +void POSIXPostSetUp() { +#if defined(V8_TARGET_ARCH_IA32) + memcopy_function = CreateMemCopyFunction(); +#endif + init_fast_sin_function(); + init_fast_cos_function(); + init_fast_tan_function(); + init_fast_log_function(); + init_fast_sqrt_function(); +} + // ---------------------------------------------------------------------------- // POSIX string support. // diff --git a/src/platform-posix.h b/src/platform-posix.h index 4ae0e526fb..7a982ed2ef 100644 --- a/src/platform-posix.h +++ b/src/platform-posix.h @@ -31,9 +31,8 @@ namespace v8 { namespace internal { -// Used by platform implementation files during OS::PostSetUp() to initialize -// the math functions. -void MathSetup(); +// Used by platform implementation files during OS::PostSetUp(). +void POSIXPostSetUp(); } } // namespace v8::internal diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc index e044dbccad..be8bbfce76 100644 --- a/src/platform-solaris.cc +++ b/src/platform-solaris.cc @@ -91,22 +91,10 @@ double ceiling(double x) { static Mutex* limit_mutex = NULL; -void OS::SetUp() { - // Seed the random number generator. - // Convert the current time to a 64-bit integer first, before converting it - // to an unsigned. Going directly will cause an overflow and the seed to be - // set to all ones. The seed will be identical for different instances that - // call this setup code within the same millisecond. - uint64_t seed = static_cast(TimeCurrentMillis()); - srandom(static_cast(seed)); - limit_mutex = CreateMutex(); -} void OS::PostSetUp() { - // Math functions depend on CPU features therefore they are initialized after - // CPU. - MathSetup(); + POSIXPostSetUp(); } @@ -724,6 +712,12 @@ class SignalSender : public Thread { : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)), interval_(interval) {} + static void SetUp() { + if (!mutex_) { + mutex_ = OS::CreateMutex(); + } + } + static void InstallSignalHandler() { struct sigaction sa; sa.sa_sigaction = ProfilerSignalHandler; @@ -741,7 +735,7 @@ class SignalSender : public Thread { } static void AddActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::AddActiveSampler(sampler); if (instance_ == NULL) { // Start a thread that will send SIGPROF signal to VM threads, @@ -754,7 +748,7 @@ class SignalSender : public Thread { } static void RemoveActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::RemoveActiveSampler(sampler); if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); @@ -848,7 +842,7 @@ class SignalSender : public Thread { RuntimeProfilerRateLimiter rate_limiter_; // Protects the process wide state below. - static LazyMutex mutex_; + static Mutex* mutex_; static SignalSender* instance_; static bool signal_handler_installed_; static struct sigaction old_signal_handler_; @@ -857,12 +851,25 @@ class SignalSender : public Thread { DISALLOW_COPY_AND_ASSIGN(SignalSender); }; -LazyMutex SignalSender::mutex_ = LAZY_MUTEX_INITIALIZER; +Mutex* SignalSender::mutex_ = NULL; SignalSender* SignalSender::instance_ = NULL; struct sigaction SignalSender::old_signal_handler_; bool SignalSender::signal_handler_installed_ = false; +void OS::SetUp() { + // Seed the random number generator. + // Convert the current time to a 64-bit integer first, before converting it + // to an unsigned. Going directly will cause an overflow and the seed to be + // set to all ones. The seed will be identical for different instances that + // call this setup code within the same millisecond. + uint64_t seed = static_cast(TimeCurrentMillis()); + srandom(static_cast(seed)); + limit_mutex = CreateMutex(); + SignalSender::SetUp(); +} + + Sampler::Sampler(Isolate* isolate, int interval) : isolate_(isolate), interval_(interval), diff --git a/src/platform-win32.cc b/src/platform-win32.cc index 3adae181e1..e36fc87539 100644 --- a/src/platform-win32.cc +++ b/src/platform-win32.cc @@ -141,20 +141,11 @@ static Mutex* limit_mutex = NULL; #if defined(V8_TARGET_ARCH_IA32) static OS::MemCopyFunction memcopy_function = NULL; -static LazyMutex memcopy_function_mutex = LAZY_MUTEX_INITIALIZER; // Defined in codegen-ia32.cc. OS::MemCopyFunction CreateMemCopyFunction(); // Copy memory area to disjoint memory area. void OS::MemCopy(void* dest, const void* src, size_t size) { - if (memcopy_function == NULL) { - ScopedLock lock(memcopy_function_mutex.Pointer()); - if (memcopy_function == NULL) { - OS::MemCopyFunction temp = CreateMemCopyFunction(); - MemoryBarrier(); - memcopy_function = temp; - } - } // Note: here we rely on dependent reads being ordered. This is true // on all architectures we currently support. (*memcopy_function)(dest, src, size); @@ -563,22 +554,13 @@ char* Time::LocalTimezone() { } -void OS::SetUp() { - // Seed the random number generator. - // Convert the current time to a 64-bit integer first, before converting it - // to an unsigned. Going directly can cause an overflow and the seed to be - // set to all ones. The seed will be identical for different instances that - // call this setup code within the same millisecond. - uint64_t seed = static_cast(TimeCurrentMillis()); - srand(static_cast(seed)); - limit_mutex = CreateMutex(); -} - - void OS::PostSetUp() { // Math functions depend on CPU features therefore they are initialized after // CPU. MathSetup(); +#if defined(V8_TARGET_ARCH_IA32) + memcopy_function = CreateMemCopyFunction(); +#endif } @@ -1967,8 +1949,14 @@ class SamplerThread : public Thread { : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)), interval_(interval) {} + static void SetUp() { + if (!mutex_) { + mutex_ = OS::CreateMutex(); + } + } + static void AddActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::AddActiveSampler(sampler); if (instance_ == NULL) { instance_ = new SamplerThread(sampler->interval()); @@ -1979,7 +1967,7 @@ class SamplerThread : public Thread { } static void RemoveActiveSampler(Sampler* sampler) { - ScopedLock lock(mutex_.Pointer()); + ScopedLock lock(mutex_); SamplerRegistry::RemoveActiveSampler(sampler); if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); @@ -2065,7 +2053,7 @@ class SamplerThread : public Thread { RuntimeProfilerRateLimiter rate_limiter_; // Protects the process wide state below. - static LazyMutex mutex_; + static Mutex* mutex_; static SamplerThread* instance_; private: @@ -2073,10 +2061,23 @@ class SamplerThread : public Thread { }; -LazyMutex SamplerThread::mutex_ = LAZY_MUTEX_INITIALIZER; +Mutex* SamplerThread::mutex_ = NULL; SamplerThread* SamplerThread::instance_ = NULL; +void OS::SetUp() { + // Seed the random number generator. + // Convert the current time to a 64-bit integer first, before converting it + // to an unsigned. Going directly can cause an overflow and the seed to be + // set to all ones. The seed will be identical for different instances that + // call this setup code within the same millisecond. + uint64_t seed = static_cast(TimeCurrentMillis()); + srand(static_cast(seed)); + limit_mutex = CreateMutex(); + SamplerThread::SetUp(); +} + + Sampler::Sampler(Isolate* isolate, int interval) : isolate_(isolate), interval_(interval), diff --git a/src/runtime-profiler.cc b/src/runtime-profiler.cc index 7d5119032d..568e48e412 100644 --- a/src/runtime-profiler.cc +++ b/src/runtime-profiler.cc @@ -101,7 +101,7 @@ RuntimeProfiler::RuntimeProfiler(Isolate* isolate) } -void RuntimeProfiler::GlobalSetup() { +void RuntimeProfiler::GlobalSetUp() { ASSERT(!has_been_globally_set_up_); enabled_ = V8::UseCrankshaft() && FLAG_opt; #ifdef DEBUG diff --git a/src/runtime-profiler.h b/src/runtime-profiler.h index 35213a8196..ab6cb378ea 100644 --- a/src/runtime-profiler.h +++ b/src/runtime-profiler.h @@ -43,7 +43,7 @@ class RuntimeProfiler { public: explicit RuntimeProfiler(Isolate* isolate); - static void GlobalSetup(); + static void GlobalSetUp(); static inline bool IsEnabled() { ASSERT(has_been_globally_set_up_); diff --git a/src/v8.cc b/src/v8.cc index d9351dcbca..45036c83f5 100644 --- a/src/v8.cc +++ b/src/v8.cc @@ -27,11 +27,13 @@ #include "v8.h" +#include "assembler.h" #include "isolate.h" #include "elements.h" #include "bootstrapper.h" #include "debug.h" #include "deoptimizer.h" +#include "frames.h" #include "heap-profiler.h" #include "hydrogen.h" #include "lithium-allocator.h" @@ -262,7 +264,7 @@ void V8::InitializeOncePerProcessImpl() { OS::PostSetUp(); - RuntimeProfiler::GlobalSetup(); + RuntimeProfiler::GlobalSetUp(); ElementsAccessor::InitializeOncePerProcess(); @@ -273,6 +275,9 @@ void V8::InitializeOncePerProcessImpl() { } LOperand::SetUpCaches(); + SetUpJSCallerSavedCodeData(); + SamplerRegistry::SetUp(); + ExternalReference::SetUp(); } void V8::InitializeOncePerProcess() { diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc index adeda0bb08..7ed81b47e1 100644 --- a/src/x64/disasm-x64.cc +++ b/src/x64/disasm-x64.cc @@ -315,7 +315,8 @@ class DisassemblerX64 { rex_(0), operand_size_(0), group_1_prefix_(0), - byte_size_operand_(false) { + byte_size_operand_(false), + instruction_table_(instruction_table.Pointer()) { tmp_buffer_[0] = '\0'; } @@ -344,6 +345,7 @@ class DisassemblerX64 { byte group_1_prefix_; // 0xF2, 0xF3, or (if no group 1 prefix is present) 0. // Byte size operand override. bool byte_size_operand_; + const InstructionTable* const instruction_table_; void setRex(byte rex) { ASSERT_EQ(0x40, rex & 0xF0); @@ -1340,7 +1342,7 @@ int DisassemblerX64::InstructionDecode(v8::internal::Vector out_buffer, data++; } - const InstructionDesc& idesc = instruction_table.Get().Get(current); + const InstructionDesc& idesc = instruction_table_->Get(current); byte_size_operand_ = idesc.byte_size_operation; switch (idesc.type) { case ZERO_OPERANDS_INSTR: