[wasm] Remove non-const reference args from fuzzers

R=ahaas@chromium.org

Bug: v8:9429, v8:9396
Change-Id: Ie6119ff58fdf48612d81fe0616986a4da95135d2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1690836
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#62569}
This commit is contained in:
Clemens Hammacher 2019-07-08 13:44:42 +02:00 committed by Commit Bot
parent edd383fbcd
commit 4c9d52e1c8
5 changed files with 109 additions and 128 deletions

View File

@ -85,33 +85,31 @@ MachineType RandomType(InputProvider* input) {
int index(MachineType type) { return static_cast<int>(type.representation()); }
Node* Constant(RawMachineAssembler& m, // NOLINT(runtime/references)
MachineType type, int value) {
Node* Constant(RawMachineAssembler* m, MachineType type, int value) {
switch (type.representation()) {
case MachineRepresentation::kWord32:
return m.Int32Constant(static_cast<int32_t>(value));
return m->Int32Constant(static_cast<int32_t>(value));
case MachineRepresentation::kWord64:
return m.Int64Constant(static_cast<int64_t>(value));
return m->Int64Constant(static_cast<int64_t>(value));
case MachineRepresentation::kFloat32:
return m.Float32Constant(static_cast<float>(value));
return m->Float32Constant(static_cast<float>(value));
case MachineRepresentation::kFloat64:
return m.Float64Constant(static_cast<double>(value));
return m->Float64Constant(static_cast<double>(value));
default:
UNREACHABLE();
}
}
Node* ToInt32(RawMachineAssembler& m, // NOLINT(runtime/references)
MachineType type, Node* a) {
Node* ToInt32(RawMachineAssembler* m, MachineType type, Node* a) {
switch (type.representation()) {
case MachineRepresentation::kWord32:
return a;
case MachineRepresentation::kWord64:
return m.TruncateInt64ToInt32(a);
return m->TruncateInt64ToInt32(a);
case MachineRepresentation::kFloat32:
return m.TruncateFloat32ToInt32(a);
return m->TruncateFloat32ToInt32(a);
case MachineRepresentation::kFloat64:
return m.RoundFloat64ToInt32(a);
return m->RoundFloat64ToInt32(a);
default:
UNREACHABLE();
}
@ -224,7 +222,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
MachineType type = desc->GetReturnType(i);
// Find a random same-type parameter to return. Use a constant if none.
if (counts[index(type)] == 0) {
returns[i] = Constant(callee, type, 42);
returns[i] = Constant(&callee, type, 42);
outputs[i] = 42;
} else {
int n = input.NextInt32(counts[index(type)]);
@ -266,18 +264,18 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// WasmContext dummy.
params[1] = caller.PointerConstant(nullptr);
for (size_t i = 0; i < param_count; ++i) {
params[i + 2] = Constant(caller, desc->GetParameterType(i + 1), inputs[i]);
params[i + 2] = Constant(&caller, desc->GetParameterType(i + 1), inputs[i]);
}
Node* call = caller.AddNode(caller.common()->Call(desc),
static_cast<int>(param_count + 2), params.get());
Node* ret = Constant(caller, MachineType::Int32(), 0);
Node* ret = Constant(&caller, MachineType::Int32(), 0);
for (size_t i = 0; i < desc->ReturnCount(); ++i) {
// Skip roughly one third of the outputs.
if (input.NextInt8(3) == 0) continue;
Node* ret_i = (desc->ReturnCount() == 1)
? call
: caller.AddNode(caller.common()->Projection(i), call);
ret = caller.Int32Add(ret, ToInt32(caller, desc->GetReturnType(i), ret_i));
ret = caller.Int32Add(ret, ToInt32(&caller, desc->GetReturnType(i), ret_i));
expect += outputs[i];
}
caller.Return(ret);

View File

@ -21,9 +21,9 @@ namespace fuzzer {
class WasmCodeFuzzer : public WasmExecutionFuzzer {
bool GenerateModule(
Isolate* isolate, Zone* zone, Vector<const uint8_t> data,
ZoneBuffer& buffer, int32_t& num_args,
std::unique_ptr<WasmValue[]>& interpreter_args,
std::unique_ptr<Handle<Object>[]>& compiler_args) override {
ZoneBuffer* buffer, int32_t* num_args,
std::unique_ptr<WasmValue[]>* interpreter_args,
std::unique_ptr<Handle<Object>[]>* compiler_args) override {
TestSignatures sigs;
WasmModuleBuilder builder(zone);
WasmFunctionBuilder* f = builder.AddFunction(sigs.i_iii());
@ -33,14 +33,15 @@ class WasmCodeFuzzer : public WasmExecutionFuzzer {
builder.AddExport(CStrVector("main"), f);
builder.SetMaxMemorySize(32);
builder.WriteTo(&buffer);
num_args = 3;
interpreter_args.reset(
builder.WriteTo(buffer);
*num_args = 3;
interpreter_args->reset(
new WasmValue[3]{WasmValue(1), WasmValue(2), WasmValue(3)});
compiler_args.reset(new Handle<Object>[3]{
handle(Smi::FromInt(1), isolate), handle(Smi::FromInt(2), isolate),
handle(Smi::FromInt(3), isolate)});
compiler_args->reset(new Handle<Object>[3] {
handle(Smi::FromInt(1), isolate), handle(Smi::FromInt(2), isolate),
handle(Smi::FromInt(3), isolate)
});
return true;
}
};

View File

@ -78,8 +78,8 @@ class DataRange {
DISALLOW_COPY_AND_ASSIGN(DataRange);
};
ValueType GetValueType(DataRange& data) { // NOLINT(runtime/references)
switch (data.get<uint8_t>() % 4) {
ValueType GetValueType(DataRange* data) {
switch (data->get<uint8_t>() % 4) {
case 0:
return kWasmI32;
case 1:
@ -94,7 +94,7 @@ ValueType GetValueType(DataRange& data) { // NOLINT(runtime/references)
class WasmGenerator {
template <WasmOpcode Op, ValueType... Args>
void op(DataRange& data) { // NOLINT(runtime/references)
void op(DataRange* data) {
Generate<Args...>(data);
builder_->Emit(Op);
}
@ -119,13 +119,13 @@ class WasmGenerator {
};
template <ValueType T>
void block(DataRange& data) { // NOLINT(runtime/references)
void block(DataRange* data) {
BlockScope block_scope(this, kExprBlock, T, T);
Generate<T>(data);
}
template <ValueType T>
void loop(DataRange& data) { // NOLINT(runtime/references)
void loop(DataRange* data) {
// When breaking to a loop header, don't provide any input value (hence
// kWasmStmt).
BlockScope block_scope(this, kExprLoop, T, kWasmStmt);
@ -135,7 +135,7 @@ class WasmGenerator {
enum IfType { kIf, kIfElse };
template <ValueType T, IfType type>
void if_(DataRange& data) { // NOLINT(runtime/references)
void if_(DataRange* data) {
static_assert(T == kWasmStmt || type == kIfElse,
"if without else cannot produce a value");
Generate<kWasmI32>(data);
@ -147,10 +147,10 @@ class WasmGenerator {
}
}
void br(DataRange& data) { // NOLINT(runtime/references)
void br(DataRange* data) {
// There is always at least the block representing the function body.
DCHECK(!blocks_.empty());
const uint32_t target_block = data.get<uint32_t>() % blocks_.size();
const uint32_t target_block = data->get<uint32_t>() % blocks_.size();
const ValueType break_type = blocks_[target_block];
Generate(break_type, data);
@ -159,10 +159,10 @@ class WasmGenerator {
}
template <ValueType wanted_type>
void br_if(DataRange& data) { // NOLINT(runtime/references)
void br_if(DataRange* data) {
// There is always at least the block representing the function body.
DCHECK(!blocks_.empty());
const uint32_t target_block = data.get<uint32_t>() % blocks_.size();
const uint32_t target_block = data->get<uint32_t>() % blocks_.size();
const ValueType break_type = blocks_[target_block];
Generate(break_type, data);
@ -208,9 +208,9 @@ class WasmGenerator {
}
template <WasmOpcode memory_op, ValueType... arg_types>
void memop(DataRange& data) { // NOLINT(runtime/references)
const uint8_t align = data.get<uint8_t>() % (max_alignment(memory_op) + 1);
const uint32_t offset = data.get<uint32_t>();
void memop(DataRange* data) {
const uint8_t align = data->get<uint8_t>() % (max_alignment(memory_op) + 1);
const uint32_t offset = data->get<uint32_t>();
// Generate the index and the arguments, if any.
Generate<kWasmI32, arg_types...>(data);
@ -220,13 +220,13 @@ class WasmGenerator {
builder_->EmitU32V(offset);
}
void drop(DataRange& data) { // NOLINT(runtime/references)
void drop(DataRange* data) {
Generate(GetValueType(data), data);
builder_->Emit(kExprDrop);
}
template <ValueType wanted_type>
void call(DataRange& data) { // NOLINT(runtime/references)
void call(DataRange* data) {
call(data, wanted_type);
}
@ -258,8 +258,7 @@ class WasmGenerator {
builder_->Emit(kConvertOpcodes[arr_idx]);
}
void ConvertOrGenerate(ValueType src, ValueType dst,
DataRange& data) { // NOLINT(runtime/references)
void ConvertOrGenerate(ValueType src, ValueType dst, DataRange* data) {
if (src == dst) return;
if (src == kWasmStmt && dst != kWasmStmt) {
Generate(dst, data);
@ -270,9 +269,8 @@ class WasmGenerator {
}
}
void call(DataRange& data, // NOLINT(runtime/references)
ValueType wanted_type) {
int func_index = data.get<uint8_t>() % functions_.size();
void call(DataRange* data, ValueType wanted_type) {
int func_index = data->get<uint8_t>() % functions_.size();
FunctionSig* sig = functions_[func_index];
// Generate arguments.
for (size_t i = 0; i < sig->parameter_count(); ++i) {
@ -303,20 +301,19 @@ class WasmGenerator {
bool is_valid() const { return type != kWasmStmt; }
};
Var GetRandomLocal(DataRange& data) { // NOLINT(runtime/references)
Var GetRandomLocal(DataRange* data) {
uint32_t num_params =
static_cast<uint32_t>(builder_->signature()->parameter_count());
uint32_t num_locals = static_cast<uint32_t>(locals_.size());
if (num_params + num_locals == 0) return {};
uint32_t index = data.get<uint8_t>() % (num_params + num_locals);
uint32_t index = data->get<uint8_t>() % (num_params + num_locals);
ValueType type = index < num_params ? builder_->signature()->GetParam(index)
: locals_[index - num_params];
return {index, type};
}
template <ValueType wanted_type>
void local_op(DataRange& data, // NOLINT(runtime/references)
WasmOpcode opcode) {
void local_op(DataRange* data, WasmOpcode opcode) {
Var local = GetRandomLocal(data);
// If there are no locals and no parameters, just generate any value (if a
// value is needed), or do nothing.
@ -333,46 +330,43 @@ class WasmGenerator {
}
template <ValueType wanted_type>
void get_local(DataRange& data) { // NOLINT(runtime/references)
void get_local(DataRange* data) {
static_assert(wanted_type != kWasmStmt, "illegal type");
local_op<wanted_type>(data, kExprGetLocal);
}
void set_local(DataRange& data) { // NOLINT(runtime/references)
local_op<kWasmStmt>(data, kExprSetLocal);
}
void set_local(DataRange* data) { local_op<kWasmStmt>(data, kExprSetLocal); }
template <ValueType wanted_type>
void tee_local(DataRange& data) { // NOLINT(runtime/references)
void tee_local(DataRange* data) {
local_op<wanted_type>(data, kExprTeeLocal);
}
template <size_t num_bytes>
void i32_const(DataRange& data) { // NOLINT(runtime/references)
builder_->EmitI32Const(data.get<int32_t, num_bytes>());
void i32_const(DataRange* data) {
builder_->EmitI32Const(data->get<int32_t, num_bytes>());
}
template <size_t num_bytes>
void i64_const(DataRange& data) { // NOLINT(runtime/references)
builder_->EmitI64Const(data.get<int64_t, num_bytes>());
void i64_const(DataRange* data) {
builder_->EmitI64Const(data->get<int64_t, num_bytes>());
}
Var GetRandomGlobal(DataRange& data, // NOLINT(runtime/references)
bool ensure_mutable) {
Var GetRandomGlobal(DataRange* data, bool ensure_mutable) {
uint32_t index;
if (ensure_mutable) {
if (mutable_globals_.empty()) return {};
index = mutable_globals_[data.get<uint8_t>() % mutable_globals_.size()];
index = mutable_globals_[data->get<uint8_t>() % mutable_globals_.size()];
} else {
if (globals_.empty()) return {};
index = data.get<uint8_t>() % globals_.size();
index = data->get<uint8_t>() % globals_.size();
}
ValueType type = globals_[index];
return {index, type};
}
template <ValueType wanted_type>
void global_op(DataRange& data) { // NOLINT(runtime/references)
void global_op(DataRange* data) {
constexpr bool is_set = wanted_type == kWasmStmt;
Var global = GetRandomGlobal(data, is_set);
// If there are no globals, just generate any value (if a value is needed),
@ -391,13 +385,13 @@ class WasmGenerator {
}
template <ValueType wanted_type>
void get_global(DataRange& data) { // NOLINT(runtime/references)
void get_global(DataRange* data) {
static_assert(wanted_type != kWasmStmt, "illegal type");
global_op<wanted_type>(data);
}
template <ValueType select_type>
void select_with_type(DataRange& data) { // NOLINT(runtime/references)
void select_with_type(DataRange* data) {
static_assert(select_type != kWasmStmt, "illegal type for select");
Generate<select_type, select_type, kWasmI32>(data);
// num_types is always 1.
@ -406,29 +400,26 @@ class WasmGenerator {
ValueTypes::ValueTypeCodeFor(select_type));
}
void set_global(DataRange& data) { // NOLINT(runtime/references)
global_op<kWasmStmt>(data);
}
void set_global(DataRange* data) { global_op<kWasmStmt>(data); }
template <ValueType... Types>
void sequence(DataRange& data) { // NOLINT(runtime/references)
void sequence(DataRange* data) {
Generate<Types...>(data);
}
void current_memory(DataRange& data) { // NOLINT(runtime/references)
void current_memory(DataRange* data) {
builder_->EmitWithU8(kExprMemorySize, 0);
}
void grow_memory(DataRange& data); // NOLINT(runtime/references)
void grow_memory(DataRange* data);
using generate_fn = void (WasmGenerator::*const)(DataRange&);
using generate_fn = void (WasmGenerator::*const)(DataRange*);
template <size_t N>
void GenerateOneOf(generate_fn (&alternates)[N],
DataRange& data) { // NOLINT(runtime/references)
void GenerateOneOf(generate_fn (&alternates)[N], DataRange* data) {
static_assert(N < std::numeric_limits<uint8_t>::max(),
"Too many alternates. Replace with a bigger type if needed.");
const auto which = data.get<uint8_t>();
const auto which = data->get<uint8_t>();
generate_fn alternate = alternates[which % N];
(this->*alternate)(data);
@ -450,8 +441,7 @@ class WasmGenerator {
WasmGenerator(WasmFunctionBuilder* fn,
const std::vector<FunctionSig*>& functions,
const std::vector<ValueType>& globals,
const std::vector<uint8_t>& mutable_globals,
DataRange& data) // NOLINT(runtime/references)
const std::vector<uint8_t>& mutable_globals, DataRange* data)
: builder_(fn),
functions_(functions),
globals_(globals),
@ -461,23 +451,23 @@ class WasmGenerator {
blocks_.push_back(sig->return_count() == 0 ? kWasmStmt : sig->GetReturn(0));
constexpr uint32_t kMaxLocals = 32;
locals_.resize(data.get<uint8_t>() % kMaxLocals);
locals_.resize(data->get<uint8_t>() % kMaxLocals);
for (ValueType& local : locals_) {
local = GetValueType(data);
fn->AddLocal(local);
}
}
void Generate(ValueType type, DataRange& data); // NOLINT(runtime/references)
void Generate(ValueType type, DataRange* data);
template <ValueType T>
void Generate(DataRange& data); // NOLINT(runtime/references)
void Generate(DataRange* data);
template <ValueType T1, ValueType T2, ValueType... Ts>
void Generate(DataRange& data) { // NOLINT(runtime/references)
void Generate(DataRange* data) {
// TODO(clemensh): Implement a more even split.
auto first_data = data.split();
Generate<T1>(first_data);
auto first_data = data->split();
Generate<T1>(&first_data);
Generate<T2, Ts...>(data);
}
@ -498,10 +488,9 @@ class WasmGenerator {
};
template <>
void WasmGenerator::Generate<kWasmStmt>(
DataRange& data) { // NOLINT(runtime/references)
void WasmGenerator::Generate<kWasmStmt>(DataRange* data) {
GeneratorRecursionScope rec_scope(this);
if (recursion_limit_reached() || data.size() == 0) return;
if (recursion_limit_reached() || data->size() == 0) return;
constexpr generate_fn alternates[] = {
&WasmGenerator::sequence<kWasmStmt, kWasmStmt>,
@ -536,11 +525,10 @@ void WasmGenerator::Generate<kWasmStmt>(
}
template <>
void WasmGenerator::Generate<kWasmI32>(
DataRange& data) { // NOLINT(runtime/references)
void WasmGenerator::Generate<kWasmI32>(DataRange* data) {
GeneratorRecursionScope rec_scope(this);
if (recursion_limit_reached() || data.size() <= 1) {
builder_->EmitI32Const(data.get<uint32_t>());
if (recursion_limit_reached() || data->size() <= 1) {
builder_->EmitI32Const(data->get<uint32_t>());
return;
}
@ -635,11 +623,10 @@ void WasmGenerator::Generate<kWasmI32>(
}
template <>
void WasmGenerator::Generate<kWasmI64>(
DataRange& data) { // NOLINT(runtime/references)
void WasmGenerator::Generate<kWasmI64>(DataRange* data) {
GeneratorRecursionScope rec_scope(this);
if (recursion_limit_reached() || data.size() <= 1) {
builder_->EmitI64Const(data.get<int64_t>());
if (recursion_limit_reached() || data->size() <= 1) {
builder_->EmitI64Const(data->get<int64_t>());
return;
}
@ -704,11 +691,10 @@ void WasmGenerator::Generate<kWasmI64>(
}
template <>
void WasmGenerator::Generate<kWasmF32>(
DataRange& data) { // NOLINT(runtime/references)
void WasmGenerator::Generate<kWasmF32>(DataRange* data) {
GeneratorRecursionScope rec_scope(this);
if (recursion_limit_reached() || data.size() <= sizeof(float)) {
builder_->EmitF32Const(data.get<float>());
if (recursion_limit_reached() || data->size() <= sizeof(float)) {
builder_->EmitF32Const(data->get<float>());
return;
}
@ -740,11 +726,10 @@ void WasmGenerator::Generate<kWasmF32>(
}
template <>
void WasmGenerator::Generate<kWasmF64>(
DataRange& data) { // NOLINT(runtime/references)
void WasmGenerator::Generate<kWasmF64>(DataRange* data) {
GeneratorRecursionScope rec_scope(this);
if (recursion_limit_reached() || data.size() <= sizeof(double)) {
builder_->EmitF64Const(data.get<double>());
if (recursion_limit_reached() || data->size() <= sizeof(double)) {
builder_->EmitF64Const(data->get<double>());
return;
}
@ -775,12 +760,12 @@ void WasmGenerator::Generate<kWasmF64>(
GenerateOneOf(alternates, data);
}
void WasmGenerator::grow_memory(DataRange& data) {
void WasmGenerator::grow_memory(DataRange* data) {
Generate<kWasmI32>(data);
builder_->EmitWithU8(kExprMemoryGrow, 0);
}
void WasmGenerator::Generate(ValueType type, DataRange& data) {
void WasmGenerator::Generate(ValueType type, DataRange* data) {
switch (type) {
case kWasmStmt:
return Generate<kWasmStmt>(data);
@ -797,12 +782,11 @@ void WasmGenerator::Generate(ValueType type, DataRange& data) {
}
}
FunctionSig* GenerateSig(Zone* zone,
DataRange& data) { // NOLINT(runtime/references)
FunctionSig* GenerateSig(Zone* zone, DataRange* data) {
// Generate enough parameters to spill some to the stack.
constexpr int kMaxParameters = 15;
int num_params = int{data.get<uint8_t>()} % (kMaxParameters + 1);
bool has_return = data.get<bool>();
int num_params = int{data->get<uint8_t>()} % (kMaxParameters + 1);
bool has_return = data->get<bool>();
FunctionSig::Builder builder(zone, has_return ? 1 : 0, num_params);
if (has_return) builder.AddReturn(GetValueType(data));
@ -815,9 +799,9 @@ FunctionSig* GenerateSig(Zone* zone,
class WasmCompileFuzzer : public WasmExecutionFuzzer {
bool GenerateModule(
Isolate* isolate, Zone* zone, Vector<const uint8_t> data,
ZoneBuffer& buffer, int32_t& num_args,
std::unique_ptr<WasmValue[]>& interpreter_args,
std::unique_ptr<Handle<Object>[]>& compiler_args) override {
ZoneBuffer* buffer, int32_t* num_args,
std::unique_ptr<WasmValue[]>* interpreter_args,
std::unique_ptr<Handle<Object>[]>* compiler_args) override {
TestSignatures sigs;
WasmModuleBuilder builder(zone);
@ -830,7 +814,7 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer {
int num_functions = 1 + (range.get<uint8_t>() % kMaxFunctions);
for (int i = 1; i < num_functions; ++i) {
function_signatures.push_back(GenerateSig(zone, range));
function_signatures.push_back(GenerateSig(zone, &range));
}
int num_globals = range.get<uint8_t>() % (kMaxGlobals + 1);
@ -840,7 +824,7 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer {
mutable_globals.reserve(num_globals);
for (int i = 0; i < num_globals; ++i) {
ValueType type = GetValueType(range);
ValueType type = GetValueType(&range);
const bool exported = range.get<bool>();
// 1/8 of globals are immutable.
const bool mutability = (range.get<uint8_t>() % 8) != 0;
@ -857,25 +841,26 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer {
WasmFunctionBuilder* f = builder.AddFunction(sig);
WasmGenerator gen(f, function_signatures, globals, mutable_globals,
function_range);
&function_range);
ValueType return_type =
sig->return_count() == 0 ? kWasmStmt : sig->GetReturn(0);
gen.Generate(return_type, function_range);
gen.Generate(return_type, &function_range);
f->Emit(kExprEnd);
if (i == 0) builder.AddExport(CStrVector("main"), f);
}
builder.SetMaxMemorySize(32);
builder.WriteTo(&buffer);
builder.WriteTo(buffer);
num_args = 3;
interpreter_args.reset(
*num_args = 3;
interpreter_args->reset(
new WasmValue[3]{WasmValue(1), WasmValue(2), WasmValue(3)});
compiler_args.reset(new Handle<Object>[3]{
handle(Smi::FromInt(1), isolate), handle(Smi::FromInt(2), isolate),
handle(Smi::FromInt(3), isolate)});
compiler_args->reset(new Handle<Object>[3] {
handle(Smi::FromInt(1), isolate), handle(Smi::FromInt(2), isolate),
handle(Smi::FromInt(3), isolate)
});
return true;
}
};

View File

@ -278,8 +278,8 @@ void WasmExecutionFuzzer::FuzzWasmModule(Vector<const uint8_t> data,
// compiled with Turbofan and which one with Liftoff.
uint8_t tier_mask = data.empty() ? 0 : data[0];
if (!data.empty()) data += 1;
if (!GenerateModule(i_isolate, &zone, data, buffer, num_args,
interpreter_args, compiler_args)) {
if (!GenerateModule(i_isolate, &zone, data, &buffer, &num_args,
&interpreter_args, &compiler_args)) {
return;
}

View File

@ -37,12 +37,9 @@ class WasmExecutionFuzzer {
protected:
virtual bool GenerateModule(
Isolate* isolate, Zone* zone, Vector<const uint8_t> data,
ZoneBuffer& buffer, // NOLINT(runtime/references)
int32_t& num_args, // NOLINT(runtime/references)
std::unique_ptr<WasmValue[]>&
interpreter_args, // NOLINT(runtime/references)
std::unique_ptr<Handle<Object>[]>&
compiler_args) = 0; // NOLINT(runtime/references)
ZoneBuffer* buffer, int32_t* num_args,
std::unique_ptr<WasmValue[]>* interpreter_args,
std::unique_ptr<Handle<Object>[]>* compiler_args) = 0;
};
} // namespace fuzzer