Revision f230a1cf deps/v8/src/platform-win32.cc
deps/v8/src/platform-win32.cc | ||
---|---|---|
240 | 240 |
class Win32Time { |
241 | 241 |
public: |
242 | 242 |
// Constructors. |
243 |
Win32Time(); |
|
243 | 244 |
explicit Win32Time(double jstime); |
244 | 245 |
Win32Time(int year, int mon, int day, int hour, int min, int sec); |
245 | 246 |
|
246 | 247 |
// Convert timestamp to JavaScript representation. |
247 | 248 |
double ToJSTime(); |
248 | 249 |
|
250 |
// Set timestamp to current time. |
|
251 |
void SetToCurrentTime(); |
|
252 |
|
|
249 | 253 |
// Returns the local timezone offset in milliseconds east of UTC. This is |
250 | 254 |
// the number of milliseconds you must add to UTC to get local time, i.e. |
251 | 255 |
// LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This |
... | ... | |
314 | 318 |
char Win32Time::dst_tz_name_[kTzNameSize]; |
315 | 319 |
|
316 | 320 |
|
321 |
// Initialize timestamp to start of epoc. |
|
322 |
Win32Time::Win32Time() { |
|
323 |
t() = 0; |
|
324 |
} |
|
325 |
|
|
326 |
|
|
317 | 327 |
// Initialize timestamp from a JavaScript timestamp. |
318 | 328 |
Win32Time::Win32Time(double jstime) { |
319 | 329 |
t() = static_cast<int64_t>(jstime) * kTimeScaler + kTimeEpoc; |
... | ... | |
340 | 350 |
} |
341 | 351 |
|
342 | 352 |
|
353 |
// Set timestamp to current time. |
|
354 |
void Win32Time::SetToCurrentTime() { |
|
355 |
// The default GetSystemTimeAsFileTime has a ~15.5ms resolution. |
|
356 |
// Because we're fast, we like fast timers which have at least a |
|
357 |
// 1ms resolution. |
|
358 |
// |
|
359 |
// timeGetTime() provides 1ms granularity when combined with |
|
360 |
// timeBeginPeriod(). If the host application for v8 wants fast |
|
361 |
// timers, it can use timeBeginPeriod to increase the resolution. |
|
362 |
// |
|
363 |
// Using timeGetTime() has a drawback because it is a 32bit value |
|
364 |
// and hence rolls-over every ~49days. |
|
365 |
// |
|
366 |
// To use the clock, we use GetSystemTimeAsFileTime as our base; |
|
367 |
// and then use timeGetTime to extrapolate current time from the |
|
368 |
// start time. To deal with rollovers, we resync the clock |
|
369 |
// any time when more than kMaxClockElapsedTime has passed or |
|
370 |
// whenever timeGetTime creates a rollover. |
|
371 |
|
|
372 |
static bool initialized = false; |
|
373 |
static TimeStamp init_time; |
|
374 |
static DWORD init_ticks; |
|
375 |
static const int64_t kHundredNanosecondsPerSecond = 10000000; |
|
376 |
static const int64_t kMaxClockElapsedTime = |
|
377 |
60*kHundredNanosecondsPerSecond; // 1 minute |
|
378 |
|
|
379 |
// If we are uninitialized, we need to resync the clock. |
|
380 |
bool needs_resync = !initialized; |
|
381 |
|
|
382 |
// Get the current time. |
|
383 |
TimeStamp time_now; |
|
384 |
GetSystemTimeAsFileTime(&time_now.ft_); |
|
385 |
DWORD ticks_now = timeGetTime(); |
|
386 |
|
|
387 |
// Check if we need to resync due to clock rollover. |
|
388 |
needs_resync |= ticks_now < init_ticks; |
|
389 |
|
|
390 |
// Check if we need to resync due to elapsed time. |
|
391 |
needs_resync |= (time_now.t_ - init_time.t_) > kMaxClockElapsedTime; |
|
392 |
|
|
393 |
// Check if we need to resync due to backwards time change. |
|
394 |
needs_resync |= time_now.t_ < init_time.t_; |
|
395 |
|
|
396 |
// Resync the clock if necessary. |
|
397 |
if (needs_resync) { |
|
398 |
GetSystemTimeAsFileTime(&init_time.ft_); |
|
399 |
init_ticks = ticks_now = timeGetTime(); |
|
400 |
initialized = true; |
|
401 |
} |
|
402 |
|
|
403 |
// Finally, compute the actual time. Why is this so hard. |
|
404 |
DWORD elapsed = ticks_now - init_ticks; |
|
405 |
this->time_.t_ = init_time.t_ + (static_cast<int64_t>(elapsed) * 10000); |
|
406 |
} |
|
407 |
|
|
408 |
|
|
343 | 409 |
// Guess the name of the timezone from the bias. |
344 | 410 |
// The guess is very biased towards the northern hemisphere. |
345 | 411 |
const char* Win32Time::GuessTimezoneNameFromBias(int bias) { |
... | ... | |
891 | 957 |
} |
892 | 958 |
|
893 | 959 |
|
894 |
void OS::DumpBacktrace() { |
|
895 |
// Currently unsupported. |
|
896 |
} |
|
897 |
|
|
898 |
|
|
899 | 960 |
class Win32MemoryMappedFile : public OS::MemoryMappedFile { |
900 | 961 |
public: |
901 | 962 |
Win32MemoryMappedFile(HANDLE file, |
... | ... | |
1208 | 1269 |
} |
1209 | 1270 |
|
1210 | 1271 |
|
1211 |
// Walk the stack using the facilities in dbghelp.dll and tlhelp32.dll |
|
1212 |
|
|
1213 |
// Switch off warning 4748 (/GS can not protect parameters and local variables |
|
1214 |
// from local buffer overrun because optimizations are disabled in function) as |
|
1215 |
// it is triggered by the use of inline assembler. |
|
1216 |
#pragma warning(push) |
|
1217 |
#pragma warning(disable : 4748) |
|
1218 |
int OS::StackWalk(Vector<OS::StackFrame> frames) { |
|
1219 |
BOOL ok; |
|
1220 |
|
|
1221 |
// Load the required functions from DLL's. |
|
1222 |
if (!LoadDbgHelpAndTlHelp32()) return kStackWalkError; |
|
1223 |
|
|
1224 |
// Get the process and thread handles. |
|
1225 |
HANDLE process_handle = GetCurrentProcess(); |
|
1226 |
HANDLE thread_handle = GetCurrentThread(); |
|
1227 |
|
|
1228 |
// Read the symbols. |
|
1229 |
if (!LoadSymbols(Isolate::Current(), process_handle)) return kStackWalkError; |
|
1230 |
|
|
1231 |
// Capture current context. |
|
1232 |
CONTEXT context; |
|
1233 |
RtlCaptureContext(&context); |
|
1234 |
|
|
1235 |
// Initialize the stack walking |
|
1236 |
STACKFRAME64 stack_frame; |
|
1237 |
memset(&stack_frame, 0, sizeof(stack_frame)); |
|
1238 |
#ifdef _WIN64 |
|
1239 |
stack_frame.AddrPC.Offset = context.Rip; |
|
1240 |
stack_frame.AddrFrame.Offset = context.Rbp; |
|
1241 |
stack_frame.AddrStack.Offset = context.Rsp; |
|
1242 |
#else |
|
1243 |
stack_frame.AddrPC.Offset = context.Eip; |
|
1244 |
stack_frame.AddrFrame.Offset = context.Ebp; |
|
1245 |
stack_frame.AddrStack.Offset = context.Esp; |
|
1246 |
#endif |
|
1247 |
stack_frame.AddrPC.Mode = AddrModeFlat; |
|
1248 |
stack_frame.AddrFrame.Mode = AddrModeFlat; |
|
1249 |
stack_frame.AddrStack.Mode = AddrModeFlat; |
|
1250 |
int frames_count = 0; |
|
1251 |
|
|
1252 |
// Collect stack frames. |
|
1253 |
int frames_size = frames.length(); |
|
1254 |
while (frames_count < frames_size) { |
|
1255 |
ok = _StackWalk64( |
|
1256 |
IMAGE_FILE_MACHINE_I386, // MachineType |
|
1257 |
process_handle, // hProcess |
|
1258 |
thread_handle, // hThread |
|
1259 |
&stack_frame, // StackFrame |
|
1260 |
&context, // ContextRecord |
|
1261 |
NULL, // ReadMemoryRoutine |
|
1262 |
_SymFunctionTableAccess64, // FunctionTableAccessRoutine |
|
1263 |
_SymGetModuleBase64, // GetModuleBaseRoutine |
|
1264 |
NULL); // TranslateAddress |
|
1265 |
if (!ok) break; |
|
1266 |
|
|
1267 |
// Store the address. |
|
1268 |
ASSERT((stack_frame.AddrPC.Offset >> 32) == 0); // 32-bit address. |
|
1269 |
frames[frames_count].address = |
|
1270 |
reinterpret_cast<void*>(stack_frame.AddrPC.Offset); |
|
1271 |
|
|
1272 |
// Try to locate a symbol for this frame. |
|
1273 |
DWORD64 symbol_displacement; |
|
1274 |
SmartArrayPointer<IMAGEHLP_SYMBOL64> symbol( |
|
1275 |
NewArray<IMAGEHLP_SYMBOL64>(kStackWalkMaxNameLen)); |
|
1276 |
if (symbol.is_empty()) return kStackWalkError; // Out of memory. |
|
1277 |
memset(*symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + kStackWalkMaxNameLen); |
|
1278 |
(*symbol)->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); |
|
1279 |
(*symbol)->MaxNameLength = kStackWalkMaxNameLen; |
|
1280 |
ok = _SymGetSymFromAddr64(process_handle, // hProcess |
|
1281 |
stack_frame.AddrPC.Offset, // Address |
|
1282 |
&symbol_displacement, // Displacement |
|
1283 |
*symbol); // Symbol |
|
1284 |
if (ok) { |
|
1285 |
// Try to locate more source information for the symbol. |
|
1286 |
IMAGEHLP_LINE64 Line; |
|
1287 |
memset(&Line, 0, sizeof(Line)); |
|
1288 |
Line.SizeOfStruct = sizeof(Line); |
|
1289 |
DWORD line_displacement; |
|
1290 |
ok = _SymGetLineFromAddr64( |
|
1291 |
process_handle, // hProcess |
|
1292 |
stack_frame.AddrPC.Offset, // dwAddr |
|
1293 |
&line_displacement, // pdwDisplacement |
|
1294 |
&Line); // Line |
|
1295 |
// Format a text representation of the frame based on the information |
|
1296 |
// available. |
|
1297 |
if (ok) { |
|
1298 |
SNPrintF(MutableCStrVector(frames[frames_count].text, |
|
1299 |
kStackWalkMaxTextLen), |
|
1300 |
"%s %s:%d:%d", |
|
1301 |
(*symbol)->Name, Line.FileName, Line.LineNumber, |
|
1302 |
line_displacement); |
|
1303 |
} else { |
|
1304 |
SNPrintF(MutableCStrVector(frames[frames_count].text, |
|
1305 |
kStackWalkMaxTextLen), |
|
1306 |
"%s", |
|
1307 |
(*symbol)->Name); |
|
1308 |
} |
|
1309 |
// Make sure line termination is in place. |
|
1310 |
frames[frames_count].text[kStackWalkMaxTextLen - 1] = '\0'; |
|
1311 |
} else { |
|
1312 |
// No text representation of this frame |
|
1313 |
frames[frames_count].text[0] = '\0'; |
|
1314 |
|
|
1315 |
// Continue if we are just missing a module (for non C/C++ frames a |
|
1316 |
// module will never be found). |
|
1317 |
int err = GetLastError(); |
|
1318 |
if (err != ERROR_MOD_NOT_FOUND) { |
|
1319 |
break; |
|
1320 |
} |
|
1321 |
} |
|
1322 |
|
|
1323 |
frames_count++; |
|
1272 |
uint64_t OS::TotalPhysicalMemory() { |
|
1273 |
MEMORYSTATUSEX memory_info; |
|
1274 |
memory_info.dwLength = sizeof(memory_info); |
|
1275 |
if (!GlobalMemoryStatusEx(&memory_info)) { |
|
1276 |
UNREACHABLE(); |
|
1277 |
return 0; |
|
1324 | 1278 |
} |
1325 | 1279 |
|
1326 |
// Return the number of frames filled in. |
|
1327 |
return frames_count; |
|
1280 |
return static_cast<uint64_t>(memory_info.ullTotalPhys); |
|
1328 | 1281 |
} |
1329 | 1282 |
|
1330 | 1283 |
|
1331 |
// Restore warnings to previous settings. |
|
1332 |
#pragma warning(pop) |
|
1333 |
|
|
1334 | 1284 |
#else // __MINGW32__ |
1335 | 1285 |
void OS::LogSharedLibraryAddresses(Isolate* isolate) { } |
1336 | 1286 |
void OS::SignalCodeMovingGC() { } |
1337 |
int OS::StackWalk(Vector<OS::StackFrame> frames) { return 0; } |
|
1338 | 1287 |
#endif // __MINGW32__ |
1339 | 1288 |
|
1340 | 1289 |
|
Also available in: Unified diff