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