[wasm][cleanup] Use enums for template parameter values instead of bool

Calls like read_leb<int32_t, true, true, true>(...) can be hard to read
and understand. This CL replaces the three boolean template parameters
with enums so that the call is read_leb<int32_t, kChecked, kAdvancePC, kTrace>(...)
now.

R=clemensh@chromium.org

Bug: v8:6921
Change-Id: Id876a727d5e17df721444e7e5a117ad5395071aa
Reviewed-on: https://chromium-review.googlesource.com/718204
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: Ben Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48607}
This commit is contained in:
Andreas Haas 2017-10-16 18:27:54 +02:00 committed by Commit Bot
parent d0e3fb4f2e
commit efa038361d
10 changed files with 266 additions and 219 deletions

View File

@ -43,6 +43,12 @@ using DecodeResult = Result<std::nullptr_t>;
// a buffer of bytes.
class Decoder {
public:
enum ValidateFlag : bool { kValidate = true, kNoValidate = false };
enum AdvancePCFlag : bool { kAdvancePc = true, kNoAdvancePc = false };
enum TraceFlag : bool { kTrace = true, kNoTrace = false };
Decoder(const byte* start, const byte* end, uint32_t buffer_offset = 0)
: start_(start), pc_(start), end_(end), buffer_offset_(buffer_offset) {}
Decoder(const byte* start, const byte* pc, const byte* end,
@ -51,7 +57,7 @@ class Decoder {
virtual ~Decoder() {}
inline bool check(const byte* pc, uint32_t length, const char* msg) {
inline bool validate_size(const byte* pc, uint32_t length, const char* msg) {
DCHECK_LE(start_, pc);
if (V8_UNLIKELY(pc + length > end_)) {
error(pc, msg);
@ -61,58 +67,62 @@ class Decoder {
}
// Reads an 8-bit unsigned integer.
template <bool checked>
template <ValidateFlag validate>
inline uint8_t read_u8(const byte* pc, const char* msg = "expected 1 byte") {
return read_little_endian<uint8_t, checked>(pc, msg);
return read_little_endian<uint8_t, validate>(pc, msg);
}
// Reads a 16-bit unsigned integer (little endian).
template <bool checked>
template <ValidateFlag validate>
inline uint16_t read_u16(const byte* pc,
const char* msg = "expected 2 bytes") {
return read_little_endian<uint16_t, checked>(pc, msg);
return read_little_endian<uint16_t, validate>(pc, msg);
}
// Reads a 32-bit unsigned integer (little endian).
template <bool checked>
template <ValidateFlag validate>
inline uint32_t read_u32(const byte* pc,
const char* msg = "expected 4 bytes") {
return read_little_endian<uint32_t, checked>(pc, msg);
return read_little_endian<uint32_t, validate>(pc, msg);
}
// Reads a 64-bit unsigned integer (little endian).
template <bool checked>
template <ValidateFlag validate>
inline uint64_t read_u64(const byte* pc,
const char* msg = "expected 8 bytes") {
return read_little_endian<uint64_t, checked>(pc, msg);
return read_little_endian<uint64_t, validate>(pc, msg);
}
// Reads a variable-length unsigned integer (little endian).
template <bool checked>
template <ValidateFlag validate>
uint32_t read_u32v(const byte* pc, uint32_t* length,
const char* name = "LEB32") {
return read_leb<uint32_t, checked, false, false>(pc, length, name);
return read_leb<uint32_t, validate, kNoAdvancePc, kNoTrace>(pc, length,
name);
}
// Reads a variable-length signed integer (little endian).
template <bool checked>
template <ValidateFlag validate>
int32_t read_i32v(const byte* pc, uint32_t* length,
const char* name = "signed LEB32") {
return read_leb<int32_t, checked, false, false>(pc, length, name);
return read_leb<int32_t, validate, kNoAdvancePc, kNoTrace>(pc, length,
name);
}
// Reads a variable-length unsigned integer (little endian).
template <bool checked>
template <ValidateFlag validate>
uint64_t read_u64v(const byte* pc, uint32_t* length,
const char* name = "LEB64") {
return read_leb<uint64_t, checked, false, false>(pc, length, name);
return read_leb<uint64_t, validate, kNoAdvancePc, kNoTrace>(pc, length,
name);
}
// Reads a variable-length signed integer (little endian).
template <bool checked>
template <ValidateFlag validate>
int64_t read_i64v(const byte* pc, uint32_t* length,
const char* name = "signed LEB64") {
return read_leb<int64_t, checked, false, false>(pc, length, name);
return read_leb<int64_t, validate, kNoAdvancePc, kNoTrace>(pc, length,
name);
}
// Reads a 8-bit unsigned integer (byte) and advances {pc_}.
@ -133,13 +143,14 @@ class Decoder {
// Reads a LEB128 variable-length unsigned 32-bit integer and advances {pc_}.
uint32_t consume_u32v(const char* name = nullptr) {
uint32_t length = 0;
return read_leb<uint32_t, true, true, true>(pc_, &length, name);
return read_leb<uint32_t, kValidate, kAdvancePc, kTrace>(pc_, &length,
name);
}
// Reads a LEB128 variable-length signed 32-bit integer and advances {pc_}.
int32_t consume_i32v(const char* name = nullptr) {
uint32_t length = 0;
return read_leb<int32_t, true, true, true>(pc_, &length, name);
return read_leb<int32_t, kValidate, kAdvancePc, kTrace>(pc_, &length, name);
}
// Consume {size} bytes and send them to the bit bucket, advancing {pc_}.
@ -261,11 +272,11 @@ class Decoder {
std::string error_msg_;
private:
template <typename IntType, bool checked>
template <typename IntType, bool validate>
inline IntType read_little_endian(const byte* pc, const char* msg) {
if (!checked) {
DCHECK(check(pc, sizeof(IntType), msg));
} else if (!check(pc, sizeof(IntType), msg)) {
if (!validate) {
DCHECK(validate_size(pc, sizeof(IntType), msg));
} else if (!validate_size(pc, sizeof(IntType), msg)) {
return IntType{0};
}
return ReadLittleEndianValue<IntType>(pc);
@ -286,17 +297,18 @@ class Decoder {
return val;
}
template <typename IntType, bool checked, bool advance_pc, bool trace>
template <typename IntType, ValidateFlag validate, AdvancePCFlag advance_pc,
TraceFlag trace>
inline IntType read_leb(const byte* pc, uint32_t* length,
const char* name = "varint") {
DCHECK_IMPLIES(advance_pc, pc == pc_);
TRACE_IF(trace, " +%u %-20s: ", pc_offset(), name);
return read_leb_tail<IntType, checked, advance_pc, trace, 0>(pc, length,
name, 0);
return read_leb_tail<IntType, validate, advance_pc, trace, 0>(pc, length,
name, 0);
}
template <typename IntType, bool checked, bool advance_pc, bool trace,
int byte_index>
template <typename IntType, ValidateFlag validate, AdvancePCFlag advance_pc,
TraceFlag trace, int byte_index>
IntType read_leb_tail(const byte* pc, uint32_t* length, const char* name,
IntType result) {
constexpr bool is_signed = std::is_signed<IntType>::value;
@ -304,7 +316,7 @@ class Decoder {
static_assert(byte_index < kMaxLength, "invalid template instantiation");
constexpr int shift = byte_index * 7;
constexpr bool is_last_byte = byte_index == kMaxLength - 1;
const bool at_end = checked && pc >= end_;
const bool at_end = validate && pc >= end_;
byte b = 0;
if (!at_end) {
DCHECK_LT(pc, end_);
@ -317,12 +329,12 @@ class Decoder {
// Compilers are not smart enough to figure out statically that the
// following call is unreachable if is_last_byte is false.
constexpr int next_byte_index = byte_index + (is_last_byte ? 0 : 1);
return read_leb_tail<IntType, checked, advance_pc, trace,
return read_leb_tail<IntType, validate, advance_pc, trace,
next_byte_index>(pc + 1, length, name, result);
}
if (advance_pc) pc_ = pc + (at_end ? 0 : 1);
*length = byte_index + (at_end ? 0 : 1);
if (checked && (at_end || (b & 0x80))) {
if (validate && (at_end || (b & 0x80))) {
TRACE_IF(trace, at_end ? "<end> " : "<length overflow> ");
errorf(pc, "expected %s", name);
result = 0;
@ -341,7 +353,7 @@ class Decoder {
bool valid_extra_bits =
checked_bits == 0 ||
(is_signed && checked_bits == kSignExtendedExtraBits);
if (!checked) {
if (!validate) {
DCHECK(valid_extra_bits);
} else if (!valid_extra_bits) {
error(pc, "extra bits in varint");

View File

@ -87,7 +87,7 @@ Vector<T> vec2vec(std::vector<T>& vec) {
}
// Helpers for decoding different kinds of operands which follow bytecodes.
template <bool validate>
template <Decoder::ValidateFlag validate>
struct LocalIndexOperand {
uint32_t index;
ValueType type = kWasmStmt;
@ -98,7 +98,7 @@ struct LocalIndexOperand {
}
};
template <bool validate>
template <Decoder::ValidateFlag validate>
struct ExceptionIndexOperand {
uint32_t index;
const WasmException* exception = nullptr;
@ -109,7 +109,7 @@ struct ExceptionIndexOperand {
}
};
template <bool validate>
template <Decoder::ValidateFlag validate>
struct ImmI32Operand {
int32_t value;
unsigned length;
@ -118,7 +118,7 @@ struct ImmI32Operand {
}
};
template <bool validate>
template <Decoder::ValidateFlag validate>
struct ImmI64Operand {
int64_t value;
unsigned length;
@ -127,7 +127,7 @@ struct ImmI64Operand {
}
};
template <bool validate>
template <Decoder::ValidateFlag validate>
struct ImmF32Operand {
float value;
unsigned length = 4;
@ -138,7 +138,7 @@ struct ImmF32Operand {
}
};
template <bool validate>
template <Decoder::ValidateFlag validate>
struct ImmF64Operand {
double value;
unsigned length = 8;
@ -149,7 +149,7 @@ struct ImmF64Operand {
}
};
template <bool validate>
template <Decoder::ValidateFlag validate>
struct GlobalIndexOperand {
uint32_t index;
ValueType type = kWasmStmt;
@ -161,7 +161,7 @@ struct GlobalIndexOperand {
}
};
template <bool validate>
template <Decoder::ValidateFlag validate>
struct BlockTypeOperand {
unsigned length = 1;
ValueType type = kWasmStmt;
@ -235,7 +235,7 @@ struct BlockTypeOperand {
}
};
template <bool validate>
template <Decoder::ValidateFlag validate>
struct BreakDepthOperand {
uint32_t depth;
unsigned length;
@ -244,7 +244,7 @@ struct BreakDepthOperand {
}
};
template <bool validate>
template <Decoder::ValidateFlag validate>
struct CallIndirectOperand {
uint32_t table_index;
uint32_t index;
@ -262,7 +262,7 @@ struct CallIndirectOperand {
}
};
template <bool validate>
template <Decoder::ValidateFlag validate>
struct CallFunctionOperand {
uint32_t index;
FunctionSig* sig = nullptr;
@ -272,7 +272,7 @@ struct CallFunctionOperand {
}
};
template <bool validate>
template <Decoder::ValidateFlag validate>
struct MemoryIndexOperand {
uint32_t index;
unsigned length = 1;
@ -284,7 +284,7 @@ struct MemoryIndexOperand {
}
};
template <bool validate>
template <Decoder::ValidateFlag validate>
struct BranchTableOperand {
uint32_t table_count;
const byte* start;
@ -299,7 +299,7 @@ struct BranchTableOperand {
};
// A helper to iterate over a branch table.
template <bool validate>
template <Decoder::ValidateFlag validate>
class BranchTableIterator {
public:
unsigned cur_index() { return index_; }
@ -337,7 +337,7 @@ class BranchTableIterator {
uint32_t table_count_; // the count of entries, not including default.
};
template <bool validate>
template <Decoder::ValidateFlag validate>
struct MemoryAccessOperand {
uint32_t alignment;
uint32_t offset;
@ -361,7 +361,7 @@ struct MemoryAccessOperand {
};
// Operand for SIMD lane operations.
template <bool validate>
template <Decoder::ValidateFlag validate>
struct SimdLaneOperand {
uint8_t lane;
unsigned length = 1;
@ -372,7 +372,7 @@ struct SimdLaneOperand {
};
// Operand for SIMD shift operations.
template <bool validate>
template <Decoder::ValidateFlag validate>
struct SimdShiftOperand {
uint8_t shift;
unsigned length = 1;
@ -383,7 +383,7 @@ struct SimdShiftOperand {
};
// Operand for SIMD S8x16 shuffle operations.
template <bool validate>
template <Decoder::ValidateFlag validate>
struct Simd8x16ShuffleOperand {
uint8_t shuffle[kSimd128Size];
@ -606,7 +606,7 @@ struct ControlWithNamedConstructors : public ControlBase<Value> {
// Generic Wasm bytecode decoder with utilities for decoding operands,
// lengths, etc.
template <bool validate>
template <Decoder::ValidateFlag validate>
class WasmDecoder : public Decoder {
public:
WasmDecoder(const WasmModule* module, FunctionSig* sig, const byte* start,
@ -703,7 +703,7 @@ class WasmDecoder : public Decoder {
break;
case kExprSetLocal: // fallthru
case kExprTeeLocal: {
LocalIndexOperand<validate> operand(decoder, pc);
LocalIndexOperand<Decoder::kValidate> operand(decoder, pc);
if (assigned->length() > 0 &&
operand.index < static_cast<uint32_t>(assigned->length())) {
// Unverified code might have an out-of-bounds index.
@ -733,7 +733,8 @@ class WasmDecoder : public Decoder {
return decoder->ok() ? assigned : nullptr;
}
inline bool Validate(const byte* pc, LocalIndexOperand<validate>& operand) {
inline bool Validate(const byte* pc,
LocalIndexOperand<Decoder::kValidate>& operand) {
if (!VALIDATE(operand.index < total_locals())) {
errorf(pc + 1, "invalid local index: %u", operand.index);
return false;
@ -943,7 +944,7 @@ class WasmDecoder : public Decoder {
case kExprSetLocal:
case kExprTeeLocal:
case kExprGetLocal: {
LocalIndexOperand<validate> operand(decoder, pc);
LocalIndexOperand<Decoder::kValidate> operand(decoder, pc);
return 1 + operand.length;
}
case kExprBrTable: {
@ -1103,7 +1104,7 @@ class WasmDecoder : public Decoder {
} \
} while (false)
template <bool validate, typename Interface>
template <Decoder::ValidateFlag validate, typename Interface>
class WasmFullDecoder : public WasmDecoder<validate> {
using Value = typename Interface::Value;
using Control = typename Interface::Control;
@ -1321,7 +1322,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
}
case kExprThrow: {
CHECK_PROTOTYPE_OPCODE(eh);
ExceptionIndexOperand<true> operand(this, this->pc_);
ExceptionIndexOperand<Decoder::kValidate> operand(this, this->pc_);
len = 1 + operand.length;
if (!this->Validate(this->pc_, operand)) break;
std::vector<Value> args;
@ -1344,7 +1345,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
case kExprCatch: {
// TODO(kschimpf): Fix to use type signature of exception.
CHECK_PROTOTYPE_OPCODE(eh);
ExceptionIndexOperand<true> operand(this, this->pc_);
ExceptionIndexOperand<Decoder::kValidate> operand(this, this->pc_);
len = 1 + operand.length;
if (!this->Validate(this->pc_, operand)) break;
@ -1576,7 +1577,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break;
}
case kExprGetLocal: {
LocalIndexOperand<validate> operand(this, this->pc_);
LocalIndexOperand<Decoder::kValidate> operand(this, this->pc_);
if (!this->Validate(this->pc_, operand)) break;
auto* value = Push(operand.type);
CALL_INTERFACE_IF_REACHABLE(GetLocal, value, operand);
@ -1584,7 +1585,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break;
}
case kExprSetLocal: {
LocalIndexOperand<validate> operand(this, this->pc_);
LocalIndexOperand<Decoder::kValidate> operand(this, this->pc_);
if (!this->Validate(this->pc_, operand)) break;
auto value = Pop(0, local_type_vec_[operand.index]);
CALL_INTERFACE_IF_REACHABLE(SetLocal, value, operand);
@ -1592,7 +1593,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break;
}
case kExprTeeLocal: {
LocalIndexOperand<validate> operand(this, this->pc_);
LocalIndexOperand<Decoder::kValidate> operand(this, this->pc_);
if (!this->Validate(this->pc_, operand)) break;
auto value = Pop(0, local_type_vec_[operand.index]);
auto* result = Push(value.type);
@ -1822,7 +1823,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
case kExprGetLocal:
case kExprSetLocal:
case kExprTeeLocal: {
LocalIndexOperand<validate> operand(this, val.pc);
LocalIndexOperand<Decoder::kValidate> operand(this, val.pc);
PrintF("[%u]", operand.index);
break;
}
@ -2330,7 +2331,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
class EmptyInterface {
public:
constexpr static bool validate = true;
static constexpr wasm::Decoder::ValidateFlag validate =
wasm::Decoder::kValidate;
using Value = ValueBase;
using Control = ControlBase<Value>;
using Decoder = WasmFullDecoder<validate, EmptyInterface>;

View File

@ -71,7 +71,9 @@ constexpr uint32_t kNullCatch = static_cast<uint32_t>(-1);
class WasmGraphBuildingInterface {
public:
using Decoder = WasmFullDecoder<true, WasmGraphBuildingInterface>;
static constexpr wasm::Decoder::ValidateFlag validate =
wasm::Decoder::kValidate;
using Decoder = WasmFullDecoder<validate, WasmGraphBuildingInterface>;
struct Value : public ValueWithNamedConstructors<Value> {
TFNode* node;
@ -259,31 +261,31 @@ class WasmGraphBuildingInterface {
}
void GetLocal(Decoder* decoder, Value* result,
const LocalIndexOperand<true>& operand) {
const LocalIndexOperand<validate>& operand) {
if (!ssa_env_->locals) return; // unreachable
result->node = ssa_env_->locals[operand.index];
}
void SetLocal(Decoder* decoder, const Value& value,
const LocalIndexOperand<true>& operand) {
const LocalIndexOperand<validate>& operand) {
if (!ssa_env_->locals) return; // unreachable
ssa_env_->locals[operand.index] = value.node;
}
void TeeLocal(Decoder* decoder, const Value& value, Value* result,
const LocalIndexOperand<true>& operand) {
const LocalIndexOperand<validate>& operand) {
result->node = value.node;
if (!ssa_env_->locals) return; // unreachable
ssa_env_->locals[operand.index] = value.node;
}
void GetGlobal(Decoder* decoder, Value* result,
const GlobalIndexOperand<true>& operand) {
const GlobalIndexOperand<validate>& operand) {
result->node = BUILD(GetGlobal, operand.index);
}
void SetGlobal(Decoder* decoder, const Value& value,
const GlobalIndexOperand<true>& operand) {
const GlobalIndexOperand<validate>& operand) {
BUILD(SetGlobal, operand.index, value.node);
}
@ -320,11 +322,11 @@ class WasmGraphBuildingInterface {
ssa_env_ = fenv;
}
void BrTable(Decoder* decoder, const BranchTableOperand<true>& operand,
void BrTable(Decoder* decoder, const BranchTableOperand<validate>& operand,
const Value& key) {
if (operand.table_count == 0) {
// Only a default target. Do the equivalent of br.
uint32_t target = BranchTableIterator<true>(decoder, operand).next();
uint32_t target = BranchTableIterator<validate>(decoder, operand).next();
BreakTo(decoder, decoder->control_at(target));
return;
}
@ -335,7 +337,7 @@ class WasmGraphBuildingInterface {
SsaEnv* copy = Steal(decoder->zone(), break_env);
ssa_env_ = copy;
BranchTableIterator<true> iterator(decoder, operand);
BranchTableIterator<validate> iterator(decoder, operand);
while (iterator.has_next()) {
uint32_t i = iterator.cur_index();
uint32_t target = iterator.next();
@ -353,15 +355,15 @@ class WasmGraphBuildingInterface {
}
void LoadMem(Decoder* decoder, ValueType type, MachineType mem_type,
const MemoryAccessOperand<true>& operand, const Value& index,
const MemoryAccessOperand<validate>& operand, const Value& index,
Value* result) {
result->node = BUILD(LoadMem, type, mem_type, index.node, operand.offset,
operand.alignment, decoder->position());
}
void StoreMem(Decoder* decoder, ValueType type, MachineType mem_type,
const MemoryAccessOperand<true>& operand, const Value& index,
const Value& value) {
const MemoryAccessOperand<validate>& operand,
const Value& index, const Value& value) {
BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment,
value.node, decoder->position(), type);
}
@ -376,13 +378,14 @@ class WasmGraphBuildingInterface {
LoadContextIntoSsa(ssa_env_);
}
void CallDirect(Decoder* decoder, const CallFunctionOperand<true>& operand,
void CallDirect(Decoder* decoder,
const CallFunctionOperand<validate>& operand,
const Value args[], Value returns[]) {
DoCall(decoder, nullptr, operand, args, returns, false);
}
void CallIndirect(Decoder* decoder, const Value& index,
const CallIndirectOperand<true>& operand,
const CallIndirectOperand<validate>& operand,
const Value args[], Value returns[]) {
DoCall(decoder, index.node, operand, args, returns, true);
}
@ -395,21 +398,21 @@ class WasmGraphBuildingInterface {
}
void SimdLaneOp(Decoder* decoder, WasmOpcode opcode,
const SimdLaneOperand<true> operand, Vector<Value> inputs,
const SimdLaneOperand<validate> operand, Vector<Value> inputs,
Value* result) {
TFNode** nodes = GetNodes(inputs);
result->node = BUILD(SimdLaneOp, opcode, operand.lane, nodes);
}
void SimdShiftOp(Decoder* decoder, WasmOpcode opcode,
const SimdShiftOperand<true> operand, const Value& input,
const SimdShiftOperand<validate> operand, const Value& input,
Value* result) {
TFNode* inputs[] = {input.node};
result->node = BUILD(SimdShiftOp, opcode, operand.shift, inputs);
}
void Simd8x16ShuffleOp(Decoder* decoder,
const Simd8x16ShuffleOperand<true>& operand,
const Simd8x16ShuffleOperand<validate>& operand,
const Value& input0, const Value& input1,
Value* result) {
TFNode* input_nodes[] = {input0.node, input1.node};
@ -417,13 +420,13 @@ class WasmGraphBuildingInterface {
}
TFNode* GetExceptionTag(Decoder* decoder,
const ExceptionIndexOperand<true>& operand) {
const ExceptionIndexOperand<validate>& operand) {
// TODO(kschimpf): Need to get runtime exception tag values. This
// code only handles non-imported/exported exceptions.
return BUILD(Int32Constant, operand.index);
}
void Throw(Decoder* decoder, const ExceptionIndexOperand<true>& operand,
void Throw(Decoder* decoder, const ExceptionIndexOperand<validate>& operand,
Control* block, const Vector<Value>& value_args) {
int count = value_args.length();
ZoneVector<TFNode*> args(count, decoder->zone());
@ -436,7 +439,7 @@ class WasmGraphBuildingInterface {
}
void CatchException(Decoder* decoder,
const ExceptionIndexOperand<true>& operand,
const ExceptionIndexOperand<validate>& operand,
Control* block, Vector<Value> values) {
DCHECK(block->is_try_catch());
current_catch_ = block->previous_catch;
@ -496,7 +499,7 @@ class WasmGraphBuildingInterface {
}
void AtomicOp(Decoder* decoder, WasmOpcode opcode, Vector<Value> args,
const MemoryAccessOperand<true>& operand, Value* result) {
const MemoryAccessOperand<validate>& operand, Value* result) {
TFNode** inputs = GetNodes(args);
TFNode* node = BUILD(AtomicOp, opcode, inputs, operand.alignment,
operand.offset, decoder->position());
@ -743,7 +746,7 @@ class WasmGraphBuildingInterface {
env->effect = builder_->EffectPhi(1, &env->effect, env->control);
builder_->Terminate(env->effect, env->control);
// The '+ 2' here is to be able to set mem_size and mem_start as assigned.
BitVector* assigned = WasmDecoder<true>::AnalyzeLoopAssignment(
BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment(
decoder, decoder->pc(), decoder->total_locals() + 2, decoder->zone());
if (decoder->failed()) return env;
if (assigned != nullptr) {
@ -846,7 +849,7 @@ class WasmGraphBuildingInterface {
}
template <typename Operand>
void DoCall(WasmFullDecoder<true, WasmGraphBuildingInterface>* decoder,
void DoCall(WasmFullDecoder<validate, WasmGraphBuildingInterface>* decoder,
TFNode* index_node, const Operand& operand, const Value args[],
Value returns[], bool is_indirect) {
if (!build(decoder)) return;
@ -879,7 +882,8 @@ class WasmGraphBuildingInterface {
bool DecodeLocalDecls(BodyLocalDecls* decls, const byte* start,
const byte* end) {
Decoder decoder(start, end);
if (WasmDecoder<true>::DecodeLocals(&decoder, nullptr, &decls->type_list)) {
if (WasmDecoder<Decoder::kValidate>::DecodeLocals(&decoder, nullptr,
&decls->type_list)) {
DCHECK(decoder.ok());
decls->encoded_size = decoder.pc_offset();
return true;
@ -902,7 +906,8 @@ DecodeResult VerifyWasmCode(AccountingAllocator* allocator,
const wasm::WasmModule* module,
FunctionBody& body) {
Zone zone(allocator, ZONE_NAME);
WasmFullDecoder<true, EmptyInterface> decoder(&zone, module, body);
WasmFullDecoder<Decoder::kValidate, EmptyInterface> decoder(&zone, module,
body);
decoder.Decode();
return decoder.toResult(nullptr);
}
@ -921,7 +926,7 @@ DecodeResult VerifyWasmCodeWithStats(AccountingAllocator* allocator,
DecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder,
FunctionBody& body) {
Zone zone(allocator, ZONE_NAME);
WasmFullDecoder<true, WasmGraphBuildingInterface> decoder(
WasmFullDecoder<Decoder::kValidate, WasmGraphBuildingInterface> decoder(
&zone, builder->module(), body, builder);
decoder.Decode();
return decoder.toResult(nullptr);
@ -929,13 +934,13 @@ DecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder,
unsigned OpcodeLength(const byte* pc, const byte* end) {
Decoder decoder(pc, end);
return WasmDecoder<false>::OpcodeLength(&decoder, pc);
return WasmDecoder<Decoder::kNoValidate>::OpcodeLength(&decoder, pc);
}
std::pair<uint32_t, uint32_t> StackEffect(const WasmModule* module,
FunctionSig* sig, const byte* pc,
const byte* end) {
WasmDecoder<false> decoder(module, sig, pc, end);
WasmDecoder<Decoder::kNoValidate> decoder(module, sig, pc, end);
return decoder.StackEffect(pc);
}
@ -963,7 +968,8 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
const wasm::WasmModule* module) {
OFStream os(stdout);
Zone zone(allocator, ZONE_NAME);
WasmDecoder<false> decoder(module, body.sig, body.start, body.end);
WasmDecoder<Decoder::kNoValidate> decoder(module, body.sig, body.start,
body.end);
int line_nr = 0;
// Print the function signature.
@ -1004,7 +1010,8 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
++line_nr;
unsigned control_depth = 0;
for (; i.has_next(); i.next()) {
unsigned length = WasmDecoder<false>::OpcodeLength(&decoder, i.pc());
unsigned length =
WasmDecoder<Decoder::kNoValidate>::OpcodeLength(&decoder, i.pc());
WasmOpcode opcode = i.current();
if (opcode == kExprElse) control_depth--;
@ -1031,7 +1038,7 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
case kExprIf:
case kExprBlock:
case kExprTry: {
BlockTypeOperand<false> operand(&i, i.pc());
BlockTypeOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << " // @" << i.pc_offset();
for (unsigned i = 0; i < operand.out_arity(); i++) {
os << " " << WasmOpcodes::TypeName(operand.out_type(i));
@ -1044,22 +1051,22 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
control_depth--;
break;
case kExprBr: {
BreakDepthOperand<false> operand(&i, i.pc());
BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << " // depth=" << operand.depth;
break;
}
case kExprBrIf: {
BreakDepthOperand<false> operand(&i, i.pc());
BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << " // depth=" << operand.depth;
break;
}
case kExprBrTable: {
BranchTableOperand<false> operand(&i, i.pc());
BranchTableOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << " // entries=" << operand.table_count;
break;
}
case kExprCallIndirect: {
CallIndirectOperand<false> operand(&i, i.pc());
CallIndirectOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << " // sig #" << operand.index;
if (decoder.Complete(i.pc(), operand)) {
os << ": " << *operand.sig;
@ -1067,7 +1074,7 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
break;
}
case kExprCallFunction: {
CallFunctionOperand<false> operand(&i, i.pc());
CallFunctionOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << " // function #" << operand.index;
if (decoder.Complete(i.pc(), operand)) {
os << ": " << *operand.sig;
@ -1087,7 +1094,7 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
const byte* start, const byte* end) {
Decoder decoder(start, end);
return WasmDecoder<true>::AnalyzeLoopAssignment(
return WasmDecoder<Decoder::kValidate>::AnalyzeLoopAssignment(
&decoder, start, static_cast<uint32_t>(num_locals), zone);
}

View File

@ -178,7 +178,8 @@ class V8_EXPORT_PRIVATE BytecodeIterator : public NON_EXPORTED_BASE(Decoder) {
}
WasmOpcode current() {
return static_cast<WasmOpcode>(read_u8<false>(pc_, "expected bytecode"));
return static_cast<WasmOpcode>(
read_u8<Decoder::kNoValidate>(pc_, "expected bytecode"));
}
void next() {
@ -191,8 +192,8 @@ class V8_EXPORT_PRIVATE BytecodeIterator : public NON_EXPORTED_BASE(Decoder) {
bool has_next() { return pc_ < end_; }
WasmOpcode prefixed_opcode() {
byte prefix = read_u8<false>(pc_, "expected prefix");
byte index = read_u8<false>(pc_ + 1, "expected index");
byte prefix = read_u8<Decoder::kNoValidate>(pc_, "expected prefix");
byte index = read_u8<Decoder::kNoValidate>(pc_ + 1, "expected index");
return static_cast<WasmOpcode>(prefix << 8 | index);
}
};

View File

@ -1177,7 +1177,7 @@ class ModuleDecoderImpl : public Decoder {
unsigned len = 0;
switch (opcode) {
case kExprGetGlobal: {
GlobalIndexOperand<true> operand(this, pc() - 1);
GlobalIndexOperand<Decoder::kValidate> operand(this, pc() - 1);
if (module->globals.size() <= operand.index) {
error("global index is out of bounds");
expr.kind = WasmInitExpr::kNone;
@ -1199,28 +1199,28 @@ class ModuleDecoderImpl : public Decoder {
break;
}
case kExprI32Const: {
ImmI32Operand<true> operand(this, pc() - 1);
ImmI32Operand<Decoder::kValidate> operand(this, pc() - 1);
expr.kind = WasmInitExpr::kI32Const;
expr.val.i32_const = operand.value;
len = operand.length;
break;
}
case kExprF32Const: {
ImmF32Operand<true> operand(this, pc() - 1);
ImmF32Operand<Decoder::kValidate> operand(this, pc() - 1);
expr.kind = WasmInitExpr::kF32Const;
expr.val.f32_const = operand.value;
len = operand.length;
break;
}
case kExprI64Const: {
ImmI64Operand<true> operand(this, pc() - 1);
ImmI64Operand<Decoder::kValidate> operand(this, pc() - 1);
expr.kind = WasmInitExpr::kI64Const;
expr.val.i64_const = operand.value;
len = operand.length;
break;
}
case kExprF64Const: {
ImmF64Operand<true> operand(this, pc() - 1);
ImmF64Operand<Decoder::kValidate> operand(this, pc() - 1);
expr.kind = WasmInitExpr::kF64Const;
expr.val.f64_const = operand.value;
len = operand.length;

View File

@ -811,7 +811,7 @@ class SideTable : public ZoneObject {
case kExprBlock:
case kExprLoop: {
bool is_loop = opcode == kExprLoop;
BlockTypeOperand<false> operand(&i, i.pc());
BlockTypeOperand<Decoder::kNoValidate> operand(&i, i.pc());
if (operand.type == kWasmVar) {
operand.sig = module->signatures[operand.sig_index];
}
@ -827,7 +827,7 @@ class SideTable : public ZoneObject {
break;
}
case kExprIf: {
BlockTypeOperand<false> operand(&i, i.pc());
BlockTypeOperand<Decoder::kNoValidate> operand(&i, i.pc());
if (operand.type == kWasmVar) {
operand.sig = module->signatures[operand.sig_index];
}
@ -875,22 +875,22 @@ class SideTable : public ZoneObject {
break;
}
case kExprBr: {
BreakDepthOperand<false> operand(&i, i.pc());
BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
TRACE("control @%u: Br[depth=%u]\n", i.pc_offset(), operand.depth);
Control* c = &control_stack[control_stack.size() - operand.depth - 1];
if (!unreachable) c->end_label->Ref(i.pc(), stack_height);
break;
}
case kExprBrIf: {
BreakDepthOperand<false> operand(&i, i.pc());
BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
TRACE("control @%u: BrIf[depth=%u]\n", i.pc_offset(), operand.depth);
Control* c = &control_stack[control_stack.size() - operand.depth - 1];
if (!unreachable) c->end_label->Ref(i.pc(), stack_height);
break;
}
case kExprBrTable: {
BranchTableOperand<false> operand(&i, i.pc());
BranchTableIterator<false> iterator(&i, operand);
BranchTableOperand<Decoder::kNoValidate> operand(&i, i.pc());
BranchTableIterator<Decoder::kNoValidate> iterator(&i, operand);
TRACE("control @%u: BrTable[count=%u]\n", i.pc_offset(),
operand.table_count);
if (!unreachable) {
@ -1366,11 +1366,13 @@ class ThreadImpl {
pc_t ReturnPc(Decoder* decoder, InterpreterCode* code, pc_t pc) {
switch (code->orig_start[pc]) {
case kExprCallFunction: {
CallFunctionOperand<false> operand(decoder, code->at(pc));
CallFunctionOperand<Decoder::kNoValidate> operand(decoder,
code->at(pc));
return pc + 1 + operand.length;
}
case kExprCallIndirect: {
CallIndirectOperand<false> operand(decoder, code->at(pc));
CallIndirectOperand<Decoder::kNoValidate> operand(decoder,
code->at(pc));
return pc + 1 + operand.length;
}
default:
@ -1439,7 +1441,8 @@ class ThreadImpl {
template <typename ctype, typename mtype>
bool ExecuteLoad(Decoder* decoder, InterpreterCode* code, pc_t pc, int& len,
MachineRepresentation rep) {
MemoryAccessOperand<false> operand(decoder, code->at(pc), sizeof(ctype));
MemoryAccessOperand<Decoder::kNoValidate> operand(decoder, code->at(pc),
sizeof(ctype));
uint32_t index = Pop().to<uint32_t>();
if (!BoundsCheck<mtype>(wasm_context_->mem_size, operand.offset, index)) {
DoTrap(kTrapMemOutOfBounds, pc);
@ -1464,7 +1467,8 @@ class ThreadImpl {
template <typename ctype, typename mtype>
bool ExecuteStore(Decoder* decoder, InterpreterCode* code, pc_t pc, int& len,
MachineRepresentation rep) {
MemoryAccessOperand<false> operand(decoder, code->at(pc), sizeof(ctype));
MemoryAccessOperand<Decoder::kNoValidate> operand(decoder, code->at(pc),
sizeof(ctype));
WasmValue val = Pop();
uint32_t index = Pop().to<uint32_t>();
@ -1584,17 +1588,20 @@ class ThreadImpl {
case kExprNop:
break;
case kExprBlock: {
BlockTypeOperand<false> operand(&decoder, code->at(pc));
BlockTypeOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
len = 1 + operand.length;
break;
}
case kExprLoop: {
BlockTypeOperand<false> operand(&decoder, code->at(pc));
BlockTypeOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
len = 1 + operand.length;
break;
}
case kExprIf: {
BlockTypeOperand<false> operand(&decoder, code->at(pc));
BlockTypeOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
WasmValue cond = Pop();
bool is_true = cond.to<uint32_t>() != 0;
if (is_true) {
@ -1620,13 +1627,15 @@ class ThreadImpl {
break;
}
case kExprBr: {
BreakDepthOperand<false> operand(&decoder, code->at(pc));
BreakDepthOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
len = DoBreak(code, pc, operand.depth);
TRACE(" br => @%zu\n", pc + len);
break;
}
case kExprBrIf: {
BreakDepthOperand<false> operand(&decoder, code->at(pc));
BreakDepthOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
WasmValue cond = Pop();
bool is_true = cond.to<uint32_t>() != 0;
if (is_true) {
@ -1639,8 +1648,9 @@ class ThreadImpl {
break;
}
case kExprBrTable: {
BranchTableOperand<false> operand(&decoder, code->at(pc));
BranchTableIterator<false> iterator(&decoder, operand);
BranchTableOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
BranchTableIterator<Decoder::kNoValidate> iterator(&decoder, operand);
uint32_t key = Pop().to<uint32_t>();
uint32_t depth = 0;
if (key >= operand.table_count) key = operand.table_count;
@ -1665,44 +1675,47 @@ class ThreadImpl {
break;
}
case kExprI32Const: {
ImmI32Operand<false> operand(&decoder, code->at(pc));
ImmI32Operand<Decoder::kNoValidate> operand(&decoder, code->at(pc));
Push(WasmValue(operand.value));
len = 1 + operand.length;
break;
}
case kExprI64Const: {
ImmI64Operand<false> operand(&decoder, code->at(pc));
ImmI64Operand<Decoder::kNoValidate> operand(&decoder, code->at(pc));
Push(WasmValue(operand.value));
len = 1 + operand.length;
break;
}
case kExprF32Const: {
ImmF32Operand<false> operand(&decoder, code->at(pc));
ImmF32Operand<Decoder::kNoValidate> operand(&decoder, code->at(pc));
Push(WasmValue(operand.value));
len = 1 + operand.length;
break;
}
case kExprF64Const: {
ImmF64Operand<false> operand(&decoder, code->at(pc));
ImmF64Operand<Decoder::kNoValidate> operand(&decoder, code->at(pc));
Push(WasmValue(operand.value));
len = 1 + operand.length;
break;
}
case kExprGetLocal: {
LocalIndexOperand<false> operand(&decoder, code->at(pc));
LocalIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
Push(GetStackValue(frames_.back().sp + operand.index));
len = 1 + operand.length;
break;
}
case kExprSetLocal: {
LocalIndexOperand<false> operand(&decoder, code->at(pc));
LocalIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
WasmValue val = Pop();
SetStackValue(frames_.back().sp + operand.index, val);
len = 1 + operand.length;
break;
}
case kExprTeeLocal: {
LocalIndexOperand<false> operand(&decoder, code->at(pc));
LocalIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
WasmValue val = Pop();
SetStackValue(frames_.back().sp + operand.index, val);
Push(val);
@ -1714,7 +1727,8 @@ class ThreadImpl {
break;
}
case kExprCallFunction: {
CallFunctionOperand<false> operand(&decoder, code->at(pc));
CallFunctionOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
InterpreterCode* target = codemap()->GetCode(operand.index);
if (target->function->imported) {
CommitPc(pc);
@ -1746,7 +1760,8 @@ class ThreadImpl {
continue; // don't bump pc
} break;
case kExprCallIndirect: {
CallIndirectOperand<false> operand(&decoder, code->at(pc));
CallIndirectOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
uint32_t entry_index = Pop().to<uint32_t>();
// Assume only one table for now.
DCHECK_LE(module()->function_tables.size(), 1u);
@ -1773,7 +1788,8 @@ class ThreadImpl {
}
} break;
case kExprGetGlobal: {
GlobalIndexOperand<false> operand(&decoder, code->at(pc));
GlobalIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
const WasmGlobal* global = &module()->globals[operand.index];
byte* ptr = wasm_context_->globals_start + global->offset;
WasmValue val;
@ -1792,7 +1808,8 @@ class ThreadImpl {
break;
}
case kExprSetGlobal: {
GlobalIndexOperand<false> operand(&decoder, code->at(pc));
GlobalIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
const WasmGlobal* global = &module()->globals[operand.index];
byte* ptr = wasm_context_->globals_start + global->offset;
WasmValue val = Pop();
@ -1898,7 +1915,8 @@ class ThreadImpl {
ASMJS_STORE_CASE(F64AsmjsStoreMem, double, double);
#undef ASMJS_STORE_CASE
case kExprGrowMemory: {
MemoryIndexOperand<false> operand(&decoder, code->at(pc));
MemoryIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
uint32_t delta_pages = Pop().to<uint32_t>();
Handle<WasmInstanceObject> instance =
codemap()->maybe_instance().ToHandleChecked();
@ -1911,7 +1929,8 @@ class ThreadImpl {
break;
}
case kExprMemorySize: {
MemoryIndexOperand<false> operand(&decoder, code->at(pc));
MemoryIndexOperand<Decoder::kNoValidate> operand(&decoder,
code->at(pc));
Push(WasmValue(static_cast<uint32_t>(wasm_context_->mem_size /
WasmModule::kPageSize)));
len = 1 + operand.length;

View File

@ -101,7 +101,7 @@ void PrintWasmText(const WasmModule* module, const ModuleWireBytes& wire_bytes,
case kExprIf:
case kExprBlock:
case kExprTry: {
BlockTypeOperand<false> operand(&i, i.pc());
BlockTypeOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode);
if (operand.type == kWasmVar) {
os << " (type " << operand.sig_index << ")";
@ -113,7 +113,7 @@ void PrintWasmText(const WasmModule* module, const ModuleWireBytes& wire_bytes,
}
case kExprBr:
case kExprBrIf: {
BreakDepthOperand<false> operand(&i, i.pc());
BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << operand.depth;
break;
}
@ -125,45 +125,45 @@ void PrintWasmText(const WasmModule* module, const ModuleWireBytes& wire_bytes,
os << "end";
break;
case kExprBrTable: {
BranchTableOperand<false> operand(&i, i.pc());
BranchTableIterator<false> iterator(&i, operand);
BranchTableOperand<Decoder::kNoValidate> operand(&i, i.pc());
BranchTableIterator<Decoder::kNoValidate> iterator(&i, operand);
os << "br_table";
while (iterator.has_next()) os << ' ' << iterator.next();
break;
}
case kExprCallIndirect: {
CallIndirectOperand<false> operand(&i, i.pc());
CallIndirectOperand<Decoder::kNoValidate> operand(&i, i.pc());
DCHECK_EQ(0, operand.table_index);
os << "call_indirect " << operand.index;
break;
}
case kExprCallFunction: {
CallFunctionOperand<false> operand(&i, i.pc());
CallFunctionOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << "call " << operand.index;
break;
}
case kExprGetLocal:
case kExprSetLocal:
case kExprTeeLocal: {
LocalIndexOperand<false> operand(&i, i.pc());
LocalIndexOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << operand.index;
break;
}
case kExprThrow:
case kExprCatch: {
ExceptionIndexOperand<false> operand(&i, i.pc());
ExceptionIndexOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << operand.index;
break;
}
case kExprGetGlobal:
case kExprSetGlobal: {
GlobalIndexOperand<false> operand(&i, i.pc());
GlobalIndexOperand<Decoder::kNoValidate> operand(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << operand.index;
break;
}
#define CASE_CONST(type, str, cast_type) \
case kExpr##type##Const: { \
Imm##type##Operand<false> operand(&i, i.pc()); \
Imm##type##Operand<Decoder::kNoValidate> operand(&i, i.pc()); \
os << #str ".const " << static_cast<cast_type>(operand.value); \
break; \
}
@ -176,7 +176,8 @@ void PrintWasmText(const WasmModule* module, const ModuleWireBytes& wire_bytes,
#define CASE_OPCODE(opcode, _, __) case kExpr##opcode:
FOREACH_LOAD_MEM_OPCODE(CASE_OPCODE)
FOREACH_STORE_MEM_OPCODE(CASE_OPCODE) {
MemoryAccessOperand<false> operand(&i, i.pc(), kMaxUInt32);
MemoryAccessOperand<Decoder::kNoValidate> operand(&i, i.pc(),
kMaxUInt32);
os << WasmOpcodes::OpcodeName(opcode) << " offset=" << operand.offset
<< " align=" << (1ULL << operand.alignment);
break;
@ -196,7 +197,8 @@ void PrintWasmText(const WasmModule* module, const ModuleWireBytes& wire_bytes,
WasmOpcode atomic_opcode = i.prefixed_opcode();
switch (atomic_opcode) {
FOREACH_ATOMIC_OPCODE(CASE_OPCODE) {
MemoryAccessOperand<false> operand(&i, i.pc(), kMaxUInt32);
MemoryAccessOperand<Decoder::kNoValidate> operand(&i, i.pc(),
kMaxUInt32);
os << WasmOpcodes::OpcodeName(atomic_opcode)
<< " offset=" << operand.offset
<< " align=" << (1ULL << operand.alignment);

View File

@ -19,50 +19,54 @@ class DecoderTest : public TestWithZone {
Decoder decoder;
};
#define CHECK_UINT32V_INLINE(expected, expected_length, ...) \
do { \
const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \
unsigned length; \
EXPECT_EQ(static_cast<uint32_t>(expected), \
decoder.read_u32v<true>(decoder.start(), &length)); \
EXPECT_EQ(static_cast<unsigned>(expected_length), length); \
EXPECT_EQ(data, decoder.pc()); \
EXPECT_TRUE(decoder.ok()); \
EXPECT_EQ(static_cast<uint32_t>(expected), decoder.consume_u32v()); \
EXPECT_EQ(data + expected_length, decoder.pc()); \
#define CHECK_UINT32V_INLINE(expected, expected_length, ...) \
do { \
const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \
unsigned length; \
EXPECT_EQ( \
static_cast<uint32_t>(expected), \
decoder.read_u32v<Decoder::kValidate>(decoder.start(), &length)); \
EXPECT_EQ(static_cast<unsigned>(expected_length), length); \
EXPECT_EQ(data, decoder.pc()); \
EXPECT_TRUE(decoder.ok()); \
EXPECT_EQ(static_cast<uint32_t>(expected), decoder.consume_u32v()); \
EXPECT_EQ(data + expected_length, decoder.pc()); \
} while (false)
#define CHECK_INT32V_INLINE(expected, expected_length, ...) \
do { \
const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \
unsigned length; \
EXPECT_EQ(expected, decoder.read_i32v<true>(decoder.start(), &length)); \
EXPECT_EQ(static_cast<unsigned>(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()); \
#define CHECK_INT32V_INLINE(expected, expected_length, ...) \
do { \
const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \
unsigned length; \
EXPECT_EQ(expected, decoder.read_i32v<Decoder::kValidate>(decoder.start(), \
&length)); \
EXPECT_EQ(static_cast<unsigned>(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, ...) \
do { \
const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \
unsigned length; \
EXPECT_EQ(static_cast<uint64_t>(expected), \
decoder.read_u64v<false>(decoder.start(), &length)); \
EXPECT_EQ(static_cast<unsigned>(expected_length), length); \
#define CHECK_UINT64V_INLINE(expected, expected_length, ...) \
do { \
const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \
unsigned length; \
EXPECT_EQ( \
static_cast<uint64_t>(expected), \
decoder.read_u64v<Decoder::kValidate>(decoder.start(), &length)); \
EXPECT_EQ(static_cast<unsigned>(expected_length), length); \
} while (false)
#define CHECK_INT64V_INLINE(expected, expected_length, ...) \
do { \
const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \
unsigned length; \
EXPECT_EQ(expected, decoder.read_i64v<false>(decoder.start(), &length)); \
EXPECT_EQ(static_cast<unsigned>(expected_length), length); \
#define CHECK_INT64V_INLINE(expected, expected_length, ...) \
do { \
const byte data[] = {__VA_ARGS__}; \
decoder.Reset(data, data + sizeof(data)); \
unsigned length; \
EXPECT_EQ(expected, decoder.read_i64v<Decoder::kValidate>(decoder.start(), \
&length)); \
EXPECT_EQ(static_cast<unsigned>(expected_length), length); \
} while (false)
TEST_F(DecoderTest, ReadU32v_OneByte) {
@ -374,7 +378,7 @@ TEST_F(DecoderTest, ReadU32v_off_end1) {
static const byte data[] = {U32V_1(11)};
unsigned length = 0;
decoder.Reset(data, data);
decoder.read_u32v<true>(decoder.start(), &length);
decoder.read_u32v<Decoder::kValidate>(decoder.start(), &length);
EXPECT_EQ(0u, length);
EXPECT_FALSE(decoder.ok());
}
@ -384,7 +388,7 @@ TEST_F(DecoderTest, ReadU32v_off_end2) {
for (size_t i = 0; i < sizeof(data); i++) {
unsigned length = 0;
decoder.Reset(data, data + i);
decoder.read_u32v<true>(decoder.start(), &length);
decoder.read_u32v<Decoder::kValidate>(decoder.start(), &length);
EXPECT_EQ(i, length);
EXPECT_FALSE(decoder.ok());
}
@ -395,7 +399,7 @@ TEST_F(DecoderTest, ReadU32v_off_end3) {
for (size_t i = 0; i < sizeof(data); i++) {
unsigned length = 0;
decoder.Reset(data, data + i);
decoder.read_u32v<true>(decoder.start(), &length);
decoder.read_u32v<Decoder::kValidate>(decoder.start(), &length);
EXPECT_EQ(i, length);
EXPECT_FALSE(decoder.ok());
}
@ -406,7 +410,7 @@ TEST_F(DecoderTest, ReadU32v_off_end4) {
for (size_t i = 0; i < sizeof(data); i++) {
unsigned length = 0;
decoder.Reset(data, data + i);
decoder.read_u32v<true>(decoder.start(), &length);
decoder.read_u32v<Decoder::kValidate>(decoder.start(), &length);
EXPECT_EQ(i, length);
EXPECT_FALSE(decoder.ok());
}
@ -417,7 +421,7 @@ TEST_F(DecoderTest, ReadU32v_off_end5) {
for (size_t i = 0; i < sizeof(data); i++) {
unsigned length = 0;
decoder.Reset(data, data + i);
decoder.read_u32v<true>(decoder.start(), &length);
decoder.read_u32v<Decoder::kValidate>(decoder.start(), &length);
EXPECT_EQ(i, length);
EXPECT_FALSE(decoder.ok());
}
@ -429,7 +433,7 @@ TEST_F(DecoderTest, ReadU32v_extra_bits) {
data[4] = static_cast<byte>(i << 4);
unsigned length = 0;
decoder.Reset(data, data + sizeof(data));
decoder.read_u32v<true>(decoder.start(), &length);
decoder.read_u32v<Decoder::kValidate>(decoder.start(), &length);
EXPECT_EQ(5u, length);
EXPECT_FALSE(decoder.ok());
}
@ -440,7 +444,7 @@ TEST_F(DecoderTest, ReadI32v_extra_bits_negative) {
unsigned length = 0;
byte data[] = {0xff, 0xff, 0xff, 0xff, 0x7f};
decoder.Reset(data, data + sizeof(data));
decoder.read_i32v<true>(decoder.start(), &length);
decoder.read_i32v<Decoder::kValidate>(decoder.start(), &length);
EXPECT_EQ(5u, length);
EXPECT_TRUE(decoder.ok());
}
@ -450,7 +454,7 @@ TEST_F(DecoderTest, ReadI32v_extra_bits_positive) {
unsigned length = 0;
byte data[] = {0x80, 0x80, 0x80, 0x80, 0x77};
decoder.Reset(data, data + sizeof(data));
decoder.read_i32v<true>(decoder.start(), &length);
decoder.read_i32v<Decoder::kValidate>(decoder.start(), &length);
EXPECT_EQ(5u, length);
EXPECT_FALSE(decoder.ok());
}
@ -485,7 +489,7 @@ TEST_F(DecoderTest, ReadU32v_Bits) {
for (unsigned limit = 0; limit <= kMaxSize; limit++) {
decoder.Reset(data, data + limit);
unsigned rlen;
uint32_t result = decoder.read_u32v<true>(data, &rlen);
uint32_t result = decoder.read_u32v<Decoder::kValidate>(data, &rlen);
if (limit < length) {
EXPECT_FALSE(decoder.ok());
} else {
@ -541,7 +545,7 @@ TEST_F(DecoderTest, ReadU64v_PowerOf2) {
for (unsigned limit = 0; limit <= kMaxSize; limit++) {
decoder.Reset(data, data + limit);
unsigned length;
uint64_t result = decoder.read_u64v<true>(data, &length);
uint64_t result = decoder.read_u64v<Decoder::kValidate>(data, &length);
if (limit <= index) {
EXPECT_FALSE(decoder.ok());
} else {
@ -582,7 +586,7 @@ TEST_F(DecoderTest, ReadU64v_Bits) {
for (unsigned limit = 0; limit <= kMaxSize; limit++) {
decoder.Reset(data, data + limit);
unsigned rlen;
uint64_t result = decoder.read_u64v<true>(data, &rlen);
uint64_t result = decoder.read_u64v<Decoder::kValidate>(data, &rlen);
if (limit < length) {
EXPECT_FALSE(decoder.ok());
} else {
@ -624,7 +628,7 @@ TEST_F(DecoderTest, ReadI64v_Bits) {
for (unsigned limit = 0; limit <= kMaxSize; limit++) {
decoder.Reset(data, data + limit);
unsigned rlen;
int64_t result = decoder.read_i64v<true>(data, &rlen);
int64_t result = decoder.read_i64v<Decoder::kValidate>(data, &rlen);
if (limit < length) {
EXPECT_FALSE(decoder.ok());
} else {
@ -643,7 +647,7 @@ TEST_F(DecoderTest, ReadU64v_extra_bits) {
data[9] = static_cast<byte>(i << 1);
unsigned length = 0;
decoder.Reset(data, data + sizeof(data));
decoder.read_u64v<true>(decoder.start(), &length);
decoder.read_u64v<Decoder::kValidate>(decoder.start(), &length);
EXPECT_EQ(10u, length);
EXPECT_FALSE(decoder.ok());
}
@ -654,7 +658,7 @@ TEST_F(DecoderTest, ReadI64v_extra_bits_negative) {
unsigned length = 0;
byte data[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f};
decoder.Reset(data, data + sizeof(data));
decoder.read_i64v<true>(decoder.start(), &length);
decoder.read_i64v<Decoder::kValidate>(decoder.start(), &length);
EXPECT_EQ(10u, length);
EXPECT_TRUE(decoder.ok());
}
@ -664,7 +668,7 @@ TEST_F(DecoderTest, ReadI64v_extra_bits_positive) {
unsigned length = 0;
byte data[] = {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x77};
decoder.Reset(data, data + sizeof(data));
decoder.read_i64v<true>(decoder.start(), &length);
decoder.read_i64v<Decoder::kValidate>(decoder.start(), &length);
EXPECT_EQ(10u, length);
EXPECT_FALSE(decoder.ok());
}

View File

@ -2533,15 +2533,15 @@ class BranchTableIteratorTest : public TestWithZone {
BranchTableIteratorTest() : TestWithZone() {}
void CheckBrTableSize(const byte* start, const byte* end) {
Decoder decoder(start, end);
BranchTableOperand<true> operand(&decoder, start);
BranchTableIterator<true> iterator(&decoder, operand);
BranchTableOperand<Decoder::kValidate> operand(&decoder, start);
BranchTableIterator<Decoder::kValidate> iterator(&decoder, operand);
EXPECT_EQ(end - start - 1u, iterator.length());
EXPECT_TRUE(decoder.ok());
}
void CheckBrTableError(const byte* start, const byte* end) {
Decoder decoder(start, end);
BranchTableOperand<true> operand(&decoder, start);
BranchTableIterator<true> iterator(&decoder, operand);
BranchTableOperand<Decoder::kValidate> operand(&decoder, start);
BranchTableIterator<Decoder::kValidate> iterator(&decoder, operand);
iterator.length();
EXPECT_FALSE(decoder.ok());
}

View File

@ -88,19 +88,19 @@ TEST_F(LEBHelperTest, sizeof_i32v) {
}
}
#define DECLARE_ENCODE_DECODE_CHECKER(ctype, name) \
static void CheckEncodeDecode_##name(ctype val) { \
static const int kSize = 16; \
static byte buffer[kSize]; \
byte* ptr = buffer; \
LEBHelper::write_##name(&ptr, val); \
EXPECT_EQ(LEBHelper::sizeof_##name(val), \
static_cast<size_t>(ptr - buffer)); \
Decoder decoder(buffer, buffer + kSize); \
unsigned length = 0; \
ctype result = decoder.read_##name<false>(buffer, &length); \
EXPECT_EQ(val, result); \
EXPECT_EQ(LEBHelper::sizeof_##name(val), static_cast<size_t>(length)); \
#define DECLARE_ENCODE_DECODE_CHECKER(ctype, name) \
static void CheckEncodeDecode_##name(ctype val) { \
static const int kSize = 16; \
static byte buffer[kSize]; \
byte* ptr = buffer; \
LEBHelper::write_##name(&ptr, val); \
EXPECT_EQ(LEBHelper::sizeof_##name(val), \
static_cast<size_t>(ptr - buffer)); \
Decoder decoder(buffer, buffer + kSize); \
unsigned length = 0; \
ctype result = decoder.read_##name<Decoder::kNoValidate>(buffer, &length); \
EXPECT_EQ(val, result); \
EXPECT_EQ(LEBHelper::sizeof_##name(val), static_cast<size_t>(length)); \
}
DECLARE_ENCODE_DECODE_CHECKER(int32_t, i32v)