Commit db860431 authored by danno@chromium.org's avatar danno@chromium.org

Minimize uses of lazy initialization by adding explicit initialization functions.

BUG=118686

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11239 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ed5d288a
......@@ -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<double>(kHoleNanInt64);
double_constants->negative_infinity = -V8_INFINITY;
}
};
static LazyInstance<DoubleConstant, InitializeDoubleConstants>::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<double>(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<void*>(
&double_constants.Pointer()->min_int));
return ExternalReference(reinterpret_cast<void*>(&double_constants.min_int));
}
ExternalReference ExternalReference::address_of_one_half() {
return ExternalReference(reinterpret_cast<void*>(
&double_constants.Pointer()->one_half));
return ExternalReference(reinterpret_cast<void*>(&double_constants.one_half));
}
ExternalReference ExternalReference::address_of_minus_zero() {
return ExternalReference(reinterpret_cast<void*>(
&double_constants.Pointer()->minus_zero));
return ExternalReference(
reinterpret_cast<void*>(&double_constants.minus_zero));
}
ExternalReference ExternalReference::address_of_zero() {
return ExternalReference(reinterpret_cast<void*>(
&double_constants.Pointer()->zero));
return ExternalReference(reinterpret_cast<void*>(&double_constants.zero));
}
ExternalReference ExternalReference::address_of_uint8_max_value() {
return ExternalReference(reinterpret_cast<void*>(
&double_constants.Pointer()->uint8_max_value));
return ExternalReference(
reinterpret_cast<void*>(&double_constants.uint8_max_value));
}
ExternalReference ExternalReference::address_of_negative_infinity() {
return ExternalReference(reinterpret_cast<void*>(
&double_constants.Pointer()->negative_infinity));
return ExternalReference(
reinterpret_cast<void*>(&double_constants.negative_infinity));
}
ExternalReference ExternalReference::address_of_canonical_non_hole_nan() {
return ExternalReference(reinterpret_cast<void*>(
&double_constants.Pointer()->canonical_non_hole_nan));
return ExternalReference(
reinterpret_cast<void*>(&double_constants.canonical_non_hole_nan));
}
ExternalReference ExternalReference::address_of_the_hole_nan() {
return ExternalReference(reinterpret_cast<void*>(
&double_constants.Pointer()->the_hole_nan));
return ExternalReference(
reinterpret_cast<void*>(&double_constants.the_hole_nan));
}
......
......@@ -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);
......
......@@ -1369,24 +1369,23 @@ int NumRegs(RegList reglist) {
struct JSCallerSavedCodeData {
JSCallerSavedCodeData() {
int reg_code[kNumJSCallerSaved];
};
JSCallerSavedCodeData caller_saved_code_data;
void SetUpJSCallerSavedCodeData() {
int i = 0;
for (int r = 0; r < kNumRegs; r++)
if ((kJSCallerSaved & (1 << r)) != 0)
reg_code[i++] = r;
caller_saved_code_data.reg_code[i++] = r;
ASSERT(i == kNumJSCallerSaved);
}
int reg_code[kNumJSCallerSaved];
};
static LazyInstance<JSCallerSavedCodeData>::type caller_saved_code_data =
LAZY_INSTANCE_INITIALIZER;
}
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];
}
......
......@@ -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);
......
......@@ -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);
......
......@@ -65,8 +65,12 @@
// 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.
// 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:
......
......@@ -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<Sampler*>* 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<Sampler*>;
} 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);
......
......@@ -437,6 +437,8 @@ class SamplerRegistry : public AllStatic {
HAS_CPU_PROFILING_SAMPLERS
};
static void SetUp();
typedef void (*VisitSampler)(Sampler*, void*);
static State GetState();
......
......@@ -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<uint64_t>(TimeCurrentMillis());
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();
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<uint64_t>(TimeCurrentMillis());
srandom(static_cast<unsigned int>(seed));
limit_mutex = CreateMutex();
SamplerThread::SetUp();
}
Sampler::Sampler(Isolate* isolate, int interval)
: isolate_(isolate),
interval_(interval),
......
......@@ -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<uint64_t>(TimeCurrentMillis());
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();
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<uint64_t>(TimeCurrentMillis());
srandom(static_cast<unsigned int>(seed));
limit_mutex = CreateMutex();
SignalSender::SetUp();
}
Sampler::Sampler(Isolate* isolate, int interval)
: isolate_(isolate),
interval_(interval),
......
......@@ -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<unsigned int>(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<unsigned int>(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),
......
......@@ -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<unsigned int>(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<unsigned int>(seed));
limit_mutex = CreateMutex();
SamplerThread::SetUp();
}
Sampler::Sampler(Isolate* isolate, int interval)
: isolate_(isolate),
interval_(interval),
......
......@@ -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<unsigned int>(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<unsigned int>(seed));
limit_mutex = CreateMutex();
SignalSender::SetUp();
}
Sampler::Sampler(Isolate* isolate, int interval)
: isolate_(isolate),
interval_(interval),
......
......@@ -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<char> 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.
//
......
......@@ -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
......
......@@ -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<uint64_t>(TimeCurrentMillis());
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();
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<uint64_t>(TimeCurrentMillis());
srandom(static_cast<unsigned int>(seed));
limit_mutex = CreateMutex();
SignalSender::SetUp();
}
Sampler::Sampler(Isolate* isolate, int interval)
: isolate_(isolate),
interval_(interval),
......
......@@ -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<uint64_t>(TimeCurrentMillis());
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();
#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<uint64_t>(TimeCurrentMillis());
srand(static_cast<unsigned int>(seed));
limit_mutex = CreateMutex();
SamplerThread::SetUp();
}
Sampler::Sampler(Isolate* isolate, int interval)
: isolate_(isolate),
interval_(interval),
......
......@@ -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
......
......@@ -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_);
......
......@@ -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() {
......
......@@ -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<char> 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:
......
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