[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:
Clemens Backes 2020-06-18 14:55:08 +02:00 committed by Commit Bot
parent 7764ff2606
commit fe3531c4c2
2 changed files with 48 additions and 45 deletions

View File

@ -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:

View File

@ -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);
}
}