double_constants.the_hole_nan = BitCast<double>(kHoleNanInt64);
double_constants.negative_infinity = -V8_INFINITY;
- math_exp_data_mutex = new Mutex;
+ math_exp_data_mutex = OS::CreateMutex();
}
// Early return?
if (math_exp_data_initialized) return;
- ScopedLock with(math_exp_data_mutex);
+ math_exp_data_mutex->Lock();
if (!math_exp_data_initialized) {
// If this is changed, generated code must be adapted too.
const int kTableSizeBits = 11;
math_exp_data_initialized = true;
}
+ math_exp_data_mutex->Unlock();
}
#include <string.h>
-#include "globals.h"
-
#include "../include/v8stdint.h"
extern "C" void V8_Fatal(const char* file, int line, const char* format, ...);
// Use C++11 static_assert if possible, which gives error
// messages that are easier to understand on first sight.
-#if V8_CXX_STATIC_ASSERT
+#if __cplusplus >= 201103L
#define STATIC_CHECK(test) static_assert(test, #test)
#else
// This is inspired by the static assertion facility in boost. This
typedef \
StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>((test))>)> \
SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__)
-#endif // V8_CXX_STATIC_ASSERT
+#endif
extern bool FLAG_enable_slow_asserts;
void RemoteDebugger::AddEvent(RemoteDebuggerEvent* event) {
- i::ScopedLock lock(&event_access_);
+ i::ScopedLock lock(event_access_);
if (head_ == NULL) {
ASSERT(tail_ == NULL);
head_ = event;
RemoteDebuggerEvent* RemoteDebugger::GetEvent() {
- i::ScopedLock lock(&event_access_);
+ i::ScopedLock lock(event_access_);
ASSERT(head_ != NULL);
RemoteDebuggerEvent* result = head_;
head_ = head_->next();
explicit RemoteDebugger(Isolate* isolate, int port)
: isolate_(isolate),
port_(port),
+ event_access_(i::OS::CreateMutex()),
event_available_(i::OS::CreateSemaphore(0)),
head_(NULL), tail_(NULL) {}
void Run();
// Linked list of events from debugged V8 and from keyboard input. Access to
// the list is guarded by a mutex and a semaphore signals new items in the
// list.
- i::Mutex event_access_;
+ i::Mutex* event_access_;
i::Semaphore* event_available_;
RemoteDebuggerEvent* head_;
RemoteDebuggerEvent* tail_;
i::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
CounterCollection Shell::local_counters_;
CounterCollection* Shell::counters_ = &local_counters_;
-i::Mutex Shell::context_mutex_;
+i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
Persistent<Context> Shell::utility_context_;
#endif // V8_SHARED
Local<Context> Shell::CreateEvaluationContext(Isolate* isolate) {
#ifndef V8_SHARED
// This needs to be a critical section since this is not thread-safe
- i::ScopedLock lock(&context_mutex_);
+ i::ScopedLock lock(context_mutex_);
#endif // V8_SHARED
// Initialize the global objects
Handle<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
"-------------+\n");
delete [] counters;
}
+ delete context_mutex_;
delete counters_file_;
delete counter_map_;
#endif // V8_SHARED
static CounterCollection local_counters_;
static CounterCollection* counters_;
static i::OS::MemoryMappedFile* counters_file_;
- static i::Mutex context_mutex_;
+ static i::Mutex* context_mutex_;
static Counter* GetCounter(const char* name, bool is_histogram);
static void InstallUtilityScript(Isolate* isolate);
"Remote debugging session already active\r\n";
void DebuggerAgent::CreateSession(Socket* client) {
- ScopedLock with(&session_access_);
+ ScopedLock with(session_access_);
// If another session is already established terminate this one.
if (session_ != NULL) {
void DebuggerAgent::CloseSession() {
- ScopedLock with(&session_access_);
+ ScopedLock with(session_access_);
// Terminate the session.
if (session_ != NULL) {
void DebuggerAgent::DebuggerMessage(const v8::Debug::Message& message) {
- ScopedLock with(&session_access_);
+ ScopedLock with(session_access_);
// Forward the message handling to the session.
if (session_ != NULL) {
}
// Terminate the session.
- ScopedLock with(&session_access_);
+ ScopedLock with(session_access_);
ASSERT(session == session_);
if (session == session_) {
session_->Shutdown();
isolate_(Isolate::Current()),
name_(StrDup(name)), port_(port),
server_(OS::CreateSocket()), terminate_(false),
- session_(NULL),
+ session_access_(OS::CreateMutex()), session_(NULL),
terminate_now_(OS::CreateSemaphore(0)),
listening_(OS::CreateSemaphore(0)) {
ASSERT(isolate_->debugger_agent_instance() == NULL);
int port_; // Port to use for the agent.
Socket* server_; // Server socket for listen/accept.
bool terminate_; // Termination flag.
- Mutex session_access_; // Mutex guarging access to session_.
+ Mutex* session_access_; // Mutex guarging access to session_.
DebuggerAgentSession* session_; // Current active session if any.
Semaphore* terminate_now_; // Semaphore to signal termination.
Semaphore* listening_;
message_handler_(NULL),
debugger_unload_pending_(false),
host_dispatch_handler_(NULL),
+ dispatch_handler_access_(OS::CreateMutex()),
debug_message_dispatch_handler_(NULL),
message_dispatch_helper_thread_(NULL),
host_dispatch_micros_(100 * 1000),
Debugger::~Debugger() {
+ delete dispatch_handler_access_;
+ dispatch_handler_access_ = 0;
delete command_received_;
command_received_ = 0;
}
void Debugger::SetDebugMessageDispatchHandler(
v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) {
- ScopedLock with(&dispatch_handler_access_);
+ ScopedLock with(dispatch_handler_access_);
debug_message_dispatch_handler_ = handler;
if (provide_locker && message_dispatch_helper_thread_ == NULL) {
MessageDispatchHelperThread* dispatch_thread;
{
- ScopedLock with(&dispatch_handler_access_);
+ ScopedLock with(dispatch_handler_access_);
dispatch_thread = message_dispatch_helper_thread_;
}
void Debugger::CallMessageDispatchHandler() {
v8::Debug::DebugMessageDispatchHandler handler;
{
- ScopedLock with(&dispatch_handler_access_);
+ ScopedLock with(dispatch_handler_access_);
handler = Debugger::debug_message_dispatch_handler_;
}
if (handler != NULL) {
LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
- : logger_(logger), queue_(size) {}
+ : logger_(logger), queue_(size) {
+ lock_ = OS::CreateMutex();
+}
-LockingCommandMessageQueue::~LockingCommandMessageQueue() {}
+LockingCommandMessageQueue::~LockingCommandMessageQueue() {
+ delete lock_;
+}
-bool LockingCommandMessageQueue::IsEmpty() {
- ScopedLock sl(&lock_);
+bool LockingCommandMessageQueue::IsEmpty() const {
+ ScopedLock sl(lock_);
return queue_.IsEmpty();
}
CommandMessage LockingCommandMessageQueue::Get() {
- ScopedLock sl(&lock_);
+ ScopedLock sl(lock_);
CommandMessage result = queue_.Get();
logger_->DebugEvent("Get", result.text());
return result;
void LockingCommandMessageQueue::Put(const CommandMessage& message) {
- ScopedLock sl(&lock_);
+ ScopedLock sl(lock_);
queue_.Put(message);
logger_->DebugEvent("Put", message.text());
}
void LockingCommandMessageQueue::Clear() {
- ScopedLock sl(&lock_);
+ ScopedLock sl(lock_);
queue_.Clear();
}
MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate)
: Thread("v8:MsgDispHelpr"),
isolate_(isolate), sem_(OS::CreateSemaphore(0)),
- already_signalled_(false) {}
+ mutex_(OS::CreateMutex()), already_signalled_(false) {
+}
MessageDispatchHelperThread::~MessageDispatchHelperThread() {
+ delete mutex_;
delete sem_;
}
void MessageDispatchHelperThread::Schedule() {
{
- ScopedLock lock(&mutex_);
+ ScopedLock lock(mutex_);
if (already_signalled_) {
return;
}
while (true) {
sem_->Wait();
{
- ScopedLock lock(&mutex_);
+ ScopedLock lock(mutex_);
already_signalled_ = false;
}
{
public:
LockingCommandMessageQueue(Logger* logger, int size);
~LockingCommandMessageQueue();
- bool IsEmpty();
+ bool IsEmpty() const;
CommandMessage Get();
void Put(const CommandMessage& message);
void Clear();
-
private:
Logger* logger_;
CommandMessageQueue queue_;
- Mutex lock_;
+ Mutex* lock_;
DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue);
};
v8::Debug::MessageHandler2 message_handler_;
bool debugger_unload_pending_; // Was message handler cleared?
v8::Debug::HostDispatchHandler host_dispatch_handler_;
- Mutex dispatch_handler_access_; // Mutex guarding dispatch handler.
+ Mutex* dispatch_handler_access_; // Mutex guarding dispatch handler.
v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
MessageDispatchHelperThread* message_dispatch_helper_thread_;
int host_dispatch_micros_;
Isolate* isolate_;
Semaphore* const sem_;
- Mutex mutex_;
+ Mutex* const mutex_;
bool already_signalled_;
DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread);
#ifndef V8_GLOBALS_H_
#define V8_GLOBALS_H_
-// ----------------------------------------------------------------------------
-// Operating system detection (V8_OS_x)
-//
-// ANDROID - Android
-// BSD4 - Any BSD 4.4 system
-// CYGWIN - Cygwin
-// DARWIN - Darwin / Mac OS X
-// FREEBSD - FreeBSD
-// LINUX - Linux
-// NACL - Native Client
-// NETBSD - NetBSD
-// OPENBSD - OpenBSD
-// SOLARIS - Solaris
-// UNIX - Any UNIX BSD/SYSV system
-// WIN32 - Win32 (Windows 2000/XP/Vista/7 and Windows Server 2003/2008)
-
-#if defined(ANDROID) || defined(__ANDROID__)
-# define V8_OS_ANDROID 1
-# define V8_OS_LINUX 1
-# define V8_OS_UNIX 1
-#elif defined(__APPLE__) && defined(__MACH__)
-# define V8_OS_DARWIN 1
-# define V8_OS_BSD4 1
-# define V8_OS_UNIX 1
-#elif defined(__CYGWIN__)
-# define V8_OS_CYGWIN 1
-# define V8_OS_UNIX 1
-#elif defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
-# define V8_OS_WIN32 1
-# define V8_OS_WIN64 1
-#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || \
- (defined(__MWERKS__) && defined(__INTEL__))
-# define V8_OS_WIN32 1
-#elif defined(__sun) || defined(sun)
-# define V8_OS_SOLARIS 1
-# define V8_OS_UNIX 1
-#elif defined(__native_client__)
-# define V8_OS_NACL 1
-# define V8_OS_UNIX 1
-#elif defined(__linux__) || defined(__linux)
-# define V8_OS_LINUX 1
-# define V8_OS_UNIX 1
-#elif defined(__FreeBSD__) || defined(__DragonFly__)
-# define V8_OS_FREEBSD 1
-# define V8_OS_BSD4 1
-# define V8_OS_UNIX 1
-#elif defined(__NetBSD__)
-# define V8_OS_NETBSD 1
-# define V8_OS_BSD4 1
-# define V8_OS_UNIX 1
-#elif defined(__OpenBSD__)
-# define V8_OS_OPENBSD 1
-# define V8_OS_BSD4 1
-# define V8_OS_UNIX 1
-#else
-# error Operating system was not detected as supported by v8
-#endif
+// Define V8_INFINITY
+#define V8_INFINITY INFINITY
+// GCC specific stuff
+#ifdef __GNUC__
-// ----------------------------------------------------------------------------
-// Compiler detection (V8_CC_x)
-//
-// CLANG - C++ front-end for the LLVM compiler
-// GNU - GNU C++ or compatible
-// INTEL - Intel C++ for Linux or Windows
-// MINGW - Minimalistic GNU for Windows Compiler
-// MIPS - MIPSpro C++
-// MSVC - Microsoft Visual C/C++ or compatible
-// RVCT - ARM Realview Compiler Suite
+#define __GNUC_VERSION_FOR_INFTY__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
-#if defined(_MSC_VER)
-# define V8_CC_MSVC 1
-# if defined(__INTEL_COMPILER)
-# define V8_CC_INTEL 1
-# endif
-#elif defined(__GNUC__)
-# define V8_CC_GNU 1
-# if defined(__MINGW64__)
-# define V8_CC_MINGW 1
-# define V8_CC_MINGW64 1
-# elif defined(__MINGW32__)
-# define V8_CC_MINGW 1
-# define V8_CC_MINGW32 1
-# elif defined(__ARMCC__) || defined(__CC_ARM)
-# define V8_CC_RVCT 1 // ARM Realview Compiler Suite also masquerades as GCC
-# elif defined(__INTEL_COMPILER)
-# define V8_CC_INTEL 1 // Intel C++ also masquerades as GCC 3.2.0
-# elif defined(__clang__)
-# define V8_CC_CLANG 1 // Clang also masquerades as GCC 4.2.1
-# ifndef __has_extension
-# define __has_extension __has_feature // Compatibility with older releases
-# endif
-# endif
-#elif defined(__ARMCC__) || defined(__CC_ARM)
-# define V8_CC_RVCT 1
-#elif defined(__INTEL_COMPILER)
-# define V8_CC_INTEL 1
-#elif defined(__SUNPRO_CC) || defined(__SUNPRO_C)
-# define V8_CC_SUN 1
-#else
-# error Compiler was not detected as supported by v8
+// Unfortunately, the INFINITY macro cannot be used with the '-pedantic'
+// warning flag and certain versions of GCC due to a bug:
+// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11931
+// For now, we use the more involved template-based version from <limits>, but
+// only when compiling with GCC versions affected by the bug (2.96.x - 4.0.x)
+// __GNUC_PREREQ is not defined in GCC for Mac OS X, so we define our own macro
+#if __GNUC_VERSION_FOR_INFTY__ >= 29600 && __GNUC_VERSION_FOR_INFTY__ < 40100
+#include <limits>
+#undef V8_INFINITY
+#define V8_INFINITY std::numeric_limits<double>::infinity()
#endif
+#undef __GNUC_VERSION_FOR_INFTY__
-#if V8_CC_GNU
-# define V8_GNUC_PREREQ(major, minor) \
- (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
-#else
-# define V8_GNUC_PREREQ(major, minor) 0
-#endif // V8_CC_GNU
-
-
-// ----------------------------------------------------------------------------
-// Compiler features
+#endif // __GNUC__
-// C++11 deleted functions
-#if __cplusplus >= 201103L
-# define V8_CXX_DELETED_FUNCTIONS 1
-#elif V8_CC_CLANG
-# define V8_CXX_DELETED_FUNCTIONS __has_feature(cxx_deleted_functions)
-#else
-# define V8_CXX_DELETED_FUNCTIONS (defined(__GXX_EXPERIMENTAL_CXX0X__) && \
- V8_GNUC_PREREQ(4, 4))
+#ifdef _MSC_VER
+#undef V8_INFINITY
+#define V8_INFINITY HUGE_VAL
#endif
-// C++11 static_assert()
-#if __cplusplus >= 201103L
-# define V8_CXX_STATIC_ASSERT 1
-#elif V8_CC_CLANG
-# define V8_CXX_STATIC_ASSERT (__has_extension(cxx_static_assert) || \
- __has_feature(cxx_static_assert))
-#else
-# define V8_CXX_STATIC_ASSERT (defined(__GXX_EXPERIMENTAL_CXX0X__) && \
- V8_GNUC_PREREQ(4, 3))
-#endif
+#include "../include/v8stdint.h"
+
+namespace v8 {
+namespace internal {
-// ----------------------------------------------------------------------------
-// Host architecture detection. For more info on what's defined, see:
+// Processor architecture detection. For more info on what's defined, see:
// http://msdn.microsoft.com/en-us/library/b0084kay.aspx
// http://www.agner.org/optimize/calling_conventions.pdf
// or with gcc, run: "echo | gcc -E -dM -"
-
#if defined(_M_X64) || defined(__x86_64__)
-# if V8_OS_NACL
+#if defined(__native_client__)
// For Native Client builds of V8, use V8_TARGET_ARCH_ARM, so that V8
// generates ARM machine code, together with a portable ARM simulator
// compiled for the host architecture in question.
//
// Since Native Client is ILP-32 on all architectures we use
// V8_HOST_ARCH_IA32 on both 32- and 64-bit x86.
-# define V8_HOST_ARCH_IA32 1
-# define V8_HOST_ARCH_32_BIT 1
-# define V8_HOST_CAN_READ_UNALIGNED 1
-# else
-# define V8_HOST_ARCH_X64 1
-# define V8_HOST_ARCH_64_BIT 1
-# define V8_HOST_CAN_READ_UNALIGNED 1
-# endif // V8_OS_NACL
+#define V8_HOST_ARCH_IA32 1
+#define V8_HOST_ARCH_32_BIT 1
+#define V8_HOST_CAN_READ_UNALIGNED 1
+#else
+#define V8_HOST_ARCH_X64 1
+#define V8_HOST_ARCH_64_BIT 1
+#define V8_HOST_CAN_READ_UNALIGNED 1
+#endif // __native_client__
#elif defined(_M_IX86) || defined(__i386__)
-# define V8_HOST_ARCH_IA32 1
-# define V8_HOST_ARCH_32_BIT 1
-# define V8_HOST_CAN_READ_UNALIGNED 1
+#define V8_HOST_ARCH_IA32 1
+#define V8_HOST_ARCH_32_BIT 1
+#define V8_HOST_CAN_READ_UNALIGNED 1
#elif defined(__ARMEL__)
-# define V8_HOST_ARCH_ARM 1
-# define V8_HOST_ARCH_32_BIT 1
+#define V8_HOST_ARCH_ARM 1
+#define V8_HOST_ARCH_32_BIT 1
#elif defined(__MIPSEL__)
-# define V8_HOST_ARCH_MIPS 1
-# define V8_HOST_ARCH_32_BIT 1
+#define V8_HOST_ARCH_MIPS 1
+#define V8_HOST_ARCH_32_BIT 1
#else
-# error Host architecture was not detected as supported by v8
+#error Host architecture was not detected as supported by v8
#endif
#if defined(__ARM_ARCH_7A__) || \
defined(__ARM_ARCH_7__)
# define CAN_USE_ARMV7_INSTRUCTIONS 1
# ifndef CAN_USE_VFP3_INSTRUCTIONS
-# define CAN_USE_VFP3_INSTRUCTIONS 1
+# define CAN_USE_VFP3_INSTRUCTIONS
# endif
#endif
-// ----------------------------------------------------------------------------
// Target architecture detection. This may be set externally. If not, detect
// in the same way as the host architecture, that is, target the native
// environment as presented by the compiler.
-
#if !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_IA32 && \
!V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_MIPS
-# if defined(_M_X64) || defined(__x86_64__)
-# define V8_TARGET_ARCH_X64 1
-# elif defined(_M_IX86) || defined(__i386__)
-# define V8_TARGET_ARCH_IA32 1
-# elif defined(__ARMEL__)
-# define V8_TARGET_ARCH_ARM 1
-# elif defined(__MIPSEL__)
-# define V8_TARGET_ARCH_MIPS 1
-# else
-# error Target architecture was not detected as supported by v8
-# endif
+#if defined(_M_X64) || defined(__x86_64__)
+#define V8_TARGET_ARCH_X64 1
+#elif defined(_M_IX86) || defined(__i386__)
+#define V8_TARGET_ARCH_IA32 1
+#elif defined(__ARMEL__)
+#define V8_TARGET_ARCH_ARM 1
+#elif defined(__MIPSEL__)
+#define V8_TARGET_ARCH_MIPS 1
+#else
+#error Target architecture was not detected as supported by v8
+#endif
#endif
// Check for supported combinations of host and target architectures.
#if V8_TARGET_ARCH_IA32 && !V8_HOST_ARCH_IA32
-# error Target architecture ia32 is only supported on ia32 host
-#elif V8_TARGET_ARCH_X64 && !V8_HOST_ARCH_X64
-# error Target architecture x64 is only supported on x64 host
-#elif V8_TARGET_ARCH_ARM && !(V8_HOST_ARCH_IA32 || V8_HOST_ARCH_ARM)
-# error Target architecture arm is only supported on arm and ia32 host
-#elif V8_TARGET_ARCH_MIPS && !(V8_HOST_ARCH_IA32 || V8_HOST_ARCH_MIPS)
-# error Target architecture mips is only supported on mips and ia32 host
+#error Target architecture ia32 is only supported on ia32 host
+#endif
+#if V8_TARGET_ARCH_X64 && !V8_HOST_ARCH_X64
+#error Target architecture x64 is only supported on x64 host
+#endif
+#if (V8_TARGET_ARCH_ARM && !(V8_HOST_ARCH_IA32 || V8_HOST_ARCH_ARM))
+#error Target architecture arm is only supported on arm and ia32 host
+#endif
+#if (V8_TARGET_ARCH_MIPS && !(V8_HOST_ARCH_IA32 || V8_HOST_ARCH_MIPS))
+#error Target architecture mips is only supported on mips and ia32 host
#endif
// Determine whether we are running in a simulated environment.
// Setting USE_SIMULATOR explicitly from the build script will force
// the use of a simulated environment.
#if !defined(USE_SIMULATOR)
-# if V8_TARGET_ARCH_ARM && !V8_HOST_ARCH_ARM
-# define USE_SIMULATOR 1
-# elif V8_TARGET_ARCH_MIPS && !V8_HOST_ARCH_MIPS
-# define USE_SIMULATOR 1
-# endif
+#if (V8_TARGET_ARCH_ARM && !V8_HOST_ARCH_ARM)
+#define USE_SIMULATOR 1
+#endif
+#if (V8_TARGET_ARCH_MIPS && !V8_HOST_ARCH_MIPS)
+#define USE_SIMULATOR 1
#endif
-
-// Determine architecture endiannes (we only support little-endian).
-#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || \
- V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
-# define V8_TARGET_LITTLE_ENDIAN 1
-#else
-# error Unknown target architecture endiannes
#endif
-
-// ----------------------------------------------------------------------------
-// Define our own macros for writing 64-bit constants. This is less fragile
-// than defining __STDC_CONSTANT_MACROS before including <stdint.h>, and it
-// works on compilers that don't have it (like MSVC).
-#if V8_HOST_ARCH_64_BIT
-# if V8_CC_MSVC
-# define V8_UINT64_C(x) (x ## UI64)
-# define V8_INT64_C(x) (x ## I64)
-# define V8_INTPTR_C(x) (x ## I64)
-# define V8_PTR_PREFIX "ll"
-# elif V8_CC_MINGW
-# define V8_UINT64_C(x) (x ## ULL)
-# define V8_INT64_C(x) (x ## LL)
-# define V8_INTPTR_C(x) (x ## LL)
-# define V8_PTR_PREFIX "I64"
-# else
-# define V8_UINT64_C(x) (x ## UL)
-# define V8_INT64_C(x) (x ## L)
-# define V8_INTPTR_C(x) (x ## L)
-# define V8_PTR_PREFIX "l"
-# endif
-#else // V8_HOST_ARCH_64_BIT
-# define V8_INTPTR_C(x) (x)
-# define V8_PTR_PREFIX ""
-#endif // V8_HOST_ARCH_64_BIT
-
-// The following macro works on both 32 and 64-bit platforms.
-// Usage: instead of writing 0x1234567890123456
-// write V8_2PART_UINT64_C(0x12345678,90123456);
-#define V8_2PART_UINT64_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
-
-#if V8_OS_DARWIN
-// Fix for Mac OS X defining uintptr_t as "unsigned long":
-# define V8PRIxPTR "lx"
-#else
-# define V8PRIxPTR V8_PTR_PREFIX "x"
-#endif // V8_OS_DARWIN
-#define V8PRIdPTR V8_PTR_PREFIX "d"
-#define V8PRIuPTR V8_PTR_PREFIX "u"
-
-
-// ----------------------------------------------------------------------------
-// Define V8_INFINITY
-#if V8_GNUC_PREREQ(2, 96) && !V8_GNUC_PREREQ(4, 1)
-// Unfortunately, the INFINITY macro cannot be used with the '-pedantic'
-// warning flag and certain versions of GCC due to a bug:
-// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11931
-// For now, we use the more involved template-based version from <limits>, but
-// only when compiling with GCC versions affected by the bug (2.96.x - 4.0.x)
-# include <limits>
-# define V8_INFINITY std::numeric_limits<double>::infinity()
-#elif V8_CC_MSVC
-# define V8_INFINITY HUGE_VAL
+// Determine architecture endiannes (we only support little-endian).
+#if V8_TARGET_ARCH_IA32
+#define V8_TARGET_LITTLE_ENDIAN 1
+#elif V8_TARGET_ARCH_X64
+#define V8_TARGET_LITTLE_ENDIAN 1
+#elif V8_TARGET_ARCH_ARM
+#define V8_TARGET_LITTLE_ENDIAN 1
+#elif V8_TARGET_ARCH_MIPS
+#define V8_TARGET_LITTLE_ENDIAN 1
#else
-# define V8_INFINITY INFINITY
+#error Unknown target architecture endiannes
#endif
-
-#include "../include/v8stdint.h"
-
-namespace v8 {
-namespace internal {
-
// Support for alternative bool type. This is only enabled if the code is
// compiled with USE_MYBOOL defined. This catches some nasty type bugs.
// For instance, 'bool b = "false";' results in b == true! This is a hidden
typedef uint8_t byte;
typedef byte* Address;
+// Define our own macros for writing 64-bit constants. This is less fragile
+// than defining __STDC_CONSTANT_MACROS before including <stdint.h>, and it
+// works on compilers that don't have it (like MSVC).
+#if V8_HOST_ARCH_64_BIT
+#if defined(_MSC_VER)
+#define V8_UINT64_C(x) (x ## UI64)
+#define V8_INT64_C(x) (x ## I64)
+#define V8_INTPTR_C(x) (x ## I64)
+#define V8_PTR_PREFIX "ll"
+#elif defined(__MINGW64__)
+#define V8_UINT64_C(x) (x ## ULL)
+#define V8_INT64_C(x) (x ## LL)
+#define V8_INTPTR_C(x) (x ## LL)
+#define V8_PTR_PREFIX "I64"
+#else
+#define V8_UINT64_C(x) (x ## UL)
+#define V8_INT64_C(x) (x ## L)
+#define V8_INTPTR_C(x) (x ## L)
+#define V8_PTR_PREFIX "l"
+#endif
+#else // V8_HOST_ARCH_64_BIT
+#define V8_INTPTR_C(x) (x)
+#define V8_PTR_PREFIX ""
+#endif // V8_HOST_ARCH_64_BIT
+
+// The following macro works on both 32 and 64-bit platforms.
+// Usage: instead of writing 0x1234567890123456
+// write V8_2PART_UINT64_C(0x12345678,90123456);
+#define V8_2PART_UINT64_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
+
+#define V8PRIxPTR V8_PTR_PREFIX "x"
+#define V8PRIdPTR V8_PTR_PREFIX "d"
+#define V8PRIuPTR V8_PTR_PREFIX "u"
+
+// Fix for Mac OS X defining uintptr_t as "unsigned long":
+#if defined(__APPLE__) && defined(__MACH__)
+#undef V8PRIxPTR
+#define V8PRIxPTR "lx"
+#endif
+
+#if (defined(__APPLE__) && defined(__MACH__)) || \
+ defined(__FreeBSD__) || defined(__OpenBSD__)
+#define USING_BSD_ABI
+#endif
+
// -----------------------------------------------------------------------------
// Constants
}
-#if V8_CXX_DELETED_FUNCTIONS
-# define DISALLOW_BY_DELETE = delete
+#if __cplusplus >= 201103L
+#define DISALLOW_BY_DELETE = delete
#else
-# define DISALLOW_BY_DELETE
+#define DISALLOW_BY_DELETE
#endif
// Define used for helping GCC to make better inlining. Don't bother for debug
// builds. On GCC 3.4.5 using __attribute__((always_inline)) causes compilation
// errors in debug build.
-#if V8_GNUC_PREREQ(4, 0) && !defined(DEBUG)
-# define INLINE(header) inline header __attribute__((always_inline))
-# define NO_INLINE(header) header __attribute__((noinline))
-#elif V8_CC_GNU && !defined(DEBUG)
-# define INLINE(header) inline __attribute__((always_inline)) header
-# define NO_INLINE(header) __attribute__((noinline)) header
-#elif V8_CC_MSVC && !defined(DEBUG)
-# define INLINE(header) __forceinline header
-# define NO_INLINE(header) header
+#if defined(__GNUC__) && !defined(DEBUG)
+#if (__GNUC__ >= 4)
+#define INLINE(header) inline header __attribute__((always_inline))
+#define NO_INLINE(header) header __attribute__((noinline))
+#else
+#define INLINE(header) inline __attribute__((always_inline)) header
+#define NO_INLINE(header) __attribute__((noinline)) header
+#endif
+#elif defined(_MSC_VER) && !defined(DEBUG)
+#define INLINE(header) __forceinline header
+#define NO_INLINE(header) header
#else
-# define INLINE(header) inline header
-# define NO_INLINE(header) header
+#define INLINE(header) inline header
+#define NO_INLINE(header) header
#endif
-#if V8_GNUC_PREREQ(4, 0)
+#if defined(__GNUC__) && __GNUC__ >= 4
#define MUST_USE_RESULT __attribute__ ((warn_unused_result))
#else
#define MUST_USE_RESULT
store_buffer()->SetUp();
- if (FLAG_parallel_recompilation) relocation_mutex_ = new Mutex;
+ if (FLAG_parallel_recompilation) relocation_mutex_ = OS::CreateMutex();
#ifdef DEBUG
relocation_mutex_locked_by_optimizer_thread_ = false;
#endif // DEBUG
// If false, it is returned as a pointer to a preallocated by caller memory
// region. Pointer to this region should be passed to a function as an
// implicit first argument.
-#if V8_OS_BSD4 || V8_CC_MINGW32 || V8_OS_CYGWIN
+#if defined(USING_BSD_ABI) || defined(__MINGW32__) || defined(__CYGWIN__)
static const bool kReturnHandlesDirectly = true;
#else
static const bool kReturnHandlesDirectly = false;
#ifdef DEBUG
Thread::LocalStorageKey PerThreadAssertScopeBase::thread_local_key;
#endif // DEBUG
-Mutex Isolate::process_wide_mutex_;
+Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex();
Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
Atomic32 Isolate::isolate_counter_ = 0;
ASSERT(!thread_id.Equals(ThreadId::Invalid()));
PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id);
{
- ScopedLock lock(&process_wide_mutex_);
+ 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);
ThreadId thread_id = ThreadId::Current();
PerIsolateThreadData* per_thread = NULL;
{
- ScopedLock lock(&process_wide_mutex_);
+ ScopedLock lock(process_wide_mutex_);
per_thread = thread_data_table_->Lookup(this, thread_id);
- }
- if (per_thread == NULL) {
- per_thread = AllocatePerIsolateThreadData(thread_id);
+ if (per_thread == NULL) {
+ per_thread = AllocatePerIsolateThreadData(thread_id);
+ }
}
return per_thread;
}
ThreadId thread_id) {
PerIsolateThreadData* per_thread = NULL;
{
- ScopedLock lock(&process_wide_mutex_);
+ ScopedLock lock(process_wide_mutex_);
per_thread = thread_data_table_->Lookup(this, thread_id);
}
return per_thread;
void Isolate::EnsureDefaultIsolate() {
- ScopedLock lock(&process_wide_mutex_);
+ ScopedLock lock(process_wide_mutex_);
if (default_isolate_ == NULL) {
isolate_key_ = Thread::CreateThreadLocalKey();
thread_id_key_ = Thread::CreateThreadLocalKey();
counters_(NULL),
code_range_(NULL),
// Must be initialized early to allow v8::SetResourceConstraints calls.
+ break_access_(OS::CreateMutex()),
debugger_initialized_(false),
// Must be initialized early to allow v8::Debug calls.
+ debugger_access_(OS::CreateMutex()),
logger_(NULL),
stats_table_(NULL),
stub_cache_(NULL),
Deinit();
- { ScopedLock lock(&process_wide_mutex_);
+ { ScopedLock lock(process_wide_mutex_);
thread_data_table_->RemoveAllThreads(this);
}
delete handle_scope_implementer_;
handle_scope_implementer_ = NULL;
+ delete break_access_;
+ break_access_ = NULL;
+ delete debugger_access_;
+ debugger_access_ = NULL;
delete compilation_cache_;
compilation_cache_ = NULL;
void Isolate::InitializeDebugger() {
#ifdef ENABLE_DEBUGGER_SUPPORT
- ScopedLock lock(&debugger_access_);
+ ScopedLock lock(debugger_access_);
if (NoBarrier_Load(&debugger_initialized_)) return;
InitializeLoggingAndCounters();
debug_ = new Debug(this);
static void EnterDefaultIsolate();
// Mutex for serializing access to break control structures.
- Mutex* break_access() { return &break_access_; }
+ Mutex* break_access() { return break_access_; }
// Mutex for serializing access to debugger.
- Mutex* debugger_access() { return &debugger_access_; }
+ Mutex* debugger_access() { return debugger_access_; }
Address get_address_from_id(AddressId id);
// This mutex protects highest_thread_id_, thread_data_table_ and
// default_isolate_.
- static Mutex process_wide_mutex_;
+ static Mutex* process_wide_mutex_;
static Thread::LocalStorageKey per_isolate_thread_data_key_;
static Thread::LocalStorageKey isolate_key_;
CompilationCache* compilation_cache_;
Counters* counters_;
CodeRange* code_range_;
- Mutex break_access_;
+ Mutex* break_access_;
Atomic32 debugger_initialized_;
- Mutex debugger_access_;
+ Mutex* debugger_access_;
Logger* logger_;
StackGuard stack_guard_;
StatsTable* stats_table_;
}
~ExecutionAccess() { Unlock(isolate_); }
- static void Lock(Isolate* isolate) { isolate->break_access()->Lock(); }
- static void Unlock(Isolate* isolate) { isolate->break_access()->Unlock(); }
+ static void Lock(Isolate* isolate) { isolate->break_access_->Lock(); }
+ static void Unlock(Isolate* isolate) { isolate->break_access_->Unlock(); }
static bool TryLock(Isolate* isolate) {
- return isolate->break_access()->TryLock();
+ return isolate->break_access_->TryLock();
}
private:
void Log::Initialize(const char* log_file_name) {
- mutex_ = new Mutex;
+ mutex_ = OS::CreateMutex();
message_buffer_ = NewArray<char>(kMessageBufferSize);
// --log-all enables all the log flags.
+++ /dev/null
-// Copyright 2013 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following
-// disclaimer in the documentation and/or other materials provided
-// with the distribution.
-// * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "mutex.h"
-
-#include <errno.h>
-
-#include "checks.h"
-
-namespace v8 {
-namespace internal {
-
-#if V8_OS_UNIX
-
-Mutex::Mutex() {
- pthread_mutexattr_t attr;
- int result = pthread_mutexattr_init(&attr);
- ASSERT_EQ(0, result);
- result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- ASSERT_EQ(0, result);
- result = pthread_mutex_init(&mutex_, &attr);
- ASSERT_EQ(0, result);
- result = pthread_mutexattr_destroy(&attr);
- ASSERT_EQ(0, result);
- USE(result);
-}
-
-
-Mutex::~Mutex() {
- pthread_mutex_destroy(&mutex_);
-}
-
-
-void Mutex::Lock() {
- int result = pthread_mutex_lock(&mutex_);
- ASSERT_EQ(0, result);
- USE(result);
-}
-
-
-void Mutex::Unlock() {
- int result = pthread_mutex_unlock(&mutex_);
- ASSERT_EQ(0, result);
- USE(result);
-}
-
-
-bool Mutex::TryLock() {
- int result = pthread_mutex_trylock(&mutex_);
- // Return false if the lock is busy and locking failed.
- if (result == EBUSY) {
- return false;
- }
- ASSERT_EQ(0, result);
- return true;
-}
-
-#elif V8_OS_WIN32
-
-Mutex::Mutex() {
- InitializeCriticalSection(&cs_);
-}
-
-
-Mutex::~Mutex() {
- DeleteCriticalSection(&cs_);
-}
-
-
-void Mutex::Lock() {
- EnterCriticalSection(&cs_);
-}
-
-
-void Mutex::Unlock() {
- LeaveCriticalSection(&cs_);
-}
-
-
-bool Mutex::TryLock() {
- return TryEnterCriticalSection(&cs_);
-}
-
-#endif // V8_OS_WIN32
-
-} } // namespace v8::internal
+++ /dev/null
-// Copyright 2013 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_MUTEX_H_
-#define V8_MUTEX_H_
-
-#include "globals.h"
-
-#if V8_OS_UNIX
-#include <pthread.h> // NOLINT
-#elif V8_OS_WIN32
-#include "win32-headers.h"
-#endif
-
-#include "checks.h"
-#include "lazy-instance.h"
-
-namespace v8 {
-namespace internal {
-
-// ----------------------------------------------------------------------------
-// Mutex
-//
-// Mutexes are used for serializing access to non-reentrant sections of code.
-// The implementations of mutex should allow for nested/recursive locking.
-//
-class Mutex {
- public:
- Mutex();
- ~Mutex();
-
- // Locks the given mutex. If the mutex is currently unlocked, it becomes
- // locked and owned by the calling thread. If the mutex is already locked
- // by another thread, suspends the calling thread until the mutex is
- // unlocked.
- void Lock();
-
- // Unlocks the given mutex. The mutex is assumed to be locked and owned
- // by the calling thread on entrance.
- void Unlock();
-
- // Tries to lock the given mutex. Returns true if the mutex was locked
- // successfully.
- bool TryLock();
-
- private:
-#if V8_OS_UNIX
- pthread_mutex_t mutex_;
-#elif V8_OS_WIN32
- CRITICAL_SECTION cs_;
-#endif
-
- DISALLOW_COPY_AND_ASSIGN(Mutex);
-};
-
-
-// ----------------------------------------------------------------------------
-// LazyMutex
-//
-// POD Mutex initialized lazily (i.e. the first time Pointer() is called).
-// Usage:
-// static LazyMutex my_mutex = LAZY_MUTEX_INITIALIZER;
-//
-// void my_function() {
-// ScopedLock my_lock(&my_mutex);
-// // Do something.
-// }
-//
-typedef LazyDynamicInstance<Mutex,
- DefaultCreateTrait<Mutex>,
- ThreadSafeInitOnceTrait>::type LazyMutex;
-
-#define LAZY_MUTEX_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
-
-
-// ----------------------------------------------------------------------------
-// ScopedLock
-//
-// Stack-allocated ScopedLocks provide block-scoped locking and
-// unlocking of a mutex.
-//
-class ScopedLock {
- public:
- explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
- ASSERT(mutex_ != NULL);
- mutex_->Lock();
- }
-
- explicit ScopedLock(LazyMutex* lazy_mutex) : mutex_(lazy_mutex->Pointer()) {
- ASSERT(mutex_ != NULL);
- mutex_->Lock();
- }
-
- ~ScopedLock() {
- mutex_->Unlock();
- }
-
- private:
- Mutex* mutex_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedLock);
-};
-
-} } // namespace v8::internal
-
-#endif // V8_MUTEX_H_
void OptimizingCompilerThread::Run() {
#ifdef DEBUG
- { ScopedLock lock(&thread_id_mutex_);
+ { ScopedLock lock(thread_id_mutex_);
thread_id_ = ThreadId::Current().ToInteger();
}
#endif
// The function may have already been optimized by OSR. Simply continue.
// Use a mutex to make sure that functions marked for install
// are always also queued.
- ScopedLock mark_and_queue(&install_mutex_);
+ ScopedLock mark_and_queue(install_mutex_);
{ Heap::RelocationLock relocation_lock(isolate_->heap());
AllowHandleDereference ahd;
optimizing_compiler->info()->closure()->MarkForInstallingRecompiledCode();
OptimizingCompiler* compiler;
while (true) {
{ // Memory barrier to ensure marked functions are queued.
- ScopedLock marked_and_queued(&install_mutex_);
+ ScopedLock marked_and_queued(install_mutex_);
if (!output_queue_.Dequeue(&compiler)) return;
}
Compiler::InstallOptimizedCode(compiler);
#ifdef DEBUG
bool OptimizingCompilerThread::IsOptimizerThread() {
if (!FLAG_parallel_recompilation) return false;
- ScopedLock lock(&thread_id_mutex_);
+ ScopedLock lock(thread_id_mutex_);
return ThreadId::Current().ToInteger() == thread_id_;
}
#endif
Thread("OptimizingCompilerThread"),
#ifdef DEBUG
thread_id_(0),
+ thread_id_mutex_(OS::CreateMutex()),
#endif
isolate_(isolate),
stop_semaphore_(OS::CreateSemaphore(0)),
input_queue_semaphore_(OS::CreateSemaphore(0)),
+ install_mutex_(OS::CreateMutex()),
time_spent_compiling_(0),
time_spent_total_(0) {
NoBarrier_Store(&stop_thread_, static_cast<AtomicWord>(false));
#endif
~OptimizingCompilerThread() {
+ delete install_mutex_;
delete input_queue_semaphore_;
delete stop_semaphore_;
+#ifdef DEBUG
+ delete thread_id_mutex_;
+#endif
}
private:
#ifdef DEBUG
int thread_id_;
- Mutex thread_id_mutex_;
+ Mutex* thread_id_mutex_;
#endif
Isolate* isolate_;
Semaphore* input_queue_semaphore_;
UnboundQueue<OptimizingCompiler*> input_queue_;
UnboundQueue<OptimizingCompiler*> output_queue_;
- Mutex install_mutex_;
+ Mutex* install_mutex_;
volatile AtomicWord stop_thread_;
volatile Atomic32 queue_length_;
int64_t time_spent_compiling_;
// call this setup code within the same millisecond.
uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
srandom(static_cast<unsigned int>(seed));
- limit_mutex = new Mutex;
+ limit_mutex = CreateMutex();
}
// call this setup code within the same millisecond.
uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
srandom(static_cast<unsigned int>(seed));
- limit_mutex = new Mutex;
+ limit_mutex = CreateMutex();
}
// Seed the random number generator. We preserve microsecond resolution.
uint64_t seed = Ticks() ^ (getpid() << 16);
srandom(static_cast<unsigned int>(seed));
- limit_mutex = new Mutex;
+ limit_mutex = CreateMutex();
}
// Seed the random number generator. We preserve microsecond resolution.
uint64_t seed = Ticks() ^ (getpid() << 16);
srandom(static_cast<unsigned int>(seed));
- limit_mutex = new Mutex;
+ limit_mutex = CreateMutex();
}
}
+class NullMutex : public Mutex {
+ public:
+ NullMutex() : data_(NULL) {
+ UNIMPLEMENTED();
+ }
+
+ virtual ~NullMutex() {
+ UNIMPLEMENTED();
+ }
+
+ virtual int Lock() {
+ UNIMPLEMENTED();
+ return 0;
+ }
+
+ virtual int Unlock() {
+ UNIMPLEMENTED();
+ return 0;
+ }
+
+ private:
+ void* data_;
+};
+
+
+Mutex* OS::CreateMutex() {
+ UNIMPLEMENTED();
+ return new NullMutex();
+}
+
+
class NullSemaphore : public Semaphore {
public:
explicit NullSemaphore(int count) : data_(NULL) {
// Seed the random number generator. We preserve microsecond resolution.
uint64_t seed = Ticks() ^ (getpid() << 16);
srandom(static_cast<unsigned int>(seed));
- limit_mutex = new Mutex;
+ limit_mutex = CreateMutex();
}
}
+class POSIXMutex : public Mutex {
+ public:
+ POSIXMutex() {
+ pthread_mutexattr_t attr;
+ memset(&attr, 0, sizeof(attr));
+ int result = pthread_mutexattr_init(&attr);
+ ASSERT(result == 0);
+ result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ ASSERT(result == 0);
+ result = pthread_mutex_init(&mutex_, &attr);
+ ASSERT(result == 0);
+ result = pthread_mutexattr_destroy(&attr);
+ ASSERT(result == 0);
+ USE(result);
+ }
+
+ virtual ~POSIXMutex() { pthread_mutex_destroy(&mutex_); }
+
+ virtual int Lock() { return pthread_mutex_lock(&mutex_); }
+
+ virtual int Unlock() { return pthread_mutex_unlock(&mutex_); }
+
+ virtual bool TryLock() {
+ int result = pthread_mutex_trylock(&mutex_);
+ // Return false if the lock is busy and locking failed.
+ if (result == EBUSY) {
+ return false;
+ }
+ ASSERT(result == 0); // Verify no other errors.
+ return true;
+ }
+
+ private:
+ pthread_mutex_t mutex_; // Pthread mutex for POSIX platforms.
+};
+
+
+Mutex* OS::CreateMutex() {
+ return new POSIXMutex();
+}
+
+
// ----------------------------------------------------------------------------
// POSIX socket support.
//
// call this setup code within the same millisecond.
uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
srandom(static_cast<unsigned int>(seed));
- limit_mutex = new Mutex;
+ limit_mutex = CreateMutex();
}
// ----------------------------------------------------------------------------
+// Win32 mutex support.
+//
+// On Win32 mutexes are implemented using CRITICAL_SECTION objects. These are
+// faster than Win32 Mutex objects because they are implemented using user mode
+// atomic instructions. Therefore we only do ring transitions if there is lock
+// contention.
+
+class Win32Mutex : public Mutex {
+ public:
+ Win32Mutex() { InitializeCriticalSection(&cs_); }
+
+ virtual ~Win32Mutex() { DeleteCriticalSection(&cs_); }
+
+ virtual int Lock() {
+ EnterCriticalSection(&cs_);
+ return 0;
+ }
+
+ virtual int Unlock() {
+ LeaveCriticalSection(&cs_);
+ return 0;
+ }
+
+
+ virtual bool TryLock() {
+ // Returns non-zero if critical section is entered successfully entered.
+ return TryEnterCriticalSection(&cs_);
+ }
+
+ private:
+ CRITICAL_SECTION cs_; // Critical section used for mutex
+};
+
+
+Mutex* OS::CreateMutex() {
+ return new Win32Mutex();
+}
+
+
+// ----------------------------------------------------------------------------
// Win32 semaphore support.
//
// On Win32 semaphores are implemented using Win32 Semaphore objects. The
// call this setup code within the same millisecond.
uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
srand(static_cast<unsigned int>(seed));
- limit_mutex = new Mutex;
+ limit_mutex = CreateMutex();
}
#endif // WIN32
-#include "mutex.h"
+#include "lazy-instance.h"
#include "utils.h"
#include "v8globals.h"
static int StackWalk(Vector<StackFrame> frames);
+ // Factory method for creating platform dependent Mutex.
+ // Please use delete to reclaim the storage for the returned Mutex.
+ static Mutex* CreateMutex();
+
// Factory method for creating platform dependent Semaphore.
// Please use delete to reclaim the storage for the returned Semaphore.
static Semaphore* CreateSemaphore(int count);
// ----------------------------------------------------------------------------
+// Mutex
+//
+// Mutexes are used for serializing access to non-reentrant sections of code.
+// The implementations of mutex should allow for nested/recursive locking.
+
+class Mutex {
+ public:
+ virtual ~Mutex() {}
+
+ // Locks the given mutex. If the mutex is currently unlocked, it becomes
+ // locked and owned by the calling thread, and immediately. If the mutex
+ // is already locked by another thread, suspends the calling thread until
+ // the mutex is unlocked.
+ virtual int Lock() = 0;
+
+ // Unlocks the given mutex. The mutex is assumed to be locked and owned by
+ // the calling thread on entrance.
+ virtual int Unlock() = 0;
+
+ // Tries to lock the given mutex. Returns whether the mutex was
+ // successfully locked.
+ virtual bool TryLock() = 0;
+};
+
+struct CreateMutexTrait {
+ static Mutex* Create() {
+ return OS::CreateMutex();
+ }
+};
+
+// POD Mutex initialized lazily (i.e. the first time Pointer() is called).
+// Usage:
+// static LazyMutex my_mutex = LAZY_MUTEX_INITIALIZER;
+//
+// void my_function() {
+// ScopedLock my_lock(my_mutex.Pointer());
+// // Do something.
+// }
+//
+typedef LazyDynamicInstance<
+ Mutex, CreateMutexTrait, ThreadSafeInitOnceTrait>::type LazyMutex;
+
+#define LAZY_MUTEX_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
+
+// ----------------------------------------------------------------------------
+// ScopedLock
+//
+// Stack-allocated ScopedLocks provide block-scoped locking and
+// unlocking of a mutex.
+class ScopedLock {
+ public:
+ explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
+ ASSERT(mutex_ != NULL);
+ mutex_->Lock();
+ }
+ ~ScopedLock() {
+ mutex_->Unlock();
+ }
+
+ private:
+ Mutex* mutex_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedLock);
+};
+
+
+// ----------------------------------------------------------------------------
// Socket
//
: Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)),
interval_(interval) {}
- static void SetUp() { if (!mutex_) mutex_ = new Mutex; }
+ static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
static void TearDown() { delete mutex_; }
static void AddActiveSampler(Sampler* sampler) {
// This is safe (not going to deadlock) since Concatenate operations
// are never performed on the same free lists at the same time in
// reverse order.
- ScopedLock lock_target(mutex());
+ ScopedLock lock_target(mutex_);
ScopedLock lock_source(category->mutex());
free_bytes = category->available();
if (end_ == NULL) {
FreeListCategory() :
top_(NULL),
end_(NULL),
+ mutex_(OS::CreateMutex()),
available_(0) {}
- ~FreeListCategory() {}
+ ~FreeListCategory() {
+ delete mutex_;
+ }
intptr_t Concatenate(FreeListCategory* category);
int available() const { return available_; }
void set_available(int available) { available_ = available; }
- Mutex* mutex() { return &mutex_; }
+ Mutex* mutex() { return mutex_; }
#ifdef DEBUG
intptr_t SumFreeList();
private:
FreeListNode* top_;
FreeListNode* end_;
- Mutex mutex_;
+ Mutex* mutex_;
// Total available bytes in all blocks of this free list category.
int available_;
void ThreadManager::Lock() {
- mutex_.Lock();
+ mutex_->Lock();
mutex_owner_ = ThreadId::Current();
ASSERT(IsLockedByCurrentThread());
}
void ThreadManager::Unlock() {
mutex_owner_ = ThreadId::Invalid();
- mutex_.Unlock();
+ mutex_->Unlock();
}
// be distinguished from not having a thread id at all (since NULL is
// defined as 0.)
ThreadManager::ThreadManager()
- : mutex_owner_(ThreadId::Invalid()),
+ : mutex_(OS::CreateMutex()),
+ mutex_owner_(ThreadId::Invalid()),
lazily_archived_thread_(ThreadId::Invalid()),
lazily_archived_thread_state_(NULL),
free_anchor_(NULL),
ThreadManager::~ThreadManager() {
+ delete mutex_;
DeleteThreadStateList(free_anchor_);
DeleteThreadStateList(in_use_anchor_);
}
void EagerlyArchiveThread();
- Mutex mutex_;
+ Mutex* mutex_;
ThreadId mutex_owner_;
ThreadId lazily_archived_thread_;
ThreadState* lazily_archived_thread_state_;
#undef ANY
#undef IGNORE
#undef GetObject
+#undef CreateMutex
#undef CreateSemaphore
'test-heap-profiler.cc',
'test-list.cc',
'test-liveedit.cc',
+ 'test-lock.cc',
'test-lockers.cc',
'test-log.cc',
'test-mark-compact.cc',
- 'test-mutex.cc',
'test-object-observe.cc',
'test-parsing.cc',
'test-platform.cc',
'test-random.cc',
'test-regexp.cc',
'test-reloc-info.cc',
- 'test-semaphore.cc',
'test-serialize.cc',
'test-sockets.cc',
'test-spaces.cc',
ThreadBarrier::ThreadBarrier(int num_threads)
: num_threads_(num_threads), num_blocked_(0) {
- lock_ = new v8::internal::Mutex;
+ lock_ = OS::CreateMutex();
sem_ = OS::CreateSemaphore(0);
invalid_ = false; // A barrier may only be used once. Then it is invalid.
}
-// Copyright 2006-2013 the V8 project authors. All rights reserved.
+// Copyright 2006-2008 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:
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
-// Tests of the Semaphore class from platform.h
+// Tests of the TokenLock class from lock.h
+
+#include <stdlib.h>
#include "v8.h"
using namespace ::v8::internal;
+// Simple test of locking logic
+TEST(Simple) {
+ Mutex* mutex = OS::CreateMutex();
+ CHECK_EQ(0, mutex->Lock()); // acquire the lock with the right token
+ CHECK_EQ(0, mutex->Unlock()); // can unlock with the right token
+ delete mutex;
+}
+
+
+TEST(MultiLock) {
+ Mutex* mutex = OS::CreateMutex();
+ CHECK_EQ(0, mutex->Lock());
+ CHECK_EQ(0, mutex->Unlock());
+ delete mutex;
+}
+
+
+TEST(ShallowLock) {
+ Mutex* mutex = OS::CreateMutex();
+ CHECK_EQ(0, mutex->Lock());
+ CHECK_EQ(0, mutex->Unlock());
+ CHECK_EQ(0, mutex->Lock());
+ CHECK_EQ(0, mutex->Unlock());
+ delete mutex;
+}
+
+
TEST(SemaphoreTimeout) {
bool ok;
Semaphore* sem = OS::CreateSemaphore(0);
+++ /dev/null
-// Copyright 2006-2013 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.
-//
-// Tests of the Mutex class from mutex.h
-
-#include "v8.h"
-
-#include "mutex.h"
-#include "cctest.h"
-
-
-using namespace ::v8::internal;
-
-
-TEST(Simple) {
- Mutex mutex;
- mutex.Lock();
- mutex.Unlock();
-}
-
-
-TEST(Recursive) {
- Mutex mutex;
- mutex.Lock();
- mutex.Lock();
- mutex.Unlock();
- mutex.Unlock();
-}
-
-
-TEST(SimpleScopedLock) {
- Mutex mutex;
- {
- ScopedLock fst(&mutex);
- }
- {
- ScopedLock snd(&mutex);
- }
-}
-
-
-TEST(RecursiveScopedLock) {
- Mutex mutex;
- ScopedLock fst(&mutex);
- ScopedLock snd(&mutex);
-}
int count = 0;
int last_count = -1;
do {
- mutex->Lock();
+ CHECK_EQ(0, mutex->Lock());
count = busy_lock_counter;
- mutex->Unlock();
+ CHECK_EQ(0, mutex->Unlock());
yield();
} while (count % 2 == rem && count < kLockCounterLimit);
if (count >= kLockCounterLimit) break;
- mutex->Lock();
+ CHECK_EQ(0, mutex->Lock());
CHECK_EQ(count, busy_lock_counter);
CHECK(last_count == -1 || count == last_count + 1);
busy_lock_counter++;
last_count = count;
- mutex->Unlock();
+ CHECK_EQ(0, mutex->Unlock());
yield();
}
}
// increment a variable.
TEST(BusyLock) {
pthread_t other;
- Mutex mutex;
+ Mutex* mutex = OS::CreateMutex();
int thread_created = pthread_create(&other,
NULL,
&RunTestBusyLock,
- &mutex);
+ mutex);
CHECK_EQ(0, thread_created);
- LoopIncrement(&mutex, 1);
+ LoopIncrement(mutex, 1);
pthread_join(other, NULL);
+ delete mutex;
}
int count = 0;
int last_count = -1;
do {
- mutex->Lock();
+ CHECK_EQ(0, mutex->Lock());
count = busy_lock_counter;
- mutex->Unlock();
+ CHECK_EQ(0, mutex->Unlock());
yield();
} while (count % 2 == rem && count < kLockCounterLimit);
if (count >= kLockCounterLimit) break;
- mutex->Lock();
+ CHECK_EQ(0, mutex->Lock());
CHECK_EQ(count, busy_lock_counter);
CHECK(last_count == -1 || count == last_count + 1);
busy_lock_counter++;
last_count = count;
- mutex->Unlock();
+ CHECK_EQ(0, mutex->Unlock());
yield();
}
}
'../../src/marking-thread.cc',
'../../src/messages.cc',
'../../src/messages.h',
- '../../src/mutex.cc',
- '../../src/mutex.h',
'../../src/natives.h',
'../../src/objects-debug.cc',
'../../src/objects-inl.h',