diff options
Diffstat (limited to 'deps/v8/src/platform-win32.cc')
-rw-r--r-- | deps/v8/src/platform-win32.cc | 495 |
1 files changed, 37 insertions, 458 deletions
diff --git a/deps/v8/src/platform-win32.cc b/deps/v8/src/platform-win32.cc index 292c24a3d..ea4f7ea11 100644 --- a/deps/v8/src/platform-win32.cc +++ b/deps/v8/src/platform-win32.cc @@ -38,12 +38,12 @@ #endif // MINGW_HAS_SECURE_API #endif // __MINGW32__ -#define V8_WIN32_HEADERS_FULL #include "win32-headers.h" #include "v8.h" #include "codegen.h" +#include "isolate-inl.h" #include "platform.h" #include "simulator.h" #include "vm-state-inl.h" @@ -125,13 +125,6 @@ int strncpy_s(char* dest, size_t dest_size, const char* source, size_t count) { #endif // __MINGW32__ -// Generate a pseudo-random number in the range 0-2^31-1. Usually -// defined in stdlib.h. Missing in both Microsoft Visual Studio C++ and MinGW. -int random() { - return rand(); -} - - namespace v8 { namespace internal { @@ -145,8 +138,6 @@ double ceiling(double x) { } -static Mutex* limit_mutex = NULL; - #if V8_TARGET_ARCH_IA32 static void MemMoveWrapper(void* dest, const void* src, size_t size) { memmove(dest, src, size); @@ -246,19 +237,15 @@ void MathSetup() { // timestamps are represented as a doubles in milliseconds since 00:00:00 UTC, // January 1, 1970. -class Time { +class Win32Time { public: // Constructors. - Time(); - explicit Time(double jstime); - Time(int year, int mon, int day, int hour, int min, int sec); + explicit Win32Time(double jstime); + Win32Time(int year, int mon, int day, int hour, int min, int sec); // Convert timestamp to JavaScript representation. double ToJSTime(); - // Set timestamp to current time. - void SetToCurrentTime(); - // Returns the local timezone offset in milliseconds east of UTC. This is // the number of milliseconds you must add to UTC to get local time, i.e. // LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This @@ -300,10 +287,6 @@ class Time { // Return whether or not daylight savings time is in effect at this time. bool InDST(); - // Return the difference (in milliseconds) between this timestamp and - // another timestamp. - int64_t Diff(Time* other); - // Accessor for FILETIME representation. FILETIME& ft() { return time_.ft_; } @@ -325,26 +308,20 @@ class Time { // Static variables. -bool Time::tz_initialized_ = false; -TIME_ZONE_INFORMATION Time::tzinfo_; -char Time::std_tz_name_[kTzNameSize]; -char Time::dst_tz_name_[kTzNameSize]; - - -// Initialize timestamp to start of epoc. -Time::Time() { - t() = 0; -} +bool Win32Time::tz_initialized_ = false; +TIME_ZONE_INFORMATION Win32Time::tzinfo_; +char Win32Time::std_tz_name_[kTzNameSize]; +char Win32Time::dst_tz_name_[kTzNameSize]; // Initialize timestamp from a JavaScript timestamp. -Time::Time(double jstime) { +Win32Time::Win32Time(double jstime) { t() = static_cast<int64_t>(jstime) * kTimeScaler + kTimeEpoc; } // Initialize timestamp from date/time components. -Time::Time(int year, int mon, int day, int hour, int min, int sec) { +Win32Time::Win32Time(int year, int mon, int day, int hour, int min, int sec) { SYSTEMTIME st; st.wYear = year; st.wMonth = mon; @@ -358,14 +335,14 @@ Time::Time(int year, int mon, int day, int hour, int min, int sec) { // Convert timestamp to JavaScript timestamp. -double Time::ToJSTime() { +double Win32Time::ToJSTime() { return static_cast<double>((t() - kTimeEpoc) / kTimeScaler); } // Guess the name of the timezone from the bias. // The guess is very biased towards the northern hemisphere. -const char* Time::GuessTimezoneNameFromBias(int bias) { +const char* Win32Time::GuessTimezoneNameFromBias(int bias) { static const int kHour = 60; switch (-bias) { case -9*kHour: return "Alaska"; @@ -390,7 +367,7 @@ const char* Time::GuessTimezoneNameFromBias(int bias) { // Initialize timezone information. The timezone information is obtained from // windows. If we cannot get the timezone information we fall back to CET. // Please notice that this code is not thread-safe. -void Time::TzSet() { +void Win32Time::TzSet() { // Just return if timezone information has already been initialized. if (tz_initialized_) return; @@ -439,78 +416,16 @@ void Time::TzSet() { } -// Return the difference in milliseconds between this and another timestamp. -int64_t Time::Diff(Time* other) { - return (t() - other->t()) / kTimeScaler; -} - - -// Set timestamp to current time. -void Time::SetToCurrentTime() { - // The default GetSystemTimeAsFileTime has a ~15.5ms resolution. - // Because we're fast, we like fast timers which have at least a - // 1ms resolution. - // - // timeGetTime() provides 1ms granularity when combined with - // timeBeginPeriod(). If the host application for v8 wants fast - // timers, it can use timeBeginPeriod to increase the resolution. - // - // Using timeGetTime() has a drawback because it is a 32bit value - // and hence rolls-over every ~49days. - // - // To use the clock, we use GetSystemTimeAsFileTime as our base; - // and then use timeGetTime to extrapolate current time from the - // start time. To deal with rollovers, we resync the clock - // any time when more than kMaxClockElapsedTime has passed or - // whenever timeGetTime creates a rollover. - - static bool initialized = false; - static TimeStamp init_time; - static DWORD init_ticks; - static const int64_t kHundredNanosecondsPerSecond = 10000000; - static const int64_t kMaxClockElapsedTime = - 60*kHundredNanosecondsPerSecond; // 1 minute - - // If we are uninitialized, we need to resync the clock. - bool needs_resync = !initialized; - - // Get the current time. - TimeStamp time_now; - GetSystemTimeAsFileTime(&time_now.ft_); - DWORD ticks_now = timeGetTime(); - - // Check if we need to resync due to clock rollover. - needs_resync |= ticks_now < init_ticks; - - // Check if we need to resync due to elapsed time. - needs_resync |= (time_now.t_ - init_time.t_) > kMaxClockElapsedTime; - - // Check if we need to resync due to backwards time change. - needs_resync |= time_now.t_ < init_time.t_; - - // Resync the clock if necessary. - if (needs_resync) { - GetSystemTimeAsFileTime(&init_time.ft_); - init_ticks = ticks_now = timeGetTime(); - initialized = true; - } - - // Finally, compute the actual time. Why is this so hard. - DWORD elapsed = ticks_now - init_ticks; - this->time_.t_ = init_time.t_ + (static_cast<int64_t>(elapsed) * 10000); -} - - // Return the local timezone offset in milliseconds east of UTC. This // takes into account whether daylight saving is in effect at the time. // Only times in the 32-bit Unix range may be passed to this function. // Also, adding the time-zone offset to the input must not overflow. // The function EquivalentTime() in date.js guarantees this. -int64_t Time::LocalOffset() { +int64_t Win32Time::LocalOffset() { // Initialize timezone information, if needed. TzSet(); - Time rounded_to_second(*this); + Win32Time rounded_to_second(*this); rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler * 1000 * kTimeScaler; // Convert to local time using POSIX localtime function. @@ -541,7 +456,7 @@ int64_t Time::LocalOffset() { // Return whether or not daylight savings time is in effect at this time. -bool Time::InDST() { +bool Win32Time::InDST() { // Initialize timezone information, if needed. TzSet(); @@ -565,14 +480,14 @@ bool Time::InDST() { // Return the daylight savings time offset for this time. -int64_t Time::DaylightSavingsOffset() { +int64_t Win32Time::DaylightSavingsOffset() { return InDST() ? 60 * kMsPerMinute : 0; } // Returns a string identifying the current timezone for the // timestamp taking into account daylight saving. -char* Time::LocalTimezone() { +char* Win32Time::LocalTimezone() { // Return the standard or DST time zone name based on whether daylight // saving is in effect at the given time. return InDST() ? dst_tz_name_ : std_tz_name_; @@ -614,22 +529,14 @@ int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { // Returns current time as the number of milliseconds since // 00:00:00 UTC, January 1, 1970. double OS::TimeCurrentMillis() { - Time t; - t.SetToCurrentTime(); - return t.ToJSTime(); -} - - -// Returns the tickcounter based on timeGetTime. -int64_t OS::Ticks() { - return timeGetTime() * 1000; // Convert to microseconds. + return Time::Now().ToJsTime(); } // Returns a string identifying the current timezone taking into // account daylight saving. const char* OS::LocalTimezone(double time) { - return Time(time).LocalTimezone(); + return Win32Time(time).LocalTimezone(); } @@ -637,7 +544,7 @@ const char* OS::LocalTimezone(double time) { // taking daylight savings time into account. double OS::LocalTimeOffset() { // Use current time, rounded to the millisecond. - Time t(TimeCurrentMillis()); + Win32Time t(TimeCurrentMillis()); // Time::LocalOffset inlcudes any daylight savings offset, so subtract it. return static_cast<double>(t.LocalOffset() - t.DaylightSavingsOffset()); } @@ -646,7 +553,7 @@ double OS::LocalTimeOffset() { // Returns the daylight savings offset in milliseconds for the given // time. double OS::DaylightSavingsOffset(double time) { - int64_t offset = Time(time).DaylightSavingsOffset(); + int64_t offset = Win32Time(time).DaylightSavingsOffset(); return static_cast<double>(offset); } @@ -835,35 +742,6 @@ void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) { #undef _TRUNCATE #undef STRUNCATE -// We keep the lowest and highest addresses mapped as a quick way of -// determining that pointers are outside the heap (used mostly in assertions -// and verification). The estimate is conservative, i.e., not all addresses in -// 'allocated' space are actually allocated to our heap. The range is -// [lowest, highest), inclusive on the low and and exclusive on the high end. -static void* lowest_ever_allocated = reinterpret_cast<void*>(-1); -static void* highest_ever_allocated = reinterpret_cast<void*>(0); - - -static void UpdateAllocatedSpaceLimits(void* address, int size) { - ASSERT(limit_mutex != NULL); - ScopedLock lock(limit_mutex); - - lowest_ever_allocated = Min(lowest_ever_allocated, address); - highest_ever_allocated = - Max(highest_ever_allocated, - reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); -} - - -bool OS::IsOutsideAllocatedSpace(void* pointer) { - if (pointer < lowest_ever_allocated || pointer >= highest_ever_allocated) - return true; - // Ask the Windows API - if (IsBadWritePtr(pointer, 1)) - return true; - return false; -} - // Get the system's page size used by VirtualAlloc() or the next power // of two. The reason for always returning a power of two is that the @@ -910,8 +788,9 @@ void* OS::GetRandomMmapAddr() { static const intptr_t kAllocationRandomAddressMin = 0x04000000; static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000; #endif - uintptr_t address = (V8::RandomPrivate(isolate) << kPageSizeBits) - | kAllocationRandomAddressMin; + uintptr_t address = + (isolate->random_number_generator()->NextInt() << kPageSizeBits) | + kAllocationRandomAddressMin; address &= kAllocationRandomAddressMax; return reinterpret_cast<void *>(address); } @@ -950,14 +829,13 @@ void* OS::Allocate(const size_t requested, prot); if (mbase == NULL) { - LOG(ISOLATE, StringEvent("OS::Allocate", "VirtualAlloc failed")); + LOG(Isolate::Current(), StringEvent("OS::Allocate", "VirtualAlloc failed")); return NULL; } ASSERT(IsAligned(reinterpret_cast<size_t>(mbase), OS::AllocateAlignment())); *allocated = msize; - UpdateAllocatedSpaceLimits(mbase, static_cast<int>(msize)); return mbase; } @@ -982,7 +860,7 @@ void OS::ProtectCode(void* address, const size_t size) { void OS::Guard(void* address, const size_t size) { DWORD oldprotect; - VirtualProtect(address, size, PAGE_READONLY | PAGE_GUARD, &oldprotect); + VirtualProtect(address, size, PAGE_NOACCESS, &oldprotect); } @@ -991,13 +869,6 @@ void OS::Sleep(int milliseconds) { } -int OS::NumberOfCores() { - SYSTEM_INFO info; - GetSystemInfo(&info); - return info.dwNumberOfProcessors; -} - - void OS::Abort() { if (IsDebuggerPresent() || FLAG_break_on_abort) { DebugBreak(); @@ -1010,6 +881,9 @@ void OS::Abort() { void OS::DebugBreak() { #ifdef _MSC_VER + // To avoid Visual Studio runtime support the following code can be used + // instead + // __asm { int 3 } __debugbreak(); #else ::DebugBreak(); @@ -1255,7 +1129,7 @@ TLHELP32_FUNCTION_LIST(DLL_FUNC_LOADED) // Load the symbols for generating stack traces. -static bool LoadSymbols(HANDLE process_handle) { +static bool LoadSymbols(Isolate* isolate, HANDLE process_handle) { static bool symbols_loaded = false; if (symbols_loaded) return true; @@ -1304,7 +1178,7 @@ static bool LoadSymbols(HANDLE process_handle) { if (err != ERROR_MOD_NOT_FOUND && err != ERROR_INVALID_HANDLE) return false; } - LOG(i::Isolate::Current(), + LOG(isolate, SharedLibraryEvent( module_entry.szExePath, reinterpret_cast<unsigned int>(module_entry.modBaseAddr), @@ -1319,14 +1193,14 @@ static bool LoadSymbols(HANDLE process_handle) { } -void OS::LogSharedLibraryAddresses() { +void OS::LogSharedLibraryAddresses(Isolate* isolate) { // SharedLibraryEvents are logged when loading symbol information. // Only the shared libraries loaded at the time of the call to // LogSharedLibraryAddresses are logged. DLLs loaded after // initialization are not accounted for. if (!LoadDbgHelpAndTlHelp32()) return; HANDLE process_handle = GetCurrentProcess(); - LoadSymbols(process_handle); + LoadSymbols(isolate, process_handle); } @@ -1352,7 +1226,7 @@ int OS::StackWalk(Vector<OS::StackFrame> frames) { HANDLE thread_handle = GetCurrentThread(); // Read the symbols. - if (!LoadSymbols(process_handle)) return kStackWalkError; + if (!LoadSymbols(Isolate::Current(), process_handle)) return kStackWalkError; // Capture current context. CONTEXT context; @@ -1458,7 +1332,7 @@ int OS::StackWalk(Vector<OS::StackFrame> frames) { #pragma warning(pop) #else // __MINGW32__ -void OS::LogSharedLibraryAddresses() { } +void OS::LogSharedLibraryAddresses(Isolate* isolate) { } void OS::SignalCodeMovingGC() { } int OS::StackWalk(Vector<OS::StackFrame> frames) { return 0; } #endif // __MINGW32__ @@ -1562,7 +1436,7 @@ bool VirtualMemory::Guard(void* address) { if (NULL == VirtualAlloc(address, OS::CommitPageSize(), MEM_COMMIT, - PAGE_READONLY | PAGE_GUARD)) { + PAGE_NOACCESS)) { return false; } return true; @@ -1579,8 +1453,6 @@ bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { if (NULL == VirtualAlloc(base, size, MEM_COMMIT, prot)) { return false; } - - UpdateAllocatedSpaceLimits(base, static_cast<int>(size)); return true; } @@ -1703,297 +1575,4 @@ void Thread::YieldCPU() { Sleep(0); } - -// ---------------------------------------------------------------------------- -// 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 -// semaphores are anonymous. Also, the semaphores are initialized to have -// no upper limit on count. - - -class Win32Semaphore : public Semaphore { - public: - explicit Win32Semaphore(int count) { - sem = ::CreateSemaphoreA(NULL, count, 0x7fffffff, NULL); - } - - ~Win32Semaphore() { - CloseHandle(sem); - } - - void Wait() { - WaitForSingleObject(sem, INFINITE); - } - - bool Wait(int timeout) { - // Timeout in Windows API is in milliseconds. - DWORD millis_timeout = timeout / 1000; - return WaitForSingleObject(sem, millis_timeout) != WAIT_TIMEOUT; - } - - void Signal() { - LONG dummy; - ReleaseSemaphore(sem, 1, &dummy); - } - - private: - HANDLE sem; -}; - - -Semaphore* OS::CreateSemaphore(int count) { - return new Win32Semaphore(count); -} - - -// ---------------------------------------------------------------------------- -// Win32 socket support. -// - -class Win32Socket : public Socket { - public: - explicit Win32Socket() { - // Create the socket. - socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - } - explicit Win32Socket(SOCKET socket): socket_(socket) { } - virtual ~Win32Socket() { Shutdown(); } - - // Server initialization. - bool Bind(const int port); - bool Listen(int backlog) const; - Socket* Accept() const; - - // Client initialization. - bool Connect(const char* host, const char* port); - - // Shutdown socket for both read and write. - bool Shutdown(); - - // Data Transimission - int Send(const char* data, int len) const; - int Receive(char* data, int len) const; - - bool SetReuseAddress(bool reuse_address); - - bool IsValid() const { return socket_ != INVALID_SOCKET; } - - private: - SOCKET socket_; -}; - - -bool Win32Socket::Bind(const int port) { - if (!IsValid()) { - return false; - } - - sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr.sin_port = htons(port); - int status = bind(socket_, - reinterpret_cast<struct sockaddr *>(&addr), - sizeof(addr)); - return status == 0; -} - - -bool Win32Socket::Listen(int backlog) const { - if (!IsValid()) { - return false; - } - - int status = listen(socket_, backlog); - return status == 0; -} - - -Socket* Win32Socket::Accept() const { - if (!IsValid()) { - return NULL; - } - - SOCKET socket = accept(socket_, NULL, NULL); - if (socket == INVALID_SOCKET) { - return NULL; - } else { - return new Win32Socket(socket); - } -} - - -bool Win32Socket::Connect(const char* host, const char* port) { - if (!IsValid()) { - return false; - } - - // Lookup host and port. - struct addrinfo *result = NULL; - struct addrinfo hints; - memset(&hints, 0, sizeof(addrinfo)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - int status = getaddrinfo(host, port, &hints, &result); - if (status != 0) { - return false; - } - - // Connect. - status = connect(socket_, - result->ai_addr, - static_cast<int>(result->ai_addrlen)); - freeaddrinfo(result); - return status == 0; -} - - -bool Win32Socket::Shutdown() { - if (IsValid()) { - // Shutdown socket for both read and write. - int status = shutdown(socket_, SD_BOTH); - closesocket(socket_); - socket_ = INVALID_SOCKET; - return status == SOCKET_ERROR; - } - return true; -} - - -int Win32Socket::Send(const char* data, int len) const { - if (len <= 0) return 0; - int written = 0; - while (written < len) { - int status = send(socket_, data + written, len - written, 0); - if (status == 0) { - break; - } else if (status > 0) { - written += status; - } else { - return 0; - } - } - return written; -} - - -int Win32Socket::Receive(char* data, int len) const { - if (len <= 0) return 0; - int status = recv(socket_, data, len, 0); - return (status == SOCKET_ERROR) ? 0 : status; -} - - -bool Win32Socket::SetReuseAddress(bool reuse_address) { - BOOL on = reuse_address ? true : false; - int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, - reinterpret_cast<char*>(&on), sizeof(on)); - return status == SOCKET_ERROR; -} - - -bool Socket::SetUp() { - // Initialize Winsock32 - int err; - WSADATA winsock_data; - WORD version_requested = MAKEWORD(1, 0); - err = WSAStartup(version_requested, &winsock_data); - if (err != 0) { - PrintF("Unable to initialize Winsock, err = %d\n", Socket::LastError()); - } - - return err == 0; -} - - -int Socket::LastError() { - return WSAGetLastError(); -} - - -uint16_t Socket::HToN(uint16_t value) { - return htons(value); -} - - -uint16_t Socket::NToH(uint16_t value) { - return ntohs(value); -} - - -uint32_t Socket::HToN(uint32_t value) { - return htonl(value); -} - - -uint32_t Socket::NToH(uint32_t value) { - return ntohl(value); -} - - -Socket* OS::CreateSocket() { - return new Win32Socket(); -} - - -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::TearDown() { - delete limit_mutex; -} - - } } // namespace v8::internal |