v8  3.11.10(node0.8.26)
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 
630 // ----------------------------------------------------------------------------
631 // Win32 console output.
632 //
633 // If a Win32 application is linked as a console application it has a normal
634 // standard output and standard error. In this case normal printf works fine
635 // for output. However, if the application is linked as a GUI application,
636 // the process doesn't have a console, and therefore (debugging) output is lost.
637 // This is the case if we are embedded in a windows program (like a browser).
638 // In order to be able to get debug output in this case the the debugging
639 // facility using OutputDebugString. This output goes to the active debugger
640 // for the process (if any). Else the output can be monitored using DBMON.EXE.
641 
643  UNKNOWN, // Output method has not yet been determined.
644  CONSOLE, // Output is written to stdout.
645  ODS // Output is written to debug facility.
646 };
647 
648 static OutputMode output_mode = UNKNOWN; // Current output mode.
649 
650 
651 // Determine if the process has a console for output.
652 static bool HasConsole() {
653  // Only check the first time. Eventual race conditions are not a problem,
654  // because all threads will eventually determine the same mode.
655  if (output_mode == UNKNOWN) {
656  // We cannot just check that the standard output is attached to a console
657  // because this would fail if output is redirected to a file. Therefore we
658  // say that a process does not have an output console if either the
659  // standard output handle is invalid or its file type is unknown.
660  if (GetStdHandle(STD_OUTPUT_HANDLE) != INVALID_HANDLE_VALUE &&
661  GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) != FILE_TYPE_UNKNOWN)
662  output_mode = CONSOLE;
663  else
664  output_mode = ODS;
665  }
666  return output_mode == CONSOLE;
667 }
668 
669 
670 static void VPrintHelper(FILE* stream, const char* format, va_list args) {
671  if (HasConsole()) {
672  vfprintf(stream, format, args);
673  } else {
674  // It is important to use safe print here in order to avoid
675  // overflowing the buffer. We might truncate the output, but this
676  // does not crash.
677  EmbeddedVector<char, 4096> buffer;
678  OS::VSNPrintF(buffer, format, args);
679  OutputDebugStringA(buffer.start());
680  }
681 }
682 
683 
684 FILE* OS::FOpen(const char* path, const char* mode) {
685  FILE* result;
686  if (fopen_s(&result, path, mode) == 0) {
687  return result;
688  } else {
689  return NULL;
690  }
691 }
692 
693 
694 bool OS::Remove(const char* path) {
695  return (DeleteFileA(path) != 0);
696 }
697 
698 
699 FILE* OS::OpenTemporaryFile() {
700  // tmpfile_s tries to use the root dir, don't use it.
701  char tempPathBuffer[MAX_PATH];
702  DWORD path_result = 0;
703  path_result = GetTempPathA(MAX_PATH, tempPathBuffer);
704  if (path_result > MAX_PATH || path_result == 0) return NULL;
705  UINT name_result = 0;
706  char tempNameBuffer[MAX_PATH];
707  name_result = GetTempFileNameA(tempPathBuffer, "", 0, tempNameBuffer);
708  if (name_result == 0) return NULL;
709  FILE* result = FOpen(tempNameBuffer, "w+"); // Same mode as tmpfile uses.
710  if (result != NULL) {
711  Remove(tempNameBuffer); // Delete on close.
712  }
713  return result;
714 }
715 
716 
717 // Open log file in binary mode to avoid /n -> /r/n conversion.
718 const char* const OS::LogFileOpenMode = "wb";
719 
720 
721 // Print (debug) message to console.
722 void OS::Print(const char* format, ...) {
723  va_list args;
724  va_start(args, format);
725  VPrint(format, args);
726  va_end(args);
727 }
728 
729 
730 void OS::VPrint(const char* format, va_list args) {
731  VPrintHelper(stdout, format, args);
732 }
733 
734 
735 void OS::FPrint(FILE* out, const char* format, ...) {
736  va_list args;
737  va_start(args, format);
738  VFPrint(out, format, args);
739  va_end(args);
740 }
741 
742 
743 void OS::VFPrint(FILE* out, const char* format, va_list args) {
744  VPrintHelper(out, format, args);
745 }
746 
747 
748 // Print error message to console.
749 void OS::PrintError(const char* format, ...) {
750  va_list args;
751  va_start(args, format);
752  VPrintError(format, args);
753  va_end(args);
754 }
755 
756 
757 void OS::VPrintError(const char* format, va_list args) {
758  VPrintHelper(stderr, format, args);
759 }
760 
761 
762 int OS::SNPrintF(Vector<char> str, const char* format, ...) {
763  va_list args;
764  va_start(args, format);
765  int result = VSNPrintF(str, format, args);
766  va_end(args);
767  return result;
768 }
769 
770 
771 int OS::VSNPrintF(Vector<char> str, const char* format, va_list args) {
772  int n = _vsnprintf_s(str.start(), str.length(), _TRUNCATE, format, args);
773  // Make sure to zero-terminate the string if the output was
774  // truncated or if there was an error.
775  if (n < 0 || n >= str.length()) {
776  if (str.length() > 0)
777  str[str.length() - 1] = '\0';
778  return -1;
779  } else {
780  return n;
781  }
782 }
783 
784 
785 char* OS::StrChr(char* str, int c) {
786  return const_cast<char*>(strchr(str, c));
787 }
788 
789 
790 void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
791  // Use _TRUNCATE or strncpy_s crashes (by design) if buffer is too small.
792  size_t buffer_size = static_cast<size_t>(dest.length());
793  if (n + 1 > buffer_size) // count for trailing '\0'
794  n = _TRUNCATE;
795  int result = strncpy_s(dest.start(), dest.length(), src, n);
796  USE(result);
797  ASSERT(result == 0 || (n == _TRUNCATE && result == STRUNCATE));
798 }
799 
800 
801 // We keep the lowest and highest addresses mapped as a quick way of
802 // determining that pointers are outside the heap (used mostly in assertions
803 // and verification). The estimate is conservative, i.e., not all addresses in
804 // 'allocated' space are actually allocated to our heap. The range is
805 // [lowest, highest), inclusive on the low and and exclusive on the high end.
806 static void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
807 static void* highest_ever_allocated = reinterpret_cast<void*>(0);
808 
809 
810 static void UpdateAllocatedSpaceLimits(void* address, int size) {
811  ASSERT(limit_mutex != NULL);
812  ScopedLock lock(limit_mutex);
813 
814  lowest_ever_allocated = Min(lowest_ever_allocated, address);
815  highest_ever_allocated =
816  Max(highest_ever_allocated,
817  reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
818 }
819 
820 
821 bool OS::IsOutsideAllocatedSpace(void* pointer) {
822  if (pointer < lowest_ever_allocated || pointer >= highest_ever_allocated)
823  return true;
824  // Ask the Windows API
825  if (IsBadWritePtr(pointer, 1))
826  return true;
827  return false;
828 }
829 
830 
831 // Get the system's page size used by VirtualAlloc() or the next power
832 // of two. The reason for always returning a power of two is that the
833 // rounding up in OS::Allocate expects that.
834 static size_t GetPageSize() {
835  static size_t page_size = 0;
836  if (page_size == 0) {
837  SYSTEM_INFO info;
838  GetSystemInfo(&info);
839  page_size = RoundUpToPowerOf2(info.dwPageSize);
840  }
841  return page_size;
842 }
843 
844 
845 // The allocation alignment is the guaranteed alignment for
846 // VirtualAlloc'ed blocks of memory.
847 size_t OS::AllocateAlignment() {
848  static size_t allocate_alignment = 0;
849  if (allocate_alignment == 0) {
850  SYSTEM_INFO info;
851  GetSystemInfo(&info);
852  allocate_alignment = info.dwAllocationGranularity;
853  }
854  return allocate_alignment;
855 }
856 
857 
858 static void* GetRandomAddr() {
859  Isolate* isolate = Isolate::UncheckedCurrent();
860  // Note that the current isolate isn't set up in a call path via
861  // CpuFeatures::Probe. We don't care about randomization in this case because
862  // the code page is immediately freed.
863  if (isolate != NULL) {
864  // The address range used to randomize RWX allocations in OS::Allocate
865  // Try not to map pages into the default range that windows loads DLLs
866  // Use a multiple of 64k to prevent committing unused memory.
867  // Note: This does not guarantee RWX regions will be within the
868  // range kAllocationRandomAddressMin to kAllocationRandomAddressMax
869 #ifdef V8_HOST_ARCH_64_BIT
870  static const intptr_t kAllocationRandomAddressMin = 0x0000000080000000;
871  static const intptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000;
872 #else
873  static const intptr_t kAllocationRandomAddressMin = 0x04000000;
874  static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000;
875 #endif
876  uintptr_t address = (V8::RandomPrivate(isolate) << kPageSizeBits)
877  | kAllocationRandomAddressMin;
878  address &= kAllocationRandomAddressMax;
879  return reinterpret_cast<void *>(address);
880  }
881  return NULL;
882 }
883 
884 
885 static void* RandomizedVirtualAlloc(size_t size, int action, int protection) {
886  LPVOID base = NULL;
887 
888  if (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS) {
889  // For exectutable pages try and randomize the allocation address
890  for (size_t attempts = 0; base == NULL && attempts < 3; ++attempts) {
891  base = VirtualAlloc(GetRandomAddr(), size, action, protection);
892  }
893  }
894 
895  // After three attempts give up and let the OS find an address to use.
896  if (base == NULL) base = VirtualAlloc(NULL, size, action, protection);
897 
898  return base;
899 }
900 
901 
902 void* OS::Allocate(const size_t requested,
903  size_t* allocated,
904  bool is_executable) {
905  // VirtualAlloc rounds allocated size to page size automatically.
906  size_t msize = RoundUp(requested, static_cast<int>(GetPageSize()));
907 
908  // Windows XP SP2 allows Data Excution Prevention (DEP).
909  int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
910 
911  LPVOID mbase = RandomizedVirtualAlloc(msize,
912  MEM_COMMIT | MEM_RESERVE,
913  prot);
914 
915  if (mbase == NULL) {
916  LOG(ISOLATE, StringEvent("OS::Allocate", "VirtualAlloc failed"));
917  return NULL;
918  }
919 
920  ASSERT(IsAligned(reinterpret_cast<size_t>(mbase), OS::AllocateAlignment()));
921 
922  *allocated = msize;
923  UpdateAllocatedSpaceLimits(mbase, static_cast<int>(msize));
924  return mbase;
925 }
926 
927 
928 void OS::Free(void* address, const size_t size) {
929  // TODO(1240712): VirtualFree has a return value which is ignored here.
930  VirtualFree(address, 0, MEM_RELEASE);
931  USE(size);
932 }
933 
934 
935 intptr_t OS::CommitPageSize() {
936  return 4096;
937 }
938 
939 
940 void OS::ProtectCode(void* address, const size_t size) {
941  DWORD old_protect;
942  VirtualProtect(address, size, PAGE_EXECUTE_READ, &old_protect);
943 }
944 
945 
946 void OS::Guard(void* address, const size_t size) {
947  DWORD oldprotect;
948  VirtualProtect(address, size, PAGE_READONLY | PAGE_GUARD, &oldprotect);
949 }
950 
951 
952 void OS::Sleep(int milliseconds) {
953  ::Sleep(milliseconds);
954 }
955 
956 
957 void OS::Abort() {
958  if (IsDebuggerPresent() || FLAG_break_on_abort) {
959  DebugBreak();
960  } else {
961  // Make the MSVCRT do a silent abort.
962  raise(SIGABRT);
963  }
964 }
965 
966 
967 void OS::DebugBreak() {
968 #ifdef _MSC_VER
969  __debugbreak();
970 #else
971  ::DebugBreak();
972 #endif
973 }
974 
975 
977  public:
979  HANDLE file_mapping,
980  void* memory,
981  int size)
982  : file_(file),
983  file_mapping_(file_mapping),
984  memory_(memory),
985  size_(size) { }
986  virtual ~Win32MemoryMappedFile();
987  virtual void* memory() { return memory_; }
988  virtual int size() { return size_; }
989  private:
990  HANDLE file_;
991  HANDLE file_mapping_;
992  void* memory_;
993  int size_;
994 };
995 
996 
997 OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
998  // Open a physical file
999  HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE,
1000  FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
1001  if (file == INVALID_HANDLE_VALUE) return NULL;
1002 
1003  int size = static_cast<int>(GetFileSize(file, NULL));
1004 
1005  // Create a file mapping for the physical file
1006  HANDLE file_mapping = CreateFileMapping(file, NULL,
1007  PAGE_READWRITE, 0, static_cast<DWORD>(size), NULL);
1008  if (file_mapping == NULL) return NULL;
1009 
1010  // Map a view of the file into memory
1011  void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size);
1012  return new Win32MemoryMappedFile(file, file_mapping, memory, size);
1013 }
1014 
1015 
1016 OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
1017  void* initial) {
1018  // Open a physical file
1019  HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE,
1020  FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
1021  if (file == NULL) return NULL;
1022  // Create a file mapping for the physical file
1023  HANDLE file_mapping = CreateFileMapping(file, NULL,
1024  PAGE_READWRITE, 0, static_cast<DWORD>(size), NULL);
1025  if (file_mapping == NULL) return NULL;
1026  // Map a view of the file into memory
1027  void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size);
1028  if (memory) memmove(memory, initial, size);
1029  return new Win32MemoryMappedFile(file, file_mapping, memory, size);
1030 }
1031 
1032 
1034  if (memory_ != NULL)
1035  UnmapViewOfFile(memory_);
1036  CloseHandle(file_mapping_);
1037  CloseHandle(file_);
1038 }
1039 
1040 
1041 // The following code loads functions defined in DbhHelp.h and TlHelp32.h
1042 // dynamically. This is to avoid being depending on dbghelp.dll and
1043 // tlhelp32.dll when running (the functions in tlhelp32.dll have been moved to
1044 // kernel32.dll at some point so loading functions defines in TlHelp32.h
1045 // dynamically might not be necessary any more - for some versions of Windows?).
1046 
1047 // Function pointers to functions dynamically loaded from dbghelp.dll.
1048 #define DBGHELP_FUNCTION_LIST(V) \
1049  V(SymInitialize) \
1050  V(SymGetOptions) \
1051  V(SymSetOptions) \
1052  V(SymGetSearchPath) \
1053  V(SymLoadModule64) \
1054  V(StackWalk64) \
1055  V(SymGetSymFromAddr64) \
1056  V(SymGetLineFromAddr64) \
1057  V(SymFunctionTableAccess64) \
1058  V(SymGetModuleBase64)
1059 
1060 // Function pointers to functions dynamically loaded from dbghelp.dll.
1061 #define TLHELP32_FUNCTION_LIST(V) \
1062  V(CreateToolhelp32Snapshot) \
1063  V(Module32FirstW) \
1064  V(Module32NextW)
1065 
1066 // Define the decoration to use for the type and variable name used for
1067 // dynamically loaded DLL function..
1068 #define DLL_FUNC_TYPE(name) _##name##_
1069 #define DLL_FUNC_VAR(name) _##name
1070 
1071 // Define the type for each dynamically loaded DLL function. The function
1072 // definitions are copied from DbgHelp.h and TlHelp32.h. The IN and VOID macros
1073 // from the Windows include files are redefined here to have the function
1074 // definitions to be as close to the ones in the original .h files as possible.
1075 #ifndef IN
1076 #define IN
1077 #endif
1078 #ifndef VOID
1079 #define VOID void
1080 #endif
1081 
1082 // DbgHelp isn't supported on MinGW yet
1083 #ifndef __MINGW32__
1084 // DbgHelp.h functions.
1085 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymInitialize))(IN HANDLE hProcess,
1088 typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymGetOptions))(VOID);
1089 typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymSetOptions))(IN DWORD SymOptions);
1090 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSearchPath))(
1091  IN HANDLE hProcess,
1092  OUT PSTR SearchPath,
1094 typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymLoadModule64))(
1095  IN HANDLE hProcess,
1097  IN PSTR ImageName,
1098  IN PSTR ModuleName,
1100  IN DWORD SizeOfDll);
1101 typedef BOOL (__stdcall *DLL_FUNC_TYPE(StackWalk64))(
1102  DWORD MachineType,
1104  HANDLE hThread,
1105  LPSTACKFRAME64 StackFrame,
1107  PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
1108  PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
1109  PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
1110  PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
1111 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSymFromAddr64))(
1112  IN HANDLE hProcess,
1114  OUT PDWORD64 pdwDisplacement,
1115  OUT PIMAGEHLP_SYMBOL64 Symbol);
1116 typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetLineFromAddr64))(
1117  IN HANDLE hProcess,
1119  OUT PDWORD pdwDisplacement,
1120  OUT PIMAGEHLP_LINE64 Line64);
1121 // DbgHelp.h typedefs. Implementation found in dbghelp.dll.
1122 typedef PVOID (__stdcall *DLL_FUNC_TYPE(SymFunctionTableAccess64))(
1123  HANDLE hProcess,
1124  DWORD64 AddrBase); // DbgHelp.h typedef PFUNCTION_TABLE_ACCESS_ROUTINE64
1125 typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymGetModuleBase64))(
1126  HANDLE hProcess,
1127  DWORD64 AddrBase); // DbgHelp.h typedef PGET_MODULE_BASE_ROUTINE64
1128 
1129 // TlHelp32.h functions.
1130 typedef HANDLE (__stdcall *DLL_FUNC_TYPE(CreateToolhelp32Snapshot))(
1131  DWORD dwFlags,
1133 typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32FirstW))(HANDLE hSnapshot,
1134  LPMODULEENTRY32W lpme);
1135 typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32NextW))(HANDLE hSnapshot,
1136  LPMODULEENTRY32W lpme);
1137 
1138 #undef IN
1139 #undef VOID
1140 
1141 // Declare a variable for each dynamically loaded DLL function.
1142 #define DEF_DLL_FUNCTION(name) DLL_FUNC_TYPE(name) DLL_FUNC_VAR(name) = NULL;
1145 #undef DEF_DLL_FUNCTION
1146 
1147 // Load the functions. This function has a lot of "ugly" macros in order to
1148 // keep down code duplication.
1149 
1150 static bool LoadDbgHelpAndTlHelp32() {
1151  static bool dbghelp_loaded = false;
1152 
1153  if (dbghelp_loaded) return true;
1154 
1155  HMODULE module;
1156 
1157  // Load functions from the dbghelp.dll module.
1158  module = LoadLibrary(TEXT("dbghelp.dll"));
1159  if (module == NULL) {
1160  return false;
1161  }
1162 
1163 #define LOAD_DLL_FUNC(name) \
1164  DLL_FUNC_VAR(name) = \
1165  reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name));
1166 
1168 
1169 #undef LOAD_DLL_FUNC
1170 
1171  // Load functions from the kernel32.dll module (the TlHelp32.h function used
1172  // to be in tlhelp32.dll but are now moved to kernel32.dll).
1173  module = LoadLibrary(TEXT("kernel32.dll"));
1174  if (module == NULL) {
1175  return false;
1176  }
1177 
1178 #define LOAD_DLL_FUNC(name) \
1179  DLL_FUNC_VAR(name) = \
1180  reinterpret_cast<DLL_FUNC_TYPE(name)>(GetProcAddress(module, #name));
1181 
1183 
1184 #undef LOAD_DLL_FUNC
1185 
1186  // Check that all functions where loaded.
1187  bool result =
1188 #define DLL_FUNC_LOADED(name) (DLL_FUNC_VAR(name) != NULL) &&
1189 
1192 
1193 #undef DLL_FUNC_LOADED
1194  true;
1195 
1196  dbghelp_loaded = result;
1197  return result;
1198  // NOTE: The modules are never unloaded and will stay around until the
1199  // application is closed.
1200 }
1201 
1202 
1203 // Load the symbols for generating stack traces.
1204 static bool LoadSymbols(HANDLE process_handle) {
1205  static bool symbols_loaded = false;
1206 
1207  if (symbols_loaded) return true;
1208 
1209  BOOL ok;
1210 
1211  // Initialize the symbol engine.
1212  ok = _SymInitialize(process_handle, // hProcess
1213  NULL, // UserSearchPath
1214  false); // fInvadeProcess
1215  if (!ok) return false;
1216 
1217  DWORD options = _SymGetOptions();
1218  options |= SYMOPT_LOAD_LINES;
1219  options |= SYMOPT_FAIL_CRITICAL_ERRORS;
1220  options = _SymSetOptions(options);
1221 
1222  char buf[OS::kStackWalkMaxNameLen] = {0};
1223  ok = _SymGetSearchPath(process_handle, buf, OS::kStackWalkMaxNameLen);
1224  if (!ok) {
1225  int err = GetLastError();
1226  PrintF("%d\n", err);
1227  return false;
1228  }
1229 
1230  HANDLE snapshot = _CreateToolhelp32Snapshot(
1231  TH32CS_SNAPMODULE, // dwFlags
1232  GetCurrentProcessId()); // th32ProcessId
1233  if (snapshot == INVALID_HANDLE_VALUE) return false;
1234  MODULEENTRY32W module_entry;
1235  module_entry.dwSize = sizeof(module_entry); // Set the size of the structure.
1236  BOOL cont = _Module32FirstW(snapshot, &module_entry);
1237  while (cont) {
1238  DWORD64 base;
1239  // NOTE the SymLoadModule64 function has the peculiarity of accepting a
1240  // both unicode and ASCII strings even though the parameter is PSTR.
1241  base = _SymLoadModule64(
1242  process_handle, // hProcess
1243  0, // hFile
1244  reinterpret_cast<PSTR>(module_entry.szExePath), // ImageName
1245  reinterpret_cast<PSTR>(module_entry.szModule), // ModuleName
1246  reinterpret_cast<DWORD64>(module_entry.modBaseAddr), // BaseOfDll
1247  module_entry.modBaseSize); // SizeOfDll
1248  if (base == 0) {
1249  int err = GetLastError();
1250  if (err != ERROR_MOD_NOT_FOUND &&
1251  err != ERROR_INVALID_HANDLE) return false;
1252  }
1253  LOG(i::Isolate::Current(),
1254  SharedLibraryEvent(
1255  module_entry.szExePath,
1256  reinterpret_cast<unsigned int>(module_entry.modBaseAddr),
1257  reinterpret_cast<unsigned int>(module_entry.modBaseAddr +
1258  module_entry.modBaseSize)));
1259  cont = _Module32NextW(snapshot, &module_entry);
1260  }
1261  CloseHandle(snapshot);
1262 
1263  symbols_loaded = true;
1264  return true;
1265 }
1266 
1267 
1269  // SharedLibraryEvents are logged when loading symbol information.
1270  // Only the shared libraries loaded at the time of the call to
1271  // LogSharedLibraryAddresses are logged. DLLs loaded after
1272  // initialization are not accounted for.
1273  if (!LoadDbgHelpAndTlHelp32()) return;
1274  HANDLE process_handle = GetCurrentProcess();
1275  LoadSymbols(process_handle);
1276 }
1277 
1278 
1279 void OS::SignalCodeMovingGC() {
1280 }
1281 
1282 
1283 // Walk the stack using the facilities in dbghelp.dll and tlhelp32.dll
1284 
1285 // Switch off warning 4748 (/GS can not protect parameters and local variables
1286 // from local buffer overrun because optimizations are disabled in function) as
1287 // it is triggered by the use of inline assembler.
1288 #pragma warning(push)
1289 #pragma warning(disable : 4748)
1290 int OS::StackWalk(Vector<OS::StackFrame> frames) {
1291  BOOL ok;
1292 
1293  // Load the required functions from DLL's.
1294  if (!LoadDbgHelpAndTlHelp32()) return kStackWalkError;
1295 
1296  // Get the process and thread handles.
1297  HANDLE process_handle = GetCurrentProcess();
1298  HANDLE thread_handle = GetCurrentThread();
1299 
1300  // Read the symbols.
1301  if (!LoadSymbols(process_handle)) return kStackWalkError;
1302 
1303  // Capture current context.
1304  CONTEXT context;
1305  RtlCaptureContext(&context);
1306 
1307  // Initialize the stack walking
1308  STACKFRAME64 stack_frame;
1309  memset(&stack_frame, 0, sizeof(stack_frame));
1310 #ifdef _WIN64
1311  stack_frame.AddrPC.Offset = context.Rip;
1312  stack_frame.AddrFrame.Offset = context.Rbp;
1313  stack_frame.AddrStack.Offset = context.Rsp;
1314 #else
1315  stack_frame.AddrPC.Offset = context.Eip;
1316  stack_frame.AddrFrame.Offset = context.Ebp;
1317  stack_frame.AddrStack.Offset = context.Esp;
1318 #endif
1319  stack_frame.AddrPC.Mode = AddrModeFlat;
1320  stack_frame.AddrFrame.Mode = AddrModeFlat;
1321  stack_frame.AddrStack.Mode = AddrModeFlat;
1322  int frames_count = 0;
1323 
1324  // Collect stack frames.
1325  int frames_size = frames.length();
1326  while (frames_count < frames_size) {
1327  ok = _StackWalk64(
1328  IMAGE_FILE_MACHINE_I386, // MachineType
1329  process_handle, // hProcess
1330  thread_handle, // hThread
1331  &stack_frame, // StackFrame
1332  &context, // ContextRecord
1333  NULL, // ReadMemoryRoutine
1334  _SymFunctionTableAccess64, // FunctionTableAccessRoutine
1335  _SymGetModuleBase64, // GetModuleBaseRoutine
1336  NULL); // TranslateAddress
1337  if (!ok) break;
1338 
1339  // Store the address.
1340  ASSERT((stack_frame.AddrPC.Offset >> 32) == 0); // 32-bit address.
1341  frames[frames_count].address =
1342  reinterpret_cast<void*>(stack_frame.AddrPC.Offset);
1343 
1344  // Try to locate a symbol for this frame.
1345  DWORD64 symbol_displacement;
1346  SmartArrayPointer<IMAGEHLP_SYMBOL64> symbol(
1347  NewArray<IMAGEHLP_SYMBOL64>(kStackWalkMaxNameLen));
1348  if (symbol.is_empty()) return kStackWalkError; // Out of memory.
1349  memset(*symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + kStackWalkMaxNameLen);
1350  (*symbol)->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
1351  (*symbol)->MaxNameLength = kStackWalkMaxNameLen;
1352  ok = _SymGetSymFromAddr64(process_handle, // hProcess
1353  stack_frame.AddrPC.Offset, // Address
1354  &symbol_displacement, // Displacement
1355  *symbol); // Symbol
1356  if (ok) {
1357  // Try to locate more source information for the symbol.
1358  IMAGEHLP_LINE64 Line;
1359  memset(&Line, 0, sizeof(Line));
1360  Line.SizeOfStruct = sizeof(Line);
1361  DWORD line_displacement;
1362  ok = _SymGetLineFromAddr64(
1363  process_handle, // hProcess
1364  stack_frame.AddrPC.Offset, // dwAddr
1365  &line_displacement, // pdwDisplacement
1366  &Line); // Line
1367  // Format a text representation of the frame based on the information
1368  // available.
1369  if (ok) {
1370  SNPrintF(MutableCStrVector(frames[frames_count].text,
1372  "%s %s:%d:%d",
1373  (*symbol)->Name, Line.FileName, Line.LineNumber,
1374  line_displacement);
1375  } else {
1376  SNPrintF(MutableCStrVector(frames[frames_count].text,
1378  "%s",
1379  (*symbol)->Name);
1380  }
1381  // Make sure line termination is in place.
1382  frames[frames_count].text[kStackWalkMaxTextLen - 1] = '\0';
1383  } else {
1384  // No text representation of this frame
1385  frames[frames_count].text[0] = '\0';
1386 
1387  // Continue if we are just missing a module (for non C/C++ frames a
1388  // module will never be found).
1389  int err = GetLastError();
1390  if (err != ERROR_MOD_NOT_FOUND) {
1391  break;
1392  }
1393  }
1394 
1395  frames_count++;
1396  }
1397 
1398  // Return the number of frames filled in.
1399  return frames_count;
1400 }
1401 
1402 // Restore warnings to previous settings.
1403 #pragma warning(pop)
1404 
1405 #else // __MINGW32__
1407 void OS::SignalCodeMovingGC() { }
1408 int OS::StackWalk(Vector<OS::StackFrame> frames) { return 0; }
1409 #endif // __MINGW32__
1410 
1411 
1413  return 0; // Windows runs on anything.
1414 }
1415 
1416 
1417 double OS::nan_value() {
1418 #ifdef _MSC_VER
1419  // Positive Quiet NaN with no payload (aka. Indeterminate) has all bits
1420  // in mask set, so value equals mask.
1421  static const __int64 nanval = kQuietNaNMask;
1422  return *reinterpret_cast<const double*>(&nanval);
1423 #else // _MSC_VER
1424  return NAN;
1425 #endif // _MSC_VER
1426 }
1427 
1428 
1430 #ifdef _WIN64
1431  return 16; // Windows 64-bit ABI requires the stack to be 16-byte aligned.
1432 #else
1433  return 8; // Floating-point math runs faster with 8-byte alignment.
1434 #endif
1435 }
1436 
1437 
1438 void OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
1439  MemoryBarrier();
1440  *ptr = value;
1441 }
1442 
1443 
1444 VirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
1445 
1446 
1447 VirtualMemory::VirtualMemory(size_t size)
1448  : address_(ReserveRegion(size)), size_(size) { }
1449 
1450 
1451 VirtualMemory::VirtualMemory(size_t size, size_t alignment)
1452  : address_(NULL), size_(0) {
1453  ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
1454  size_t request_size = RoundUp(size + alignment,
1455  static_cast<intptr_t>(OS::AllocateAlignment()));
1456  void* address = ReserveRegion(request_size);
1457  if (address == NULL) return;
1458  Address base = RoundUp(static_cast<Address>(address), alignment);
1459  // Try reducing the size by freeing and then reallocating a specific area.
1460  bool result = ReleaseRegion(address, request_size);
1461  USE(result);
1462  ASSERT(result);
1463  address = VirtualAlloc(base, size, MEM_RESERVE, PAGE_NOACCESS);
1464  if (address != NULL) {
1465  request_size = size;
1466  ASSERT(base == static_cast<Address>(address));
1467  } else {
1468  // Resizing failed, just go with a bigger area.
1469  address = ReserveRegion(request_size);
1470  if (address == NULL) return;
1471  }
1472  address_ = address;
1473  size_ = request_size;
1474 }
1475 
1476 
1477 VirtualMemory::~VirtualMemory() {
1478  if (IsReserved()) {
1479  bool result = ReleaseRegion(address_, size_);
1480  ASSERT(result);
1481  USE(result);
1482  }
1483 }
1484 
1485 
1486 bool VirtualMemory::IsReserved() {
1487  return address_ != NULL;
1488 }
1489 
1490 
1491 void VirtualMemory::Reset() {
1492  address_ = NULL;
1493  size_ = 0;
1494 }
1495 
1496 
1497 bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
1498  if (CommitRegion(address, size, is_executable)) {
1499  UpdateAllocatedSpaceLimits(address, static_cast<int>(size));
1500  return true;
1501  }
1502  return false;
1503 }
1504 
1505 
1506 bool VirtualMemory::Uncommit(void* address, size_t size) {
1507  ASSERT(IsReserved());
1508  return UncommitRegion(address, size);
1509 }
1510 
1511 
1512 void* VirtualMemory::ReserveRegion(size_t size) {
1513  return RandomizedVirtualAlloc(size, MEM_RESERVE, PAGE_NOACCESS);
1514 }
1515 
1516 
1517 bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
1518  int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
1519  if (NULL == VirtualAlloc(base, size, MEM_COMMIT, prot)) {
1520  return false;
1521  }
1522 
1523  UpdateAllocatedSpaceLimits(base, static_cast<int>(size));
1524  return true;
1525 }
1526 
1527 
1528 bool VirtualMemory::Guard(void* address) {
1529  if (NULL == VirtualAlloc(address,
1530  OS::CommitPageSize(),
1531  MEM_COMMIT,
1532  PAGE_READONLY | PAGE_GUARD)) {
1533  return false;
1534  }
1535  return true;
1536 }
1537 
1538 
1539 bool VirtualMemory::UncommitRegion(void* base, size_t size) {
1540  return VirtualFree(base, size, MEM_DECOMMIT) != 0;
1541 }
1542 
1543 
1544 bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
1545  return VirtualFree(base, 0, MEM_RELEASE) != 0;
1546 }
1547 
1548 
1549 // ----------------------------------------------------------------------------
1550 // Win32 thread support.
1551 
1552 // Definition of invalid thread handle and id.
1553 static const HANDLE kNoThread = INVALID_HANDLE_VALUE;
1554 
1555 // Entry point for threads. The supplied argument is a pointer to the thread
1556 // object. The entry function dispatches to the run method in the thread
1557 // object. It is important that this function has __stdcall calling
1558 // convention.
1559 static unsigned int __stdcall ThreadEntry(void* arg) {
1560  Thread* thread = reinterpret_cast<Thread*>(arg);
1561  thread->Run();
1562  return 0;
1563 }
1564 
1565 
1566 class Thread::PlatformData : public Malloced {
1567  public:
1568  explicit PlatformData(HANDLE thread) : thread_(thread) {}
1570  unsigned thread_id_;
1571 };
1572 
1573 
1574 // Initialize a Win32 thread object. The thread has an invalid thread
1575 // handle until it is started.
1576 
1577 Thread::Thread(const Options& options)
1578  : stack_size_(options.stack_size()) {
1579  data_ = new PlatformData(kNoThread);
1580  set_name(options.name());
1581 }
1582 
1583 
1584 void Thread::set_name(const char* name) {
1585  OS::StrNCpy(Vector<char>(name_, sizeof(name_)), name, strlen(name));
1586  name_[sizeof(name_) - 1] = '\0';
1587 }
1588 
1589 
1590 // Close our own handle for the thread.
1591 Thread::~Thread() {
1592  if (data_->thread_ != kNoThread) CloseHandle(data_->thread_);
1593  delete data_;
1594 }
1595 
1596 
1597 // Create a new thread. It is important to use _beginthreadex() instead of
1598 // the Win32 function CreateThread(), because the CreateThread() does not
1599 // initialize thread specific structures in the C runtime library.
1600 void Thread::Start() {
1601  data_->thread_ = reinterpret_cast<HANDLE>(
1602  _beginthreadex(NULL,
1603  static_cast<unsigned>(stack_size_),
1604  ThreadEntry,
1605  this,
1606  0,
1607  &data_->thread_id_));
1608 }
1609 
1610 
1611 // Wait for thread to terminate.
1612 void Thread::Join() {
1613  if (data_->thread_id_ != GetCurrentThreadId()) {
1614  WaitForSingleObject(data_->thread_, INFINITE);
1615  }
1616 }
1617 
1618 
1620  DWORD result = TlsAlloc();
1621  ASSERT(result != TLS_OUT_OF_INDEXES);
1622  return static_cast<LocalStorageKey>(result);
1623 }
1624 
1625 
1627  BOOL result = TlsFree(static_cast<DWORD>(key));
1628  USE(result);
1629  ASSERT(result);
1630 }
1631 
1632 
1634  return TlsGetValue(static_cast<DWORD>(key));
1635 }
1636 
1637 
1638 void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
1639  BOOL result = TlsSetValue(static_cast<DWORD>(key), value);
1640  USE(result);
1641  ASSERT(result);
1642 }
1643 
1644 
1645 
1646 void Thread::YieldCPU() {
1647  Sleep(0);
1648 }
1649 
1650 
1651 // ----------------------------------------------------------------------------
1652 // Win32 mutex support.
1653 //
1654 // On Win32 mutexes are implemented using CRITICAL_SECTION objects. These are
1655 // faster than Win32 Mutex objects because they are implemented using user mode
1656 // atomic instructions. Therefore we only do ring transitions if there is lock
1657 // contention.
1658 
1659 class Win32Mutex : public Mutex {
1660  public:
1661  Win32Mutex() { InitializeCriticalSection(&cs_); }
1662 
1663  virtual ~Win32Mutex() { DeleteCriticalSection(&cs_); }
1664 
1665  virtual int Lock() {
1666  EnterCriticalSection(&cs_);
1667  return 0;
1668  }
1669 
1670  virtual int Unlock() {
1671  LeaveCriticalSection(&cs_);
1672  return 0;
1673  }
1674 
1675 
1676  virtual bool TryLock() {
1677  // Returns non-zero if critical section is entered successfully entered.
1678  return TryEnterCriticalSection(&cs_);
1679  }
1680 
1681  private:
1682  CRITICAL_SECTION cs_; // Critical section used for mutex
1683 };
1684 
1685 
1686 Mutex* OS::CreateMutex() {
1687  return new Win32Mutex();
1688 }
1689 
1690 
1691 // ----------------------------------------------------------------------------
1692 // Win32 semaphore support.
1693 //
1694 // On Win32 semaphores are implemented using Win32 Semaphore objects. The
1695 // semaphores are anonymous. Also, the semaphores are initialized to have
1696 // no upper limit on count.
1697 
1698 
1699 class Win32Semaphore : public Semaphore {
1700  public:
1701  explicit Win32Semaphore(int count) {
1702  sem = ::CreateSemaphoreA(NULL, count, 0x7fffffff, NULL);
1703  }
1704 
1706  CloseHandle(sem);
1707  }
1708 
1709  void Wait() {
1710  WaitForSingleObject(sem, INFINITE);
1711  }
1712 
1713  bool Wait(int timeout) {
1714  // Timeout in Windows API is in milliseconds.
1715  DWORD millis_timeout = timeout / 1000;
1716  return WaitForSingleObject(sem, millis_timeout) != WAIT_TIMEOUT;
1717  }
1718 
1719  void Signal() {
1720  LONG dummy;
1721  ReleaseSemaphore(sem, 1, &dummy);
1722  }
1723 
1724  private:
1725  HANDLE sem;
1726 };
1727 
1728 
1729 Semaphore* OS::CreateSemaphore(int count) {
1730  return new Win32Semaphore(count);
1731 }
1732 
1733 
1734 // ----------------------------------------------------------------------------
1735 // Win32 socket support.
1736 //
1737 
1738 class Win32Socket : public Socket {
1739  public:
1740  explicit Win32Socket() {
1741  // Create the socket.
1742  socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
1743  }
1744  explicit Win32Socket(SOCKET socket): socket_(socket) { }
1745  virtual ~Win32Socket() { Shutdown(); }
1746 
1747  // Server initialization.
1748  bool Bind(const int port);
1749  bool Listen(int backlog) const;
1750  Socket* Accept() const;
1751 
1752  // Client initialization.
1753  bool Connect(const char* host, const char* port);
1754 
1755  // Shutdown socket for both read and write.
1756  bool Shutdown();
1757 
1758  // Data Transimission
1759  int Send(const char* data, int len) const;
1760  int Receive(char* data, int len) const;
1761 
1762  bool SetReuseAddress(bool reuse_address);
1763 
1764  bool IsValid() const { return socket_ != INVALID_SOCKET; }
1765 
1766  private:
1767  SOCKET socket_;
1768 };
1769 
1770 
1771 bool Win32Socket::Bind(const int port) {
1772  if (!IsValid()) {
1773  return false;
1774  }
1775 
1776  sockaddr_in addr;
1777  memset(&addr, 0, sizeof(addr));
1778  addr.sin_family = AF_INET;
1779  addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1780  addr.sin_port = htons(port);
1781  int status = bind(socket_,
1782  reinterpret_cast<struct sockaddr *>(&addr),
1783  sizeof(addr));
1784  return status == 0;
1785 }
1786 
1787 
1788 bool Win32Socket::Listen(int backlog) const {
1789  if (!IsValid()) {
1790  return false;
1791  }
1792 
1793  int status = listen(socket_, backlog);
1794  return status == 0;
1795 }
1796 
1797 
1799  if (!IsValid()) {
1800  return NULL;
1801  }
1802 
1803  SOCKET socket = accept(socket_, NULL, NULL);
1804  if (socket == INVALID_SOCKET) {
1805  return NULL;
1806  } else {
1807  return new Win32Socket(socket);
1808  }
1809 }
1810 
1811 
1812 bool Win32Socket::Connect(const char* host, const char* port) {
1813  if (!IsValid()) {
1814  return false;
1815  }
1816 
1817  // Lookup host and port.
1818  struct addrinfo *result = NULL;
1819  struct addrinfo hints;
1820  memset(&hints, 0, sizeof(addrinfo));
1821  hints.ai_family = AF_INET;
1822  hints.ai_socktype = SOCK_STREAM;
1823  hints.ai_protocol = IPPROTO_TCP;
1824  int status = getaddrinfo(host, port, &hints, &result);
1825  if (status != 0) {
1826  return false;
1827  }
1828 
1829  // Connect.
1830  status = connect(socket_,
1831  result->ai_addr,
1832  static_cast<int>(result->ai_addrlen));
1833  freeaddrinfo(result);
1834  return status == 0;
1835 }
1836 
1837 
1839  if (IsValid()) {
1840  // Shutdown socket for both read and write.
1841  int status = shutdown(socket_, SD_BOTH);
1842  closesocket(socket_);
1843  socket_ = INVALID_SOCKET;
1844  return status == SOCKET_ERROR;
1845  }
1846  return true;
1847 }
1848 
1849 
1850 int Win32Socket::Send(const char* data, int len) const {
1851  if (len <= 0) return 0;
1852  int written = 0;
1853  while (written < len) {
1854  int status = send(socket_, data + written, len - written, 0);
1855  if (status == 0) {
1856  break;
1857  } else if (status > 0) {
1858  written += status;
1859  } else {
1860  return 0;
1861  }
1862  }
1863  return written;
1864 }
1865 
1866 
1867 int Win32Socket::Receive(char* data, int len) const {
1868  if (len <= 0) return 0;
1869  int status = recv(socket_, data, len, 0);
1870  return (status == SOCKET_ERROR) ? 0 : status;
1871 }
1872 
1873 
1874 bool Win32Socket::SetReuseAddress(bool reuse_address) {
1875  BOOL on = reuse_address ? true : false;
1876  int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
1877  reinterpret_cast<char*>(&on), sizeof(on));
1878  return status == SOCKET_ERROR;
1879 }
1880 
1881 
1882 bool Socket::SetUp() {
1883  // Initialize Winsock32
1884  int err;
1885  WSADATA winsock_data;
1886  WORD version_requested = MAKEWORD(1, 0);
1887  err = WSAStartup(version_requested, &winsock_data);
1888  if (err != 0) {
1889  PrintF("Unable to initialize Winsock, err = %d\n", Socket::LastError());
1890  }
1891 
1892  return err == 0;
1893 }
1894 
1895 
1896 int Socket::LastError() {
1897  return WSAGetLastError();
1898 }
1899 
1900 
1902  return htons(value);
1903 }
1904 
1905 
1907  return ntohs(value);
1908 }
1909 
1910 
1911 uint32_t Socket::HToN(uint32_t value) {
1912  return htonl(value);
1913 }
1914 
1915 
1916 uint32_t Socket::NToH(uint32_t value) {
1917  return ntohl(value);
1918 }
1919 
1920 
1921 Socket* OS::CreateSocket() {
1922  return new Win32Socket();
1923 }
1924 
1925 
1926 // ----------------------------------------------------------------------------
1927 // Win32 profiler support.
1928 
1929 class Sampler::PlatformData : public Malloced {
1930  public:
1931  // Get a handle to the calling thread. This is the thread that we are
1932  // going to profile. We need to make a copy of the handle because we are
1933  // going to use it in the sampler thread. Using GetThreadHandle() will
1934  // not work in this case. We're using OpenThread because DuplicateHandle
1935  // for some reason doesn't work in Chrome's sandbox.
1936  PlatformData() : profiled_thread_(OpenThread(THREAD_GET_CONTEXT |
1937  THREAD_SUSPEND_RESUME |
1938  THREAD_QUERY_INFORMATION,
1939  false,
1940  GetCurrentThreadId())) {}
1941 
1943  if (profiled_thread_ != NULL) {
1944  CloseHandle(profiled_thread_);
1945  profiled_thread_ = NULL;
1946  }
1947  }
1948 
1949  HANDLE profiled_thread() { return profiled_thread_; }
1950 
1951  private:
1952  HANDLE profiled_thread_;
1953 };
1954 
1955 
1956 class SamplerThread : public Thread {
1957  public:
1958  static const int kSamplerThreadStackSize = 64 * KB;
1959 
1960  explicit SamplerThread(int interval)
1961  : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)),
1962  interval_(interval) {}
1963 
1964  static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
1965  static void TearDown() { delete mutex_; }
1966 
1967  static void AddActiveSampler(Sampler* sampler) {
1968  ScopedLock lock(mutex_);
1970  if (instance_ == NULL) {
1971  instance_ = new SamplerThread(sampler->interval());
1972  instance_->Start();
1973  } else {
1974  ASSERT(instance_->interval_ == sampler->interval());
1975  }
1976  }
1977 
1978  static void RemoveActiveSampler(Sampler* sampler) {
1979  ScopedLock lock(mutex_);
1983  delete instance_;
1984  instance_ = NULL;
1985  }
1986  }
1987 
1988  // Implement Thread::Run().
1989  virtual void Run() {
1990  SamplerRegistry::State state;
1991  while ((state = SamplerRegistry::GetState()) !=
1993  bool cpu_profiling_enabled =
1995  bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
1996  // When CPU profiling is enabled both JavaScript and C++ code is
1997  // profiled. We must not suspend.
1998  if (!cpu_profiling_enabled) {
1999  if (rate_limiter_.SuspendIfNecessary()) continue;
2000  }
2001  if (cpu_profiling_enabled) {
2002  if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
2003  return;
2004  }
2005  }
2006  if (runtime_profiler_enabled) {
2007  if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
2008  return;
2009  }
2010  }
2011  OS::Sleep(interval_);
2012  }
2013  }
2014 
2015  static void DoCpuProfile(Sampler* sampler, void* raw_sampler_thread) {
2016  if (!sampler->isolate()->IsInitialized()) return;
2017  if (!sampler->IsProfiling()) return;
2018  SamplerThread* sampler_thread =
2019  reinterpret_cast<SamplerThread*>(raw_sampler_thread);
2020  sampler_thread->SampleContext(sampler);
2021  }
2022 
2023  static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
2024  if (!sampler->isolate()->IsInitialized()) return;
2025  sampler->isolate()->runtime_profiler()->NotifyTick();
2026  }
2027 
2028  void SampleContext(Sampler* sampler) {
2029  HANDLE profiled_thread = sampler->platform_data()->profiled_thread();
2030  if (profiled_thread == NULL) return;
2031 
2032  // Context used for sampling the register state of the profiled thread.
2033  CONTEXT context;
2034  memset(&context, 0, sizeof(context));
2035 
2036  TickSample sample_obj;
2038  if (sample == NULL) sample = &sample_obj;
2039 
2040  static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
2041  if (SuspendThread(profiled_thread) == kSuspendFailed) return;
2042  sample->state = sampler->isolate()->current_vm_state();
2043 
2044  context.ContextFlags = CONTEXT_FULL;
2045  if (GetThreadContext(profiled_thread, &context) != 0) {
2046 #if V8_HOST_ARCH_X64
2047  sample->pc = reinterpret_cast<Address>(context.Rip);
2048  sample->sp = reinterpret_cast<Address>(context.Rsp);
2049  sample->fp = reinterpret_cast<Address>(context.Rbp);
2050 #else
2051  sample->pc = reinterpret_cast<Address>(context.Eip);
2052  sample->sp = reinterpret_cast<Address>(context.Esp);
2053  sample->fp = reinterpret_cast<Address>(context.Ebp);
2054 #endif
2055  sampler->SampleStack(sample);
2056  sampler->Tick(sample);
2057  }
2058  ResumeThread(profiled_thread);
2059  }
2060 
2061  const int interval_;
2062  RuntimeProfilerRateLimiter rate_limiter_;
2063 
2064  // Protects the process wide state below.
2065  static Mutex* mutex_;
2066  static SamplerThread* instance_;
2067 
2068  private:
2070 };
2071 
2072 
2073 Mutex* SamplerThread::mutex_ = NULL;
2074 SamplerThread* SamplerThread::instance_ = NULL;
2075 
2076 
2077 void OS::SetUp() {
2078  // Seed the random number generator.
2079  // Convert the current time to a 64-bit integer first, before converting it
2080  // to an unsigned. Going directly can cause an overflow and the seed to be
2081  // set to all ones. The seed will be identical for different instances that
2082  // call this setup code within the same millisecond.
2083  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
2084  srand(static_cast<unsigned int>(seed));
2085  limit_mutex = CreateMutex();
2087 }
2088 
2089 
2090 void OS::TearDown() {
2092  delete limit_mutex;
2093 }
2094 
2095 
2096 Sampler::Sampler(Isolate* isolate, int interval)
2097  : isolate_(isolate),
2098  interval_(interval),
2099  profiling_(false),
2100  active_(false),
2101  samples_taken_(0) {
2102  data_ = new PlatformData;
2103 }
2104 
2105 
2107  ASSERT(!IsActive());
2108  delete data_;
2109 }
2110 
2111 
2112 void Sampler::Start() {
2113  ASSERT(!IsActive());
2114  SetActive(true);
2116 }
2117 
2118 
2119 void Sampler::Stop() {
2120  ASSERT(IsActive());
2122  SetActive(false);
2123 }
2124 
2125 
2126 } } // namespace v8::internal
byte * Address
Definition: globals.h:172
HANDLE HANDLE LPSTACKFRAME64 PVOID PREAD_PROCESS_MEMORY_ROUTINE64 PFUNCTION_TABLE_ACCESS_ROUTINE64 PGET_MODULE_BASE_ROUTINE64 PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
const SwVfpRegister s2
static void * GetThreadLocal(LocalStorageKey key)
static void RemoveActiveSampler(Sampler *sampler)
int random()
void Reset()
Definition: flags.cc:1446
#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:745
static int VSNPrintF(Vector< char > str, const char *format, va_list args)
StateTag current_vm_state()
Definition: isolate.h:991
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:221
static FILE * OpenTemporaryFile()
#define CHECK_GT(a, b)
Definition: checks.h:227
bool IsActive() const
Definition: platform.h:734
Isolate * isolate()
Definition: platform.h:736
static void SignalCodeMovingGC()
OUT PSTR SearchPath
value format" "after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false, "print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false, "print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false, "report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true, "garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true, "flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true, "use incremental marking") DEFINE_bool(incremental_marking_steps, true, "do incremental marking steps") DEFINE_bool(trace_incremental_marking, false, "trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true, "Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false, "Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true, "use inline caching") DEFINE_bool(native_code_counters, false, "generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false, "Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true, "Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false, "Never perform compaction on full GC-testing only") DEFINE_bool(compact_code_space, true, "Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true, "Flush inline caches prior to mark compact collection and" "flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0, "Default seed for initializing random generator" "(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true, "allows verbose printing") DEFINE_bool(allow_natives_syntax, false, "allow natives syntax") DEFINE_bool(trace_sim, false, "Trace simulator execution") DEFINE_bool(check_icache, false, "Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0, "Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8, "Stack alingment in bytes in simulator(4 or 8, 8 is default)") DEFINE_bool(trace_exception, false, "print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false, "preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true, "randomize hashes to avoid predictable hash collisions" "(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0, "Fixed seed to use to hash property keys(0 means random)" "(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false, "activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true, "generate optimized regexp code") DEFINE_bool(testing_bool_flag, true, "testing_bool_flag") DEFINE_int(testing_int_flag, 13, "testing_int_flag") DEFINE_float(testing_float_flag, 2.5, "float-flag") DEFINE_string(testing_string_flag, "Hello, world!", "string-flag") DEFINE_int(testing_prng_seed, 42, "Seed used for threading test randomness") DEFINE_string(testing_serialization_file, "/tmp/serdes", "file in which to serialize heap") DEFINE_bool(help, false, "Print usage message, including flags, on console") DEFINE_bool(dump_counters, false, "Dump counters on exit") DEFINE_string(map_counters, "", "Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT, "Pass all remaining arguments to the script.Alias for\"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#43"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2#define FLAG_MODE_DEFINE_DEFAULTS#1"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flag-definitions.h"1#define FLAG_FULL(ftype, ctype, nam, def, cmt)#define FLAG_READONLY(ftype, ctype, nam, def, cmt)#define DEFINE_implication(whenflag, thenflag)#define DEFINE_bool(nam, def, cmt)#define DEFINE_int(nam, def, cmt)#define DEFINE_float(nam, def, cmt)#define DEFINE_string(nam, def, cmt)#define DEFINE_args(nam, def, cmt)#define FLAG DEFINE_bool(use_strict, false,"enforce strict mode") DEFINE_bool(es5_readonly, false,"activate correct semantics for inheriting readonliness") DEFINE_bool(es52_globals, false,"activate new semantics for global var declarations") DEFINE_bool(harmony_typeof, false,"enable harmony semantics for typeof") DEFINE_bool(harmony_scoping, false,"enable harmony block scoping") DEFINE_bool(harmony_modules, false,"enable harmony modules (implies block scoping)") DEFINE_bool(harmony_proxies, false,"enable harmony proxies") DEFINE_bool(harmony_collections, false,"enable harmony collections (sets, maps, and weak maps)") DEFINE_bool(harmony, false,"enable all harmony features (except typeof)") DEFINE_implication(harmony, harmony_scoping) DEFINE_implication(harmony, harmony_modules) DEFINE_implication(harmony, harmony_proxies) DEFINE_implication(harmony, harmony_collections) DEFINE_implication(harmony_modules, harmony_scoping) DEFINE_bool(packed_arrays, false,"optimizes arrays that have no holes") DEFINE_bool(smi_only_arrays, true,"tracks arrays with only smi values") DEFINE_bool(clever_optimizations, true,"Optimize object size, Array shift, DOM strings and string +") DEFINE_bool(unbox_double_arrays, true,"automatically unbox arrays of doubles") DEFINE_bool(string_slices, true,"use string slices") DEFINE_bool(crankshaft, true,"use crankshaft") DEFINE_string(hydrogen_filter,"","optimization filter") DEFINE_bool(use_range, true,"use hydrogen range analysis") DEFINE_bool(eliminate_dead_phis, true,"eliminate dead phis") DEFINE_bool(use_gvn, true,"use hydrogen global value numbering") DEFINE_bool(use_canonicalizing, true,"use hydrogen instruction canonicalizing") DEFINE_bool(use_inlining, true,"use function inlining") DEFINE_int(max_inlined_source_size, 600,"maximum source size in bytes considered for a single inlining") DEFINE_int(max_inlined_nodes, 196,"maximum number of AST nodes considered for a single inlining") DEFINE_int(max_inlined_nodes_cumulative, 196,"maximum cumulative number of AST nodes considered for inlining") DEFINE_bool(loop_invariant_code_motion, true,"loop invariant code motion") DEFINE_bool(collect_megamorphic_maps_from_stub_cache, true,"crankshaft harvests type feedback from stub cache") DEFINE_bool(hydrogen_stats, false,"print statistics for hydrogen") DEFINE_bool(trace_hydrogen, false,"trace generated hydrogen to file") DEFINE_string(trace_phase,"Z","trace generated IR for specified phases") DEFINE_bool(trace_inlining, false,"trace inlining decisions") DEFINE_bool(trace_alloc, false,"trace register allocator") DEFINE_bool(trace_all_uses, false,"trace all use positions") DEFINE_bool(trace_range, false,"trace range analysis") DEFINE_bool(trace_gvn, false,"trace global value numbering") DEFINE_bool(trace_representation, false,"trace representation types") DEFINE_bool(stress_pointer_maps, false,"pointer map for every instruction") DEFINE_bool(stress_environments, false,"environment for every instruction") DEFINE_int(deopt_every_n_times, 0,"deoptimize every n times a deopt point is passed") DEFINE_bool(trap_on_deopt, false,"put a break point before deoptimizing") DEFINE_bool(deoptimize_uncommon_cases, true,"deoptimize uncommon cases") DEFINE_bool(polymorphic_inlining, true,"polymorphic inlining") DEFINE_bool(use_osr, true,"use on-stack replacement") DEFINE_bool(array_bounds_checks_elimination, false,"perform array bounds checks elimination") DEFINE_bool(array_index_dehoisting, false,"perform array index dehoisting") DEFINE_bool(trace_osr, false,"trace on-stack replacement") DEFINE_int(stress_runs, 0,"number of stress runs") DEFINE_bool(optimize_closures, true,"optimize closures") DEFINE_bool(inline_construct, true,"inline constructor calls") DEFINE_bool(inline_arguments, true,"inline functions with arguments object") DEFINE_int(loop_weight, 1,"loop weight for representation inference") DEFINE_bool(optimize_for_in, true,"optimize functions containing for-in loops") DEFINE_bool(experimental_profiler, true,"enable all profiler experiments") DEFINE_bool(watch_ic_patching, false,"profiler considers IC stability") DEFINE_int(frame_count, 1,"number of stack frames inspected by the profiler") DEFINE_bool(self_optimization, false,"primitive functions trigger their own optimization") DEFINE_bool(direct_self_opt, false,"call recompile stub directly when self-optimizing") DEFINE_bool(retry_self_opt, false,"re-try self-optimization if it failed") DEFINE_bool(count_based_interrupts, false,"trigger profiler ticks based on counting instead of timing") DEFINE_bool(interrupt_at_exit, false,"insert an interrupt check at function exit") DEFINE_bool(weighted_back_edges, false,"weight back edges by jump distance for interrupt triggering") DEFINE_int(interrupt_budget, 5900,"execution budget before interrupt is triggered") DEFINE_int(type_info_threshold, 15,"percentage of ICs that must have type info to allow optimization") DEFINE_int(self_opt_count, 130,"call count before self-optimization") DEFINE_implication(experimental_profiler, watch_ic_patching) DEFINE_implication(experimental_profiler, self_optimization) DEFINE_implication(experimental_profiler, retry_self_opt) DEFINE_implication(experimental_profiler, count_based_interrupts) DEFINE_implication(experimental_profiler, interrupt_at_exit) DEFINE_implication(experimental_profiler, weighted_back_edges) DEFINE_bool(trace_opt_verbose, false,"extra verbose compilation tracing") DEFINE_implication(trace_opt_verbose, trace_opt) DEFINE_bool(debug_code, false,"generate extra code (assertions) for debugging") DEFINE_bool(code_comments, false,"emit comments in code disassembly") DEFINE_bool(enable_sse2, true,"enable use of SSE2 instructions if available") DEFINE_bool(enable_sse3, true,"enable use of SSE3 instructions if available") DEFINE_bool(enable_sse4_1, true,"enable use of SSE4.1 instructions if available") DEFINE_bool(enable_cmov, true,"enable use of CMOV instruction if available") DEFINE_bool(enable_rdtsc, true,"enable use of RDTSC instruction if available") DEFINE_bool(enable_sahf, true,"enable use of SAHF instruction if available (X64 only)") DEFINE_bool(enable_vfp3, true,"enable use of VFP3 instructions if available - this implies ""enabling ARMv7 instructions (ARM only)") DEFINE_bool(enable_armv7, true,"enable use of ARMv7 instructions if available (ARM only)") DEFINE_bool(enable_fpu, true,"enable use of MIPS FPU instructions if available (MIPS only)") DEFINE_string(expose_natives_as, NULL,"expose natives in global object") DEFINE_string(expose_debug_as, NULL,"expose debug in global object") DEFINE_bool(expose_gc, false,"expose gc extension") DEFINE_bool(expose_externalize_string, false,"expose externalize string extension") DEFINE_int(stack_trace_limit, 10,"number of stack frames to capture") DEFINE_bool(builtins_in_stack_traces, false,"show built-in functions in stack traces") DEFINE_bool(disable_native_files, false,"disable builtin natives files") DEFINE_bool(inline_new, true,"use fast inline allocation") DEFINE_bool(stack_trace_on_abort, true,"print a stack trace if an assertion failure occurs") DEFINE_bool(trace, false,"trace function calls") DEFINE_bool(mask_constants_with_cookie, true,"use random jit cookie to mask large constants") DEFINE_bool(lazy, true,"use lazy compilation") DEFINE_bool(trace_opt, false,"trace lazy optimization") DEFINE_bool(trace_opt_stats, false,"trace lazy optimization statistics") DEFINE_bool(opt, true,"use adaptive optimizations") DEFINE_bool(always_opt, false,"always try to optimize functions") DEFINE_bool(prepare_always_opt, false,"prepare for turning on always opt") DEFINE_bool(trace_deopt, false,"trace deoptimization") DEFINE_int(min_preparse_length, 1024,"minimum length for automatic enable preparsing") DEFINE_bool(always_full_compiler, false,"try to use the dedicated run-once backend for all code") DEFINE_bool(trace_bailout, false,"print reasons for falling back to using the classic V8 backend") DEFINE_bool(compilation_cache, true,"enable compilation cache") DEFINE_bool(cache_prototype_transitions, true,"cache prototype transitions") DEFINE_bool(trace_debug_json, false,"trace debugging JSON request/response") DEFINE_bool(debugger_auto_break, true,"automatically set the debug break flag when debugger commands are ""in the queue") DEFINE_bool(enable_liveedit, true,"enable liveedit experimental feature") DEFINE_bool(break_on_abort, true,"always cause a debug break before aborting") DEFINE_int(stack_size, kPointerSize *123,"default size of stack region v8 is allowed to use (in kBytes)") DEFINE_int(max_stack_trace_source_length, 300,"maximum length of function source code printed in a stack trace.") DEFINE_bool(always_inline_smi_code, false,"always inline smi code in non-opt code") DEFINE_int(max_new_space_size, 0,"max size of the new generation (in kBytes)") DEFINE_int(max_old_space_size, 0,"max size of the old generation (in Mbytes)") DEFINE_int(max_executable_size, 0,"max size of executable memory (in Mbytes)") DEFINE_bool(gc_global, false,"always perform global GCs") DEFINE_int(gc_interval,-1,"garbage collect after <n> allocations") DEFINE_bool(trace_gc, false,"print one trace line following each garbage collection") DEFINE_bool(trace_gc_nvp, false,"print one detailed trace line in name=value format ""after each garbage collection") DEFINE_bool(print_cumulative_gc_stat, false,"print cumulative GC statistics in name=value format on exit") DEFINE_bool(trace_gc_verbose, false,"print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false,"report fragmentation for old pointer and data pages") DEFINE_bool(collect_maps, true,"garbage collect maps from which no objects can be reached") DEFINE_bool(flush_code, true,"flush code that we expect not to use again before full gc") DEFINE_bool(incremental_marking, true,"use incremental marking") DEFINE_bool(incremental_marking_steps, true,"do incremental marking steps") DEFINE_bool(trace_incremental_marking, false,"trace progress of the incremental marking") DEFINE_bool(use_idle_notification, true,"Use idle notification to reduce memory footprint.") DEFINE_bool(send_idle_notification, false,"Send idle notifcation between stress runs.") DEFINE_bool(use_ic, true,"use inline caching") DEFINE_bool(native_code_counters, false,"generate extra code for manipulating stats counters") DEFINE_bool(always_compact, false,"Perform compaction on every full GC") DEFINE_bool(lazy_sweeping, true,"Use lazy sweeping for old pointer and data spaces") DEFINE_bool(never_compact, false,"Never perform compaction on full GC - testing only") DEFINE_bool(compact_code_space, true,"Compact code space on full non-incremental collections") DEFINE_bool(cleanup_code_caches_at_gc, true,"Flush inline caches prior to mark compact collection and ""flush code caches in maps during mark compact cycle.") DEFINE_int(random_seed, 0,"Default seed for initializing random generator ""(0, the default, means to use system random).") DEFINE_bool(use_verbose_printer, true,"allows verbose printing") DEFINE_bool(allow_natives_syntax, false,"allow natives syntax") DEFINE_bool(trace_sim, false,"Trace simulator execution") DEFINE_bool(check_icache, false,"Check icache flushes in ARM and MIPS simulator") DEFINE_int(stop_sim_at, 0,"Simulator stop after x number of instructions") DEFINE_int(sim_stack_alignment, 8,"Stack alingment in bytes in simulator (4 or 8, 8 is default)") DEFINE_bool(trace_exception, false,"print stack trace when throwing exceptions") DEFINE_bool(preallocate_message_memory, false,"preallocate some memory to build stack traces.") DEFINE_bool(randomize_hashes, true,"randomize hashes to avoid predictable hash collisions ""(with snapshots this option cannot override the baked-in seed)") DEFINE_int(hash_seed, 0,"Fixed seed to use to hash property keys (0 means random)""(with snapshots this option cannot override the baked-in seed)") DEFINE_bool(preemption, false,"activate a 100ms timer that switches between V8 threads") DEFINE_bool(regexp_optimization, true,"generate optimized regexp code") DEFINE_bool(testing_bool_flag, true,"testing_bool_flag") DEFINE_int(testing_int_flag, 13,"testing_int_flag") DEFINE_float(testing_float_flag, 2.5,"float-flag") DEFINE_string(testing_string_flag,"Hello, world!","string-flag") DEFINE_int(testing_prng_seed, 42,"Seed used for threading test randomness") DEFINE_string(testing_serialization_file,"/tmp/serdes","file in which to serialize heap") DEFINE_bool(help, false,"Print usage message, including flags, on console") DEFINE_bool(dump_counters, false,"Dump counters on exit") DEFINE_string(map_counters,"","Map counters to a file") DEFINE_args(js_arguments, JSARGUMENTS_INIT,"Pass all remaining arguments to the script. Alias for \"--\".") DEFINE_bool(debug_compile_events, true,"Enable debugger compile events") DEFINE_bool(debug_script_collected_events, true,"Enable debugger script collected events") DEFINE_bool(gdbjit, false,"enable GDBJIT interface (disables compacting GC)") DEFINE_bool(gdbjit_full, false,"enable GDBJIT interface for all code objects") DEFINE_bool(gdbjit_dump, false,"dump elf objects with debug info to disk") DEFINE_string(gdbjit_dump_filter,"","dump only objects containing this substring") DEFINE_bool(force_marking_deque_overflows, false,"force overflows of marking deque by reducing it's size ""to 64 words") DEFINE_bool(stress_compaction, false,"stress the GC compactor to flush out bugs (implies ""--force_marking_deque_overflows)")#define FLAG DEFINE_bool(enable_slow_asserts, false,"enable asserts that are slow to execute") DEFINE_bool(trace_codegen, false,"print name of functions for which code is generated") DEFINE_bool(print_source, false,"pretty print source code") DEFINE_bool(print_builtin_source, false,"pretty print source code for builtins") DEFINE_bool(print_ast, false,"print source AST") DEFINE_bool(print_builtin_ast, false,"print source AST for builtins") DEFINE_string(stop_at,"","function name where to insert a breakpoint") DEFINE_bool(print_builtin_scopes, false,"print scopes for builtins") DEFINE_bool(print_scopes, false,"print scopes") DEFINE_bool(trace_contexts, false,"trace contexts operations") DEFINE_bool(gc_greedy, false,"perform GC prior to some allocations") DEFINE_bool(gc_verbose, false,"print stuff during garbage collection") DEFINE_bool(heap_stats, false,"report heap statistics before and after GC") DEFINE_bool(code_stats, false,"report code statistics after GC") DEFINE_bool(verify_heap, false,"verify heap pointers before and after GC") DEFINE_bool(print_handles, false,"report handles after GC") DEFINE_bool(print_global_handles, false,"report global handles after GC") DEFINE_bool(trace_ic, false,"trace inline cache state transitions") DEFINE_bool(print_interfaces, false,"print interfaces") DEFINE_bool(print_interface_details, false,"print interface inference details") DEFINE_int(print_interface_depth, 5,"depth for printing interfaces") DEFINE_bool(trace_normalization, false,"prints when objects are turned into dictionaries.") DEFINE_bool(trace_lazy, false,"trace lazy compilation") DEFINE_bool(collect_heap_spill_statistics, false,"report heap spill statistics along with heap_stats ""(requires heap_stats)") DEFINE_bool(trace_isolates, false,"trace isolate state changes") DEFINE_bool(log_state_changes, false,"Log state changes.") DEFINE_bool(regexp_possessive_quantifier, false,"enable possessive quantifier syntax for testing") DEFINE_bool(trace_regexp_bytecodes, false,"trace regexp bytecode execution") DEFINE_bool(trace_regexp_assembler, false,"trace regexp macro assembler calls.")#define FLAG DEFINE_bool(log, false,"Minimal logging (no API, code, GC, suspect, or handles samples).") DEFINE_bool(log_all, false,"Log all events to the log file.") DEFINE_bool(log_runtime, false,"Activate runtime system %Log call.") DEFINE_bool(log_api, false,"Log API events to the log file.") DEFINE_bool(log_code, false,"Log code events to the log file without profiling.") DEFINE_bool(log_gc, false,"Log heap samples on garbage collection for the hp2ps tool.") DEFINE_bool(log_handles, false,"Log global handle events.") DEFINE_bool(log_snapshot_positions, false,"log positions of (de)serialized objects in the snapshot.") DEFINE_bool(log_suspect, false,"Log suspect operations.") DEFINE_bool(prof, false,"Log statistical profiling information (implies --log-code).") DEFINE_bool(prof_auto, true,"Used with --prof, starts profiling automatically") DEFINE_bool(prof_lazy, false,"Used with --prof, only does sampling and logging"" when profiler is active (implies --noprof_auto).") DEFINE_bool(prof_browser_mode, true,"Used with --prof, turns on browser-compatible mode for profiling.") DEFINE_bool(log_regexp, false,"Log regular expression execution.") DEFINE_bool(sliding_state_window, false,"Update sliding state window counters.") DEFINE_string(logfile,"v8.log","Specify the name of the log file.") DEFINE_bool(ll_prof, false,"Enable low-level linux profiler.")#define FLAG DEFINE_bool(trace_elements_transitions, false,"trace elements transitions") DEFINE_bool(print_code_stubs, false,"print code stubs") DEFINE_bool(test_secondary_stub_cache, false,"test secondary stub cache by disabling the primary one") DEFINE_bool(test_primary_stub_cache, false,"test primary stub cache by disabling the secondary one") DEFINE_bool(print_code, false,"print generated code") DEFINE_bool(print_opt_code, false,"print optimized code") DEFINE_bool(print_unopt_code, false,"print unoptimized code before ""printing optimized code based on it") DEFINE_bool(print_code_verbose, false,"print more information for code") DEFINE_bool(print_builtin_code, false,"print generated code for builtins")#47"/Users/thlorenz/dev/dx/v8-perf/build/v8/src/flags.cc"2 namespace{struct Flag{enum FlagType{TYPE_BOOL, TYPE_INT, TYPE_FLOAT, TYPE_STRING, TYPE_ARGS} name
Definition: flags.cc:1349
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:268
static bool IsOutsideAllocatedSpace(void *pointer)
static const char * LocalTimezone(double time)
Vector< char > MutableCStrVector(char *data)
Definition: utils.h:529
static const int kStackWalkError
Definition: platform.h:223
static SamplerThread * instance_
static int GetUserTime(uint32_t *secs, uint32_t *usecs)
static const int kStackWalkMaxTextLen
Definition: platform.h:225
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:712
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:1783
unsigned int seed
Definition: test-strings.cc:17
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:314
RuntimeProfiler * runtime_profiler()
Definition: isolate.h:811
static TickSample * TickSampleEvent(Isolate *isolate)
IN PSTR UserSearchPath
HANDLE HANDLE LPSTACKFRAME64 PVOID ContextRecord
bool IsProfiling() const
Definition: platform.h:729
static void ProtectCode(void *address, const size_t size)
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 trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt 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 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
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:321
intptr_t AtomicWord
Definition: atomicops.h:72
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 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()
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:501
static Semaphore * CreateSemaphore(int count)
#define ISOLATE
Definition: isolate.h:1410
static const int kStackWalkMaxNameLen
Definition: platform.h:224
#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:178
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:1762
#define DLL_FUNC_TYPE(name)
static void PrintError(const char *format,...)
void SampleStack(TickSample *sample)
Definition: platform.h:715
static void LogSharedLibraryAddresses()
OUT PSTR IN DWORD SearchPathLength
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 trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt 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 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
static void SetUp()
void USE(T)
Definition: globals.h:303
static void StrNCpy(Vector< char > dest, const char *src, size_t n)
static int ActivationFrameAlignment()
const char * name() const
Definition: platform.h:439
IN DWORD64 OUT PDWORD64 OUT PIMAGEHLP_SYMBOL64 Symbol
static double DaylightSavingsOffset(double time)
static size_t AllocateAlignment()
static void AddActiveSampler(Sampler *sampler)
Definition: log.cc:1771
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:100
static intptr_t MaxVirtualMemory()
static bool IterateActiveSamplers(VisitSampler func, void *param)
Definition: log.cc:1745
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:164
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