fmt::format() optimization (fmt::unveil template)

This commit is contained in:
Nekotekina 2015-01-19 01:54:56 +03:00
parent 87f1a9d9dc
commit 0d28f378a7
20 changed files with 343 additions and 309 deletions

View file

@ -758,86 +758,86 @@ template<typename T, typename T1, T1 value> struct _se<be_t<T>, T1, value> : pub
#define se32(x) _se<u32, decltype(x), x>::value
#define se64(x) _se<u64, decltype(x), x>::value
template<typename T> __forceinline static u8 Read8(T& f)
template<typename T> __forceinline u8 Read8(T& f)
{
u8 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static u16 Read16(T& f)
template<typename T> __forceinline u16 Read16(T& f)
{
be_t<u16> ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static u32 Read32(T& f)
template<typename T> __forceinline u32 Read32(T& f)
{
be_t<u32> ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static u64 Read64(T& f)
template<typename T> __forceinline u64 Read64(T& f)
{
be_t<u64> ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static u16 Read16LE(T& f)
template<typename T> __forceinline u16 Read16LE(T& f)
{
u16 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static u32 Read32LE(T& f)
template<typename T> __forceinline u32 Read32LE(T& f)
{
u32 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static u64 Read64LE(T& f)
template<typename T> __forceinline u64 Read64LE(T& f)
{
u64 ret;
f.Read(&ret, sizeof(ret));
return ret;
}
template<typename T> __forceinline static void Write8(T& f, const u8 data)
template<typename T> __forceinline void Write8(T& f, const u8 data)
{
f.Write(&data, sizeof(data));
}
template<typename T> __forceinline static void Write16LE(T& f, const u16 data)
template<typename T> __forceinline void Write16LE(T& f, const u16 data)
{
f.Write(&data, sizeof(data));
}
template<typename T> __forceinline static void Write32LE(T& f, const u32 data)
template<typename T> __forceinline void Write32LE(T& f, const u32 data)
{
f.Write(&data, sizeof(data));
}
template<typename T> __forceinline static void Write64LE(T& f, const u64 data)
template<typename T> __forceinline void Write64LE(T& f, const u64 data)
{
f.Write(&data, sizeof(data));
}
template<typename T> __forceinline static void Write16(T& f, const u16 data)
template<typename T> __forceinline void Write16(T& f, const u16 data)
{
Write16LE(f, re16(data));
}
template<typename T> __forceinline static void Write32(T& f, const u32 data)
template<typename T> __forceinline void Write32(T& f, const u32 data)
{
Write32LE(f, re32(data));
}
template<typename T> __forceinline static void Write64(T& f, const u64 data)
template<typename T> __forceinline void Write64(T& f, const u64 data)
{
Write64LE(f, re64(data));
}

View file

@ -235,3 +235,18 @@ LogChannel &LogManager::getChannel(LogType type)
{
return mChannels[static_cast<u32>(type)];
}
void log_message(Log::LogType type, Log::LogSeverity sev, const char* text)
{
//another msvc bug makes this not work, uncomment this and delete everything else in this function when it's fixed
//Log::LogManager::getInstance().log({logType, severity, text})
Log::LogMessage msg{ type, sev, text };
Log::LogManager::getInstance().log(msg);
}
void log_message(Log::LogType type, Log::LogSeverity sev, const std::string& text)
{
Log::LogMessage msg{ type, sev, text };
Log::LogManager::getInstance().log(msg);
}

View file

@ -126,24 +126,11 @@ static struct { inline operator Log::LogType() { return Log::LogType::SPU; } } S
static struct { inline operator Log::LogType() { return Log::LogType::ARMv7; } } ARMv7;
static struct { inline operator Log::LogType() { return Log::LogType::TTY; } } TTY;
inline void log_message(Log::LogType type, Log::LogSeverity sev, const char* text)
{
//another msvc bug makes this not work, uncomment this and delete everything else in this function when it's fixed
//Log::LogManager::getInstance().log({logType, severity, text})
void log_message(Log::LogType type, Log::LogSeverity sev, const char* text);
void log_message(Log::LogType type, Log::LogSeverity sev, const std::string& text);
Log::LogMessage msg{ type, sev, text };
Log::LogManager::getInstance().log(msg);
template<typename... Targs>
__noinline void log_message(Log::LogType type, Log::LogSeverity sev, const char* fmt, Targs... args)
{
log_message(type, sev, fmt::detail::format(fmt, strlen(fmt), fmt::do_unveil(args)...));
}
inline void log_message(Log::LogType type, Log::LogSeverity sev, const std::string& text)
{
Log::LogMessage msg{ type, sev, text };
Log::LogManager::getInstance().log(msg);
}
template<typename T, typename... Ts>
inline void log_message(Log::LogType type, Log::LogSeverity sev, const char* text, T arg, Ts... args)
{
Log::LogMessage msg{ type, sev, fmt::format(text, arg, args...) };
Log::LogManager::getInstance().log(msg);
}

View file

@ -3,7 +3,7 @@
std::string u128::to_hex() const
{
return fmt::Format("%016llx%016llx", _u64[1], _u64[0]);
return fmt::format("%016llx%016llx", _u64[1], _u64[0]);
}
std::string u128::to_xyzw() const
@ -11,6 +11,106 @@ std::string u128::to_xyzw() const
return fmt::Format("x: %g y: %g z: %g w: %g", _f[3], _f[2], _f[1], _f[0]);
}
std::string fmt::detail::to_hex(u64 value, size_t count)
{
assert(count - 1 < 16);
count = std::max<u64>(count, 16 - cntlz64(value) / 4);
char res[16] = {};
for (size_t i = count - 1; ~i; i--, value /= 16)
{
res[i] = "0123456789abcdef"[value % 16];
}
return std::string(res, count);
}
size_t fmt::detail::get_fmt_start(const char* fmt, size_t len)
{
for (size_t i = 0; i < len; i++)
{
if (fmt[i] == '%')
{
return i;
}
}
return len;
}
size_t fmt::detail::get_fmt_len(const char* fmt, size_t len)
{
assert(len >= 2 && fmt[0] == '%');
size_t res = 2;
if (fmt[1] == '.' || fmt[1] == '0')
{
assert(len >= 4 && fmt[2] - '1' < 9);
res += 2;
fmt += 2;
len -= 2;
if (fmt[1] == '1')
{
assert(len >= 3 && fmt[2] - '0' < 7);
res++;
fmt++;
len--;
}
}
if (fmt[1] == 'l')
{
assert(len >= 3);
res++;
fmt++;
len--;
}
if (fmt[1] == 'l')
{
assert(len >= 3);
res++;
fmt++;
len--;
}
return res;
}
size_t fmt::detail::get_fmt_precision(const char* fmt, size_t len)
{
assert(len >= 2);
if (fmt[1] == '.' || fmt[1] == '0')
{
assert(len >= 4 && fmt[2] - '1' < 9);
if (fmt[2] == '1')
{
assert(len >= 5 && fmt[3] - '0' < 7);
return 10 + fmt[3] - '0';
}
return fmt[2] - '0';
}
return 1;
}
std::string fmt::detail::format(const char* fmt, size_t len)
{
const size_t fmt_start = get_fmt_start(fmt, len);
if (fmt_start != len)
{
throw "Excessive formatting: " + std::string(fmt, len);
}
return std::string(fmt, len);
}
extern const std::string fmt::placeholder = "???";
std::string replace_first(const std::string& src, const std::string& from, const std::string& to)

View file

@ -175,114 +175,16 @@ namespace fmt
namespace detail
{
static std::string to_hex(u64 value, size_t count = 1)
{
assert(count - 1 < 16);
count = std::max<u64>(count, 16 - cntlz64(value) / 4);
std::string to_hex(u64 value, size_t count = 1);
char res[16] = {};
size_t get_fmt_start(const char* fmt, size_t len);
size_t get_fmt_len(const char* fmt, size_t len);
size_t get_fmt_precision(const char* fmt, size_t len);
for (size_t i = count - 1; ~i; i--, value /= 16)
{
res[i] = "0123456789abcdef"[value % 16];
}
return std::string(res, count);
}
static size_t get_fmt_start(const char* fmt, size_t len)
{
for (size_t i = 0; i < len; i++)
{
if (fmt[i] == '%')
{
return i;
}
}
return len;
}
static size_t get_fmt_len(const char* fmt, size_t len)
{
assert(len >= 2 && fmt[0] == '%');
size_t res = 2;
if (fmt[1] == '.' || fmt[1] == '0')
{
assert(len >= 4 && fmt[2] - '1' < 9);
res += 2;
fmt += 2;
len -= 2;
if (fmt[1] == '1')
{
assert(len >= 3 && fmt[2] - '0' < 7);
res++;
fmt++;
len--;
}
}
if (fmt[1] == 'l')
{
assert(len >= 3);
res++;
fmt++;
len--;
}
if (fmt[1] == 'l')
{
assert(len >= 3);
res++;
fmt++;
len--;
}
return res;
}
static size_t get_fmt_precision(const char* fmt, size_t len)
{
assert(len >= 2);
if (fmt[1] == '.' || fmt[1] == '0')
{
assert(len >= 4 && fmt[2] - '1' < 9);
if (fmt[2] == '1')
{
assert(len >= 5 && fmt[3] - '0' < 7);
return 10 + fmt[3] - '0';
}
return fmt[2] - '0';
}
return 1;
}
template<typename T, bool is_enum = std::is_enum<T>::value>
template<typename T>
struct get_fmt
{
static_assert(is_enum, "Unsupported fmt::format argument");
typedef typename std::underlying_type<T>::type underlying_type;
static std::string text(const char* fmt, size_t len, const T& arg)
{
return get_fmt<underlying_type>::text(fmt, len, (underlying_type)arg);
}
};
template<typename T, typename T2>
struct get_fmt<be_t<T, T2>, false>
{
static std::string text(const char* fmt, size_t len, const be_t<T, T2>& arg)
{
return get_fmt<T>::text(fmt, len, arg.value());
}
static_assert(!sizeof(T), "Unsupported fmt::format argument");
};
template<>
@ -621,16 +523,10 @@ namespace fmt
}
};
static std::string format(const char* fmt, size_t len)
{
const size_t fmt_start = get_fmt_start(fmt, len);
assert(fmt_start == len);
return std::string(fmt, len);
}
std::string format(const char* fmt, size_t len); // terminator
template<typename T, typename... Args>
static std::string format(const char* fmt, size_t len, const T& arg, Args... args)
std::string format(const char* fmt, size_t len, const T& arg, Args... args)
{
const size_t fmt_start = get_fmt_start(fmt, len);
const size_t fmt_len = get_fmt_len(fmt + fmt_start, len - fmt_start);
@ -640,8 +536,72 @@ namespace fmt
}
};
// formatting function with very limited functionality (compared to printf-like formatting) and be_t<> support
template<typename T, bool is_enum = std::is_enum<T>::value>
struct unveil
{
typedef T result_type;
__forceinline static result_type get_value(const T& arg)
{
return arg;
}
};
template<size_t N>
struct unveil<const char[N], false>
{
typedef const char* result_type;
__forceinline static result_type get_value(const char(&arg)[N])
{
return arg;
}
};
template<>
struct unveil<std::string, false>
{
typedef const std::string& result_type;
__forceinline static result_type get_value(const std::string& arg)
{
return arg;
}
};
template<typename T>
struct unveil<T, true>
{
typedef typename std::underlying_type<T>::type result_type;
__forceinline static result_type get_value(const T& arg)
{
return static_cast<result_type>(arg);
}
};
template<typename T, typename T2>
struct unveil<be_t<T, T2>, false>
{
typedef typename unveil<T>::result_type result_type;
__forceinline static result_type get_value(const be_t<T, T2>& arg)
{
return unveil<T>::get_value(arg.value());
}
};
template<typename T>
__forceinline typename unveil<T>::result_type do_unveil(const T& arg)
{
return unveil<T>::get_value(arg);
}
/*
fmt::format(const char* fmt, args...)
Formatting function with very limited functionality (compared to printf-like formatting) and be_t<> support
Supported types:
u8, s8 (%x, %d)
@ -652,16 +612,17 @@ namespace fmt
double (%x, %f)
bool (%x, %d, %s)
char*, const char*, std::string (%s)
be_t<> of any appropriate type in this list
enum of any appropriate type in this list
be_t<> of any appropriate type in this list (fmt::unveil)
enum of any appropriate type in this list (fmt::unveil)
External specializations (can be found in another headers):
vm::ps3::ptr (vm_ptr.h) (with appropriate address type, using .addr() can be avoided)
vm::ps3::bptr (vm_ptr.h)
vm::psv::ptr (vm_ptr.h)
vm::ps3::ref (vm_ref.h)
vm::ps3::bref (vm_ref.h)
vm::psv::ref (vm_ref.h)
vm::ps3::ptr (fmt::unveil) (vm_ptr.h) (with appropriate address type, using .addr() can be avoided)
vm::ps3::bptr (fmt::unveil) (vm_ptr.h)
vm::psv::ptr (fmt::unveil) (vm_ptr.h)
vm::ps3::ref (fmt::unveil) (vm_ref.h)
vm::ps3::bref (fmt::unveil) (vm_ref.h)
vm::psv::ref (fmt::unveil) (vm_ref.h)
Supported formatting:
%d - decimal; only basic std::to_string() functionality
@ -672,9 +633,9 @@ namespace fmt
Other features are not supported.
*/
template<typename... Args>
__forceinline static std::string format(const char* fmt, Args... args)
__forceinline std::string format(const char* fmt, Args... args)
{
return detail::format(fmt, strlen(fmt), args...);
return detail::format(fmt, strlen(fmt), do_unveil(args)...);
}
//convert a wxString to a std::string encoded in utf8

View file

@ -90,9 +90,9 @@ void decode_x64_reg_op(const u8* code, x64_op_t& decoded_op, x64_reg_t& decoded_
{
switch (const u8 prefix = *code)
{
case 0xf0: throw fmt::Format("decode_x64_reg_op(%.16llXh): 0x%.2X (LOCK prefix) found", code - decoded_size, prefix); // group 1
case 0xf2: throw fmt::Format("decode_x64_reg_op(%.16llXh): 0x%.2X (REPNE/REPNZ prefix) found", code - decoded_size, prefix); // group 1
case 0xf3: throw fmt::Format("decode_x64_reg_op(%.16llXh): 0x%.2X (REP/REPE/REPZ prefix) found", code - decoded_size, prefix); // group 1
case 0xf0: throw fmt::format("decode_x64_reg_op(%016llxh): 0x%02x (LOCK prefix) found", (size_t)code - decoded_size, prefix); // group 1
case 0xf2: throw fmt::format("decode_x64_reg_op(%016llxh): 0x%02x (REPNE/REPNZ prefix) found", (size_t)code - decoded_size, prefix); // group 1
case 0xf3: throw fmt::format("decode_x64_reg_op(%016llxh): 0x%02x (REP/REPE/REPZ prefix) found", (size_t)code - decoded_size, prefix); // group 1
case 0x2e: // group 2
case 0x36:
@ -108,12 +108,12 @@ void decode_x64_reg_op(const u8* code, x64_op_t& decoded_op, x64_reg_t& decoded_
}
else
{
throw fmt::Format("decode_x64_reg_op(%.16llXh): 0x%.2X (group 2 prefix) found after 0x%.2X", code - decoded_size, prefix, pg2);
throw fmt::format("decode_x64_reg_op(%016llxh): 0x%02x (group 2 prefix) found after 0x%02x", (size_t)code - decoded_size, prefix, pg2);
}
}
case 0x66: throw fmt::Format("decode_x64_reg_op(%.16llXh): 0x%.2X (operand-size override prefix) found", code - decoded_size, prefix); // group 3
case 0x67: throw fmt::Format("decode_x64_reg_op(%.16llXh): 0x%.2X (address-size override prefix) found", code - decoded_size, prefix); // group 4
case 0x66: throw fmt::format("decode_x64_reg_op(%016llxh): 0x%02x (operand-size override prefix) found", (size_t)code - decoded_size, prefix); // group 3
case 0x67: throw fmt::format("decode_x64_reg_op(%016llxh): 0x%02x (address-size override prefix) found", (size_t)code - decoded_size, prefix); // group 4
default:
{
@ -121,11 +121,11 @@ void decode_x64_reg_op(const u8* code, x64_op_t& decoded_op, x64_reg_t& decoded_
{
if (rex)
{
throw fmt::Format("decode_x64_reg_op(%.16llXh): 0x%.2X (REX prefix) found after 0x%.2X", code - decoded_size, prefix, rex);
throw fmt::format("decode_x64_reg_op(%016llxh): 0x%02x (REX prefix) found after 0x%02x", (size_t)code - decoded_size, prefix, rex);
}
if (prefix & 0x80) // check REX.W bit
{
throw fmt::Format("decode_x64_reg_op(%.16llXh): 0x%.2X (REX.W bit) found", code - decoded_size, prefix);
throw fmt::format("decode_x64_reg_op(%016llxh): 0x%02x (REX.W bit) found", (size_t)code - decoded_size, prefix);
}
if (prefix & 0x04) // check REX.R bit
{
@ -185,7 +185,7 @@ void decode_x64_reg_op(const u8* code, x64_op_t& decoded_op, x64_reg_t& decoded_
}
default:
{
throw fmt::Format("decode_x64_reg_op(%.16llXh): unsupported opcode found (0x%.2X, 0x%.2X, 0x%.2X)", code - decoded_size, op1, code[0], code[1]);
throw fmt::format("decode_x64_reg_op(%016llxh): unsupported opcode found (0x%02x, 0x%02x, 0x%02x)", (size_t)code - decoded_size, op1, code[0], code[1]);
}
}
}
@ -297,7 +297,7 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
// it's dangerous because destructors won't be executed
}
throw fmt::Format("Access violation %s location 0x%llx", is_writing ? "writing" : "reading", addr64);
throw fmt::format("Access violation %s location 0x%llx", is_writing ? "writing" : "reading", addr64);
}
// else some fatal error (should crash)
@ -316,7 +316,7 @@ void signal_handler(int sig, siginfo_t* info, void* uct)
}
// TODO: this may be wrong
throw fmt::Format("Access violation %s location 0x%llx", /*is_writing ? "writing" : "reading"*/ "at", addr64);
throw fmt::format("Access violation at location 0x%llx", addr64);
}
// else some fatal error
@ -354,7 +354,7 @@ void SetCurrentNamedThread(NamedThreadBase* value)
if (value && value->m_tls_assigned.exchange(true))
{
LOG_ERROR(GENERAL, "Thread '%s' was already assigned to g_tls_this_thread of another thread", value->GetThreadName().c_str());
LOG_ERROR(GENERAL, "Thread '%s' was already assigned to g_tls_this_thread of another thread", value->GetThreadName());
g_tls_this_thread = nullptr;
}
else