Commit ea1cdd1a authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

tweak size checks in to_ascii

Summary: If inlining and constant folding can determine that the buffer is larger than the `to_ascii_size_max` constant, then there is no need to call the `to_ascii_size` function an extra time.

Differential Revision: D27986105

fbshipit-source-id: d088001a7b3632dabb794c86dafdaa93dd0c1348
parent a8a754aa
......@@ -252,12 +252,6 @@ FOLLY_ALWAYS_INLINE void to_ascii_with_basic(
}
out[0] = xlate(uint8_t(v));
}
template <uint64_t Base, typename Alphabet>
FOLLY_ALWAYS_INLINE size_t to_ascii_with_basic(char* out, uint64_t v) {
auto const size = to_ascii_size_route<Base>(v);
to_ascii_with_basic<Base, Alphabet>(out, size, v);
return size;
}
// A variant of the straightforward implementation, but using a lookup table.
template <uint64_t Base, typename Alphabet>
......@@ -266,12 +260,6 @@ FOLLY_ALWAYS_INLINE void to_ascii_with_array(
using array = to_ascii_array<Base, Alphabet>; // also an alphabet
to_ascii_with_basic<Base, array>(out, size, v);
}
template <uint64_t Base, typename Alphabet>
FOLLY_ALWAYS_INLINE size_t to_ascii_with_array(char* out, uint64_t v) {
auto const size = to_ascii_size_route<Base>(v);
to_ascii_with_array<Base, Alphabet>(out, size, v);
return size;
}
// A trickier implementation which performs half as many divides as the other,
// more straightforward, implementation. On modern hardware, the divides are
......@@ -309,6 +297,24 @@ FOLLY_ALWAYS_INLINE size_t to_ascii_with_table(char* out, uint64_t v) {
return size;
}
template <uint64_t Base, typename Alphabet>
FOLLY_ALWAYS_INLINE size_t
to_ascii_with_route(char* outb, char const* oute, uint64_t v) {
auto const size = to_ascii_size_route<Base>(v);
if (FOLLY_UNLIKELY(oute < outb || size_t(oute - outb) < size)) {
return 0;
}
kIsMobile //
? to_ascii_with_array<Base, Alphabet>(outb, size, v)
: to_ascii_with_table<Base, Alphabet>(outb, size, v);
return size;
}
template <uint64_t Base, typename Alphabet, size_t N>
FOLLY_ALWAYS_INLINE size_t to_ascii_with_route(char (&out)[N], uint64_t v) {
static_assert(N >= to_ascii_powers<Base, decltype(v)>::size, "out too small");
return to_ascii_with_table<Base, Alphabet>(out, v);
}
} // namespace detail
// to_ascii_size_max
......@@ -364,18 +370,11 @@ inline size_t to_ascii_size_decimal(uint64_t v) {
// async-signal-safe
template <uint64_t Base, typename Alphabet>
size_t to_ascii_with(char* outb, char const* oute, uint64_t v) {
auto const size = to_ascii_size<Base>(v);
if (FOLLY_UNLIKELY(oute < outb || size_t(oute - outb) < size)) {
return 0;
}
return kIsMobile //
? detail::to_ascii_with_array<Base, Alphabet>(outb, v)
: detail::to_ascii_with_table<Base, Alphabet>(outb, v);
return detail::to_ascii_with_route<Base, Alphabet>(outb, oute, v);
}
template <uint64_t Base, typename Alphabet, size_t N>
size_t to_ascii_with(char (&out)[N], uint64_t v) {
static_assert(N >= to_ascii_size_max<Base, decltype(v)>, "out too small");
return detail::to_ascii_with_table<Base, Alphabet>(out, v);
return detail::to_ascii_with_route<Base, Alphabet>(out, v);
}
// to_ascii_lower
......
......@@ -44,7 +44,18 @@ using abc = folly::to_ascii_alphabet_lower;
} \
extern "C" FOLLY_KEEP size_t check_return_to_ascii_with_##impl##_##base( \
char* buf, uint64_t v) { \
return folly::detail::to_ascii_with_##impl<base, abc>(buf, v); \
auto const size = folly::to_ascii_size<base>(v); \
folly::detail::to_ascii_with_##impl<base, abc>(buf, size, v); \
return size; \
}
#define FOLLY_TO_ASCII_BENCH_CHECK(base) \
extern "C" FOLLY_KEEP size_t check_to_ascii_range_##base( \
char* outb, char* oute, uint64_t v) { \
return folly::detail::to_ascii_with_route<base, abc>(outb, oute, v); \
} \
extern "C" FOLLY_KEEP size_t check_to_ascii_array_##base( \
char(&out)[folly::to_ascii_size_max<base, uint64_t>], uint64_t v) { \
return folly::detail::to_ascii_with_route<base, abc>(out, v); \
}
FOLLY_TO_ASCII_BENCH_CHECK_SIZE(imuls, 16)
FOLLY_TO_ASCII_BENCH_CHECK_SIZE(imuls, 10)
......@@ -67,6 +78,9 @@ FOLLY_TO_ASCII_BENCH_CHECK_WITH(array, 8)
FOLLY_TO_ASCII_BENCH_CHECK_WITH(table, 16)
FOLLY_TO_ASCII_BENCH_CHECK_WITH(table, 10)
FOLLY_TO_ASCII_BENCH_CHECK_WITH(table, 8)
FOLLY_TO_ASCII_BENCH_CHECK(16)
FOLLY_TO_ASCII_BENCH_CHECK(10)
FOLLY_TO_ASCII_BENCH_CHECK(8)
namespace {
......
......@@ -243,18 +243,24 @@ using abc = folly::to_ascii_alphabet_lower;
TEST_F(ToAsciiTest, to_ascii_basic_10_compare) {
to_ascii_compare<10>([](auto out, auto v) {
return folly::detail::to_ascii_with_basic<10, abc>(out, v);
auto size = folly::to_ascii_size<10>(v);
folly::detail::to_ascii_with_basic<10, abc>(out, size, v);
return size;
});
}
TEST_F(ToAsciiTest, to_ascii_array_10_compare) {
to_ascii_compare<10>([](auto out, auto v) {
return folly::detail::to_ascii_with_array<10, abc>(out, v);
auto size = folly::to_ascii_size<10>(v);
folly::detail::to_ascii_with_array<10, abc>(out, size, v);
return size;
});
}
TEST_F(ToAsciiTest, to_ascii_table_10_compare) {
to_ascii_compare<10>([](auto out, auto v) {
return folly::detail::to_ascii_with_table<10, abc>(out, v);
auto size = folly::to_ascii_size<10>(v);
folly::detail::to_ascii_with_table<10, abc>(out, size, v);
return size;
});
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment