mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
Bug 1539605 - add fast paths for integer formatting on nsTSubstring; r=erahm
This way we don't have to go through a bunch of printf nonsense, and we ought to be able to arrive at optimized routines that take advantage of constant radices, etc. Differential Revision: https://phabricator.services.mozilla.com/D25141 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
20b6a59a5e
commit
dc25b5a9dc
@ -72,6 +72,9 @@ typedef mozilla::Vector<NumArgState, 20, mozilla::MallocAllocPolicy>
|
||||
#define FLAG_ZEROS 0x8
|
||||
#define FLAG_NEG 0x10
|
||||
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
static const char HEX[] = "0123456789ABCDEF";
|
||||
|
||||
// Fill into the buffer using the data in src
|
||||
bool mozilla::PrintfTarget::fill2(const char* src, int srclen, int width,
|
||||
int flags) {
|
||||
@ -167,6 +170,55 @@ bool mozilla::PrintfTarget::fill_n(const char* src, int srclen, int width,
|
||||
return true;
|
||||
}
|
||||
|
||||
// All that the cvt_* functions care about as far as the TYPE_* constants is
|
||||
// that the low bit is set to indicate unsigned, or unset to indicate signed.
|
||||
// So we don't try to hard to ensure that the passed TYPE_* constant lines
|
||||
// up with the actual size of the number being printed here. The main printf
|
||||
// code, below, does have to care so that the correct bits are extracted from
|
||||
// the varargs list.
|
||||
bool mozilla::PrintfTarget::appendIntDec(int32_t num) {
|
||||
int flags = 0;
|
||||
long n = num;
|
||||
if (n < 0) {
|
||||
n = -n;
|
||||
flags |= FLAG_NEG;
|
||||
}
|
||||
return cvt_l(n, -1, -1, 10, TYPE_INTN, flags, hex);
|
||||
}
|
||||
|
||||
bool mozilla::PrintfTarget::appendIntDec(uint32_t num) {
|
||||
return cvt_l(num, -1, -1, 10, TYPE_UINTN, 0, hex);
|
||||
}
|
||||
|
||||
bool mozilla::PrintfTarget::appendIntOct(uint32_t num) {
|
||||
return cvt_l(num, -1, -1, 8, TYPE_UINTN, 0, hex);
|
||||
}
|
||||
|
||||
bool mozilla::PrintfTarget::appendIntHex(uint32_t num) {
|
||||
return cvt_l(num, -1, -1, 16, TYPE_UINTN, 0, hex);
|
||||
}
|
||||
|
||||
bool mozilla::PrintfTarget::appendIntDec(int64_t num) {
|
||||
int flags = 0;
|
||||
if (num < 0) {
|
||||
num = -num;
|
||||
flags |= FLAG_NEG;
|
||||
}
|
||||
return cvt_ll(num, -1, -1, 10, TYPE_INTN, flags, hex);
|
||||
}
|
||||
|
||||
bool mozilla::PrintfTarget::appendIntDec(uint64_t num) {
|
||||
return cvt_ll(num, -1, -1, 10, TYPE_UINTN, 0, hex);
|
||||
}
|
||||
|
||||
bool mozilla::PrintfTarget::appendIntOct(uint64_t num) {
|
||||
return cvt_ll(num, -1, -1, 8, TYPE_UINTN, 0, hex);
|
||||
}
|
||||
|
||||
bool mozilla::PrintfTarget::appendIntHex(uint64_t num) {
|
||||
return cvt_ll(num, -1, -1, 16, TYPE_UINTN, 0, hex);
|
||||
}
|
||||
|
||||
/* Convert a long into its printable form. */
|
||||
bool mozilla::PrintfTarget::cvt_l(long num, int width, int prec, int radix,
|
||||
int type, int flags, const char* hexp) {
|
||||
@ -562,8 +614,6 @@ bool mozilla::PrintfTarget::vprint(const char* fmt, va_list ap) {
|
||||
#endif
|
||||
} u;
|
||||
const char* fmt0;
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
static const char HEX[] = "0123456789ABCDEF";
|
||||
const char* hexp;
|
||||
int i;
|
||||
char pattern[20];
|
||||
|
@ -76,6 +76,18 @@ class PrintfTarget {
|
||||
/* The Vprintf-like interface. */
|
||||
bool MFBT_API vprint(const char* format, va_list) MOZ_FORMAT_PRINTF(2, 0);
|
||||
|
||||
/* Fast paths for formatting integers as though by %d, %o, %u, or %x.
|
||||
Since octal and hex formatting always treat numbers as unsigned, there
|
||||
are no signed overloads for AppendInt{Oct,Hex}. */
|
||||
bool MFBT_API appendIntDec(int32_t);
|
||||
bool MFBT_API appendIntDec(uint32_t);
|
||||
bool MFBT_API appendIntOct(uint32_t);
|
||||
bool MFBT_API appendIntHex(uint32_t);
|
||||
bool MFBT_API appendIntDec(int64_t);
|
||||
bool MFBT_API appendIntDec(uint64_t);
|
||||
bool MFBT_API appendIntOct(uint64_t);
|
||||
bool MFBT_API appendIntHex(uint64_t);
|
||||
|
||||
protected:
|
||||
MFBT_API PrintfTarget();
|
||||
virtual ~PrintfTarget() {}
|
||||
|
@ -1221,6 +1221,78 @@ void nsTSubstring<T>::AppendPrintf(const char* aFormat, va_list aAp) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::AppendIntDec(int32_t aInteger) {
|
||||
PrintfAppend<T> appender(this);
|
||||
bool r = appender.appendIntDec(aInteger);
|
||||
if (MOZ_UNLIKELY(!r)) {
|
||||
MOZ_CRASH("Allocation or other failure while appending integers");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::AppendIntDec(uint32_t aInteger) {
|
||||
PrintfAppend<T> appender(this);
|
||||
bool r = appender.appendIntDec(aInteger);
|
||||
if (MOZ_UNLIKELY(!r)) {
|
||||
MOZ_CRASH("Allocation or other failure while appending integers");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::AppendIntOct(uint32_t aInteger) {
|
||||
PrintfAppend<T> appender(this);
|
||||
bool r = appender.appendIntOct(aInteger);
|
||||
if (MOZ_UNLIKELY(!r)) {
|
||||
MOZ_CRASH("Allocation or other failure while appending integers");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::AppendIntHex(uint32_t aInteger) {
|
||||
PrintfAppend<T> appender(this);
|
||||
bool r = appender.appendIntHex(aInteger);
|
||||
if (MOZ_UNLIKELY(!r)) {
|
||||
MOZ_CRASH("Allocation or other failure while appending integers");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::AppendIntDec(int64_t aInteger) {
|
||||
PrintfAppend<T> appender(this);
|
||||
bool r = appender.appendIntDec(aInteger);
|
||||
if (MOZ_UNLIKELY(!r)) {
|
||||
MOZ_CRASH("Allocation or other failure while appending integers");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::AppendIntDec(uint64_t aInteger) {
|
||||
PrintfAppend<T> appender(this);
|
||||
bool r = appender.appendIntDec(aInteger);
|
||||
if (MOZ_UNLIKELY(!r)) {
|
||||
MOZ_CRASH("Allocation or other failure while appending integers");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::AppendIntOct(uint64_t aInteger) {
|
||||
PrintfAppend<T> appender(this);
|
||||
bool r = appender.appendIntOct(aInteger);
|
||||
if (MOZ_UNLIKELY(!r)) {
|
||||
MOZ_CRASH("Allocation or other failure while appending integers");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void nsTSubstring<T>::AppendIntHex(uint64_t aInteger) {
|
||||
PrintfAppend<T> appender(this);
|
||||
bool r = appender.appendIntHex(aInteger);
|
||||
if (MOZ_UNLIKELY(!r)) {
|
||||
MOZ_CRASH("Allocation or other failure while appending integers");
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the length of the formatted aDouble in aBuf.
|
||||
static int FormatWithoutTrailingZeros(char (&aBuf)[40], double aDouble,
|
||||
int aPrecision) {
|
||||
|
@ -656,37 +656,58 @@ class nsTSubstring : public mozilla::detail::nsTStringRepr<T> {
|
||||
*/
|
||||
void AppendPrintf(const char* aFormat, ...) MOZ_FORMAT_PRINTF(2, 3);
|
||||
void AppendPrintf(const char* aFormat, va_list aAp) MOZ_FORMAT_PRINTF(2, 0);
|
||||
void AppendInt(int32_t aInteger) { AppendPrintf("%" PRId32, aInteger); }
|
||||
void AppendInt(int32_t aInteger) { AppendIntDec(aInteger); }
|
||||
void AppendInt(int32_t aInteger, int aRadix) {
|
||||
if (aRadix == 10) {
|
||||
AppendPrintf("%" PRId32, aInteger);
|
||||
AppendIntDec(aInteger);
|
||||
} else if (aRadix == 8) {
|
||||
AppendIntOct(static_cast<uint32_t>(aInteger));
|
||||
} else {
|
||||
AppendPrintf(aRadix == 8 ? "%" PRIo32 : "%" PRIx32,
|
||||
static_cast<uint32_t>(aInteger));
|
||||
AppendIntHex(static_cast<uint32_t>(aInteger));
|
||||
}
|
||||
}
|
||||
void AppendInt(uint32_t aInteger) { AppendPrintf("%" PRIu32, aInteger); }
|
||||
void AppendInt(uint32_t aInteger) { AppendIntDec(aInteger); }
|
||||
void AppendInt(uint32_t aInteger, int aRadix) {
|
||||
AppendPrintf(
|
||||
aRadix == 10 ? "%" PRIu32 : aRadix == 8 ? "%" PRIo32 : "%" PRIx32,
|
||||
aInteger);
|
||||
if (aRadix == 10) {
|
||||
AppendIntDec(aInteger);
|
||||
} else if (aRadix == 8) {
|
||||
AppendIntOct(aInteger);
|
||||
} else {
|
||||
AppendIntHex(aInteger);
|
||||
}
|
||||
}
|
||||
void AppendInt(int64_t aInteger) { AppendPrintf("%" PRId64, aInteger); }
|
||||
void AppendInt(int64_t aInteger) { AppendIntDec(aInteger); }
|
||||
void AppendInt(int64_t aInteger, int aRadix) {
|
||||
if (aRadix == 10) {
|
||||
AppendPrintf("%" PRId64, aInteger);
|
||||
AppendIntDec(aInteger);
|
||||
} else if (aRadix == 8) {
|
||||
AppendIntOct(static_cast<uint64_t>(aInteger));
|
||||
} else {
|
||||
AppendPrintf(aRadix == 8 ? "%" PRIo64 : "%" PRIx64,
|
||||
static_cast<uint64_t>(aInteger));
|
||||
AppendIntHex(static_cast<uint64_t>(aInteger));
|
||||
}
|
||||
}
|
||||
void AppendInt(uint64_t aInteger) { AppendPrintf("%" PRIu64, aInteger); }
|
||||
void AppendInt(uint64_t aInteger) { AppendIntDec(aInteger); }
|
||||
void AppendInt(uint64_t aInteger, int aRadix) {
|
||||
AppendPrintf(
|
||||
aRadix == 10 ? "%" PRIu64 : aRadix == 8 ? "%" PRIo64 : "%" PRIx64,
|
||||
aInteger);
|
||||
if (aRadix == 10) {
|
||||
AppendIntDec(aInteger);
|
||||
} else if (aRadix == 8) {
|
||||
AppendIntOct(aInteger);
|
||||
} else {
|
||||
AppendIntHex(aInteger);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void AppendIntDec(int32_t);
|
||||
void AppendIntDec(uint32_t);
|
||||
void AppendIntOct(uint32_t);
|
||||
void AppendIntHex(uint32_t);
|
||||
void AppendIntDec(int64_t);
|
||||
void AppendIntDec(uint64_t);
|
||||
void AppendIntOct(uint64_t);
|
||||
void AppendIntHex(uint64_t);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Append the given float to this string
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user