diff options
Diffstat (limited to 'deps/v8/src/platform-win32.cc')
-rw-r--r-- | deps/v8/src/platform-win32.cc | 198 |
1 files changed, 75 insertions, 123 deletions
diff --git a/deps/v8/src/platform-win32.cc b/deps/v8/src/platform-win32.cc index c50424e57a4..badc31beb3d 100644 --- a/deps/v8/src/platform-win32.cc +++ b/deps/v8/src/platform-win32.cc @@ -26,70 +26,14 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Platform specific code for Win32. -#ifndef WIN32_LEAN_AND_MEAN -// WIN32_LEAN_AND_MEAN implies NOCRYPT and NOGDI. -#define WIN32_LEAN_AND_MEAN -#endif -#ifndef NOMINMAX -#define NOMINMAX -#endif -#ifndef NOKERNEL -#define NOKERNEL -#endif -#ifndef NOUSER -#define NOUSER -#endif -#ifndef NOSERVICE -#define NOSERVICE -#endif -#ifndef NOSOUND -#define NOSOUND -#endif -#ifndef NOMCX -#define NOMCX -#endif -// Require Windows XP or higher (this is required for the RtlCaptureContext -// function to be present). -#ifndef _WIN32_WINNT -#define _WIN32_WINNT 0x501 -#endif -#include <windows.h> - -#include <time.h> // For LocalOffset() implementation. -#include <mmsystem.h> // For timeGetTime(). -#ifdef __MINGW32__ -// Require Windows XP or higher when compiling with MinGW. This is for MinGW -// header files to expose getaddrinfo. -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x501 -#endif // __MINGW32__ -#ifndef __MINGW32__ -#include <dbghelp.h> // For SymLoadModule64 and al. -#endif // __MINGW32__ -#include <limits.h> // For INT_MAX and al. -#include <tlhelp32.h> // For Module32First and al. - -// These additional WIN32 includes have to be right here as the #undef's below -// makes it impossible to have them elsewhere. -#include <winsock2.h> -#include <ws2tcpip.h> -#include <process.h> // for _beginthreadex() -#include <stdlib.h> - -#undef VOID -#undef DELETE -#undef IN -#undef THIS -#undef CONST -#undef NAN -#undef GetObject -#undef CreateMutex -#undef CreateSemaphore +#define V8_WIN32_HEADERS_FULL +#include "win32-headers.h" #include "v8.h" #include "platform.h" +#include "vm-state-inl.h" // Extra POSIX/ANSI routines for Win32 when when using Visual Studio C++. Please // refer to The Open Group Base Specification for specification of the correct @@ -207,6 +151,12 @@ int strncpy_s(char* strDest, size_t numberOfElements, return 0; } + +inline void MemoryBarrier() { + int barrier = 0; + __asm__ __volatile__("xchgl %%eax,%0 ":"=r" (barrier)); +} + #endif // __MINGW32__ // Generate a pseudo-random number in the range 0-2^31-1. Usually @@ -858,13 +808,14 @@ void* OS::Allocate(const size_t requested, // VirtualAlloc rounds allocated size to page size automatically. size_t msize = RoundUp(requested, static_cast<int>(GetPageSize())); - intptr_t address = NULL; + intptr_t address = 0; // Windows XP SP2 allows Data Excution Prevention (DEP). int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; // For exectutable pages try and randomize the allocation address - if (prot == PAGE_EXECUTE_READWRITE && msize >= Page::kPageSize) { + if (prot == PAGE_EXECUTE_READWRITE && + msize >= static_cast<size_t>(Page::kPageSize)) { address = (V8::RandomPrivate() << kPageSizeBits) | kAllocationRandomAddressMin; address &= kAllocationRandomAddressMax; @@ -874,7 +825,7 @@ void* OS::Allocate(const size_t requested, msize, MEM_COMMIT | MEM_RESERVE, prot); - if (mbase == NULL && address != NULL) + if (mbase == NULL && address != 0) mbase = VirtualAlloc(NULL, msize, MEM_COMMIT | MEM_RESERVE, prot); if (mbase == NULL) { @@ -1155,7 +1106,7 @@ static bool LoadSymbols(HANDLE process_handle) { // Initialize the symbol engine. ok = _SymInitialize(process_handle, // hProcess NULL, // UserSearchPath - FALSE); // fInvadeProcess + false); // fInvadeProcess if (!ok) return false; DWORD options = _SymGetOptions(); @@ -1347,6 +1298,7 @@ int OS::StackWalk(Vector<OS::StackFrame> frames) { #else // __MINGW32__ void OS::LogSharedLibraryAddresses() { } +void OS::SignalCodeMovingGC() { } int OS::StackWalk(Vector<OS::StackFrame> frames) { return 0; } #endif // __MINGW32__ @@ -1414,7 +1366,7 @@ bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { bool VirtualMemory::Uncommit(void* address, size_t size) { ASSERT(IsReserved()); - return VirtualFree(address, size, MEM_DECOMMIT) != FALSE; + return VirtualFree(address, size, MEM_DECOMMIT) != false; } @@ -1574,18 +1526,24 @@ class Win32Mutex : public Mutex { Win32Mutex() { InitializeCriticalSection(&cs_); } - ~Win32Mutex() { DeleteCriticalSection(&cs_); } + virtual ~Win32Mutex() { DeleteCriticalSection(&cs_); } - int Lock() { + virtual int Lock() { EnterCriticalSection(&cs_); return 0; } - int Unlock() { + 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 }; @@ -1768,7 +1726,7 @@ int Win32Socket::Receive(char* data, int len) const { bool Win32Socket::SetReuseAddress(bool reuse_address) { - BOOL on = reuse_address ? TRUE : FALSE; + BOOL on = reuse_address ? true : false; int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&on), sizeof(on)); return status == SOCKET_ERROR; @@ -1838,53 +1796,48 @@ class Sampler::PlatformData : public Malloced { Sampler* sampler_; HANDLE sampler_thread_; HANDLE profiled_thread_; + RuntimeProfilerRateLimiter rate_limiter_; // Sampler thread handler. void Runner() { - // Context used for sampling the register state of the profiled thread. - CONTEXT context; - memset(&context, 0, sizeof(context)); - // Loop until the sampler is disengaged, keeping the specified - // sampling frequency. - for ( ; sampler_->IsActive(); Sleep(sampler_->interval_)) { + while (sampler_->IsActive()) { + if (rate_limiter_.SuspendIfNecessary()) continue; + Sample(); + Sleep(sampler_->interval_); + } + } + + void Sample() { + if (sampler_->IsProfiling()) { + // Context used for sampling the register state of the profiled thread. + CONTEXT context; + memset(&context, 0, sizeof(context)); + TickSample sample_obj; TickSample* sample = CpuProfiler::TickSampleEvent(); if (sample == NULL) sample = &sample_obj; - // If the sampler runs in sync with the JS thread, we try to - // suspend it. If we fail, we skip the current sample. - if (sampler_->IsSynchronous()) { - static const DWORD kSuspendFailed = static_cast<DWORD>(-1); - if (SuspendThread(profiled_thread_) == kSuspendFailed) continue; - } - - // We always sample the VM state. - sample->state = VMState::current_state(); + static const DWORD kSuspendFailed = static_cast<DWORD>(-1); + if (SuspendThread(profiled_thread_) == kSuspendFailed) return; + sample->state = Top::current_vm_state(); - // If profiling, we record the pc and sp of the profiled thread. - if (sampler_->IsProfiling()) { - context.ContextFlags = CONTEXT_FULL; - if (GetThreadContext(profiled_thread_, &context) != 0) { + context.ContextFlags = CONTEXT_FULL; + if (GetThreadContext(profiled_thread_, &context) != 0) { #if V8_HOST_ARCH_X64 - sample->pc = reinterpret_cast<Address>(context.Rip); - sample->sp = reinterpret_cast<Address>(context.Rsp); - sample->fp = reinterpret_cast<Address>(context.Rbp); + sample->pc = reinterpret_cast<Address>(context.Rip); + sample->sp = reinterpret_cast<Address>(context.Rsp); + sample->fp = reinterpret_cast<Address>(context.Rbp); #else - sample->pc = reinterpret_cast<Address>(context.Eip); - sample->sp = reinterpret_cast<Address>(context.Esp); - sample->fp = reinterpret_cast<Address>(context.Ebp); + sample->pc = reinterpret_cast<Address>(context.Eip); + sample->sp = reinterpret_cast<Address>(context.Esp); + sample->fp = reinterpret_cast<Address>(context.Ebp); #endif - sampler_->SampleStack(sample); - } + sampler_->SampleStack(sample); + sampler_->Tick(sample); } - - // Invoke tick handler with program counter and stack pointer. - sampler_->Tick(sample); - - // If the sampler runs in sync with the JS thread, we have to - // remember to resume it. - if (sampler_->IsSynchronous()) ResumeThread(profiled_thread_); + ResumeThread(profiled_thread_); } + if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick(); } }; @@ -1899,10 +1852,9 @@ static unsigned int __stdcall SamplerEntry(void* arg) { // Initialize a profile sampler. -Sampler::Sampler(int interval, bool profiling) +Sampler::Sampler(int interval) : interval_(interval), - profiling_(profiling), - synchronous_(profiling), + profiling_(false), active_(false), samples_taken_(0) { data_ = new PlatformData(this); @@ -1916,26 +1868,25 @@ Sampler::~Sampler() { // Start profiling. void Sampler::Start() { - // If we are starting a synchronous sampler, we need to be able to - // access the calling thread. - if (IsSynchronous()) { - // Get a handle to the calling thread. This is the thread that we are - // going to profile. We need to make a copy of the handle because we are - // going to use it in the sampler thread. Using GetThreadHandle() will - // not work in this case. We're using OpenThread because DuplicateHandle - // for some reason doesn't work in Chrome's sandbox. - data_->profiled_thread_ = OpenThread(THREAD_GET_CONTEXT | - THREAD_SUSPEND_RESUME | - THREAD_QUERY_INFORMATION, - FALSE, - GetCurrentThreadId()); - BOOL ok = data_->profiled_thread_ != NULL; - if (!ok) return; - } + // Do not start multiple threads for the same sampler. + ASSERT(!IsActive()); + + // Get a handle to the calling thread. This is the thread that we are + // going to profile. We need to make a copy of the handle because we are + // going to use it in the sampler thread. Using GetThreadHandle() will + // not work in this case. We're using OpenThread because DuplicateHandle + // for some reason doesn't work in Chrome's sandbox. + data_->profiled_thread_ = OpenThread(THREAD_GET_CONTEXT | + THREAD_SUSPEND_RESUME | + THREAD_QUERY_INFORMATION, + false, + GetCurrentThreadId()); + BOOL ok = data_->profiled_thread_ != NULL; + if (!ok) return; // Start sampler thread. unsigned int tid; - active_ = true; + SetActive(true); data_->sampler_thread_ = reinterpret_cast<HANDLE>( _beginthreadex(NULL, 0, SamplerEntry, data_, 0, &tid)); // Set thread to high priority to increase sampling accuracy. @@ -1947,9 +1898,10 @@ void Sampler::Start() { void Sampler::Stop() { // Seting active to false triggers termination of the sampler // thread. - active_ = false; + SetActive(false); // Wait for sampler thread to terminate. + Top::WakeUpRuntimeProfilerThreadBeforeShutdown(); WaitForSingleObject(data_->sampler_thread_, INFINITE); // Release the thread handles |