Commit dde9c073 authored by clemensh's avatar clemensh Committed by Commit bot

[wasm] Implement decoding of i32v values

I use it in a follow-up commit to delta-encode asm.js source positions.

This commit also removes the redundant consume_bytes function.

R=ahaas@chromium.org, titzer@chromium.org
BUG=v8:4203

Review-Url: https://codereview.chromium.org/2406163002
Cr-Commit-Position: refs/heads/master@{#40157}
parent 1b586141
......@@ -173,48 +173,14 @@ class Decoder {
return traceOffEnd<uint32_t>();
}
// Reads a LEB128 variable-length 32-bit integer and advances {pc_}.
// Reads a LEB128 variable-length unsigned 32-bit integer and advances {pc_}.
uint32_t consume_u32v(const char* name = nullptr) {
TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
name ? name : "varint");
if (checkAvailable(1)) {
const byte* pos = pc_;
const byte* end = pc_ + 5;
if (end > limit_) end = limit_;
uint32_t result = 0;
int shift = 0;
byte b = 0;
while (pc_ < end) {
b = *pc_++;
TRACE("%02x ", b);
result = result | ((b & 0x7F) << shift);
if ((b & 0x80) == 0) break;
shift += 7;
}
int length = static_cast<int>(pc_ - pos);
if (pc_ == end && (b & 0x80)) {
error(pc_ - 1, "varint too large");
} else if (length == 0) {
error(pc_, "varint of length 0");
} else {
TRACE("= %u\n", result);
}
return result;
}
return traceOffEnd<uint32_t>();
return consume_leb<uint32_t, false>(name);
}
// Consume {size} bytes and send them to the bit bucket, advancing {pc_}.
void consume_bytes(int size) {
TRACE(" +%d %-20s: %d bytes\n", static_cast<int>(pc_ - start_), "skip",
size);
if (checkAvailable(size)) {
pc_ += size;
} else {
pc_ = limit_;
}
// Reads a LEB128 variable-length signed 32-bit integer and advances {pc_}.
int32_t consume_i32v(const char* name = nullptr) {
return consume_leb<int32_t, true>(name);
}
// Consume {size} bytes and send them to the bit bucket, advancing {pc_}.
......@@ -383,6 +349,47 @@ class Decoder {
}
return result;
}
template <typename IntType, bool is_signed>
IntType consume_leb(const char* name = nullptr) {
TRACE(" +%d %-20s: ", static_cast<int>(pc_ - start_),
name ? name : "varint");
if (checkAvailable(1)) {
const int kMaxLength = (sizeof(IntType) * 8 + 6) / 7;
const byte* pos = pc_;
const byte* end = pc_ + kMaxLength;
if (end > limit_) end = limit_;
IntType result = 0;
int shift = 0;
byte b = 0;
while (pc_ < end) {
b = *pc_++;
TRACE("%02x ", b);
result = result | (static_cast<IntType>(b & 0x7F) << shift);
shift += 7;
if ((b & 0x80) == 0) break;
}
int length = static_cast<int>(pc_ - pos);
if (pc_ == end && (b & 0x80)) {
error(pc_ - 1, "varint too large");
} else if (length == 0) {
error(pc_, "varint of length 0");
} else if (is_signed) {
if (length < kMaxLength) {
int sign_ext_shift = 8 * sizeof(IntType) - shift;
// Perform sign extension.
result = (result << sign_ext_shift) >> sign_ext_shift;
}
TRACE("= %" PRIi64 "\n", static_cast<int64_t>(result));
} else {
TRACE("= %" PRIu64 "\n", static_cast<uint64_t>(result));
}
return result;
}
return traceOffEnd<uint32_t>();
}
};
#undef TRACE
......
......@@ -49,6 +49,11 @@ class ZoneBuffer : public ZoneObject {
LEBHelper::write_u32v(&pos_, val);
}
void write_i32v(int32_t val) {
EnsureSpace(kMaxVarInt32Size);
LEBHelper::write_i32v(&pos_, val);
}
void write_size(size_t val) {
EnsureSpace(kMaxVarInt32Size);
DCHECK_EQ(val, static_cast<uint32_t>(val));
......
......@@ -27,6 +27,10 @@ class DecoderTest : public TestWithZone {
EXPECT_EQ(expected, \
decoder.checked_read_u32v(decoder.start(), 0, &length)); \
EXPECT_EQ(expected_length, length); \
EXPECT_EQ(data, decoder.pc()); \
EXPECT_TRUE(decoder.ok()); \
EXPECT_EQ(expected, decoder.consume_u32v()); \
EXPECT_EQ(data + expected_length, decoder.pc()); \
} while (false)
#define CHECK_INT32V_INLINE(expected, expected_length, ...) \
......@@ -37,6 +41,10 @@ class DecoderTest : public TestWithZone {
EXPECT_EQ(expected, \
decoder.checked_read_i32v(decoder.start(), 0, &length)); \
EXPECT_EQ(expected_length, length); \
EXPECT_EQ(data, decoder.pc()); \
EXPECT_TRUE(decoder.ok()); \
EXPECT_EQ(expected, decoder.consume_i32v()); \
EXPECT_EQ(data + expected_length, decoder.pc()); \
} while (false)
#define CHECK_UINT64V_INLINE(expected, expected_length, ...) \
......
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