13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Platform specific code for Win32. 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define V8_WIN32_HEADERS_FULL 31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "win32-headers.h" 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "codegen.h" 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "platform.h" 37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "vm-state-inl.h" 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _MSC_VER 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Case-insensitive bounded string comparisons. Use stricmp() on Win32. Usually 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// defined in strings.h. 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint strncasecmp(const char* s1, const char* s2, int n) { 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return _strnicmp(s1, s2, n); 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // _MSC_VER 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Extra functions for MinGW. Most of these are the _s functions which are in 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the Microsoft Visual Studio C++ CRT. 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef __MINGW32__ 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint localtime_s(tm* out_tm, const time_t* time) { 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tm* posix_local_time_struct = localtime(time); 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (posix_local_time_struct == NULL) return 1; 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *out_tm = *posix_local_time_struct; 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochint fopen_s(FILE** pFile, const char* filename, const char* mode) { 6385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch *pFile = fopen(filename, mode); 6485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch return *pFile != NULL ? 0 : 1; 6585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch} 663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifndef __MINGW64_VERSION_MAJOR 693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Not sure this the correct interpretation of _mkgmtime 713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtime_t _mkgmtime(tm* timeptr) { 723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return mktime(timeptr); 733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch#define _TRUNCATE 0 7785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch#define STRUNCATE 80 785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif // __MINGW64_VERSION_MAJOR 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint _vsnprintf_s(char* buffer, size_t sizeOfBuffer, size_t count, 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const char* format, va_list argptr) { 843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(count == _TRUNCATE); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return _vsnprintf(buffer, sizeOfBuffer, format, argptr); 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint strncpy_s(char* dest, size_t dest_size, const char* source, size_t count) { 903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK(source != NULL); 913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK(dest != NULL); 923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_GT(dest_size, 0); 933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (count == _TRUNCATE) { 953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch while (dest_size > 0 && *source != 0) { 963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch *(dest++) = *(source++); 973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch --dest_size; 983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (dest_size == 0) { 1003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch *(dest - 1) = 0; 1013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return STRUNCATE; 1023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 1043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch while (dest_size > 0 && count > 0 && *source != 0) { 1053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch *(dest++) = *(source++); 1063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch --dest_size; 1073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch --count; 1083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_GT(dest_size, 0); 1113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch *dest = 0; 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifndef __MINGW64_VERSION_MAJOR 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochinline void MemoryBarrier() { 119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int barrier = 0; 120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __asm__ __volatile__("xchgl %%eax,%0 ":"=r" (barrier)); 121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif // __MINGW64_VERSION_MAJOR 1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // __MINGW32__ 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate a pseudo-random number in the range 0-2^31-1. Usually 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// defined in stdlib.h. Missing in both Microsoft Visual Studio C++ and MinGW. 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint random() { 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return rand(); 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochintptr_t OS::MaxVirtualMemory() { 1393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return 0; 1403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 1413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockdouble ceiling(double x) { 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ceil(x); 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 14844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic Mutex* limit_mutex = NULL; 14944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#if defined(V8_TARGET_ARCH_IA32) 1518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic OS::MemCopyFunction memcopy_function = NULL; 1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic LazyMutex memcopy_function_mutex = LAZY_MUTEX_INITIALIZER; 1538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Defined in codegen-ia32.cc. 1548b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochOS::MemCopyFunction CreateMemCopyFunction(); 1558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copy memory area to disjoint memory area. 1578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid OS::MemCopy(void* dest, const void* src, size_t size) { 1588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (memcopy_function == NULL) { 1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopedLock lock(memcopy_function_mutex.Pointer()); 1608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (memcopy_function == NULL) { 1618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch OS::MemCopyFunction temp = CreateMemCopyFunction(); 1628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch MemoryBarrier(); 1638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch memcopy_function = temp; 1648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 1668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Note: here we rely on dependent reads being ordered. This is true 1678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // on all architectures we currently support. 1688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch (*memcopy_function)(dest, src, size); 1698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG 1708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_EQ(0, memcmp(dest, src, size)); 1718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif 1728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 1738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif // V8_TARGET_ARCH_IA32 17444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1753ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#ifdef _WIN64 1763ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blocktypedef double (*ModuloFunction)(double, double); 1778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic ModuloFunction modulo_function = NULL; 1783ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block// Defined in codegen-x64.cc. 1793ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve BlockModuloFunction CreateModuloFunction(); 1803ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid init_modulo_function() { 1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch modulo_function = CreateModuloFunction(); 1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1853ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockdouble modulo(double x, double y) { 1868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Note: here we rely on dependent reads being ordered. This is true 1878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // on all architectures we currently support. 1888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return (*modulo_function)(x, y); 1893ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 1903ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#else // Win32 1913ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 1923ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Blockdouble modulo(double x, double y) { 1933ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Workaround MS fmod bugs. ECMA-262 says: 1943ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // dividend is finite and divisor is an infinity => result equals dividend 1953ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // dividend is a zero and divisor is nonzero finite => result equals dividend 1963ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block if (!(isfinite(x) && (!isfinite(y) && !isnan(y))) && 1973ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block !(x == 0 && (y != 0 && isfinite(y)))) { 1983ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block x = fmod(x, y); 1993ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block } 2003ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block return x; 2013ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block} 2023ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2033ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block#endif // _WIN64 2043ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define UNARY_MATH_FUNCTION(name, generator) \ 2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic UnaryMathFunction fast_##name##_function = NULL; \ 2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid init_fast_##name##_function() { \ 2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fast_##name##_function = generator; \ 2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} \ 2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochdouble fast_##name(double x) { \ 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return (*fast_##name##_function)(x); \ 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochUNARY_MATH_FUNCTION(sin, CreateTranscendentalFunction(TranscendentalCache::SIN)) 2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochUNARY_MATH_FUNCTION(cos, CreateTranscendentalFunction(TranscendentalCache::COS)) 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochUNARY_MATH_FUNCTION(tan, CreateTranscendentalFunction(TranscendentalCache::TAN)) 2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochUNARY_MATH_FUNCTION(log, CreateTranscendentalFunction(TranscendentalCache::LOG)) 2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochUNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction()) 2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef MATH_FUNCTION 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid MathSetup() { 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef _WIN64 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch init_modulo_function(); 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch init_fast_sin_function(); 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch init_fast_cos_function(); 2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch init_fast_tan_function(); 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch init_fast_log_function(); 2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch init_fast_sqrt_function(); 2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The Time class represents time on win32. A timestamp is represented as 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// a 64-bit integer in 100 nanoseconds since January 1, 1601 (UTC). JavaScript 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// timestamps are represented as a doubles in milliseconds since 00:00:00 UTC, 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// January 1, 1970. 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Time { 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Constructors. 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Time(); 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Time(double jstime); 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Time(int year, int mon, int day, int hour, int min, int sec); 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert timestamp to JavaScript representation. 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block double ToJSTime(); 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set timestamp to current time. 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetToCurrentTime(); 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the local timezone offset in milliseconds east of UTC. This is 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the number of milliseconds you must add to UTC to get local time, i.e. 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // routine also takes into account whether daylight saving is effect 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // at the time. 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int64_t LocalOffset(); 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns the daylight savings time offset for the time in milliseconds. 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int64_t DaylightSavingsOffset(); 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Returns a string identifying the current timezone for the 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // timestamp taking into account daylight saving. 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* LocalTimezone(); 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Constants for time conversion. 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int64_t kTimeEpoc = 116444736000000000LL; 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int64_t kTimeScaler = 10000; 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int64_t kMsPerMinute = 60000; 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Constants for timezone information. 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kTzNameSize = 128; 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const bool kShortTzNames = false; 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Timezone information. We need to have static buffers for the 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // timezone names because we return pointers to these in 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // LocalTimezone(). 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static bool tz_initialized_; 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static TIME_ZONE_INFORMATION tzinfo_; 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static char std_tz_name_[kTzNameSize]; 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static char dst_tz_name_[kTzNameSize]; 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize the timezone information (if not already done). 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static void TzSet(); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Guess the name of the timezone from the bias. 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const char* GuessTimezoneNameFromBias(int bias); 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return whether or not daylight savings time is in effect at this time. 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool InDST(); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the difference (in milliseconds) between this timestamp and 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // another timestamp. 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int64_t Diff(Time* other); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessor for FILETIME representation. 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILETIME& ft() { return time_.ft_; } 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Accessor for integer representation. 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int64_t& t() { return time_.t_; } 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Although win32 uses 64-bit integers for representing timestamps, 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // these are packed into a FILETIME structure. The FILETIME structure 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // is just a struct representing a 64-bit integer. The TimeStamp union 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // allows access to both a FILETIME and an integer representation of 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the timestamp. 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block union TimeStamp { 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILETIME ft_; 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int64_t t_; 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TimeStamp time_; 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Static variables. 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Time::tz_initialized_ = false; 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTIME_ZONE_INFORMATION Time::tzinfo_; 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar Time::std_tz_name_[kTzNameSize]; 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar Time::dst_tz_name_[kTzNameSize]; 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Initialize timestamp to start of epoc. 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTime::Time() { 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block t() = 0; 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Initialize timestamp from a JavaScript timestamp. 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTime::Time(double jstime) { 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block t() = static_cast<int64_t>(jstime) * kTimeScaler + kTimeEpoc; 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Initialize timestamp from date/time components. 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTime::Time(int year, int mon, int day, int hour, int min, int sec) { 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SYSTEMTIME st; 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block st.wYear = year; 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block st.wMonth = mon; 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block st.wDay = day; 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block st.wHour = hour; 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block st.wMinute = min; 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block st.wSecond = sec; 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block st.wMilliseconds = 0; 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SystemTimeToFileTime(&st, &ft()); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Convert timestamp to JavaScript timestamp. 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockdouble Time::ToJSTime() { 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return static_cast<double>((t() - kTimeEpoc) / kTimeScaler); 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Guess the name of the timezone from the bias. 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The guess is very biased towards the northern hemisphere. 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* Time::GuessTimezoneNameFromBias(int bias) { 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kHour = 60; 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (-bias) { 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case -9*kHour: return "Alaska"; 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case -8*kHour: return "Pacific"; 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case -7*kHour: return "Mountain"; 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case -6*kHour: return "Central"; 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case -5*kHour: return "Eastern"; 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case -4*kHour: return "Atlantic"; 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 0*kHour: return "GMT"; 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case +1*kHour: return "Central Europe"; 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case +2*kHour: return "Eastern Europe"; 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case +3*kHour: return "Russia"; 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case +5*kHour + 30: return "India"; 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case +8*kHour: return "China"; 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case +9*kHour: return "Japan"; 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case +12*kHour: return "New Zealand"; 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: return "Local"; 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Initialize timezone information. The timezone information is obtained from 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// windows. If we cannot get the timezone information we fall back to CET. 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Please notice that this code is not thread-safe. 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Time::TzSet() { 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Just return if timezone information has already been initialized. 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (tz_initialized_) return; 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize POSIX time zone data. 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block _tzset(); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Obtain timezone information from operating system. 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block memset(&tzinfo_, 0, sizeof(tzinfo_)); 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (GetTimeZoneInformation(&tzinfo_) == TIME_ZONE_ID_INVALID) { 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we cannot get timezone information we fall back to CET. 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tzinfo_.Bias = -60; 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tzinfo_.StandardDate.wMonth = 10; 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tzinfo_.StandardDate.wDay = 5; 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tzinfo_.StandardDate.wHour = 3; 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tzinfo_.StandardBias = 0; 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tzinfo_.DaylightDate.wMonth = 3; 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tzinfo_.DaylightDate.wDay = 5; 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tzinfo_.DaylightDate.wHour = 2; 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tzinfo_.DaylightBias = -60; 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make standard and DST timezone names. 407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch WideCharToMultiByte(CP_UTF8, 0, tzinfo_.StandardName, -1, 408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch std_tz_name_, kTzNameSize, NULL, NULL); 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block std_tz_name_[kTzNameSize - 1] = '\0'; 410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch WideCharToMultiByte(CP_UTF8, 0, tzinfo_.DaylightName, -1, 411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dst_tz_name_, kTzNameSize, NULL, NULL); 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block dst_tz_name_[kTzNameSize - 1] = '\0'; 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If OS returned empty string or resource id (like "@tzres.dll,-211") 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // simply guess the name from the UTC bias of the timezone. 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // To properly resolve the resource identifier requires a library load, 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // which is not possible in a sandbox. 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (std_tz_name_[0] == '\0' || std_tz_name_[0] == '@') { 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::SNPrintF(Vector<char>(std_tz_name_, kTzNameSize - 1), 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%s Standard Time", 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GuessTimezoneNameFromBias(tzinfo_.Bias)); 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dst_tz_name_[0] == '\0' || dst_tz_name_[0] == '@') { 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::SNPrintF(Vector<char>(dst_tz_name_, kTzNameSize - 1), 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%s Daylight Time", 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GuessTimezoneNameFromBias(tzinfo_.Bias)); 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Timezone information initialized. 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tz_initialized_ = true; 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Return the difference in milliseconds between this and another timestamp. 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint64_t Time::Diff(Time* other) { 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (t() - other->t()) / kTimeScaler; 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Set timestamp to current time. 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Time::SetToCurrentTime() { 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The default GetSystemTimeAsFileTime has a ~15.5ms resolution. 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Because we're fast, we like fast timers which have at least a 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 1ms resolution. 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // timeGetTime() provides 1ms granularity when combined with 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // timeBeginPeriod(). If the host application for v8 wants fast 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // timers, it can use timeBeginPeriod to increase the resolution. 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Using timeGetTime() has a drawback because it is a 32bit value 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and hence rolls-over every ~49days. 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // To use the clock, we use GetSystemTimeAsFileTime as our base; 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and then use timeGetTime to extrapolate current time from the 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // start time. To deal with rollovers, we resync the clock 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // any time when more than kMaxClockElapsedTime has passed or 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // whenever timeGetTime creates a rollover. 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static bool initialized = false; 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static TimeStamp init_time; 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static DWORD init_ticks; 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int64_t kHundredNanosecondsPerSecond = 10000000; 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int64_t kMaxClockElapsedTime = 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 60*kHundredNanosecondsPerSecond; // 1 minute 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we are uninitialized, we need to resync the clock. 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool needs_resync = !initialized; 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the current time. 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TimeStamp time_now; 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GetSystemTimeAsFileTime(&time_now.ft_); 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD ticks_now = timeGetTime(); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if we need to resync due to clock rollover. 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block needs_resync |= ticks_now < init_ticks; 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if we need to resync due to elapsed time. 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block needs_resync |= (time_now.t_ - init_time.t_) > kMaxClockElapsedTime; 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Resync the clock if necessary. 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (needs_resync) { 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GetSystemTimeAsFileTime(&init_time.ft_); 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block init_ticks = ticks_now = timeGetTime(); 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialized = true; 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Finally, compute the actual time. Why is this so hard. 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD elapsed = ticks_now - init_ticks; 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this->time_.t_ = init_time.t_ + (static_cast<int64_t>(elapsed) * 10000); 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Return the local timezone offset in milliseconds east of UTC. This 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// takes into account whether daylight saving is in effect at the time. 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Only times in the 32-bit Unix range may be passed to this function. 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Also, adding the time-zone offset to the input must not overflow. 4973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// The function EquivalentTime() in date.js guarantees this. 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint64_t Time::LocalOffset() { 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize timezone information, if needed. 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TzSet(); 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Time rounded_to_second(*this); 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler * 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1000 * kTimeScaler; 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert to local time using POSIX localtime function. 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Windows XP Service Pack 3 made SystemTimeToTzSpecificLocalTime() 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // very slow. Other browsers use localtime(). 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert from JavaScript milliseconds past 1/1/1970 0:00:00 to 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // POSIX seconds past 1/1/1970 0:00:00. 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block double unchecked_posix_time = rounded_to_second.ToJSTime() / 1000; 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (unchecked_posix_time > INT_MAX || unchecked_posix_time < 0) { 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Because _USE_32BIT_TIME_T is defined, time_t is a 32-bit int. 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block time_t posix_time = static_cast<time_t>(unchecked_posix_time); 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert to local time, as struct with fields for day, hour, year, etc. 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block tm posix_local_time_struct; 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (localtime_s(&posix_local_time_struct, &posix_time)) return 0; 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert local time in struct to POSIX time as if it were a UTC time. 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block time_t local_posix_time = _mkgmtime(&posix_local_time_struct); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Time localtime(1000.0 * local_posix_time); 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return localtime.Diff(&rounded_to_second); 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Return whether or not daylight savings time is in effect at this time. 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Time::InDST() { 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize timezone information, if needed. 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TzSet(); 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Determine if DST is in effect at the specified time. 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool in_dst = false; 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (tzinfo_.StandardDate.wMonth != 0 || tzinfo_.DaylightDate.wMonth != 0) { 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the local timezone offset for the timestamp in milliseconds. 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int64_t offset = LocalOffset(); 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute the offset for DST. The bias parameters in the timezone info 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // are specified in minutes. These must be converted to milliseconds. 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int64_t dstofs = -(tzinfo_.Bias + tzinfo_.DaylightBias) * kMsPerMinute; 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If the local time offset equals the timezone bias plus the daylight 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // bias then DST is in effect. 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block in_dst = offset == dstofs; 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return in_dst; 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Return the daylight savings time offset for this time. 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint64_t Time::DaylightSavingsOffset() { 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return InDST() ? 60 * kMsPerMinute : 0; 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns a string identifying the current timezone for the 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// timestamp taking into account daylight saving. 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* Time::LocalTimezone() { 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the standard or DST time zone name based on whether daylight 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // saving is in effect at the given time. 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return InDST() ? dst_tz_name_ : std_tz_name_; 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::SetUp() { 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Seed the random number generator. 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert the current time to a 64-bit integer first, before converting it 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to an unsigned. Going directly can cause an overflow and the seed to be 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // set to all ones. The seed will be identical for different instances that 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // call this setup code within the same millisecond. 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()); 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block srand(static_cast<unsigned int>(seed)); 57644f0eee88ff00398ff7f715fab053374d808c90dSteve Block limit_mutex = CreateMutex(); 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::PostSetUp() { 5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Math functions depend on CPU features therefore they are initialized after 5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // CPU. 5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MathSetup(); 5843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the accumulated user time for thread. 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILETIME dummy; 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint64_t usertime; 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the amount of time that the thread has executed in user mode. 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!GetThreadTimes(GetCurrentThread(), &dummy, &dummy, &dummy, 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<FILETIME*>(&usertime))) return -1; 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Adjust the resolution to micro-seconds. 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block usertime /= 10; 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Convert to seconds and microseconds 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *secs = static_cast<uint32_t>(usertime / 1000000); 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *usecs = static_cast<uint32_t>(usertime % 1000000); 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns current time as the number of milliseconds since 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 00:00:00 UTC, January 1, 1970. 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockdouble OS::TimeCurrentMillis() { 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Time t; 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block t.SetToCurrentTime(); 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return t.ToJSTime(); 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the tickcounter based on timeGetTime. 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint64_t OS::Ticks() { 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return timeGetTime() * 1000; // Convert to microseconds. 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns a string identifying the current timezone taking into 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// account daylight saving. 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst char* OS::LocalTimezone(double time) { 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Time(time).LocalTimezone(); 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the local time offset in milliseconds east of UTC without 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// taking daylight savings time into account. 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockdouble OS::LocalTimeOffset() { 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use current time, rounded to the millisecond. 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Time t(TimeCurrentMillis()); 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Time::LocalOffset inlcudes any daylight savings offset, so subtract it. 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return static_cast<double>(t.LocalOffset() - t.DaylightSavingsOffset()); 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Returns the daylight savings offset in milliseconds for the given 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// time. 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockdouble OS::DaylightSavingsOffset(double time) { 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int64_t offset = Time(time).DaylightSavingsOffset(); 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return static_cast<double>(offset); 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 645756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrickint OS::GetLastError() { 646756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick return ::GetLastError(); 647756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick} 648756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 649756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Win32 console output. 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// If a Win32 application is linked as a console application it has a normal 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// standard output and standard error. In this case normal printf works fine 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// for output. However, if the application is linked as a GUI application, 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the process doesn't have a console, and therefore (debugging) output is lost. 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// This is the case if we are embedded in a windows program (like a browser). 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// In order to be able to get debug output in this case the the debugging 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// facility using OutputDebugString. This output goes to the active debugger 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// for the process (if any). Else the output can be monitored using DBMON.EXE. 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockenum OutputMode { 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UNKNOWN, // Output method has not yet been determined. 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CONSOLE, // Output is written to stdout. 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ODS // Output is written to debug facility. 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic OutputMode output_mode = UNKNOWN; // Current output mode. 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Determine if the process has a console for output. 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool HasConsole() { 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Only check the first time. Eventual race conditions are not a problem, 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // because all threads will eventually determine the same mode. 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (output_mode == UNKNOWN) { 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // We cannot just check that the standard output is attached to a console 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // because this would fail if output is redirected to a file. Therefore we 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // say that a process does not have an output console if either the 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // standard output handle is invalid or its file type is unknown. 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE && 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) != FILE_TYPE_UNKNOWN) 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block output_mode = CONSOLE; 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block else 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block output_mode = ODS; 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return output_mode == CONSOLE; 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void VPrintHelper(FILE* stream, const char* format, va_list args) { 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (HasConsole()) { 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block vfprintf(stream, format, args); 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // It is important to use safe print here in order to avoid 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // overflowing the buffer. We might truncate the output, but this 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // does not crash. 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EmbeddedVector<char, 4096> buffer; 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OS::VSNPrintF(buffer, format, args); 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OutputDebugStringA(buffer.start()); 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFILE* OS::FOpen(const char* path, const char* mode) { 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILE* result; 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (fopen_s(&result, path, mode) == 0) { 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockbool OS::Remove(const char* path) { 7151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return (DeleteFileA(path) != 0); 7161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 7171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7193fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochFILE* OS::OpenTemporaryFile() { 7203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // tmpfile_s tries to use the root dir, don't use it. 7213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch char tempPathBuffer[MAX_PATH]; 7223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DWORD path_result = 0; 7233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch path_result = GetTempPathA(MAX_PATH, tempPathBuffer); 7243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (path_result > MAX_PATH || path_result == 0) return NULL; 7253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch UINT name_result = 0; 7263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch char tempNameBuffer[MAX_PATH]; 7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch name_result = GetTempFileNameA(tempPathBuffer, "", 0, tempNameBuffer); 7283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (name_result == 0) return NULL; 7293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FILE* result = FOpen(tempNameBuffer, "w+"); // Same mode as tmpfile uses. 7303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (result != NULL) { 7313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Remove(tempNameBuffer); // Delete on close. 7323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return result; 7343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 7353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Open log file in binary mode to avoid /n -> /r/n conversion. 73844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockconst char* const OS::LogFileOpenMode = "wb"; 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print (debug) message to console. 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Print(const char* format, ...) { 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_list args; 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_start(args, format); 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block VPrint(format, args); 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_end(args); 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::VPrint(const char* format, va_list args) { 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block VPrintHelper(stdout, format, args); 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid OS::FPrint(FILE* out, const char* format, ...) { 756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_list args; 757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_start(args, format); 758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VFPrint(out, format, args); 759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_end(args); 760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid OS::VFPrint(FILE* out, const char* format, va_list args) { 764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VPrintHelper(out, format, args); 765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Print error message to console. 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::PrintError(const char* format, ...) { 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_list args; 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_start(args, format); 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block VPrintError(format, args); 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_end(args); 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::VPrintError(const char* format, va_list args) { 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block VPrintHelper(stderr, format, args); 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::SNPrintF(Vector<char> str, const char* format, ...) { 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_list args; 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_start(args, format); 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = VSNPrintF(str, format, args); 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block va_end(args); 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::VSNPrintF(Vector<char> str, const char* format, va_list args) { 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int n = _vsnprintf_s(str.start(), str.length(), _TRUNCATE, format, args); 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure to zero-terminate the string if the output was 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // truncated or if there was an error. 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (n < 0 || n >= str.length()) { 796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (str.length() > 0) 797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch str[str.length() - 1] = '\0'; 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return -1; 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return n; 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockchar* OS::StrChr(char* str, int c) { 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return const_cast<char*>(strchr(str, c)); 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::StrNCpy(Vector<char> dest, const char* src, size_t n) { 81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Use _TRUNCATE or strncpy_s crashes (by design) if buffer is too small. 81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block size_t buffer_size = static_cast<size_t>(dest.length()); 81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (n + 1 > buffer_size) // count for trailing '\0' 81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block n = _TRUNCATE; 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int result = strncpy_s(dest.start(), dest.length(), src, n); 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 81744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(result == 0 || (n == _TRUNCATE && result == STRUNCATE)); 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// We keep the lowest and highest addresses mapped as a quick way of 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// determining that pointers are outside the heap (used mostly in assertions 8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// and verification). The estimate is conservative, i.e., not all addresses in 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 'allocated' space are actually allocated to our heap. The range is 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// [lowest, highest), inclusive on the low and and exclusive on the high end. 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* lowest_ever_allocated = reinterpret_cast<void*>(-1); 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void* highest_ever_allocated = reinterpret_cast<void*>(0); 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void UpdateAllocatedSpaceLimits(void* address, int size) { 83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(limit_mutex != NULL); 83244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ScopedLock lock(limit_mutex); 83344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lowest_ever_allocated = Min(lowest_ever_allocated, address); 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block highest_ever_allocated = 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Max(highest_ever_allocated, 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size)); 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool OS::IsOutsideAllocatedSpace(void* pointer) { 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (pointer < lowest_ever_allocated || pointer >= highest_ever_allocated) 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ask the Windows API 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (IsBadWritePtr(pointer, 1)) 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Get the system's page size used by VirtualAlloc() or the next power 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// of two. The reason for always returning a power of two is that the 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// rounding up in OS::Allocate expects that. 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic size_t GetPageSize() { 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static size_t page_size = 0; 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (page_size == 0) { 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SYSTEM_INFO info; 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GetSystemInfo(&info); 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block page_size = RoundUpToPowerOf2(info.dwPageSize); 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return page_size; 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The allocation alignment is the guaranteed alignment for 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// VirtualAlloc'ed blocks of memory. 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocksize_t OS::AllocateAlignment() { 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static size_t allocate_alignment = 0; 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (allocate_alignment == 0) { 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SYSTEM_INFO info; 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GetSystemInfo(&info); 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block allocate_alignment = info.dwAllocationGranularity; 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return allocate_alignment; 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void* GetRandomAddr() { 8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Isolate* isolate = Isolate::UncheckedCurrent(); 8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Note that the current isolate isn't set up in a call path via 8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // CpuFeatures::Probe. We don't care about randomization in this case because 8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the code page is immediately freed. 8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (isolate != NULL) { 8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The address range used to randomize RWX allocations in OS::Allocate 8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Try not to map pages into the default range that windows loads DLLs 8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Use a multiple of 64k to prevent committing unused memory. 8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Note: This does not guarantee RWX regions will be within the 8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // range kAllocationRandomAddressMin to kAllocationRandomAddressMax 889bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch#ifdef V8_HOST_ARCH_64_BIT 8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const intptr_t kAllocationRandomAddressMin = 0x0000000080000000; 8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const intptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000; 892bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch#else 8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const intptr_t kAllocationRandomAddressMin = 0x04000000; 8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000; 895bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch#endif 8963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uintptr_t address = (V8::RandomPrivate(isolate) << kPageSizeBits) 8973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch | kAllocationRandomAddressMin; 8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address &= kAllocationRandomAddressMax; 8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return reinterpret_cast<void *>(address); 9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return NULL; 9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 904592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void* RandomizedVirtualAlloc(size_t size, int action, int protection) { 9063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LPVOID base = NULL; 9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS) { 9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // For exectutable pages try and randomize the allocation address 9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (size_t attempts = 0; base == NULL && attempts < 3; ++attempts) { 9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch base = VirtualAlloc(GetRandomAddr(), size, action, protection); 9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // After three attempts give up and let the OS find an address to use. 9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (base == NULL) base = VirtualAlloc(NULL, size, action, protection); 9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return base; 9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid* OS::Allocate(const size_t requested, 9233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t* allocated, 9243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_executable) { 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // VirtualAlloc rounds allocated size to page size automatically. 926d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block size_t msize = RoundUp(requested, static_cast<int>(GetPageSize())); 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Windows XP SP2 allows Data Excution Prevention (DEP). 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 930bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LPVOID mbase = RandomizedVirtualAlloc(msize, 9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MEM_COMMIT | MEM_RESERVE, 9333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch prot); 934bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mbase == NULL) { 93644f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(ISOLATE, StringEvent("OS::Allocate", "VirtualAlloc failed")); 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(IsAligned(reinterpret_cast<size_t>(mbase), OS::AllocateAlignment())); 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *allocated = msize; 943d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block UpdateAllocatedSpaceLimits(mbase, static_cast<int>(msize)); 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return mbase; 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Free(void* address, const size_t size) { 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // TODO(1240712): VirtualFree has a return value which is ignored here. 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block VirtualFree(address, 0, MEM_RELEASE); 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(size); 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochintptr_t OS::CommitPageSize() { 9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return 4096; 9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid OS::ProtectCode(void* address, const size_t size) { 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD old_protect; 9623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect); 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid OS::Guard(void* address, const size_t size) { 9673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DWORD oldprotect; 9683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VirtualProtect(address, size, PAGE_READONLY | PAGE_GUARD, &oldprotect); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Sleep(int milliseconds) { 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ::Sleep(milliseconds); 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::Abort() { 9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (IsDebuggerPresent() || FLAG_break_on_abort) { 97985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch DebugBreak(); 9803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make the MSVCRT do a silent abort. 9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch raise(SIGABRT); 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::DebugBreak() { 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _MSC_VER 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __debugbreak(); 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ::DebugBreak(); 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Win32MemoryMappedFile : public OS::MemoryMappedFile { 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 9981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Win32MemoryMappedFile(HANDLE file, 9991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HANDLE file_mapping, 10001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void* memory, 10011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int size) 10021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block : file_(file), 10031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block file_mapping_(file_mapping), 10041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block memory_(memory), 10051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block size_(size) { } 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~Win32MemoryMappedFile(); 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual void* memory() { return memory_; } 10081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block virtual int size() { return size_; } 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE file_; 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE file_mapping_; 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* memory_; 10131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int size_; 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 10171e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { 10181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Open a physical file 10191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 10201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); 1021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (file == INVALID_HANDLE_VALUE) return NULL; 10221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int size = static_cast<int>(GetFileSize(file, NULL)); 10241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Create a file mapping for the physical file 10261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HANDLE file_mapping = CreateFileMapping(file, NULL, 10271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PAGE_READWRITE, 0, static_cast<DWORD>(size), NULL); 10281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (file_mapping == NULL) return NULL; 10291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Map a view of the file into memory 10311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size); 10321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return new Win32MemoryMappedFile(file, file_mapping, memory, size); 10331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 10341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 10351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size, 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* initial) { 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Open a physical file 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL); 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (file == NULL) return NULL; 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create a file mapping for the physical file 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE file_mapping = CreateFileMapping(file, NULL, 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PAGE_READWRITE, 0, static_cast<DWORD>(size), NULL); 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (file_mapping == NULL) return NULL; 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Map a view of the file into memory 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size); 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (memory) memmove(memory, initial, size); 10491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return new Win32MemoryMappedFile(file, file_mapping, memory, size); 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockWin32MemoryMappedFile::~Win32MemoryMappedFile() { 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (memory_ != NULL) 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block UnmapViewOfFile(memory_); 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CloseHandle(file_mapping_); 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CloseHandle(file_); 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The following code loads functions defined in DbhHelp.h and TlHelp32.h 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// dynamically. This is to avoid being depending on dbghelp.dll and 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// tlhelp32.dll when running (the functions in tlhelp32.dll have been moved to 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// kernel32.dll at some point so loading functions defines in TlHelp32.h 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// dynamically might not be necessary any more - for some versions of Windows?). 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Function pointers to functions dynamically loaded from dbghelp.dll. 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define DBGHELP_FUNCTION_LIST(V) \ 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V(SymInitialize) \ 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V(SymGetOptions) \ 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V(SymSetOptions) \ 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V(SymGetSearchPath) \ 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V(SymLoadModule64) \ 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V(StackWalk64) \ 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V(SymGetSymFromAddr64) \ 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V(SymGetLineFromAddr64) \ 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V(SymFunctionTableAccess64) \ 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V(SymGetModuleBase64) 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Function pointers to functions dynamically loaded from dbghelp.dll. 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define TLHELP32_FUNCTION_LIST(V) \ 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V(CreateToolhelp32Snapshot) \ 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V(Module32FirstW) \ 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V(Module32NextW) 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Define the decoration to use for the type and variable name used for 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// dynamically loaded DLL function.. 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define DLL_FUNC_TYPE(name) _##name##_ 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define DLL_FUNC_VAR(name) _##name 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Define the type for each dynamically loaded DLL function. The function 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// definitions are copied from DbgHelp.h and TlHelp32.h. The IN and VOID macros 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from the Windows include files are redefined here to have the function 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// definitions to be as close to the ones in the original .h files as possible. 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef IN 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define IN 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef VOID 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define VOID void 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DbgHelp isn't supported on MinGW yet 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef __MINGW32__ 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DbgHelp.h functions. 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef BOOL (__stdcall *DLL_FUNC_TYPE(SymInitialize))(IN HANDLE hProcess, 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN PSTR UserSearchPath, 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN BOOL fInvadeProcess); 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef DWORD (__stdcall *DLL_FUNC_TYPE(SymGetOptions))(VOID); 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef DWORD (__stdcall *DLL_FUNC_TYPE(SymSetOptions))(IN DWORD SymOptions); 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSearchPath))( 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN HANDLE hProcess, 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OUT PSTR SearchPath, 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN DWORD SearchPathLength); 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymLoadModule64))( 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN HANDLE hProcess, 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN HANDLE hFile, 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN PSTR ImageName, 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN PSTR ModuleName, 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN DWORD64 BaseOfDll, 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN DWORD SizeOfDll); 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef BOOL (__stdcall *DLL_FUNC_TYPE(StackWalk64))( 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD MachineType, 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE hProcess, 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE hThread, 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LPSTACKFRAME64 StackFrame, 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PVOID ContextRecord, 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSymFromAddr64))( 1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN HANDLE hProcess, 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN DWORD64 qwAddr, 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OUT PDWORD64 pdwDisplacement, 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OUT PIMAGEHLP_SYMBOL64 Symbol); 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetLineFromAddr64))( 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN HANDLE hProcess, 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IN DWORD64 qwAddr, 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OUT PDWORD pdwDisplacement, 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block OUT PIMAGEHLP_LINE64 Line64); 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DbgHelp.h typedefs. Implementation found in dbghelp.dll. 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef PVOID (__stdcall *DLL_FUNC_TYPE(SymFunctionTableAccess64))( 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE hProcess, 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD64 AddrBase); // DbgHelp.h typedef PFUNCTION_TABLE_ACCESS_ROUTINE64 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymGetModuleBase64))( 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE hProcess, 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD64 AddrBase); // DbgHelp.h typedef PGET_MODULE_BASE_ROUTINE64 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// TlHelp32.h functions. 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef HANDLE (__stdcall *DLL_FUNC_TYPE(CreateToolhelp32Snapshot))( 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD dwFlags, 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD th32ProcessID); 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32FirstW))(HANDLE hSnapshot, 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LPMODULEENTRY32W lpme); 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32NextW))(HANDLE hSnapshot, 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LPMODULEENTRY32W lpme); 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef IN 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef VOID 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Declare a variable for each dynamically loaded DLL function. 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define DEF_DLL_FUNCTION(name) DLL_FUNC_TYPE(name) DLL_FUNC_VAR(name) = NULL; 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDBGHELP_FUNCTION_LIST(DEF_DLL_FUNCTION) 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTLHELP32_FUNCTION_LIST(DEF_DLL_FUNCTION) 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DEF_DLL_FUNCTION 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load the functions. This function has a lot of "ugly" macros in order to 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// keep down code duplication. 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool LoadDbgHelpAndTlHelp32() { 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static bool dbghelp_loaded = false; 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (dbghelp_loaded) return true; 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HMODULE module; 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load functions from the dbghelp.dll module. 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block module = LoadLibrary(TEXT("dbghelp.dll")); 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (module == NULL) { 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define LOAD_DLL_FUNC(name) \ 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DLL_FUNC_VAR(name) = \ 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name)); 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDBGHELP_FUNCTION_LIST(LOAD_DLL_FUNC) 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef LOAD_DLL_FUNC 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load functions from the kernel32.dll module (the TlHelp32.h function used 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to be in tlhelp32.dll but are now moved to kernel32.dll). 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block module = LoadLibrary(TEXT("kernel32.dll")); 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (module == NULL) { 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define LOAD_DLL_FUNC(name) \ 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DLL_FUNC_VAR(name) = \ 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name)); 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTLHELP32_FUNCTION_LIST(LOAD_DLL_FUNC) 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef LOAD_DLL_FUNC 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that all functions where loaded. 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool result = 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define DLL_FUNC_LOADED(name) (DLL_FUNC_VAR(name) != NULL) && 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockDBGHELP_FUNCTION_LIST(DLL_FUNC_LOADED) 1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTLHELP32_FUNCTION_LIST(DLL_FUNC_LOADED) 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DLL_FUNC_LOADED 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block true; 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block dbghelp_loaded = result; 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // NOTE: The modules are never unloaded and will stay around until the 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // application is closed. 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Load the symbols for generating stack traces. 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool LoadSymbols(HANDLE process_handle) { 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static bool symbols_loaded = false; 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (symbols_loaded) return true; 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BOOL ok; 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize the symbol engine. 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ok = _SymInitialize(process_handle, // hProcess 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NULL, // UserSearchPath 1234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false); // fInvadeProcess 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!ok) return false; 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD options = _SymGetOptions(); 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block options |= SYMOPT_LOAD_LINES; 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block options |= SYMOPT_FAIL_CRITICAL_ERRORS; 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block options = _SymSetOptions(options); 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char buf[OS::kStackWalkMaxNameLen] = {0}; 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ok = _SymGetSearchPath(process_handle, buf, OS::kStackWalkMaxNameLen); 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!ok) { 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int err = GetLastError(); 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("%d\n", err); 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE snapshot = _CreateToolhelp32Snapshot( 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TH32CS_SNAPMODULE, // dwFlags 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block GetCurrentProcessId()); // th32ProcessId 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (snapshot == INVALID_HANDLE_VALUE) return false; 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MODULEENTRY32W module_entry; 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block module_entry.dwSize = sizeof(module_entry); // Set the size of the structure. 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BOOL cont = _Module32FirstW(snapshot, &module_entry); 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (cont) { 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD64 base; 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // NOTE the SymLoadModule64 function has the peculiarity of accepting a 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // both unicode and ASCII strings even though the parameter is PSTR. 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block base = _SymLoadModule64( 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block process_handle, // hProcess 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0, // hFile 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<PSTR>(module_entry.szExePath), // ImageName 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<PSTR>(module_entry.szModule), // ModuleName 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<DWORD64>(module_entry.modBaseAddr), // BaseOfDll 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block module_entry.modBaseSize); // SizeOfDll 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (base == 0) { 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int err = GetLastError(); 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (err != ERROR_MOD_NOT_FOUND && 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block err != ERROR_INVALID_HANDLE) return false; 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 127344f0eee88ff00398ff7f715fab053374d808c90dSteve Block LOG(i::Isolate::Current(), 127444f0eee88ff00398ff7f715fab053374d808c90dSteve Block SharedLibraryEvent( 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block module_entry.szExePath, 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<unsigned int>(module_entry.modBaseAddr), 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<unsigned int>(module_entry.modBaseAddr + 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block module_entry.modBaseSize))); 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cont = _Module32NextW(snapshot, &module_entry); 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CloseHandle(snapshot); 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block symbols_loaded = true; 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::LogSharedLibraryAddresses() { 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // SharedLibraryEvents are logged when loading symbol information. 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Only the shared libraries loaded at the time of the call to 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // LogSharedLibraryAddresses are logged. DLLs loaded after 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // initialization are not accounted for. 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!LoadDbgHelpAndTlHelp32()) return; 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE process_handle = GetCurrentProcess(); 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadSymbols(process_handle); 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1299f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid OS::SignalCodeMovingGC() { 1300f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 1301f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1302f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Walk the stack using the facilities in dbghelp.dll and tlhelp32.dll 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Switch off warning 4748 (/GS can not protect parameters and local variables 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from local buffer overrun because optimizations are disabled in function) as 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// it is triggered by the use of inline assembler. 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#pragma warning(push) 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#pragma warning(disable : 4748) 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::StackWalk(Vector<OS::StackFrame> frames) { 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BOOL ok; 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the required functions from DLL's. 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!LoadDbgHelpAndTlHelp32()) return kStackWalkError; 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the process and thread handles. 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE process_handle = GetCurrentProcess(); 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE thread_handle = GetCurrentThread(); 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read the symbols. 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!LoadSymbols(process_handle)) return kStackWalkError; 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Capture current context. 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CONTEXT context; 1325d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block RtlCaptureContext(&context); 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize the stack walking 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block STACKFRAME64 stack_frame; 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block memset(&stack_frame, 0, sizeof(stack_frame)); 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_frame.AddrPC.Offset = context.Rip; 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_frame.AddrFrame.Offset = context.Rbp; 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_frame.AddrStack.Offset = context.Rsp; 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_frame.AddrPC.Offset = context.Eip; 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_frame.AddrFrame.Offset = context.Ebp; 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_frame.AddrStack.Offset = context.Esp; 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_frame.AddrPC.Mode = AddrModeFlat; 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_frame.AddrFrame.Mode = AddrModeFlat; 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_frame.AddrStack.Mode = AddrModeFlat; 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int frames_count = 0; 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Collect stack frames. 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int frames_size = frames.length(); 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (frames_count < frames_size) { 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ok = _StackWalk64( 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IMAGE_FILE_MACHINE_I386, // MachineType 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block process_handle, // hProcess 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block thread_handle, // hThread 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &stack_frame, // StackFrame 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &context, // ContextRecord 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NULL, // ReadMemoryRoutine 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block _SymFunctionTableAccess64, // FunctionTableAccessRoutine 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block _SymGetModuleBase64, // GetModuleBaseRoutine 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block NULL); // TranslateAddress 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!ok) break; 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the address. 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT((stack_frame.AddrPC.Offset >> 32) == 0); // 32-bit address. 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frames[frames_count].address = 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<void*>(stack_frame.AddrPC.Offset); 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Try to locate a symbol for this frame. 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD64 symbol_displacement; 1366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SmartArrayPointer<IMAGEHLP_SYMBOL64> symbol( 136725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen NewArray<IMAGEHLP_SYMBOL64>(kStackWalkMaxNameLen)); 136825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (symbol.is_empty()) return kStackWalkError; // Out of memory. 136925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen memset(*symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + kStackWalkMaxNameLen); 137025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (*symbol)->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); 137125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (*symbol)->MaxNameLength = kStackWalkMaxNameLen; 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ok = _SymGetSymFromAddr64(process_handle, // hProcess 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_frame.AddrPC.Offset, // Address 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &symbol_displacement, // Displacement 137525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen *symbol); // Symbol 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ok) { 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Try to locate more source information for the symbol. 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block IMAGEHLP_LINE64 Line; 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block memset(&Line, 0, sizeof(Line)); 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Line.SizeOfStruct = sizeof(Line); 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD line_displacement; 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ok = _SymGetLineFromAddr64( 1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block process_handle, // hProcess 1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_frame.AddrPC.Offset, // dwAddr 1385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &line_displacement, // pdwDisplacement 1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block &Line); // Line 1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Format a text representation of the frame based on the information 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // available. 1389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (ok) { 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SNPrintF(MutableCStrVector(frames[frames_count].text, 1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block kStackWalkMaxTextLen), 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%s %s:%d:%d", 139325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (*symbol)->Name, Line.FileName, Line.LineNumber, 1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block line_displacement); 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SNPrintF(MutableCStrVector(frames[frames_count].text, 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block kStackWalkMaxTextLen), 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "%s", 139925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (*symbol)->Name); 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure line termination is in place. 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frames[frames_count].text[kStackWalkMaxTextLen - 1] = '\0'; 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // No text representation of this frame 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frames[frames_count].text[0] = '\0'; 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Continue if we are just missing a module (for non C/C++ frames a 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // module will never be found). 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int err = GetLastError(); 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (err != ERROR_MOD_NOT_FOUND) { 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block break; 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frames_count++; 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the number of frames filled in. 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return frames_count; 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Restore warnings to previous settings. 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#pragma warning(pop) 1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else // __MINGW32__ 1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid OS::LogSharedLibraryAddresses() { } 1427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid OS::SignalCodeMovingGC() { } 1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::StackWalk(Vector<OS::StackFrame> frames) { return 0; } 1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // __MINGW32__ 1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1432d0582a6c46733687d045e4188a1bcd0123c758a1Steve Blockuint64_t OS::CpuFeaturesImpliedByPlatform() { 1433d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block return 0; // Windows runs on anything. 1434d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block} 1435d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1436d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block 1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockdouble OS::nan_value() { 1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _MSC_VER 1439d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // Positive Quiet NaN with no payload (aka. Indeterminate) has all bits 1440d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block // in mask set, so value equals mask. 1441d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static const __int64 nanval = kQuietNaNMask; 1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return *reinterpret_cast<const double*>(&nanval); 1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else // _MSC_VER 1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NAN; 1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // _MSC_VER 1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint OS::ActivationFrameAlignment() { 1450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 16; // Windows 64-bit ABI requires the stack to be 16-byte aligned. 1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 8; // Floating-point math runs faster with 8-byte alignment. 1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1458f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkevoid OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) { 1459f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke MemoryBarrier(); 1460f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke *ptr = value; 1461f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke} 1462f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1463f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { } 1465592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1466592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory(size_t size) 14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : address_(ReserveRegion(size)), size_(size) { } 14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14713ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory(size_t size, size_t alignment) 14723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : address_(NULL), size_(0) { 14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment()))); 14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_t request_size = RoundUp(size + alignment, 14753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static_cast<intptr_t>(OS::AllocateAlignment())); 14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void* address = ReserveRegion(request_size); 14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (address == NULL) return; 14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address base = RoundUp(static_cast<Address>(address), alignment); 14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Try reducing the size by freeing and then reallocating a specific area. 14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool result = ReleaseRegion(address, request_size); 14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch USE(result); 14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(result); 14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address = VirtualAlloc(base, size, MEM_RESERVE, PAGE_NOACCESS); 14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (address != NULL) { 14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch request_size = size; 14863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(base == static_cast<Address>(address)); 14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Resizing failed, just go with a bigger area. 14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address = ReserveRegion(request_size); 14903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (address == NULL) return; 14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 14923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = address; 14933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_ = request_size; 1494592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 1495592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1496592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 149785b71799222b55eb5dd74ea26efe0c64ab655c8cBen MurdochVirtualMemory::~VirtualMemory() { 149885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch if (IsReserved()) { 14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool result = ReleaseRegion(address_, size_); 15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(result); 15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch USE(result); 1502592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 1503592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 1504592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 1505592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::IsReserved() { 15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return address_ != NULL; 15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid VirtualMemory::Reset() { 15123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch address_ = NULL; 15133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch size_ = 0; 15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 15153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 151785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) { 15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (CommitRegion(address, size, is_executable)) { 15193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UpdateAllocatedSpaceLimits(address, static_cast<int>(size)); 15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 15243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Uncommit(void* address, size_t size) { 15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(IsReserved()); 15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return UncommitRegion(address, size); 15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid* VirtualMemory::ReserveRegion(size_t size) { 15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return RandomizedVirtualAlloc(size, MEM_RESERVE, PAGE_NOACCESS); 15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) { 1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (NULL == VirtualAlloc(base, size, MEM_COMMIT, prot)) { 1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UpdateAllocatedSpaceLimits(base, static_cast<int>(size)); 1544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Guard(void* address) { 15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (NULL == VirtualAlloc(address, 15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::CommitPageSize(), 15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MEM_COMMIT, 15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PAGE_READONLY | PAGE_GUARD)) { 15533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::UncommitRegion(void* base, size_t size) { 15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return VirtualFree(base, size, MEM_DECOMMIT) != 0; 15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::ReleaseRegion(void* base, size_t size) { 15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return VirtualFree(base, 0, MEM_RELEASE) != 0; 1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Win32 thread support. 1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Definition of invalid thread handle and id. 1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic const HANDLE kNoThread = INVALID_HANDLE_VALUE; 1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Entry point for threads. The supplied argument is a pointer to the thread 1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// object. The entry function dispatches to the run method in the thread 1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// object. It is important that this function has __stdcall calling 1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// convention. 1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic unsigned int __stdcall ThreadEntry(void* arg) { 1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Thread* thread = reinterpret_cast<Thread*>(arg); 1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block thread->Run(); 1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Thread::PlatformData : public Malloced { 1587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit PlatformData(HANDLE thread) : thread_(thread) {} 1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE thread_; 15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned thread_id_; 1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Initialize a Win32 thread object. The thread has an invalid thread 1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// handle until it is started. 1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15973fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochThread::Thread(const Options& options) 15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : stack_size_(options.stack_size()) { 15999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block data_ = new PlatformData(kNoThread); 16003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_name(options.name()); 16019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 16029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 16039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 16049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid Thread::set_name(const char* name) { 1605b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch OS::StrNCpy(Vector<char>(name_, sizeof(name_)), name, strlen(name)); 16069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name_[sizeof(name_) - 1] = '\0'; 1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Close our own handle for the thread. 1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockThread::~Thread() { 1612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (data_->thread_ != kNoThread) CloseHandle(data_->thread_); 1613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete data_; 1614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Create a new thread. It is important to use _beginthreadex() instead of 1618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the Win32 function CreateThread(), because the CreateThread() does not 1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// initialize thread specific structures in the C runtime library. 1620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::Start() { 1621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data_->thread_ = reinterpret_cast<HANDLE>( 1622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block _beginthreadex(NULL, 162344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static_cast<unsigned>(stack_size_), 1624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ThreadEntry, 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this, 1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0, 16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &data_->thread_id_)); 1628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Wait for thread to terminate. 1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::Join() { 16333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (data_->thread_id_ != GetCurrentThreadId()) { 16343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch WaitForSingleObject(data_->thread_, INFINITE); 16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockThread::LocalStorageKey Thread::CreateThreadLocalKey() { 1640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD result = TlsAlloc(); 1641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result != TLS_OUT_OF_INDEXES); 1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return static_cast<LocalStorageKey>(result); 1643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::DeleteThreadLocalKey(LocalStorageKey key) { 1647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BOOL result = TlsFree(static_cast<DWORD>(key)); 1648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result); 1650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid* Thread::GetThreadLocal(LocalStorageKey key) { 1654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return TlsGetValue(static_cast<DWORD>(key)); 1655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::SetThreadLocal(LocalStorageKey key, void* value) { 1659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BOOL result = TlsSetValue(static_cast<DWORD>(key), value); 1660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block USE(result); 1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(result); 1662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Thread::YieldCPU() { 1667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Sleep(0); 1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 1672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Win32 mutex support. 1673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// On Win32 mutexes are implemented using CRITICAL_SECTION objects. These are 1675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// faster than Win32 Mutex objects because they are implemented using user mode 1676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// atomic instructions. Therefore we only do ring transitions if there is lock 1677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contention. 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Win32Mutex : public Mutex { 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Win32Mutex() { InitializeCriticalSection(&cs_); } 1682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual ~Win32Mutex() { DeleteCriticalSection(&cs_); } 1684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual int Lock() { 1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EnterCriticalSection(&cs_); 1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual int Unlock() { 1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LeaveCriticalSection(&cs_); 1692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual bool TryLock() { 1697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Returns non-zero if critical section is entered successfully entered. 1698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return TryEnterCriticalSection(&cs_); 1699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CRITICAL_SECTION cs_; // Critical section used for mutex 1703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockMutex* OS::CreateMutex() { 1707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new Win32Mutex(); 1708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 1712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Win32 semaphore support. 1713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 1714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// On Win32 semaphores are implemented using Win32 Semaphore objects. The 1715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// semaphores are anonymous. Also, the semaphores are initialized to have 1716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// no upper limit on count. 1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Win32Semaphore : public Semaphore { 1720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 1721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Win32Semaphore(int count) { 1722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sem = ::CreateSemaphoreA(NULL, count, 0x7fffffff, NULL); 1723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ~Win32Semaphore() { 1726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CloseHandle(sem); 1727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Wait() { 1730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WaitForSingleObject(sem, INFINITE); 1731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool Wait(int timeout) { 1734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Timeout in Windows API is in milliseconds. 1735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block DWORD millis_timeout = timeout / 1000; 1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return WaitForSingleObject(sem, millis_timeout) != WAIT_TIMEOUT; 1737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Signal() { 1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LONG dummy; 1741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ReleaseSemaphore(sem, 1, &dummy); 1742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE sem; 1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSemaphore* OS::CreateSemaphore(int count) { 1750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new Win32Semaphore(count); 1751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 1755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Win32 socket support. 1756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 1757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Win32Socket : public Socket { 1759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Win32Socket() { 1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Create the socket. 1762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 1763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block explicit Win32Socket(SOCKET socket): socket_(socket) { } 1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block virtual ~Win32Socket() { Shutdown(); } 1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Server initialization. 1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool Bind(const int port); 1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool Listen(int backlog) const; 1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Socket* Accept() const; 1771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Client initialization. 1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool Connect(const char* host, const char* port); 1774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shutdown socket for both read and write. 1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool Shutdown(); 1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Data Transimission 1779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int Send(const char* data, int len) const; 1780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int Receive(char* data, int len) const; 1781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool SetReuseAddress(bool reuse_address); 1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsValid() const { return socket_ != INVALID_SOCKET; } 1785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 1787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SOCKET socket_; 1788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Win32Socket::Bind(const int port) { 1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!IsValid()) { 1793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 1794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sockaddr_in addr; 1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block memset(&addr, 0, sizeof(addr)); 1798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr.sin_family = AF_INET; 1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 1800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addr.sin_port = htons(port); 1801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int status = bind(socket_, 1802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<struct sockaddr *>(&addr), 1803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sizeof(addr)); 1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return status == 0; 1805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Win32Socket::Listen(int backlog) const { 1809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!IsValid()) { 1810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int status = listen(socket_, backlog); 1814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return status == 0; 1815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSocket* Win32Socket::Accept() const { 1819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!IsValid()) { 1820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 1821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SOCKET socket = accept(socket_, NULL, NULL); 1824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (socket == INVALID_SOCKET) { 1825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return NULL; 1826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new Win32Socket(socket); 1828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Win32Socket::Connect(const char* host, const char* port) { 1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!IsValid()) { 1834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Lookup host and port. 1838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct addrinfo *result = NULL; 1839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block struct addrinfo hints; 1840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block memset(&hints, 0, sizeof(addrinfo)); 1841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block hints.ai_family = AF_INET; 1842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block hints.ai_socktype = SOCK_STREAM; 1843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block hints.ai_protocol = IPPROTO_TCP; 1844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int status = getaddrinfo(host, port, &hints, &result); 1845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (status != 0) { 1846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 1847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Connect. 1850d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block status = connect(socket_, 1851d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block result->ai_addr, 1852d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block static_cast<int>(result->ai_addrlen)); 1853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block freeaddrinfo(result); 1854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return status == 0; 1855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Win32Socket::Shutdown() { 1859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (IsValid()) { 1860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shutdown socket for both read and write. 1861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int status = shutdown(socket_, SD_BOTH); 1862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block closesocket(socket_); 1863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block socket_ = INVALID_SOCKET; 1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return status == SOCKET_ERROR; 1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 1867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Win32Socket::Send(const char* data, int len) const { 1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int status = send(socket_, data, len, 0); 1872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return status; 1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Win32Socket::Receive(char* data, int len) const { 1877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int status = recv(socket_, data, len, 0); 1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return status; 1879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool Win32Socket::SetReuseAddress(bool reuse_address) { 1883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BOOL on = reuse_address ? true : false; 1884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, 1885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reinterpret_cast<char*>(&on), sizeof(on)); 1886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return status == SOCKET_ERROR; 1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool Socket::SetUp() { 1891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize Winsock32 1892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int err; 1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WSADATA winsock_data; 1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block WORD version_requested = MAKEWORD(1, 0); 1895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block err = WSAStartup(version_requested, &winsock_data); 1896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (err != 0) { 1897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PrintF("Unable to initialize Winsock, err = %d\n", Socket::LastError()); 1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return err == 0; 1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint Socket::LastError() { 1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return WSAGetLastError(); 1906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuint16_t Socket::HToN(uint16_t value) { 1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return htons(value); 1911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuint16_t Socket::NToH(uint16_t value) { 1915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ntohs(value); 1916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuint32_t Socket::HToN(uint32_t value) { 1920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return htonl(value); 1921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockuint32_t Socket::NToH(uint32_t value) { 1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ntohl(value); 1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSocket* OS::CreateSocket() { 1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new Win32Socket(); 1931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ---------------------------------------------------------------------------- 1935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Win32 profiler support. 1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Sampler::PlatformData : public Malloced { 1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 193944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get a handle to the calling thread. This is the thread that we are 194044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // going to profile. We need to make a copy of the handle because we are 194144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // going to use it in the sampler thread. Using GetThreadHandle() will 194244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // not work in this case. We're using OpenThread because DuplicateHandle 194344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // for some reason doesn't work in Chrome's sandbox. 194444f0eee88ff00398ff7f715fab053374d808c90dSteve Block PlatformData() : profiled_thread_(OpenThread(THREAD_GET_CONTEXT | 194544f0eee88ff00398ff7f715fab053374d808c90dSteve Block THREAD_SUSPEND_RESUME | 194644f0eee88ff00398ff7f715fab053374d808c90dSteve Block THREAD_QUERY_INFORMATION, 194744f0eee88ff00398ff7f715fab053374d808c90dSteve Block false, 194844f0eee88ff00398ff7f715fab053374d808c90dSteve Block GetCurrentThreadId())) {} 194944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 195044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ~PlatformData() { 195144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (profiled_thread_ != NULL) { 195244f0eee88ff00398ff7f715fab053374d808c90dSteve Block CloseHandle(profiled_thread_); 195344f0eee88ff00398ff7f715fab053374d808c90dSteve Block profiled_thread_ = NULL; 195444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 195744f0eee88ff00398ff7f715fab053374d808c90dSteve Block HANDLE profiled_thread() { return profiled_thread_; } 195844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 195944f0eee88ff00398ff7f715fab053374d808c90dSteve Block private: 1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HANDLE profiled_thread_; 196144f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 196244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 196344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 196444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass SamplerThread : public Thread { 196544f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static const int kSamplerThreadStackSize = 64 * KB; 19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 196844f0eee88ff00398ff7f715fab053374d808c90dSteve Block explicit SamplerThread(int interval) 19693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)), 197044f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval_(interval) {} 197144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 197244f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void AddActiveSampler(Sampler* sampler) { 19733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopedLock lock(mutex_.Pointer()); 197444f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::AddActiveSampler(sampler); 197544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (instance_ == NULL) { 197644f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_ = new SamplerThread(sampler->interval()); 197744f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_->Start(); 197844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 197944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(instance_->interval_ == sampler->interval()); 198044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 198144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 198244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 198344f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void RemoveActiveSampler(Sampler* sampler) { 19843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopedLock lock(mutex_.Pointer()); 198544f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::RemoveActiveSampler(sampler); 198644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { 19873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); 198844f0eee88ff00398ff7f715fab053374d808c90dSteve Block delete instance_; 198944f0eee88ff00398ff7f715fab053374d808c90dSteve Block instance_ = NULL; 199044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 199144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 1992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 199344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Implement Thread::Run(). 199444f0eee88ff00398ff7f715fab053374d808c90dSteve Block virtual void Run() { 199544f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::State state; 199644f0eee88ff00398ff7f715fab053374d808c90dSteve Block while ((state = SamplerRegistry::GetState()) != 199744f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerRegistry::HAS_NO_SAMPLERS) { 199844f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool cpu_profiling_enabled = 199944f0eee88ff00398ff7f715fab053374d808c90dSteve Block (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS); 200044f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled(); 200144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // When CPU profiling is enabled both JavaScript and C++ code is 200244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // profiled. We must not suspend. 200344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!cpu_profiling_enabled) { 200444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (rate_limiter_.SuspendIfNecessary()) continue; 200544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 200644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (cpu_profiling_enabled) { 200744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) { 200844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 200944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 201044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 201144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (runtime_profiler_enabled) { 201244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) { 201344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 201444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 201544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 201644f0eee88ff00398ff7f715fab053374d808c90dSteve Block OS::Sleep(interval_); 2017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 202044f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void DoCpuProfile(Sampler* sampler, void* raw_sampler_thread) { 202144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!sampler->isolate()->IsInitialized()) return; 202244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!sampler->IsProfiling()) return; 202344f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerThread* sampler_thread = 202444f0eee88ff00398ff7f715fab053374d808c90dSteve Block reinterpret_cast<SamplerThread*>(raw_sampler_thread); 202544f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler_thread->SampleContext(sampler); 202644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 202744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 202844f0eee88ff00398ff7f715fab053374d808c90dSteve Block static void DoRuntimeProfile(Sampler* sampler, void* ignored) { 202944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!sampler->isolate()->IsInitialized()) return; 203044f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->isolate()->runtime_profiler()->NotifyTick(); 203144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 203244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 203344f0eee88ff00398ff7f715fab053374d808c90dSteve Block void SampleContext(Sampler* sampler) { 203444f0eee88ff00398ff7f715fab053374d808c90dSteve Block HANDLE profiled_thread = sampler->platform_data()->profiled_thread(); 203544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (profiled_thread == NULL) return; 2036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 203744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Context used for sampling the register state of the profiled thread. 203844f0eee88ff00398ff7f715fab053374d808c90dSteve Block CONTEXT context; 203944f0eee88ff00398ff7f715fab053374d808c90dSteve Block memset(&context, 0, sizeof(context)); 2040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 204144f0eee88ff00398ff7f715fab053374d808c90dSteve Block TickSample sample_obj; 204244f0eee88ff00398ff7f715fab053374d808c90dSteve Block TickSample* sample = CpuProfiler::TickSampleEvent(sampler->isolate()); 204344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (sample == NULL) sample = &sample_obj; 2044f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 204544f0eee88ff00398ff7f715fab053374d808c90dSteve Block static const DWORD kSuspendFailed = static_cast<DWORD>(-1); 204644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (SuspendThread(profiled_thread) == kSuspendFailed) return; 204744f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->state = sampler->isolate()->current_vm_state(); 204844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 204944f0eee88ff00398ff7f715fab053374d808c90dSteve Block context.ContextFlags = CONTEXT_FULL; 205044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (GetThreadContext(profiled_thread, &context) != 0) { 2051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if V8_HOST_ARCH_X64 205244f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->pc = reinterpret_cast<Address>(context.Rip); 205344f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->sp = reinterpret_cast<Address>(context.Rsp); 205444f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->fp = reinterpret_cast<Address>(context.Rbp); 2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 205644f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->pc = reinterpret_cast<Address>(context.Eip); 205744f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->sp = reinterpret_cast<Address>(context.Esp); 205844f0eee88ff00398ff7f715fab053374d808c90dSteve Block sample->fp = reinterpret_cast<Address>(context.Ebp); 2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 206044f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->SampleStack(sample); 206144f0eee88ff00398ff7f715fab053374d808c90dSteve Block sampler->Tick(sample); 2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 206344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ResumeThread(profiled_thread); 2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 206544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 206644f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int interval_; 206744f0eee88ff00398ff7f715fab053374d808c90dSteve Block RuntimeProfilerRateLimiter rate_limiter_; 206844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 206944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Protects the process wide state below. 20703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch static LazyMutex mutex_; 207144f0eee88ff00398ff7f715fab053374d808c90dSteve Block static SamplerThread* instance_; 207244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 20733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private: 207444f0eee88ff00398ff7f715fab053374d808c90dSteve Block DISALLOW_COPY_AND_ASSIGN(SamplerThread); 2075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20783ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochLazyMutex SamplerThread::mutex_ = LAZY_MUTEX_INITIALIZER; 207944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSamplerThread* SamplerThread::instance_ = NULL; 2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 208244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSampler::Sampler(Isolate* isolate, int interval) 208344f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(isolate), 208444f0eee88ff00398ff7f715fab053374d808c90dSteve Block interval_(interval), 2085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch profiling_(false), 20868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang active_(false), 20878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang samples_taken_(0) { 208844f0eee88ff00398ff7f715fab053374d808c90dSteve Block data_ = new PlatformData; 2089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSampler::~Sampler() { 209344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!IsActive()); 2094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete data_; 2095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Sampler::Start() { 2099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsActive()); 2100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetActive(true); 210144f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerThread::AddActiveSampler(this); 2102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid Sampler::Stop() { 210644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(IsActive()); 210744f0eee88ff00398ff7f715fab053374d808c90dSteve Block SamplerThread::RemoveActiveSampler(this); 2108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetActive(false); 2109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 2113