dart-sdk/runtime/bin/utils_win.cc
Ryan Macnak 877284947b Rename TARGET_OS_* to HOST_OS_*.
Like HOST_ARCH_*, HOST_OS_* describes the OS the VM is running on, which may be different from the OS the VM is generating code for during AOT compilation.

Currently we conflate the two when emitting AOT as assembly, and we get away with it because Flutter only uses assembly for targeting iOS and one can only target iOS from a Mac, but we expect to use assembly for Android as well so native tools can unwind Dart frames.

R=zra@google.com

Review-Url: https://codereview.chromium.org/2750843003 .
2017-03-15 13:11:05 -07:00

264 lines
8.1 KiB
C++

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/globals.h"
#if defined(HOST_OS_WINDOWS)
#include <errno.h> // NOLINT
#include <time.h> // NOLINT
#include "bin/log.h"
#include "bin/utils.h"
#include "bin/utils_win.h"
#include "platform/assert.h"
namespace dart {
namespace bin {
void FormatMessageIntoBuffer(DWORD code, wchar_t* buffer, int buffer_length) {
DWORD message_size = FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, buffer_length, NULL);
if (message_size == 0) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
Log::PrintErr("FormatMessage failed for error code %d (error %d)\n", code,
GetLastError());
}
_snwprintf(buffer, buffer_length, L"OS Error %d", code);
}
// Ensure string termination.
buffer[buffer_length - 1] = 0;
}
OSError::OSError() : sub_system_(kSystem), code_(0), message_(NULL) {
set_code(GetLastError());
static const int kMaxMessageLength = 256;
wchar_t message[kMaxMessageLength];
FormatMessageIntoBuffer(code_, message, kMaxMessageLength);
char* utf8 = StringUtilsWin::WideToUtf8(message);
SetMessage(utf8);
}
void OSError::SetCodeAndMessage(SubSystem sub_system, int code) {
set_sub_system(sub_system);
set_code(code);
static const int kMaxMessageLength = 256;
wchar_t message[kMaxMessageLength];
FormatMessageIntoBuffer(code_, message, kMaxMessageLength);
char* utf8 = StringUtilsWin::WideToUtf8(message);
SetMessage(utf8);
}
char* StringUtils::ConsoleStringToUtf8(char* str,
intptr_t len,
intptr_t* result_len) {
int wide_len = MultiByteToWideChar(CP_ACP, 0, str, len, NULL, 0);
wchar_t* wide;
wide =
reinterpret_cast<wchar_t*>(Dart_ScopeAllocate(wide_len * sizeof(*wide)));
MultiByteToWideChar(CP_ACP, 0, str, len, wide, wide_len);
char* utf8 = StringUtilsWin::WideToUtf8(wide, wide_len, result_len);
return utf8;
}
char* StringUtils::Utf8ToConsoleString(char* utf8,
intptr_t len,
intptr_t* result_len) {
intptr_t wide_len;
wchar_t* wide = StringUtilsWin::Utf8ToWide(utf8, len, &wide_len);
int system_len =
WideCharToMultiByte(CP_ACP, 0, wide, wide_len, NULL, 0, NULL, NULL);
char* ansi;
ansi =
reinterpret_cast<char*>(Dart_ScopeAllocate(system_len * sizeof(*ansi)));
if (ansi == NULL) {
return NULL;
}
WideCharToMultiByte(CP_ACP, 0, wide, wide_len, ansi, system_len, NULL, NULL);
if (result_len != NULL) {
*result_len = system_len;
}
return ansi;
}
char* StringUtilsWin::WideToUtf8(wchar_t* wide,
intptr_t len,
intptr_t* result_len) {
// If len is -1 then WideCharToMultiByte will include the terminating
// NUL byte in the length.
int utf8_len =
WideCharToMultiByte(CP_UTF8, 0, wide, len, NULL, 0, NULL, NULL);
char* utf8;
utf8 = reinterpret_cast<char*>(Dart_ScopeAllocate(utf8_len * sizeof(*utf8)));
WideCharToMultiByte(CP_UTF8, 0, wide, len, utf8, utf8_len, NULL, NULL);
if (result_len != NULL) {
*result_len = utf8_len;
}
return utf8;
}
wchar_t* StringUtilsWin::Utf8ToWide(char* utf8,
intptr_t len,
intptr_t* result_len) {
// If len is -1 then MultiByteToWideChar will include the terminating
// NUL byte in the length.
int wide_len = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
wchar_t* wide;
wide =
reinterpret_cast<wchar_t*>(Dart_ScopeAllocate(wide_len * sizeof(*wide)));
MultiByteToWideChar(CP_UTF8, 0, utf8, len, wide, wide_len);
if (result_len != NULL) {
*result_len = wide_len;
}
return wide;
}
const char* StringUtils::Utf8ToConsoleString(const char* utf8,
intptr_t len,
intptr_t* result_len) {
return const_cast<const char*>(StringUtils::Utf8ToConsoleString(
const_cast<char*>(utf8), len, result_len));
}
const char* StringUtils::ConsoleStringToUtf8(const char* str,
intptr_t len,
intptr_t* result_len) {
return const_cast<const char*>(StringUtils::ConsoleStringToUtf8(
const_cast<char*>(str), len, result_len));
}
const char* StringUtilsWin::WideToUtf8(const wchar_t* wide,
intptr_t len,
intptr_t* result_len) {
return const_cast<const char*>(
StringUtilsWin::WideToUtf8(const_cast<wchar_t*>(wide), len, result_len));
}
const wchar_t* StringUtilsWin::Utf8ToWide(const char* utf8,
intptr_t len,
intptr_t* result_len) {
return const_cast<const wchar_t*>(
StringUtilsWin::Utf8ToWide(const_cast<char*>(utf8), len, result_len));
}
char* StringUtils::StrNDup(const char* s, intptr_t n) {
intptr_t len = strlen(s);
if ((n < 0) || (len < 0)) {
return NULL;
}
if (n < len) {
len = n;
}
char* result = reinterpret_cast<char*>(malloc(len + 1));
if (result == NULL) {
return NULL;
}
result[len] = '\0';
return reinterpret_cast<char*>(memmove(result, s, len));
}
bool ShellUtils::GetUtf8Argv(int argc, char** argv) {
wchar_t* command_line = GetCommandLineW();
int unicode_argc;
wchar_t** unicode_argv = CommandLineToArgvW(command_line, &unicode_argc);
if (unicode_argv == NULL) {
return false;
}
// The argc passed to main should have the same argc as we get here.
ASSERT(argc == unicode_argc);
if (argc < unicode_argc) {
unicode_argc = argc;
}
for (int i = 0; i < unicode_argc; i++) {
wchar_t* arg = unicode_argv[i];
int arg_len = WideCharToMultiByte(CP_UTF8, 0, arg, -1, NULL, 0, NULL, NULL);
char* utf8_arg = reinterpret_cast<char*>(malloc(arg_len));
WideCharToMultiByte(CP_UTF8, 0, arg, -1, utf8_arg, arg_len, NULL, NULL);
argv[i] = utf8_arg;
}
LocalFree(unicode_argv);
return true;
}
// Although win32 uses 64-bit integers for representing timestamps,
// these are packed into a FILETIME structure. The FILETIME
// structure is just a struct representing a 64-bit integer. The
// TimeStamp union allows access to both a FILETIME and an integer
// representation of the timestamp. The Windows timestamp is in
// 100-nanosecond intervals since January 1, 1601.
union TimeStamp {
FILETIME ft_;
int64_t t_;
};
static int64_t GetCurrentTimeMicros() {
static const int64_t kTimeEpoc = 116444736000000000LL;
static const int64_t kTimeScaler = 10; // 100 ns to us.
TimeStamp time;
GetSystemTimeAsFileTime(&time.ft_);
return (time.t_ - kTimeEpoc) / kTimeScaler;
}
static int64_t qpc_ticks_per_second = 0;
void TimerUtils::InitOnce() {
LARGE_INTEGER ticks_per_sec;
if (!QueryPerformanceFrequency(&ticks_per_sec)) {
qpc_ticks_per_second = 0;
} else {
qpc_ticks_per_second = static_cast<int64_t>(ticks_per_sec.QuadPart);
}
}
int64_t TimerUtils::GetCurrentMonotonicMillis() {
return GetCurrentMonotonicMicros() / 1000;
}
int64_t TimerUtils::GetCurrentMonotonicMicros() {
if (qpc_ticks_per_second == 0) {
// QueryPerformanceCounter not supported, fallback.
return GetCurrentTimeMicros();
}
// Grab performance counter value.
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
int64_t qpc_value = static_cast<int64_t>(now.QuadPart);
// Convert to microseconds.
int64_t seconds = qpc_value / qpc_ticks_per_second;
int64_t leftover_ticks = qpc_value - (seconds * qpc_ticks_per_second);
int64_t result = seconds * kMicrosecondsPerSecond;
result += ((leftover_ticks * kMicrosecondsPerSecond) / qpc_ticks_per_second);
return result;
}
void TimerUtils::Sleep(int64_t millis) {
::Sleep(millis);
}
} // namespace bin
} // namespace dart
#endif // defined(HOST_OS_WINDOWS)