瀏覽代碼

Reimplement ConsumeDecimalNumber.

The old implementation caused odd crashes on ARM, which were fixed by
changing a local variable type. The main suspect is the use of a static
local variable. This CL replaces the static local variable with
constexpr, which still ensures the compiler sees the expressions as
constants.

The CL also replaces Slice operations in the functions' inner loop with
iterator-style pointer operations, which can help the compiler generate
less code.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=192832175
naive_version
costan 6 年之前
committed by Victor Costan
父節點
當前提交
a0008deb67
共有 1 個文件被更改,包括 29 次插入19 次删除
  1. +29
    -19
      util/logging.cc

+ 29
- 19
util/logging.cc 查看文件

@ -46,28 +46,38 @@ std::string EscapeString(const Slice& value) {
}
bool ConsumeDecimalNumber(Slice* in, uint64_t* val) {
uint64_t v = 0;
int digits = 0;
while (!in->empty()) {
char c = (*in)[0];
if (c >= '0' && c <= '9') {
++digits;
// |delta| intentionally unit64_t to avoid Android crash (see log).
const uint64_t delta = (c - '0');
static const uint64_t kMaxUint64 = ~static_cast<uint64_t>(0);
if (v > kMaxUint64/10 ||
(v == kMaxUint64/10 && delta > kMaxUint64%10)) {
// Overflow
return false;
}
v = (v * 10) + delta;
in->remove_prefix(1);
} else {
// Constants that will be optimized away.
constexpr const uint64_t kMaxUint64 = std::numeric_limits<uint64_t>::max();
constexpr const char kLastDigitOfMaxUint64 =
'0' + static_cast<char>(kMaxUint64 % 10);
uint64_t value = 0;
// reinterpret_cast-ing from char* to unsigned char* to avoid signedness.
const unsigned char* start =
reinterpret_cast<const unsigned char*>(in->data());
const unsigned char* end = start + in->size();
const unsigned char* current = start;
for (; current != end; ++current) {
const unsigned char ch = *current;
if (ch < '0' || ch > '9')
break;
// Overflow check.
// kMaxUint64 / 10 is also constant and will be optimized away.
if (value > kMaxUint64 / 10 ||
(value == kMaxUint64 / 10 && ch > kLastDigitOfMaxUint64)) {
return false;
}
value = (value * 10) + (ch - '0');
}
*val = v;
return (digits > 0);
*val = value;
const size_t digits_consumed = current - start;
in->remove_prefix(digits_consumed);
return digits_consumed != 0;
}
} // namespace leveldb

Loading…
取消
儲存