[V8] Fix stack alignment corruption for MinGW32 build
[qt:qtjsbackend.git] / src / 3rdparty / v8 / src / platform-win32.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 // Platform specific code for Win32.
29
30 // Secure API functions are not available using MinGW with msvcrt.dll
31 // on Windows XP. Make sure MINGW_HAS_SECURE_API is not defined to
32 // disable definition of secure API functions in standard headers that
33 // would conflict with our own implementation.
34 #ifdef __MINGW32__
35 #include <_mingw.h>
36 #ifdef MINGW_HAS_SECURE_API
37 #undef MINGW_HAS_SECURE_API
38 #endif  // MINGW_HAS_SECURE_API
39 #endif  // __MINGW32__
40
41 #define V8_WIN32_HEADERS_FULL
42 #include "win32-headers.h"
43
44 #include "v8.h"
45
46 #include "codegen.h"
47 #include "platform.h"
48 #include "vm-state-inl.h"
49
50 #ifdef _MSC_VER
51
52 // Case-insensitive bounded string comparisons. Use stricmp() on Win32. Usually
53 // defined in strings.h.
54 int strncasecmp(const char* s1, const char* s2, int n) {
55   return _strnicmp(s1, s2, n);
56 }
57
58 #endif  // _MSC_VER
59
60
61 #ifdef _WIN32_WCE
62 // Convert a Latin1 string into a utf16 string
63 wchar_t* wce_mbtowc(const char* a) {
64     int length = strlen(a);
65     wchar_t *wbuf = new wchar_t[length];
66
67     for (int i = 0; i < length; ++i)
68         wbuf[i] = (wchar_t)a[i];
69
70     return wbuf;
71 }
72 #endif // _WIN32_WCE
73
74
75 // Extra functions for MinGW. Most of these are the _s functions which are in
76 // the Microsoft Visual Studio C++ CRT.
77 #ifdef __MINGW32__
78
79
80 #ifndef __MINGW64_VERSION_MAJOR
81
82 #define _TRUNCATE 0
83 #define STRUNCATE 80
84
85 inline void MemoryBarrier() {
86   int barrier = 0;
87   __asm__ __volatile__("xchgl %%eax,%0 ":"=r" (barrier));
88 }
89
90 #endif  // __MINGW64_VERSION_MAJOR
91
92
93 int localtime_s(tm* out_tm, const time_t* time) {
94   tm* posix_local_time_struct = localtime(time);
95   if (posix_local_time_struct == NULL) return 1;
96   *out_tm = *posix_local_time_struct;
97   return 0;
98 }
99
100
101 int fopen_s(FILE** pFile, const char* filename, const char* mode) {
102   *pFile = fopen(filename, mode);
103   return *pFile != NULL ? 0 : 1;
104 }
105
106 int _vsnprintf_s(char* buffer, size_t sizeOfBuffer, size_t count,
107                  const char* format, va_list argptr) {
108   ASSERT(count == _TRUNCATE);
109   return _vsnprintf(buffer, sizeOfBuffer, format, argptr);
110 }
111
112
113 int strncpy_s(char* dest, size_t dest_size, const char* source, size_t count) {
114   CHECK(source != NULL);
115   CHECK(dest != NULL);
116   CHECK_GT(dest_size, 0);
117
118   if (count == _TRUNCATE) {
119     while (dest_size > 0 && *source != 0) {
120       *(dest++) = *(source++);
121       --dest_size;
122     }
123     if (dest_size == 0) {
124       *(dest - 1) = 0;
125       return STRUNCATE;
126     }
127   } else {
128     while (dest_size > 0 && count > 0 && *source != 0) {
129       *(dest++) = *(source++);
130       --dest_size;
131       --count;
132     }
133   }
134   CHECK_GT(dest_size, 0);
135   *dest = 0;
136   return 0;
137 }
138
139 #endif  // __MINGW32__
140
141 // Generate a pseudo-random number in the range 0-2^31-1. Usually
142 // defined in stdlib.h. Missing in both Microsoft Visual Studio C++ and MinGW.
143 int random() {
144   return rand();
145 }
146
147
148 namespace v8 {
149 namespace internal {
150
151 intptr_t OS::MaxVirtualMemory() {
152   return 0;
153 }
154
155
156 double ceiling(double x) {
157   return ceil(x);
158 }
159
160
161 static Mutex* limit_mutex = NULL;
162
163 #if defined(V8_TARGET_ARCH_IA32)
164 static OS::MemCopyFunction memcopy_function = NULL;
165 // Defined in codegen-ia32.cc.
166 OS::MemCopyFunction CreateMemCopyFunction();
167
168 // Copy memory area to disjoint memory area.
169 void OS::MemCopy(void* dest, const void* src, size_t size) {
170   // Note: here we rely on dependent reads being ordered. This is true
171   // on all architectures we currently support.
172   (*memcopy_function)(dest, src, size);
173 #ifdef DEBUG
174   CHECK_EQ(0, memcmp(dest, src, size));
175 #endif
176 }
177 #endif  // V8_TARGET_ARCH_IA32
178
179 #ifdef _WIN32_WCE
180 // TODO: Implement
181 CpuImplementer OS::GetCpuImplementer() {
182     return UNKNOWN_IMPLEMENTER;
183 }
184 #endif // _WIN32_WCE
185
186 #ifdef _WIN64
187 typedef double (*ModuloFunction)(double, double);
188 static ModuloFunction modulo_function = NULL;
189 // Defined in codegen-x64.cc.
190 ModuloFunction CreateModuloFunction();
191
192 void init_modulo_function() {
193   modulo_function = CreateModuloFunction();
194 }
195
196 double modulo(double x, double y) {
197   // Note: here we rely on dependent reads being ordered. This is true
198   // on all architectures we currently support.
199   return (*modulo_function)(x, y);
200 }
201 #else  // Win32
202
203 double modulo(double x, double y) {
204   // Workaround MS fmod bugs. ECMA-262 says:
205   // dividend is finite and divisor is an infinity => result equals dividend
206   // dividend is a zero and divisor is nonzero finite => result equals dividend
207   if (!(isfinite(x) && (!isfinite(y) && !isnan(y))) &&
208       !(x == 0 && (y != 0 && isfinite(y)))) {
209     x = fmod(x, y);
210   }
211   return x;
212 }
213
214 #endif  // _WIN64
215
216
217 #define UNARY_MATH_FUNCTION(name, generator)             \
218 static UnaryMathFunction fast_##name##_function = NULL;  \
219 void init_fast_##name##_function() {                     \
220   fast_##name##_function = generator;                    \
221 }                                                        \
222 double fast_##name(double x) {                           \
223   return (*fast_##name##_function)(x);                   \
224 }
225
226 UNARY_MATH_FUNCTION(sin, CreateTranscendentalFunction(TranscendentalCache::SIN))
227 UNARY_MATH_FUNCTION(cos, CreateTranscendentalFunction(TranscendentalCache::COS))
228 UNARY_MATH_FUNCTION(tan, CreateTranscendentalFunction(TranscendentalCache::TAN))
229 UNARY_MATH_FUNCTION(log, CreateTranscendentalFunction(TranscendentalCache::LOG))
230 UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction())
231
232 #undef UNARY_MATH_FUNCTION
233
234
235 void MathSetup() {
236 #ifdef _WIN64
237   init_modulo_function();
238 #endif
239   init_fast_sin_function();
240   init_fast_cos_function();
241   init_fast_tan_function();
242   init_fast_log_function();
243   init_fast_sqrt_function();
244 }
245
246
247 // ----------------------------------------------------------------------------
248 // The Time class represents time on win32. A timestamp is represented as
249 // a 64-bit integer in 100 nanoseconds since January 1, 1601 (UTC). JavaScript
250 // timestamps are represented as a doubles in milliseconds since 00:00:00 UTC,
251 // January 1, 1970.
252
253 class Time {
254  public:
255   // Constructors.
256   Time();
257   explicit Time(double jstime);
258   Time(int year, int mon, int day, int hour, int min, int sec);
259
260   // Convert timestamp to JavaScript representation.
261   double ToJSTime();
262
263   // Set timestamp to current time.
264   void SetToCurrentTime();
265
266   // Returns the local timezone offset in milliseconds east of UTC. This is
267   // the number of milliseconds you must add to UTC to get local time, i.e.
268   // LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This
269   // routine also takes into account whether daylight saving is effect
270   // at the time.
271   int64_t LocalOffset();
272
273   // Returns the daylight savings time offset for the time in milliseconds.
274   int64_t DaylightSavingsOffset();
275
276   // Returns a string identifying the current timezone for the
277   // timestamp taking into account daylight saving.
278   char* LocalTimezone();
279
280  private:
281   // Constants for time conversion.
282   static const int64_t kTimeEpoc = 116444736000000000LL;
283   static const int64_t kTimeScaler = 10000;
284   static const int64_t kMsPerMinute = 60000;
285
286   // Constants for timezone information.
287   static const int kTzNameSize = 128;
288   static const bool kShortTzNames = false;
289
290   // Timezone information. We need to have static buffers for the
291   // timezone names because we return pointers to these in
292   // LocalTimezone().
293   static bool tz_initialized_;
294   static TIME_ZONE_INFORMATION tzinfo_;
295   static char std_tz_name_[kTzNameSize];
296   static char dst_tz_name_[kTzNameSize];
297
298   // Initialize the timezone information (if not already done).
299   static void TzSet();
300
301   // Guess the name of the timezone from the bias.
302   static const char* GuessTimezoneNameFromBias(int bias);
303
304   // Return whether or not daylight savings time is in effect at this time.
305   bool InDST();
306
307   // Return the difference (in milliseconds) between this timestamp and
308   // another timestamp.
309   int64_t Diff(Time* other);
310
311   // Accessor for FILETIME representation.
312   FILETIME& ft() { return time_.ft_; }
313
314   // Accessor for integer representation.
315   int64_t& t() { return time_.t_; }
316
317   // Although win32 uses 64-bit integers for representing timestamps,
318   // these are packed into a FILETIME structure. The FILETIME structure
319   // is just a struct representing a 64-bit integer. The TimeStamp union
320   // allows access to both a FILETIME and an integer representation of
321   // the timestamp.
322   union TimeStamp {
323     FILETIME ft_;
324     int64_t t_;
325   };
326
327   TimeStamp time_;
328 };
329
330 // Static variables.
331 bool Time::tz_initialized_ = false;
332 TIME_ZONE_INFORMATION Time::tzinfo_;
333 char Time::std_tz_name_[kTzNameSize];
334 char Time::dst_tz_name_[kTzNameSize];
335
336
337 // Initialize timestamp to start of epoc.
338 Time::Time() {
339   t() = 0;
340 }
341
342
343 // Initialize timestamp from a JavaScript timestamp.
344 Time::Time(double jstime) {
345   t() = static_cast<int64_t>(jstime) * kTimeScaler + kTimeEpoc;
346 }
347
348
349 // Initialize timestamp from date/time components.
350 Time::Time(int year, int mon, int day, int hour, int min, int sec) {
351   SYSTEMTIME st;
352   st.wYear = year;
353   st.wMonth = mon;
354   st.wDay = day;
355   st.wHour = hour;
356   st.wMinute = min;
357   st.wSecond = sec;
358   st.wMilliseconds = 0;
359   SystemTimeToFileTime(&st, &ft());
360 }
361
362
363 // Convert timestamp to JavaScript timestamp.
364 double Time::ToJSTime() {
365   return static_cast<double>((t() - kTimeEpoc) / kTimeScaler);
366 }
367
368
369 // Guess the name of the timezone from the bias.
370 // The guess is very biased towards the northern hemisphere.
371 const char* Time::GuessTimezoneNameFromBias(int bias) {
372   static const int kHour = 60;
373   switch (-bias) {
374     case -9*kHour: return "Alaska";
375     case -8*kHour: return "Pacific";
376     case -7*kHour: return "Mountain";
377     case -6*kHour: return "Central";
378     case -5*kHour: return "Eastern";
379     case -4*kHour: return "Atlantic";
380     case  0*kHour: return "GMT";
381     case +1*kHour: return "Central Europe";
382     case +2*kHour: return "Eastern Europe";
383     case +3*kHour: return "Russia";
384     case +5*kHour + 30: return "India";
385     case +8*kHour: return "China";
386     case +9*kHour: return "Japan";
387     case +12*kHour: return "New Zealand";
388     default: return "Local";
389   }
390 }
391
392
393 // Initialize timezone information. The timezone information is obtained from
394 // windows. If we cannot get the timezone information we fall back to CET.
395 // Please notice that this code is not thread-safe.
396 void Time::TzSet() {
397   // Just return if timezone information has already been initialized.
398   if (tz_initialized_) return;
399
400   // Initialize POSIX time zone data.
401 #ifndef _WIN32_WCE
402   _tzset();
403 #endif // _WIN32_WCE
404   // Obtain timezone information from operating system.
405   memset(&tzinfo_, 0, sizeof(tzinfo_));
406   if (GetTimeZoneInformation(&tzinfo_) == TIME_ZONE_ID_INVALID) {
407     // If we cannot get timezone information we fall back to CET.
408     tzinfo_.Bias = -60;
409     tzinfo_.StandardDate.wMonth = 10;
410     tzinfo_.StandardDate.wDay = 5;
411     tzinfo_.StandardDate.wHour = 3;
412     tzinfo_.StandardBias = 0;
413     tzinfo_.DaylightDate.wMonth = 3;
414     tzinfo_.DaylightDate.wDay = 5;
415     tzinfo_.DaylightDate.wHour = 2;
416     tzinfo_.DaylightBias = -60;
417   }
418
419   // Make standard and DST timezone names.
420   WideCharToMultiByte(CP_UTF8, 0, tzinfo_.StandardName, -1,
421                       std_tz_name_, kTzNameSize, NULL, NULL);
422   std_tz_name_[kTzNameSize - 1] = '\0';
423   WideCharToMultiByte(CP_UTF8, 0, tzinfo_.DaylightName, -1,
424                       dst_tz_name_, kTzNameSize, NULL, NULL);
425   dst_tz_name_[kTzNameSize - 1] = '\0';
426
427   // If OS returned empty string or resource id (like "@tzres.dll,-211")
428   // simply guess the name from the UTC bias of the timezone.
429   // To properly resolve the resource identifier requires a library load,
430   // which is not possible in a sandbox.
431   if (std_tz_name_[0] == '\0' || std_tz_name_[0] == '@') {
432     OS::SNPrintF(Vector<char>(std_tz_name_, kTzNameSize - 1),
433                  "%s Standard Time",
434                  GuessTimezoneNameFromBias(tzinfo_.Bias));
435   }
436   if (dst_tz_name_[0] == '\0' || dst_tz_name_[0] == '@') {
437     OS::SNPrintF(Vector<char>(dst_tz_name_, kTzNameSize - 1),
438                  "%s Daylight Time",
439                  GuessTimezoneNameFromBias(tzinfo_.Bias));
440   }
441
442   // Timezone information initialized.
443   tz_initialized_ = true;
444 }
445
446
447 // Return the difference in milliseconds between this and another timestamp.
448 int64_t Time::Diff(Time* other) {
449   return (t() - other->t()) / kTimeScaler;
450 }
451
452
453 // Set timestamp to current time.
454 void Time::SetToCurrentTime() {
455   // The default GetSystemTimeAsFileTime has a ~15.5ms resolution.
456   // Because we're fast, we like fast timers which have at least a
457   // 1ms resolution.
458   //
459   // timeGetTime() provides 1ms granularity when combined with
460   // timeBeginPeriod().  If the host application for v8 wants fast
461   // timers, it can use timeBeginPeriod to increase the resolution.
462   //
463   // Using timeGetTime() has a drawback because it is a 32bit value
464   // and hence rolls-over every ~49days.
465   //
466   // To use the clock, we use GetSystemTimeAsFileTime as our base;
467   // and then use timeGetTime to extrapolate current time from the
468   // start time.  To deal with rollovers, we resync the clock
469   // any time when more than kMaxClockElapsedTime has passed or
470   // whenever timeGetTime creates a rollover.
471
472   static bool initialized = false;
473   static TimeStamp init_time;
474   static DWORD init_ticks;
475   static const int64_t kHundredNanosecondsPerSecond = 10000000;
476   static const int64_t kMaxClockElapsedTime =
477       60*kHundredNanosecondsPerSecond;  // 1 minute
478
479   // If we are uninitialized, we need to resync the clock.
480   bool needs_resync = !initialized;
481
482   // Get the current time.
483   TimeStamp time_now;
484   GetSystemTimeAsFileTime(&time_now.ft_);
485   DWORD ticks_now = timeGetTime();
486
487   // Check if we need to resync due to clock rollover.
488   needs_resync |= ticks_now < init_ticks;
489
490   // Check if we need to resync due to elapsed time.
491   needs_resync |= (time_now.t_ - init_time.t_) > kMaxClockElapsedTime;
492
493   // Check if we need to resync due to backwards time change.
494   needs_resync |= time_now.t_ < init_time.t_;
495
496   // Resync the clock if necessary.
497   if (needs_resync) {
498     GetSystemTimeAsFileTime(&init_time.ft_);
499     init_ticks = ticks_now = timeGetTime();
500     initialized = true;
501   }
502
503   // Finally, compute the actual time.  Why is this so hard.
504   DWORD elapsed = ticks_now - init_ticks;
505   this->time_.t_ = init_time.t_ + (static_cast<int64_t>(elapsed) * 10000);
506 }
507
508
509 // Return the local timezone offset in milliseconds east of UTC. This
510 // takes into account whether daylight saving is in effect at the time.
511 // Only times in the 32-bit Unix range may be passed to this function.
512 // Also, adding the time-zone offset to the input must not overflow.
513 // The function EquivalentTime() in date.js guarantees this.
514 int64_t Time::LocalOffset() {
515 #ifndef _WIN32_WCE
516   // Initialize timezone information, if needed.
517   TzSet();
518
519   Time rounded_to_second(*this);
520   rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler *
521       1000 * kTimeScaler;
522   // Convert to local time using POSIX localtime function.
523   // Windows XP Service Pack 3 made SystemTimeToTzSpecificLocalTime()
524   // very slow.  Other browsers use localtime().
525
526   // Convert from JavaScript milliseconds past 1/1/1970 0:00:00 to
527   // POSIX seconds past 1/1/1970 0:00:00.
528   double unchecked_posix_time = rounded_to_second.ToJSTime() / 1000;
529   if (unchecked_posix_time > INT_MAX || unchecked_posix_time < 0) {
530     return 0;
531   }
532   // Because _USE_32BIT_TIME_T is defined, time_t is a 32-bit int.
533   time_t posix_time = static_cast<time_t>(unchecked_posix_time);
534
535   // Convert to local time, as struct with fields for day, hour, year, etc.
536   tm posix_local_time_struct;
537   if (localtime_s(&posix_local_time_struct, &posix_time)) return 0;
538
539   if (posix_local_time_struct.tm_isdst > 0) {
540     return (tzinfo_.Bias + tzinfo_.DaylightBias) * -kMsPerMinute;
541   } else if (posix_local_time_struct.tm_isdst == 0) {
542     return (tzinfo_.Bias + tzinfo_.StandardBias) * -kMsPerMinute;
543   } else {
544     return tzinfo_.Bias * -kMsPerMinute;
545   }
546 #else
547   // Windows CE has a different handling of Timezones.
548   // TODO: Adapt this for Windows CE
549   return 0;
550 #endif
551 }
552
553
554 // Return whether or not daylight savings time is in effect at this time.
555 bool Time::InDST() {
556   // Initialize timezone information, if needed.
557   TzSet();
558
559   // Determine if DST is in effect at the specified time.
560   bool in_dst = false;
561   if (tzinfo_.StandardDate.wMonth != 0 || tzinfo_.DaylightDate.wMonth != 0) {
562     // Get the local timezone offset for the timestamp in milliseconds.
563     int64_t offset = LocalOffset();
564
565     // Compute the offset for DST. The bias parameters in the timezone info
566     // are specified in minutes. These must be converted to milliseconds.
567     int64_t dstofs = -(tzinfo_.Bias + tzinfo_.DaylightBias) * kMsPerMinute;
568
569     // If the local time offset equals the timezone bias plus the daylight
570     // bias then DST is in effect.
571     in_dst = offset == dstofs;
572   }
573
574   return in_dst;
575 }
576
577
578 // Return the daylight savings time offset for this time.
579 int64_t Time::DaylightSavingsOffset() {
580   return InDST() ? 60 * kMsPerMinute : 0;
581 }
582
583
584 // Returns a string identifying the current timezone for the
585 // timestamp taking into account daylight saving.
586 char* Time::LocalTimezone() {
587   // Return the standard or DST time zone name based on whether daylight
588   // saving is in effect at the given time.
589   return InDST() ? dst_tz_name_ : std_tz_name_;
590 }
591
592
593 void OS::PostSetUp() {
594   // Math functions depend on CPU features therefore they are initialized after
595   // CPU.
596   MathSetup();
597 #if defined(V8_TARGET_ARCH_IA32)
598   memcopy_function = CreateMemCopyFunction();
599 #endif
600 }
601
602 #ifdef V8_TARGET_ARCH_ARM
603 // TODO: Implement
604 // Windows CE is the only platform right now that supports ARM.
605 bool OS::ArmCpuHasFeature(CpuFeature feature) {
606   return false;
607 }
608 #endif // V8_TARGET_ARCH_ARM
609
610
611 // Returns the accumulated user time for thread.
612 int OS::GetUserTime(uint32_t* secs,  uint32_t* usecs) {
613   FILETIME dummy;
614   uint64_t usertime;
615
616   // Get the amount of time that the thread has executed in user mode.
617   if (!GetThreadTimes(GetCurrentThread(), &dummy, &dummy, &dummy,
618                       reinterpret_cast<FILETIME*>(&usertime))) return -1;
619
620   // Adjust the resolution to micro-seconds.
621   usertime /= 10;
622
623   // Convert to seconds and microseconds
624   *secs = static_cast<uint32_t>(usertime / 1000000);
625   *usecs = static_cast<uint32_t>(usertime % 1000000);
626   return 0;
627 }
628
629
630 // Returns current time as the number of milliseconds since
631 // 00:00:00 UTC, January 1, 1970.
632 double OS::TimeCurrentMillis() {
633   Time t;
634   t.SetToCurrentTime();
635   return t.ToJSTime();
636 }
637
638 // Returns the tickcounter based on timeGetTime.
639 int64_t OS::Ticks() {
640   return timeGetTime() * 1000;  // Convert to microseconds.
641 }
642
643
644 // Returns a string identifying the current timezone taking into
645 // account daylight saving.
646 const char* OS::LocalTimezone(double time) {
647   return Time(time).LocalTimezone();
648 }
649
650
651 // Returns the local time offset in milliseconds east of UTC without
652 // taking daylight savings time into account.
653 double OS::LocalTimeOffset() {
654   // Use current time, rounded to the millisecond.
655   Time t(TimeCurrentMillis());
656   // Time::LocalOffset inlcudes any daylight savings offset, so subtract it.
657   return static_cast<double>(t.LocalOffset() - t.DaylightSavingsOffset());
658 }
659
660
661 // Returns the daylight savings offset in milliseconds for the given
662 // time.
663 double OS::DaylightSavingsOffset(double time) {
664   int64_t offset = Time(time).DaylightSavingsOffset();
665   return static_cast<double>(offset);
666 }
667
668
669 int OS::GetLastError() {
670   return ::GetLastError();
671 }
672
673
674 int OS::GetCurrentProcessId() {
675   return static_cast<int>(::GetCurrentProcessId());
676 }
677
678
679 // ----------------------------------------------------------------------------
680 // Win32 console output.
681 //
682 // If a Win32 application is linked as a console application it has a normal
683 // standard output and standard error. In this case normal printf works fine
684 // for output. However, if the application is linked as a GUI application,
685 // the process doesn't have a console, and therefore (debugging) output is lost.
686 // This is the case if we are embedded in a windows program (like a browser).
687 // In order to be able to get debug output in this case the the debugging
688 // facility using OutputDebugString. This output goes to the active debugger
689 // for the process (if any). Else the output can be monitored using DBMON.EXE.
690
691 enum OutputMode {
692   UNKNOWN,  // Output method has not yet been determined.
693   CONSOLE,  // Output is written to stdout.
694   ODS       // Output is written to debug facility.
695 };
696
697 static OutputMode output_mode = UNKNOWN;  // Current output mode.
698
699
700 // Determine if the process has a console for output.
701 static bool HasConsole() {
702   // Only check the first time. Eventual race conditions are not a problem,
703   // because all threads will eventually determine the same mode.
704 #ifndef _WIN32_WCE
705   if (output_mode == UNKNOWN) {
706     // We cannot just check that the standard output is attached to a console
707     // because this would fail if output is redirected to a file. Therefore we
708     // say that a process does not have an output console if either the
709     // standard output handle is invalid or its file type is unknown.
710     if (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE &&
711         GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) != FILE_TYPE_UNKNOWN)
712       output_mode = CONSOLE;
713     else
714       output_mode = ODS;
715   }
716   return output_mode == CONSOLE;
717 #else
718   // Windows CE has no shell enabled in the standard BSP
719   return false;
720 #endif // _WIN32_WCE
721 }
722
723
724 static void VPrintHelper(FILE* stream, const char* format, va_list args) {
725   if (HasConsole()) {
726     vfprintf(stream, format, args);
727   } else {
728     // It is important to use safe print here in order to avoid
729     // overflowing the buffer. We might truncate the output, but this
730     // does not crash.
731     EmbeddedVector<char, 4096> buffer;
732     OS::VSNPrintF(buffer, format, args);
733 #ifdef _WIN32_WCE
734     wchar_t wbuf[4096];
735     for (int i = 0; i < 4096; ++i)
736         wbuf[i] = (wchar_t)buffer.start()[i];
737     OutputDebugStringW(wbuf);
738 #else
739     OutputDebugStringA(buffer.start());
740 #endif // _WIN32_WCE
741   }
742 }
743
744
745 FILE* OS::FOpen(const char* path, const char* mode) {
746   FILE* result;
747   if (fopen_s(&result, path, mode) == 0) {
748     return result;
749   } else {
750     return NULL;
751   }
752 }
753
754
755 bool OS::Remove(const char* path) {
756 #ifndef _WIN32_WCE
757   return (DeleteFileA(path) != 0);
758 #else
759     wchar_t *wpath = wce_mbtowc(path);
760     bool ret = (DeleteFileW(wpath) != 0);
761     delete wpath;
762     return ret;
763 #endif // _WIN32_WCE
764 }
765
766
767 FILE* OS::OpenTemporaryFile() {
768   // tmpfile_s tries to use the root dir, don't use it.
769   wchar_t tempPathBuffer[MAX_PATH];
770   DWORD path_result = 0;
771   path_result = GetTempPathW(MAX_PATH, tempPathBuffer);
772   if (path_result > MAX_PATH || path_result == 0) return NULL;
773   UINT name_result = 0;
774   wchar_t tempNameBuffer[MAX_PATH];
775   name_result = GetTempFileNameW(tempPathBuffer, L"", 0, tempNameBuffer);
776   if (name_result == 0) return NULL;
777   FILE* result = _wfopen(tempNameBuffer, L"w+");  // Same mode as tmpfile uses.
778   if (result != NULL) {
779     DeleteFileW(tempNameBuffer);  // Delete on close.
780   }
781   return result;
782 }
783
784
785 // Open log file in binary mode to avoid /n -> /r/n conversion.
786 const char* const OS::LogFileOpenMode = "wb";
787
788
789 // Print (debug) message to console.
790 void OS::Print(const char* format, ...) {
791   va_list args;
792   va_start(args, format);
793   VPrint(format, args);
794   va_end(args);
795 }
796
797
798 void OS::VPrint(const char* format, va_list args) {
799   VPrintHelper(stdout, format, args);
800 }
801
802
803 void OS::FPrint(FILE* out, const char* format, ...) {
804   va_list args;
805   va_start(args, format);
806   VFPrint(out, format, args);
807   va_end(args);
808 }
809
810
811 void OS::VFPrint(FILE* out, const char* format, va_list args) {
812   VPrintHelper(out, format, args);
813 }
814
815
816 // Print error message to console.
817 void OS::PrintError(const char* format, ...) {
818   va_list args;
819   va_start(args, format);
820   VPrintError(format, args);
821   va_end(args);
822 }
823
824
825 void OS::VPrintError(const char* format, va_list args) {
826   VPrintHelper(stderr, format, args);
827 }
828
829
830 int OS::SNPrintF(Vector<char> str, const char* format, ...) {
831   va_list args;
832   va_start(args, format);
833   int result = VSNPrintF(str, format, args);
834   va_end(args);
835   return result;
836 }
837
838
839 int OS::VSNPrintF(Vector<char> str, const char* format, va_list args) {
840   int n = _vsnprintf_s(str.start(), str.length(), _TRUNCATE, format, args);
841   // Make sure to zero-terminate the string if the output was
842   // truncated or if there was an error.
843   if (n < 0 || n >= str.length()) {
844     if (str.length() > 0)
845       str[str.length() - 1] = '\0';
846     return -1;
847   } else {
848     return n;
849   }
850 }
851
852
853 char* OS::StrChr(char* str, int c) {
854   return const_cast<char*>(strchr(str, c));
855 }
856
857
858 void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
859   // Use _TRUNCATE or strncpy_s crashes (by design) if buffer is too small.
860   size_t buffer_size = static_cast<size_t>(dest.length());
861   if (n + 1 > buffer_size)  // count for trailing '\0'
862     n = _TRUNCATE;
863   int result = strncpy_s(dest.start(), dest.length(), src, n);
864   USE(result);
865   ASSERT(result == 0 || (n == _TRUNCATE && result == STRUNCATE));
866 }
867
868
869 #undef _TRUNCATE
870 #undef STRUNCATE
871
872 // We keep the lowest and highest addresses mapped as a quick way of
873 // determining that pointers are outside the heap (used mostly in assertions
874 // and verification).  The estimate is conservative, i.e., not all addresses in
875 // 'allocated' space are actually allocated to our heap.  The range is
876 // [lowest, highest), inclusive on the low and and exclusive on the high end.
877 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
878 static void* highest_ever_allocated = reinterpret_cast<void*>(0);
879
880
881 static void UpdateAllocatedSpaceLimits(void* address, int size) {
882   ASSERT(limit_mutex != NULL);
883   ScopedLock lock(limit_mutex);
884
885   lowest_ever_allocated = Min(lowest_ever_allocated, address);
886   highest_ever_allocated =
887       Max(highest_ever_allocated,
888           reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
889 }
890
891
892 bool OS::IsOutsideAllocatedSpace(void* pointer) {
893   if (pointer < lowest_ever_allocated || pointer >= highest_ever_allocated)
894     return true;
895   // Ask the Windows API
896   if (IsBadWritePtr(pointer, 1))
897     return true;
898   return false;
899 }
900
901
902 // Get the system's page size used by VirtualAlloc() or the next power
903 // of two. The reason for always returning a power of two is that the
904 // rounding up in OS::Allocate expects that.
905 static size_t GetPageSize() {
906   static size_t page_size = 0;
907   if (page_size == 0) {
908     SYSTEM_INFO info;
909     GetSystemInfo(&info);
910     page_size = RoundUpToPowerOf2(info.dwPageSize);
911   }
912   return page_size;
913 }
914
915
916 // The allocation alignment is the guaranteed alignment for
917 // VirtualAlloc'ed blocks of memory.
918 size_t OS::AllocateAlignment() {
919   static size_t allocate_alignment = 0;
920   if (allocate_alignment == 0) {
921     SYSTEM_INFO info;
922     GetSystemInfo(&info);
923     allocate_alignment = info.dwAllocationGranularity;
924   }
925   return allocate_alignment;
926 }
927
928
929 static void* GetRandomAddr() {
930   Isolate* isolate = Isolate::UncheckedCurrent();
931   // Note that the current isolate isn't set up in a call path via
932   // CpuFeatures::Probe. We don't care about randomization in this case because
933   // the code page is immediately freed.
934   if (isolate != NULL) {
935     // The address range used to randomize RWX allocations in OS::Allocate
936     // Try not to map pages into the default range that windows loads DLLs
937     // Use a multiple of 64k to prevent committing unused memory.
938     // Note: This does not guarantee RWX regions will be within the
939     // range kAllocationRandomAddressMin to kAllocationRandomAddressMax
940 #ifdef V8_HOST_ARCH_64_BIT
941     static const intptr_t kAllocationRandomAddressMin = 0x0000000080000000;
942     static const intptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000;
943 #else
944     static const intptr_t kAllocationRandomAddressMin = 0x04000000;
945     static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000;
946 #endif
947     uintptr_t address = (V8::RandomPrivate(isolate) << kPageSizeBits)
948         | kAllocationRandomAddressMin;
949     address &= kAllocationRandomAddressMax;
950     return reinterpret_cast<void *>(address);
951   }
952   return NULL;
953 }
954
955
956 static void* RandomizedVirtualAlloc(size_t size, int action, int protection) {
957   LPVOID base = NULL;
958
959   if (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS) {
960     // For exectutable pages try and randomize the allocation address
961     for (size_t attempts = 0; base == NULL && attempts < 3; ++attempts) {
962       base = VirtualAlloc(GetRandomAddr(), size, action, protection);
963     }
964   }
965
966   // After three attempts give up and let the OS find an address to use.
967   if (base == NULL) base = VirtualAlloc(NULL, size, action, protection);
968
969   return base;
970 }
971
972
973 void* OS::Allocate(const size_t requested,
974                    size_t* allocated,
975                    bool is_executable) {
976   // VirtualAlloc rounds allocated size to page size automatically.
977   size_t msize = RoundUp(requested, static_cast<int>(GetPageSize()));
978
979   // Windows XP SP2 allows Data Excution Prevention (DEP).
980   int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
981
982   LPVOID mbase = RandomizedVirtualAlloc(msize,
983                                         MEM_COMMIT | MEM_RESERVE,
984                                         prot);
985
986   if (mbase == NULL) {
987     LOG(ISOLATE, StringEvent("OS::Allocate", "VirtualAlloc failed"));
988     return NULL;
989   }
990
991   ASSERT(IsAligned(reinterpret_cast<size_t>(mbase), OS::AllocateAlignment()));
992
993   *allocated = msize;
994   UpdateAllocatedSpaceLimits(mbase, static_cast<int>(msize));
995   return mbase;
996 }
997
998
999 void OS::Free(void* address, const size_t size) {
1000   // TODO(1240712): VirtualFree has a return value which is ignored here.
1001   VirtualFree(address, 0, MEM_RELEASE);
1002   USE(size);
1003 }
1004
1005
1006 intptr_t OS::CommitPageSize() {
1007   return 4096;
1008 }
1009
1010
1011 void OS::ProtectCode(void* address, const size_t size) {
1012   DWORD old_protect;
1013   VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect);
1014 }
1015
1016
1017 void OS::Guard(void* address, const size_t size) {
1018   DWORD oldprotect;
1019   VirtualProtect(address, size, PAGE_READONLY | PAGE_GUARD, &oldprotect);
1020 }
1021
1022
1023 void OS::Sleep(int milliseconds) {
1024   ::Sleep(milliseconds);
1025 }
1026
1027
1028 void OS::Abort() {
1029   if (IsDebuggerPresent() || FLAG_break_on_abort) {
1030     DebugBreak();
1031   } else {
1032     // Make the MSVCRT do a silent abort.
1033 #ifndef _WIN32_WCE
1034     raise(SIGABRT);
1035 #else
1036     exit(3);
1037 #endif // _WIN32_WCE
1038   }
1039 }
1040
1041
1042 void OS::DebugBreak() {
1043 #ifdef _MSC_VER
1044   __debugbreak();
1045 #else
1046   ::DebugBreak();
1047 #endif
1048 }
1049
1050
1051 class Win32MemoryMappedFile : public OS::MemoryMappedFile {
1052  public:
1053   Win32MemoryMappedFile(HANDLE file,
1054                         HANDLE file_mapping,
1055                         void* memory,
1056                         int size)
1057       : file_(file),
1058         file_mapping_(file_mapping),
1059         memory_(memory),
1060         size_(size) { }
1061   virtual ~Win32MemoryMappedFile();
1062   virtual void* memory() { return memory_; }
1063   virtual int size() { return size_; }
1064  private:
1065   HANDLE file_;
1066   HANDLE file_mapping_;
1067   void* memory_;
1068   int size_;
1069 };
1070
1071
1072 OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
1073   // Open a physical file
1074 #ifndef _WIN32_WCE
1075   HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE,
1076       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
1077 #else
1078   wchar_t *wname = wce_mbtowc(name);
1079   HANDLE file = CreateFileW(wname, GENERIC_READ | GENERIC_WRITE,
1080       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
1081   delete wname;
1082 #endif // _WIN32_WCE
1083   if (file == INVALID_HANDLE_VALUE) return NULL;
1084
1085   int size = static_cast<int>(GetFileSize(file, NULL));
1086
1087   // Create a file mapping for the physical file
1088   HANDLE file_mapping = CreateFileMapping(file, NULL,
1089       PAGE_READWRITE, 0, static_cast<DWORD>(size), NULL);
1090   if (file_mapping == NULL) return NULL;
1091
1092   // Map a view of the file into memory
1093   void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size);
1094   return new Win32MemoryMappedFile(file, file_mapping, memory, size);
1095 }
1096
1097
1098 OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
1099     void* initial) {
1100   // Open a physical file
1101 #ifndef _WIN32_WCE
1102   HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE,
1103       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
1104 #else
1105   wchar_t *wname = wce_mbtowc(name);
1106   HANDLE file = CreateFileW(wname, GENERIC_READ | GENERIC_WRITE,
1107       FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
1108   delete wname;
1109 #endif // _WIN32_WCE
1110   if (file == NULL) return NULL;
1111   // Create a file mapping for the physical file
1112   HANDLE file_mapping = CreateFileMapping(file, NULL,
1113       PAGE_READWRITE, 0, static_cast<DWORD>(size), NULL);
1114   if (file_mapping == NULL) return NULL;
1115   // Map a view of the file into memory
1116   void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size);
1117   if (memory) memmove(memory, initial, size);
1118   return new Win32MemoryMappedFile(file, file_mapping, memory, size);
1119 }
1120
1121
1122 Win32MemoryMappedFile::~Win32MemoryMappedFile() {
1123   if (memory_ != NULL)
1124     UnmapViewOfFile(memory_);
1125   CloseHandle(file_mapping_);
1126   CloseHandle(file_);
1127 }
1128
1129
1130 // The following code loads functions defined in DbhHelp.h and TlHelp32.h
1131 // dynamically. This is to avoid being depending on dbghelp.dll and
1132 // tlhelp32.dll when running (the functions in tlhelp32.dll have been moved to
1133 // kernel32.dll at some point so loading functions defines in TlHelp32.h
1134 // dynamically might not be necessary any more - for some versions of Windows?).
1135
1136 // Function pointers to functions dynamically loaded from dbghelp.dll.
1137 #define DBGHELP_FUNCTION_LIST(V)  \
1138   V(SymInitialize)                \
1139   V(SymGetOptions)                \
1140   V(SymSetOptions)                \
1141   V(SymGetSearchPath)             \
1142   V(SymLoadModule64)              \
1143   V(StackWalk64)                  \
1144   V(SymGetSymFromAddr64)          \
1145   V(SymGetLineFromAddr64)         \
1146   V(SymFunctionTableAccess64)     \
1147   V(SymGetModuleBase64)
1148
1149 // Function pointers to functions dynamically loaded from dbghelp.dll.
1150 #define TLHELP32_FUNCTION_LIST(V)  \
1151   V(CreateToolhelp32Snapshot)      \
1152   V(Module32FirstW)                \
1153   V(Module32NextW)
1154
1155 // Define the decoration to use for the type and variable name used for
1156 // dynamically loaded DLL function..
1157 #define DLL_FUNC_TYPE(name) _##name##_
1158 #define DLL_FUNC_VAR(name) _##name
1159
1160 // Define the type for each dynamically loaded DLL function. The function
1161 // definitions are copied from DbgHelp.h and TlHelp32.h. The IN and VOID macros
1162 // from the Windows include files are redefined here to have the function
1163 // definitions to be as close to the ones in the original .h files as possible.
1164 #ifndef IN
1165 #define IN
1166 #endif
1167 #ifndef VOID
1168 #define VOID void
1169 #endif
1170
1171 // DbgHelp isn't supported on MinGW yet, nor does Windows CE have it
1172 #if !defined(__MINGW32__) && !defined(_WIN32_WCE)
1173 // DbgHelp.h functions.
1174 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymInitialize))(IN HANDLE hProcess,
1175                                                        IN PSTR UserSearchPath,
1176                                                        IN BOOL fInvadeProcess);
1177 typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymGetOptions))(VOID);
1178 typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymSetOptions))(IN DWORD SymOptions);
1179 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSearchPath))(
1180     IN HANDLE hProcess,
1181     OUT PSTR SearchPath,
1182     IN DWORD SearchPathLength);
1183 typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymLoadModule64))(
1184     IN HANDLE hProcess,
1185     IN HANDLE hFile,
1186     IN PSTR ImageName,
1187     IN PSTR ModuleName,
1188     IN DWORD64 BaseOfDll,
1189     IN DWORD SizeOfDll);
1190 typedef BOOL (__stdcall *DLL_FUNC_TYPE(StackWalk64))(
1191     DWORD MachineType,
1192     HANDLE hProcess,
1193     HANDLE hThread,
1194     LPSTACKFRAME64 StackFrame,
1195     PVOID ContextRecord,
1196     PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
1197     PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
1198     PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
1199     PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
1200 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSymFromAddr64))(
1201     IN HANDLE hProcess,
1202     IN DWORD64 qwAddr,
1203     OUT PDWORD64 pdwDisplacement,
1204     OUT PIMAGEHLP_SYMBOL64 Symbol);
1205 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetLineFromAddr64))(
1206     IN HANDLE hProcess,
1207     IN DWORD64 qwAddr,
1208     OUT PDWORD pdwDisplacement,
1209     OUT PIMAGEHLP_LINE64 Line64);
1210 // DbgHelp.h typedefs. Implementation found in dbghelp.dll.
1211 typedef PVOID (__stdcall *DLL_FUNC_TYPE(SymFunctionTableAccess64))(
1212     HANDLE hProcess,
1213     DWORD64 AddrBase);  // DbgHelp.h typedef PFUNCTION_TABLE_ACCESS_ROUTINE64
1214 typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymGetModuleBase64))(
1215     HANDLE hProcess,
1216     DWORD64 AddrBase);  // DbgHelp.h typedef PGET_MODULE_BASE_ROUTINE64
1217
1218 // TlHelp32.h functions.
1219 typedef HANDLE (__stdcall *DLL_FUNC_TYPE(CreateToolhelp32Snapshot))(
1220     DWORD dwFlags,
1221     DWORD th32ProcessID);
1222 typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32FirstW))(HANDLE hSnapshot,
1223                                                         LPMODULEENTRY32W lpme);
1224 typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32NextW))(HANDLE hSnapshot,
1225                                                        LPMODULEENTRY32W lpme);
1226
1227 #undef IN
1228 #undef VOID
1229
1230 // Declare a variable for each dynamically loaded DLL function.
1231 #define DEF_DLL_FUNCTION(name) DLL_FUNC_TYPE(name) DLL_FUNC_VAR(name) = NULL;
1232 DBGHELP_FUNCTION_LIST(DEF_DLL_FUNCTION)
1233 TLHELP32_FUNCTION_LIST(DEF_DLL_FUNCTION)
1234 #undef DEF_DLL_FUNCTION
1235
1236 // Load the functions. This function has a lot of "ugly" macros in order to
1237 // keep down code duplication.
1238
1239 static bool LoadDbgHelpAndTlHelp32() {
1240   static bool dbghelp_loaded = false;
1241
1242   if (dbghelp_loaded) return true;
1243
1244   HMODULE module;
1245
1246   // Load functions from the dbghelp.dll module.
1247   module = LoadLibrary(TEXT("dbghelp.dll"));
1248   if (module == NULL) {
1249     return false;
1250   }
1251
1252 #define LOAD_DLL_FUNC(name)                                                 \
1253   DLL_FUNC_VAR(name) =                                                      \
1254       reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name));
1255
1256 DBGHELP_FUNCTION_LIST(LOAD_DLL_FUNC)
1257
1258 #undef LOAD_DLL_FUNC
1259
1260   // Load functions from the kernel32.dll module (the TlHelp32.h function used
1261   // to be in tlhelp32.dll but are now moved to kernel32.dll).
1262   module = LoadLibrary(TEXT("kernel32.dll"));
1263   if (module == NULL) {
1264     return false;
1265   }
1266
1267 #define LOAD_DLL_FUNC(name)                                                 \
1268   DLL_FUNC_VAR(name) =                                                      \
1269       reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name));
1270
1271 TLHELP32_FUNCTION_LIST(LOAD_DLL_FUNC)
1272
1273 #undef LOAD_DLL_FUNC
1274
1275   // Check that all functions where loaded.
1276   bool result =
1277 #define DLL_FUNC_LOADED(name) (DLL_FUNC_VAR(name) != NULL) &&
1278
1279 DBGHELP_FUNCTION_LIST(DLL_FUNC_LOADED)
1280 TLHELP32_FUNCTION_LIST(DLL_FUNC_LOADED)
1281
1282 #undef DLL_FUNC_LOADED
1283   true;
1284
1285   dbghelp_loaded = result;
1286   return result;
1287   // NOTE: The modules are never unloaded and will stay around until the
1288   // application is closed.
1289 }
1290
1291 #undef DBGHELP_FUNCTION_LIST
1292 #undef TLHELP32_FUNCTION_LIST
1293 #undef DLL_FUNC_VAR
1294 #undef DLL_FUNC_TYPE
1295
1296
1297 // Load the symbols for generating stack traces.
1298 static bool LoadSymbols(HANDLE process_handle) {
1299   static bool symbols_loaded = false;
1300
1301   if (symbols_loaded) return true;
1302
1303   BOOL ok;
1304
1305   // Initialize the symbol engine.
1306   ok = _SymInitialize(process_handle,  // hProcess
1307                       NULL,            // UserSearchPath
1308                       false);          // fInvadeProcess
1309   if (!ok) return false;
1310
1311   DWORD options = _SymGetOptions();
1312   options |= SYMOPT_LOAD_LINES;
1313   options |= SYMOPT_FAIL_CRITICAL_ERRORS;
1314   options = _SymSetOptions(options);
1315
1316   char buf[OS::kStackWalkMaxNameLen] = {0};
1317   ok = _SymGetSearchPath(process_handle, buf, OS::kStackWalkMaxNameLen);
1318   if (!ok) {
1319     int err = GetLastError();
1320     PrintF("%d\n", err);
1321     return false;
1322   }
1323
1324   HANDLE snapshot = _CreateToolhelp32Snapshot(
1325       TH32CS_SNAPMODULE,       // dwFlags
1326       GetCurrentProcessId());  // th32ProcessId
1327   if (snapshot == INVALID_HANDLE_VALUE) return false;
1328   MODULEENTRY32W module_entry;
1329   module_entry.dwSize = sizeof(module_entry);  // Set the size of the structure.
1330   BOOL cont = _Module32FirstW(snapshot, &module_entry);
1331   while (cont) {
1332     DWORD64 base;
1333     // NOTE the SymLoadModule64 function has the peculiarity of accepting a
1334     // both unicode and ASCII strings even though the parameter is PSTR.
1335     base = _SymLoadModule64(
1336         process_handle,                                       // hProcess
1337         0,                                                    // hFile
1338         reinterpret_cast<PSTR>(module_entry.szExePath),       // ImageName
1339         reinterpret_cast<PSTR>(module_entry.szModule),        // ModuleName
1340         reinterpret_cast<DWORD64>(module_entry.modBaseAddr),  // BaseOfDll
1341         module_entry.modBaseSize);                            // SizeOfDll
1342     if (base == 0) {
1343       int err = GetLastError();
1344       if (err != ERROR_MOD_NOT_FOUND &&
1345           err != ERROR_INVALID_HANDLE) return false;
1346     }
1347     LOG(i::Isolate::Current(),
1348         SharedLibraryEvent(
1349             module_entry.szExePath,
1350             reinterpret_cast<unsigned int>(module_entry.modBaseAddr),
1351             reinterpret_cast<unsigned int>(module_entry.modBaseAddr +
1352                                            module_entry.modBaseSize)));
1353     cont = _Module32NextW(snapshot, &module_entry);
1354   }
1355   CloseHandle(snapshot);
1356
1357   symbols_loaded = true;
1358   return true;
1359 }
1360
1361
1362 void OS::LogSharedLibraryAddresses() {
1363   // SharedLibraryEvents are logged when loading symbol information.
1364   // Only the shared libraries loaded at the time of the call to
1365   // LogSharedLibraryAddresses are logged.  DLLs loaded after
1366   // initialization are not accounted for.
1367   if (!LoadDbgHelpAndTlHelp32()) return;
1368   HANDLE process_handle = GetCurrentProcess();
1369   LoadSymbols(process_handle);
1370 }
1371
1372
1373 void OS::SignalCodeMovingGC() {
1374 }
1375
1376
1377 // Walk the stack using the facilities in dbghelp.dll and tlhelp32.dll
1378
1379 // Switch off warning 4748 (/GS can not protect parameters and local variables
1380 // from local buffer overrun because optimizations are disabled in function) as
1381 // it is triggered by the use of inline assembler.
1382 #pragma warning(push)
1383 #pragma warning(disable : 4748)
1384 int OS::StackWalk(Vector<OS::StackFrame> frames) {
1385   BOOL ok;
1386
1387   // Load the required functions from DLL's.
1388   if (!LoadDbgHelpAndTlHelp32()) return kStackWalkError;
1389
1390   // Get the process and thread handles.
1391   HANDLE process_handle = GetCurrentProcess();
1392   HANDLE thread_handle = GetCurrentThread();
1393
1394   // Read the symbols.
1395   if (!LoadSymbols(process_handle)) return kStackWalkError;
1396
1397   // Capture current context.
1398   CONTEXT context;
1399   RtlCaptureContext(&context);
1400
1401   // Initialize the stack walking
1402   STACKFRAME64 stack_frame;
1403   memset(&stack_frame, 0, sizeof(stack_frame));
1404 #ifdef  _WIN64
1405   stack_frame.AddrPC.Offset = context.Rip;
1406   stack_frame.AddrFrame.Offset = context.Rbp;
1407   stack_frame.AddrStack.Offset = context.Rsp;
1408 #else
1409   stack_frame.AddrPC.Offset = context.Eip;
1410   stack_frame.AddrFrame.Offset = context.Ebp;
1411   stack_frame.AddrStack.Offset = context.Esp;
1412 #endif
1413   stack_frame.AddrPC.Mode = AddrModeFlat;
1414   stack_frame.AddrFrame.Mode = AddrModeFlat;
1415   stack_frame.AddrStack.Mode = AddrModeFlat;
1416   int frames_count = 0;
1417
1418   // Collect stack frames.
1419   int frames_size = frames.length();
1420   while (frames_count < frames_size) {
1421     ok = _StackWalk64(
1422         IMAGE_FILE_MACHINE_I386,    // MachineType
1423         process_handle,             // hProcess
1424         thread_handle,              // hThread
1425         &stack_frame,               // StackFrame
1426         &context,                   // ContextRecord
1427         NULL,                       // ReadMemoryRoutine
1428         _SymFunctionTableAccess64,  // FunctionTableAccessRoutine
1429         _SymGetModuleBase64,        // GetModuleBaseRoutine
1430         NULL);                      // TranslateAddress
1431     if (!ok) break;
1432
1433     // Store the address.
1434     ASSERT((stack_frame.AddrPC.Offset >> 32) == 0);  // 32-bit address.
1435     frames[frames_count].address =
1436         reinterpret_cast<void*>(stack_frame.AddrPC.Offset);
1437
1438     // Try to locate a symbol for this frame.
1439     DWORD64 symbol_displacement;
1440     SmartArrayPointer<IMAGEHLP_SYMBOL64> symbol(
1441         NewArray<IMAGEHLP_SYMBOL64>(kStackWalkMaxNameLen));
1442     if (symbol.is_empty()) return kStackWalkError;  // Out of memory.
1443     memset(*symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + kStackWalkMaxNameLen);
1444     (*symbol)->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
1445     (*symbol)->MaxNameLength = kStackWalkMaxNameLen;
1446     ok = _SymGetSymFromAddr64(process_handle,             // hProcess
1447                               stack_frame.AddrPC.Offset,  // Address
1448                               &symbol_displacement,       // Displacement
1449                               *symbol);                   // Symbol
1450     if (ok) {
1451       // Try to locate more source information for the symbol.
1452       IMAGEHLP_LINE64 Line;
1453       memset(&Line, 0, sizeof(Line));
1454       Line.SizeOfStruct = sizeof(Line);
1455       DWORD line_displacement;
1456       ok = _SymGetLineFromAddr64(
1457           process_handle,             // hProcess
1458           stack_frame.AddrPC.Offset,  // dwAddr
1459           &line_displacement,         // pdwDisplacement
1460           &Line);                     // Line
1461       // Format a text representation of the frame based on the information
1462       // available.
1463       if (ok) {
1464         SNPrintF(MutableCStrVector(frames[frames_count].text,
1465                                    kStackWalkMaxTextLen),
1466                  "%s %s:%d:%d",
1467                  (*symbol)->Name, Line.FileName, Line.LineNumber,
1468                  line_displacement);
1469       } else {
1470         SNPrintF(MutableCStrVector(frames[frames_count].text,
1471                                    kStackWalkMaxTextLen),
1472                  "%s",
1473                  (*symbol)->Name);
1474       }
1475       // Make sure line termination is in place.
1476       frames[frames_count].text[kStackWalkMaxTextLen - 1] = '\0';
1477     } else {
1478       // No text representation of this frame
1479       frames[frames_count].text[0] = '\0';
1480
1481       // Continue if we are just missing a module (for non C/C++ frames a
1482       // module will never be found).
1483       int err = GetLastError();
1484       if (err != ERROR_MOD_NOT_FOUND) {
1485         break;
1486       }
1487     }
1488
1489     frames_count++;
1490   }
1491
1492   // Return the number of frames filled in.
1493   return frames_count;
1494 }
1495
1496 // Restore warnings to previous settings.
1497 #pragma warning(pop)
1498
1499 #else  // __MINGW32__
1500 void OS::LogSharedLibraryAddresses() { }
1501 void OS::SignalCodeMovingGC() { }
1502 int OS::StackWalk(Vector<OS::StackFrame> frames) { return 0; }
1503 #endif  // __MINGW32__
1504
1505
1506 uint64_t OS::CpuFeaturesImpliedByPlatform() {
1507   return 0;  // Windows runs on anything.
1508 }
1509
1510
1511 double OS::nan_value() {
1512 #ifdef _MSC_VER
1513   // Positive Quiet NaN with no payload (aka. Indeterminate) has all bits
1514   // in mask set, so value equals mask.
1515   static const __int64 nanval = kQuietNaNMask;
1516   return *reinterpret_cast<const double*>(&nanval);
1517 #else  // _MSC_VER
1518   return NAN;
1519 #endif  // _MSC_VER
1520 }
1521
1522
1523 int OS::ActivationFrameAlignment() {
1524 #ifdef _WIN64
1525   return 16;  // Windows 64-bit ABI requires the stack to be 16-byte aligned.
1526 #elif defined(__MINGW32__)
1527   // With gcc 4.4 the tree vectorization optimizer can generate code
1528   // that requires 16 byte alignment such as movdqa on x86.
1529   return 16;
1530 #endif
1531   return 8;  // Floating-point math runs faster with 8-byte alignment.
1532 }
1533
1534
1535 void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
1536   MemoryBarrier();
1537   *ptr = value;
1538 }
1539
1540
1541 VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
1542
1543
1544 VirtualMemory::VirtualMemory(size_t size)
1545     : address_(ReserveRegion(size)), size_(size) { }
1546
1547
1548 VirtualMemory::VirtualMemory(size_t size, size_t alignment)
1549     : address_(NULL), size_(0) {
1550   ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
1551   size_t request_size = RoundUp(size + alignment,
1552                                 static_cast<intptr_t>(OS::AllocateAlignment()));
1553   void* address = ReserveRegion(request_size);
1554   if (address == NULL) return;
1555   Address base = RoundUp(static_cast<Address>(address), alignment);
1556   // Try reducing the size by freeing and then reallocating a specific area.
1557   bool result = ReleaseRegion(address, request_size);
1558   USE(result);
1559   ASSERT(result);
1560   address = VirtualAlloc(base, size, MEM_RESERVE, PAGE_NOACCESS);
1561   if (address != NULL) {
1562     request_size = size;
1563     ASSERT(base == static_cast<Address>(address));
1564   } else {
1565     // Resizing failed, just go with a bigger area.
1566     address = ReserveRegion(request_size);
1567     if (address == NULL) return;
1568   }
1569   address_ = address;
1570   size_ = request_size;
1571 }
1572
1573
1574 VirtualMemory::~VirtualMemory() {
1575   if (IsReserved()) {
1576     bool result = ReleaseRegion(address_, size_);
1577     ASSERT(result);
1578     USE(result);
1579   }
1580 }
1581
1582
1583 bool VirtualMemory::IsReserved() {
1584   return address_ != NULL;
1585 }
1586
1587
1588 void VirtualMemory::Reset() {
1589   address_ = NULL;
1590   size_ = 0;
1591 }
1592
1593
1594 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
1595   if (CommitRegion(address, size, is_executable)) {
1596     UpdateAllocatedSpaceLimits(address, static_cast<int>(size));
1597     return true;
1598   }
1599   return false;
1600 }
1601
1602
1603 bool VirtualMemory::Uncommit(void* address, size_t size) {
1604   ASSERT(IsReserved());
1605   return UncommitRegion(address, size);
1606 }
1607
1608
1609 void* VirtualMemory::ReserveRegion(size_t size) {
1610   return RandomizedVirtualAlloc(size, MEM_RESERVE, PAGE_NOACCESS);
1611 }
1612
1613
1614 bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
1615   int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
1616   if (NULL == VirtualAlloc(base, size, MEM_COMMIT, prot)) {
1617     return false;
1618   }
1619
1620   UpdateAllocatedSpaceLimits(base, static_cast<int>(size));
1621   return true;
1622 }
1623
1624
1625 bool VirtualMemory::Guard(void* address) {
1626   if (NULL == VirtualAlloc(address,
1627                            OS::CommitPageSize(),
1628                            MEM_COMMIT,
1629                            PAGE_READONLY | PAGE_GUARD)) {
1630     return false;
1631   }
1632   return true;
1633 }
1634
1635
1636 bool VirtualMemory::UncommitRegion(void* base, size_t size) {
1637   return VirtualFree(base, size, MEM_DECOMMIT) != 0;
1638 }
1639
1640
1641 bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
1642   return VirtualFree(base, 0, MEM_RELEASE) != 0;
1643 }
1644
1645
1646 bool VirtualMemory::HasLazyCommits() {
1647   // TODO(alph): implement for the platform.
1648   return false;
1649 }
1650
1651
1652 // ----------------------------------------------------------------------------
1653 // Win32 thread support.
1654
1655 // Definition of invalid thread handle and id.
1656 static const HANDLE kNoThread = INVALID_HANDLE_VALUE;
1657
1658 // Entry point for threads. The supplied argument is a pointer to the thread
1659 // object. The entry function dispatches to the run method in the thread
1660 // object. It is important that this function has __stdcall calling
1661 // convention.
1662 static unsigned int __stdcall ThreadEntry(void* arg) {
1663   Thread* thread = reinterpret_cast<Thread*>(arg);
1664   thread->Run();
1665   return 0;
1666 }
1667
1668
1669 class Thread::PlatformData : public Malloced {
1670  public:
1671   explicit PlatformData(HANDLE thread) : thread_(thread) {}
1672   HANDLE thread_;
1673   unsigned thread_id_;
1674 };
1675
1676
1677 // Initialize a Win32 thread object. The thread has an invalid thread
1678 // handle until it is started.
1679
1680 Thread::Thread(const Options& options)
1681     : stack_size_(options.stack_size()) {
1682   data_ = new PlatformData(kNoThread);
1683   set_name(options.name());
1684 }
1685
1686
1687 void Thread::set_name(const char* name) {
1688   OS::StrNCpy(Vector<char>(name_, sizeof(name_)), name, strlen(name));
1689   name_[sizeof(name_) - 1] = '\0';
1690 }
1691
1692
1693 // Close our own handle for the thread.
1694 Thread::~Thread() {
1695   if (data_->thread_ != kNoThread) CloseHandle(data_->thread_);
1696   delete data_;
1697 }
1698
1699
1700 // Create a new thread. It is important to use _beginthreadex() instead of
1701 // the Win32 function CreateThread(), because the CreateThread() does not
1702 // initialize thread specific structures in the C runtime library.
1703 void Thread::Start() {
1704 #ifndef _WIN32_WCE
1705   data_->thread_ = reinterpret_cast<HANDLE>(
1706       _beginthreadex(NULL,
1707                      static_cast<unsigned>(stack_size_),
1708                      ThreadEntry,
1709                      this,
1710                      0,
1711                      &data_->thread_id_));
1712 #else
1713     unsigned initflag = 0;
1714     if (stack_size_ > 0)
1715         initflag |= STACK_SIZE_PARAM_IS_A_RESERVATION;
1716     data_->thread_ = reinterpret_cast<HANDLE>(
1717         CreateThread( NULL,
1718                       static_cast<unsigned>(stack_size_),
1719                       (LPTHREAD_START_ROUTINE)ThreadEntry,
1720                       this,
1721                       initflag,
1722                       (LPDWORD)&data_->thread_id_));
1723 #endif // _WIN32_WCE
1724 }
1725
1726
1727 // Wait for thread to terminate.
1728 void Thread::Join() {
1729   if (data_->thread_id_ != GetCurrentThreadId()) {
1730     WaitForSingleObject(data_->thread_, INFINITE);
1731   }
1732 }
1733
1734
1735 Thread::LocalStorageKey Thread::CreateThreadLocalKey() {
1736   DWORD result = TlsAlloc();
1737   ASSERT(result != TLS_OUT_OF_INDEXES);
1738   return static_cast<LocalStorageKey>(result);
1739 }
1740
1741
1742 void Thread::DeleteThreadLocalKey(LocalStorageKey key) {
1743   BOOL result = TlsFree(static_cast<DWORD>(key));
1744   USE(result);
1745   ASSERT(result);
1746 }
1747
1748
1749 void* Thread::GetThreadLocal(LocalStorageKey key) {
1750   return TlsGetValue(static_cast<DWORD>(key));
1751 }
1752
1753
1754 void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
1755   BOOL result = TlsSetValue(static_cast<DWORD>(key), value);
1756   USE(result);
1757   ASSERT(result);
1758 }
1759
1760
1761
1762 void Thread::YieldCPU() {
1763   Sleep(0);
1764 }
1765
1766
1767 // ----------------------------------------------------------------------------
1768 // Win32 mutex support.
1769 //
1770 // On Win32 mutexes are implemented using CRITICAL_SECTION objects. These are
1771 // faster than Win32 Mutex objects because they are implemented using user mode
1772 // atomic instructions. Therefore we only do ring transitions if there is lock
1773 // contention.
1774
1775 class Win32Mutex : public Mutex {
1776  public:
1777   Win32Mutex() { InitializeCriticalSection(&cs_); }
1778
1779   virtual ~Win32Mutex() { DeleteCriticalSection(&cs_); }
1780
1781   virtual int Lock() {
1782     EnterCriticalSection(&cs_);
1783     return 0;
1784   }
1785
1786   virtual int Unlock() {
1787     LeaveCriticalSection(&cs_);
1788     return 0;
1789   }
1790
1791
1792   virtual bool TryLock() {
1793     // Returns non-zero if critical section is entered successfully entered.
1794     return TryEnterCriticalSection(&cs_);
1795   }
1796
1797  private:
1798   CRITICAL_SECTION cs_;  // Critical section used for mutex
1799 };
1800
1801
1802 Mutex* OS::CreateMutex() {
1803   return new Win32Mutex();
1804 }
1805
1806
1807 // ----------------------------------------------------------------------------
1808 // Win32 semaphore support.
1809 //
1810 // On Win32 semaphores are implemented using Win32 Semaphore objects. The
1811 // semaphores are anonymous. Also, the semaphores are initialized to have
1812 // no upper limit on count.
1813
1814
1815 class Win32Semaphore : public Semaphore {
1816  public:
1817   explicit Win32Semaphore(int count) {
1818     sem = ::CreateSemaphoreW(NULL, count, 0x7fffffff, NULL);
1819   }
1820
1821   ~Win32Semaphore() {
1822     CloseHandle(sem);
1823   }
1824
1825   void Wait() {
1826     WaitForSingleObject(sem, INFINITE);
1827   }
1828
1829   bool Wait(int timeout) {
1830     // Timeout in Windows API is in milliseconds.
1831     DWORD millis_timeout = timeout / 1000;
1832     return WaitForSingleObject(sem, millis_timeout) != WAIT_TIMEOUT;
1833   }
1834
1835   void Signal() {
1836     LONG dummy;
1837     ReleaseSemaphore(sem, 1, &dummy);
1838   }
1839
1840  private:
1841   HANDLE sem;
1842 };
1843
1844
1845 Semaphore* OS::CreateSemaphore(int count) {
1846   return new Win32Semaphore(count);
1847 }
1848
1849
1850 // ----------------------------------------------------------------------------
1851 // Win32 socket support.
1852 //
1853
1854 class Win32Socket : public Socket {
1855  public:
1856   explicit Win32Socket() {
1857     // Create the socket.
1858     socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1859   }
1860   explicit Win32Socket(SOCKET socket): socket_(socket) { }
1861   virtual ~Win32Socket() { Shutdown(); }
1862
1863   // Server initialization.
1864   bool Bind(const int port);
1865   bool Listen(int backlog) const;
1866   Socket* Accept() const;
1867
1868   // Client initialization.
1869   bool Connect(const char* host, const char* port);
1870
1871   // Shutdown socket for both read and write.
1872   bool Shutdown();
1873
1874   // Data Transimission
1875   int Send(const char* data, int len) const;
1876   int Receive(char* data, int len) const;
1877
1878   bool SetReuseAddress(bool reuse_address);
1879
1880   bool IsValid() const { return socket_ != INVALID_SOCKET; }
1881
1882  private:
1883   SOCKET socket_;
1884 };
1885
1886
1887 bool Win32Socket::Bind(const int port) {
1888   if (!IsValid())  {
1889     return false;
1890   }
1891
1892   sockaddr_in addr;
1893   memset(&addr, 0, sizeof(addr));
1894   addr.sin_family = AF_INET;
1895   addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1896   addr.sin_port = htons(port);
1897   int status = bind(socket_,
1898                     reinterpret_cast<struct sockaddr *>(&addr),
1899                     sizeof(addr));
1900   return status == 0;
1901 }
1902
1903
1904 bool Win32Socket::Listen(int backlog) const {
1905   if (!IsValid()) {
1906     return false;
1907   }
1908
1909   int status = listen(socket_, backlog);
1910   return status == 0;
1911 }
1912
1913
1914 Socket* Win32Socket::Accept() const {
1915   if (!IsValid()) {
1916     return NULL;
1917   }
1918
1919   SOCKET socket = accept(socket_, NULL, NULL);
1920   if (socket == INVALID_SOCKET) {
1921     return NULL;
1922   } else {
1923     return new Win32Socket(socket);
1924   }
1925 }
1926
1927
1928 bool Win32Socket::Connect(const char* host, const char* port) {
1929   if (!IsValid()) {
1930     return false;
1931   }
1932
1933   // Lookup host and port.
1934   struct addrinfo *result = NULL;
1935   struct addrinfo hints;
1936   memset(&hints, 0, sizeof(addrinfo));
1937   hints.ai_family = AF_INET;
1938   hints.ai_socktype = SOCK_STREAM;
1939   hints.ai_protocol = IPPROTO_TCP;
1940   int status = getaddrinfo(host, port, &hints, &result);
1941   if (status != 0) {
1942     return false;
1943   }
1944
1945   // Connect.
1946   status = connect(socket_,
1947                    result->ai_addr,
1948                    static_cast<int>(result->ai_addrlen));
1949   freeaddrinfo(result);
1950   return status == 0;
1951 }
1952
1953
1954 bool Win32Socket::Shutdown() {
1955   if (IsValid()) {
1956     // Shutdown socket for both read and write.
1957     int status = shutdown(socket_, SD_BOTH);
1958     closesocket(socket_);
1959     socket_ = INVALID_SOCKET;
1960     return status == SOCKET_ERROR;
1961   }
1962   return true;
1963 }
1964
1965
1966 int Win32Socket::Send(const char* data, int len) const {
1967   if (len <= 0) return 0;
1968   int written = 0;
1969   while (written < len) {
1970     int status = send(socket_, data + written, len - written, 0);
1971     if (status == 0) {
1972       break;
1973     } else if (status > 0) {
1974       written += status;
1975     } else {
1976       return 0;
1977     }
1978   }
1979   return written;
1980 }
1981
1982
1983 int Win32Socket::Receive(char* data, int len) const {
1984   if (len <= 0) return 0;
1985   int status = recv(socket_, data, len, 0);
1986   return (status == SOCKET_ERROR) ? 0 : status;
1987 }
1988
1989
1990 bool Win32Socket::SetReuseAddress(bool reuse_address) {
1991   BOOL on = reuse_address ? true : false;
1992   int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
1993                           reinterpret_cast<char*>(&on), sizeof(on));
1994   return status == SOCKET_ERROR;
1995 }
1996
1997
1998 bool Socket::SetUp() {
1999   // Initialize Winsock32
2000   int err;
2001   WSADATA winsock_data;
2002   WORD version_requested = MAKEWORD(1, 0);
2003   err = WSAStartup(version_requested, &winsock_data);
2004   if (err != 0) {
2005     PrintF("Unable to initialize Winsock, err = %d\n", Socket::LastError());
2006   }
2007
2008   return err == 0;
2009 }
2010
2011
2012 int Socket::LastError() {
2013   return WSAGetLastError();
2014 }
2015
2016
2017 uint16_t Socket::HToN(uint16_t value) {
2018   return htons(value);
2019 }
2020
2021
2022 uint16_t Socket::NToH(uint16_t value) {
2023   return ntohs(value);
2024 }
2025
2026
2027 uint32_t Socket::HToN(uint32_t value) {
2028   return htonl(value);
2029 }
2030
2031
2032 uint32_t Socket::NToH(uint32_t value) {
2033   return ntohl(value);
2034 }
2035
2036
2037 Socket* OS::CreateSocket() {
2038   return new Win32Socket();
2039 }
2040
2041
2042 // ----------------------------------------------------------------------------
2043 // Win32 profiler support.
2044
2045 class Sampler::PlatformData : public Malloced {
2046  public:
2047   // Get a handle to the calling thread. This is the thread that we are
2048   // going to profile. We need to make a copy of the handle because we are
2049   // going to use it in the sampler thread. Using GetThreadHandle() will
2050   // not work in this case. We're using OpenThread because DuplicateHandle
2051   // for some reason doesn't work in Chrome's sandbox.
2052   PlatformData() : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
2053                                                THREAD_SUSPEND_RESUME |
2054                                                THREAD_QUERY_INFORMATION,
2055                                                false,
2056                                                GetCurrentThreadId())) {}
2057
2058   ~PlatformData() {
2059     if (profiled_thread_ != NULL) {
2060       CloseHandle(profiled_thread_);
2061       profiled_thread_ = NULL;
2062     }
2063   }
2064
2065   HANDLE profiled_thread() { return profiled_thread_; }
2066
2067  private:
2068   HANDLE profiled_thread_;
2069 };
2070
2071
2072 class SamplerThread : public Thread {
2073  public:
2074   static const int kSamplerThreadStackSize = 64 * KB;
2075
2076   explicit SamplerThread(int interval)
2077       : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)),
2078         interval_(interval) {}
2079
2080   static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
2081   static void TearDown() { delete mutex_; }
2082
2083   static void AddActiveSampler(Sampler* sampler) {
2084     ScopedLock lock(mutex_);
2085     SamplerRegistry::AddActiveSampler(sampler);
2086     if (instance_ == NULL) {
2087       instance_ = new SamplerThread(sampler->interval());
2088       instance_->Start();
2089     } else {
2090       ASSERT(instance_->interval_ == sampler->interval());
2091     }
2092   }
2093
2094   static void RemoveActiveSampler(Sampler* sampler) {
2095     ScopedLock lock(mutex_);
2096     SamplerRegistry::RemoveActiveSampler(sampler);
2097     if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
2098       RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
2099       delete instance_;
2100       instance_ = NULL;
2101     }
2102   }
2103
2104   // Implement Thread::Run().
2105   virtual void Run() {
2106     SamplerRegistry::State state;
2107     while ((state = SamplerRegistry::GetState()) !=
2108            SamplerRegistry::HAS_NO_SAMPLERS) {
2109       bool cpu_profiling_enabled =
2110           (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
2111       bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
2112       // When CPU profiling is enabled both JavaScript and C++ code is
2113       // profiled. We must not suspend.
2114       if (!cpu_profiling_enabled) {
2115         if (rate_limiter_.SuspendIfNecessary()) continue;
2116       }
2117       if (cpu_profiling_enabled) {
2118         if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
2119           return;
2120         }
2121       }
2122       if (runtime_profiler_enabled) {
2123         if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
2124           return;
2125         }
2126       }
2127       OS::Sleep(interval_);
2128     }
2129   }
2130
2131   static void DoCpuProfile(Sampler* sampler, void* raw_sampler_thread) {
2132     if (!sampler->isolate()->IsInitialized()) return;
2133     if (!sampler->IsProfiling()) return;
2134     SamplerThread* sampler_thread =
2135         reinterpret_cast<SamplerThread*>(raw_sampler_thread);
2136     sampler_thread->SampleContext(sampler);
2137   }
2138
2139   static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
2140     if (!sampler->isolate()->IsInitialized()) return;
2141     sampler->isolate()->runtime_profiler()->NotifyTick();
2142   }
2143
2144   void SampleContext(Sampler* sampler) {
2145     HANDLE profiled_thread = sampler->platform_data()->profiled_thread();
2146     if (profiled_thread == NULL) return;
2147
2148     // Context used for sampling the register state of the profiled thread.
2149     CONTEXT context;
2150     memset(&context, 0, sizeof(context));
2151
2152     TickSample sample_obj;
2153     TickSample* sample = CpuProfiler::TickSampleEvent(sampler->isolate());
2154     if (sample == NULL) sample = &sample_obj;
2155
2156     static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
2157     if (SuspendThread(profiled_thread) == kSuspendFailed) return;
2158     sample->state = sampler->isolate()->current_vm_state();
2159
2160     context.ContextFlags = CONTEXT_FULL;
2161     if (GetThreadContext(profiled_thread, &context) != 0) {
2162 #if V8_HOST_ARCH_X64
2163       sample->pc = reinterpret_cast<Address>(context.Rip);
2164       sample->sp = reinterpret_cast<Address>(context.Rsp);
2165       sample->fp = reinterpret_cast<Address>(context.Rbp);
2166 #elif V8_HOST_ARCH_IA32
2167       sample->pc = reinterpret_cast<Address>(context.Eip);
2168       sample->sp = reinterpret_cast<Address>(context.Esp);
2169       sample->fp = reinterpret_cast<Address>(context.Ebp);
2170 #elif V8_HOST_ARCH_ARM
2171       // Taken from http://msdn.microsoft.com/en-us/library/aa448762.aspx
2172       sample->pc = reinterpret_cast<Address>(context.Pc);
2173       sample->sp = reinterpret_cast<Address>(context.Sp);
2174       sample->fp = reinterpret_cast<Address>(context.R11);
2175 #else
2176 #error This Platform is not supported.
2177 #endif
2178       sampler->SampleStack(sample);
2179       sampler->Tick(sample);
2180     }
2181     ResumeThread(profiled_thread);
2182   }
2183
2184   const int interval_;
2185   RuntimeProfilerRateLimiter rate_limiter_;
2186
2187   // Protects the process wide state below.
2188   static Mutex* mutex_;
2189   static SamplerThread* instance_;
2190
2191  private:
2192   DISALLOW_COPY_AND_ASSIGN(SamplerThread);
2193 };
2194
2195
2196 Mutex* SamplerThread::mutex_ = NULL;
2197 SamplerThread* SamplerThread::instance_ = NULL;
2198
2199
2200 void OS::SetUp() {
2201   // Seed the random number generator.
2202   // Convert the current time to a 64-bit integer first, before converting it
2203   // to an unsigned. Going directly can cause an overflow and the seed to be
2204   // set to all ones. The seed will be identical for different instances that
2205   // call this setup code within the same millisecond.
2206   uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
2207   srand(static_cast<unsigned int>(seed));
2208   limit_mutex = CreateMutex();
2209   SamplerThread::SetUp();
2210 }
2211
2212
2213 void OS::TearDown() {
2214   SamplerThread::TearDown();
2215   delete limit_mutex;
2216 }
2217
2218
2219 Sampler::Sampler(Isolate* isolate, int interval)
2220     : isolate_(isolate),
2221       interval_(interval),
2222       profiling_(false),
2223       active_(false),
2224       samples_taken_(0) {
2225   data_ = new PlatformData;
2226 }
2227
2228
2229 Sampler::~Sampler() {
2230   ASSERT(!IsActive());
2231   delete data_;
2232 }
2233
2234
2235 void Sampler::Start() {
2236   ASSERT(!IsActive());
2237   SetActive(true);
2238   SamplerThread::AddActiveSampler(this);
2239 }
2240
2241
2242 void Sampler::Stop() {
2243   ASSERT(IsActive());
2244   SamplerThread::RemoveActiveSampler(this);
2245   SetActive(false);
2246 }
2247
2248
2249 } }  // namespace v8::internal