[wasm][fuzzer] Avoid creating temporary std::vectors
Instead of creating temporary {std::vector}s (which always allocate on the heap) create more vectors on the stack, via initializer lists. As this is "only" a fuzzer, performance is not really critical, but still has some impact on the efficiency of the whole fuzzer. That said, this CL is mostly a cleanup to replace unwanted code pattern by better code. R=jkummerow@chromium.org Change-Id: I924c15e5d64ed584fc96c85715eef1dca5aef150 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2249928 Commit-Queue: Clemens Backes <clemensb@chromium.org> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Cr-Commit-Position: refs/heads/master@{#68413}
This commit is contained in:
parent
7764ff2606
commit
fe3531c4c2
@ -113,9 +113,7 @@ class Vector {
|
||||
}
|
||||
|
||||
// Implicit conversion from Vector<T> to Vector<const T>.
|
||||
inline operator Vector<const T>() const {
|
||||
return Vector<const T>::cast(*this);
|
||||
}
|
||||
operator Vector<const T>() const { return {start_, length_}; }
|
||||
|
||||
template <typename S>
|
||||
static Vector<T> cast(Vector<S> input) {
|
||||
@ -298,6 +296,14 @@ inline constexpr auto VectorOf(Container&& c)
|
||||
return VectorOf(c.data(), c.size());
|
||||
}
|
||||
|
||||
// Construct a Vector from an initializer list. The vector can obviously only be
|
||||
// used as long as the initializer list is live. Valid uses include direct use
|
||||
// in parameter lists: F(VectorOf({1, 2, 3}));
|
||||
template <typename T>
|
||||
inline constexpr Vector<const T> VectorOf(std::initializer_list<T> list) {
|
||||
return VectorOf(list.begin(), list.size());
|
||||
}
|
||||
|
||||
template <typename T, size_t kSize>
|
||||
class EmbeddedVector : public Vector<T> {
|
||||
public:
|
||||
|
@ -115,11 +115,11 @@ class WasmGenerator {
|
||||
class BlockScope {
|
||||
public:
|
||||
BlockScope(WasmGenerator* gen, WasmOpcode block_type,
|
||||
const std::vector<ValueType>& param_types,
|
||||
const std::vector<ValueType>& result_types,
|
||||
const std::vector<ValueType>& br_types)
|
||||
Vector<const ValueType> param_types,
|
||||
Vector<const ValueType> result_types,
|
||||
Vector<const ValueType> br_types)
|
||||
: gen_(gen) {
|
||||
gen->blocks_.push_back(br_types);
|
||||
gen->blocks_.emplace_back(br_types.begin(), br_types.end());
|
||||
if (param_types.size() == 0 && result_types.size() == 0) {
|
||||
gen->builder_->EmitWithU8(block_type, kWasmStmt.value_type_code());
|
||||
return;
|
||||
@ -155,8 +155,8 @@ class WasmGenerator {
|
||||
WasmGenerator* const gen_;
|
||||
};
|
||||
|
||||
void block(const std::vector<ValueType>& param_types,
|
||||
const std::vector<ValueType>& return_types, DataRange* data) {
|
||||
void block(Vector<const ValueType> param_types,
|
||||
Vector<const ValueType> return_types, DataRange* data) {
|
||||
BlockScope block_scope(this, kExprBlock, param_types, return_types,
|
||||
return_types);
|
||||
ConsumeAndGenerate(param_types, return_types, data);
|
||||
@ -164,11 +164,11 @@ class WasmGenerator {
|
||||
|
||||
template <ValueType::Kind T>
|
||||
void block(DataRange* data) {
|
||||
block({}, {ValueType::Primitive(T)}, data);
|
||||
block({}, VectorOf({ValueType::Primitive(T)}), data);
|
||||
}
|
||||
|
||||
void loop(const std::vector<ValueType>& param_types,
|
||||
const std::vector<ValueType>& return_types, DataRange* data) {
|
||||
void loop(Vector<const ValueType> param_types,
|
||||
Vector<const ValueType> return_types, DataRange* data) {
|
||||
BlockScope block_scope(this, kExprLoop, param_types, return_types,
|
||||
param_types);
|
||||
ConsumeAndGenerate(param_types, return_types, data);
|
||||
@ -176,14 +176,13 @@ class WasmGenerator {
|
||||
|
||||
template <ValueType::Kind T>
|
||||
void loop(DataRange* data) {
|
||||
loop({}, {ValueType::Primitive(T)}, data);
|
||||
loop({}, VectorOf({ValueType::Primitive(T)}), data);
|
||||
}
|
||||
|
||||
enum IfType { kIf, kIfElse };
|
||||
|
||||
void if_(const std::vector<ValueType>& param_types,
|
||||
const std::vector<ValueType>& return_types, IfType type,
|
||||
DataRange* data) {
|
||||
void if_(Vector<const ValueType> param_types,
|
||||
Vector<const ValueType> return_types, IfType type, DataRange* data) {
|
||||
// One-armed "if" are only valid if the input and output types are the same.
|
||||
DCHECK_IMPLIES(type == kIf, param_types == return_types);
|
||||
Generate(kWasmI32, data);
|
||||
@ -200,14 +199,14 @@ class WasmGenerator {
|
||||
void if_(DataRange* data) {
|
||||
static_assert(T == ValueType::kStmt || type == kIfElse,
|
||||
"if without else cannot produce a value");
|
||||
auto return_type = T == ValueType::kStmt
|
||||
? std::vector<ValueType>{}
|
||||
: std::vector<ValueType>{ValueType::Primitive(T)};
|
||||
if_({}, return_type, type, data);
|
||||
if_({},
|
||||
T == ValueType::kStmt ? Vector<ValueType>{}
|
||||
: VectorOf({ValueType::Primitive(T)}),
|
||||
type, data);
|
||||
}
|
||||
|
||||
void any_block(const std::vector<ValueType>& param_types,
|
||||
const std::vector<ValueType>& return_types, DataRange* data) {
|
||||
void any_block(Vector<const ValueType> param_types,
|
||||
Vector<const ValueType> return_types, DataRange* data) {
|
||||
uint8_t block_type = data->get<uint8_t>() % 4;
|
||||
switch (block_type) {
|
||||
case 0:
|
||||
@ -244,17 +243,17 @@ class WasmGenerator {
|
||||
// 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 auto break_types = blocks_[target_block];
|
||||
const auto break_types = VectorOf(blocks_[target_block]);
|
||||
|
||||
Generate(VectorOf(break_types), data);
|
||||
Generate(break_types, data);
|
||||
Generate(kWasmI32, data);
|
||||
builder_->EmitWithI32V(
|
||||
kExprBrIf, static_cast<uint32_t>(blocks_.size()) - 1 - target_block);
|
||||
auto return_type =
|
||||
wanted_type == ValueType::kStmt
|
||||
? std::vector<ValueType>{}
|
||||
: std::vector<ValueType>{ValueType::Primitive(wanted_type)};
|
||||
ConsumeAndGenerate(break_types, return_type, data);
|
||||
ConsumeAndGenerate(break_types,
|
||||
wanted_type == ValueType::kStmt
|
||||
? Vector<ValueType>{}
|
||||
: VectorOf({ValueType::Primitive(wanted_type)}),
|
||||
data);
|
||||
}
|
||||
|
||||
// TODO(eholk): make this function constexpr once gcc supports it
|
||||
@ -489,11 +488,9 @@ class WasmGenerator {
|
||||
}
|
||||
return;
|
||||
}
|
||||
std::vector<ValueType> return_types(sig->returns().begin(),
|
||||
sig->returns().end());
|
||||
auto wanted_types = wanted_type == kWasmStmt
|
||||
? std::vector<ValueType>{}
|
||||
: std::vector<ValueType>{wanted_type};
|
||||
auto return_types = VectorOf(sig->returns().begin(), sig->return_count());
|
||||
auto wanted_types =
|
||||
VectorOf(&wanted_type, wanted_type == kWasmStmt ? 0 : 1);
|
||||
ConsumeAndGenerate(return_types, wanted_types, data);
|
||||
}
|
||||
|
||||
@ -681,8 +678,8 @@ class WasmGenerator {
|
||||
|
||||
std::vector<ValueType> GenerateTypes(DataRange* data);
|
||||
void Generate(Vector<const ValueType> types, DataRange* data);
|
||||
void ConsumeAndGenerate(const std::vector<ValueType>& parameter_types,
|
||||
const std::vector<ValueType>& return_types,
|
||||
void ConsumeAndGenerate(Vector<const ValueType> parameter_types,
|
||||
Vector<const ValueType> return_types,
|
||||
DataRange* data);
|
||||
|
||||
private:
|
||||
@ -1535,7 +1532,7 @@ void WasmGenerator::Generate(Vector<const ValueType> types, DataRange* data) {
|
||||
if (!recursion_limit_reached()) {
|
||||
const auto param_types = GenerateTypes(data);
|
||||
Generate(VectorOf(param_types), data);
|
||||
any_block(param_types, {types.begin(), types.end()}, data);
|
||||
any_block(VectorOf(param_types), types, data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1552,20 +1549,20 @@ void WasmGenerator::Generate(Vector<const ValueType> types, DataRange* data) {
|
||||
// Split the types in two halves and recursively generate each half.
|
||||
// Each half is non empty to ensure termination.
|
||||
size_t split_index = data->get<uint8_t>() % (types.size() - 1) + 1;
|
||||
Vector<const ValueType> lower_half(types.begin(), split_index);
|
||||
Vector<const ValueType> upper_half(types.begin() + split_index,
|
||||
types.size() - split_index);
|
||||
Vector<const ValueType> lower_half = types.SubVector(0, split_index);
|
||||
Vector<const ValueType> upper_half =
|
||||
types.SubVector(split_index, types.size() - split_index);
|
||||
DataRange first_range = data->split();
|
||||
Generate(lower_half, &first_range);
|
||||
Generate(upper_half, data);
|
||||
}
|
||||
|
||||
// Emit code to match an arbitrary signature.
|
||||
void WasmGenerator::ConsumeAndGenerate(
|
||||
const std::vector<ValueType>& param_types,
|
||||
const std::vector<ValueType>& return_types, DataRange* data) {
|
||||
void WasmGenerator::ConsumeAndGenerate(Vector<const ValueType> param_types,
|
||||
Vector<const ValueType> return_types,
|
||||
DataRange* data) {
|
||||
if (param_types.size() == 0) {
|
||||
Generate(VectorOf(return_types), data);
|
||||
Generate(return_types, data);
|
||||
return;
|
||||
}
|
||||
// Keep exactly one of the parameters on the stack with a combination of drops
|
||||
@ -1586,7 +1583,7 @@ void WasmGenerator::ConsumeAndGenerate(
|
||||
builder_->Emit(kExprDrop);
|
||||
} else {
|
||||
Convert(param_types[0], return_types[0]);
|
||||
Generate(VectorOf(return_types) + 1, data);
|
||||
Generate(return_types + 1, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user