Commit 74d9a764 authored by Manos Koukoutos's avatar Manos Koukoutos Committed by V8 LUCI CQ

[wasm][fuzzer] Complex init. expressions in JS testcase

We enable struct.new and array.init initializer expressions in the JS
testcase generated by --wasm-fuzzer-gen-test. We needed to make some
changes in the WasmInitExpr class, and to implement a new interface for
the WasmFullDecoder, which constructs a WasmInitExpr.
Changes:
- Make WasmInitExpr a ZoneObject. Use a pointer for its operands_ field.
  This is needed so WasmInitExpr is trivially copiable, and thus usable
  as a Value type in WasmFullDecoder.
- Implement a WasmFullDecoder interface in wasm-fuzzer-common that
  constructs a WasmInitExpr. Use it to decode initializers in the
  module generated by the fuzzer.
- Change AppendInitExpr to take a WasmInitExpr as argument.
- Fix an issue with printing of struct definitions.
- Change initializer expression used for structs to struct.new_with_rtt.
  This is consistent with the currently used structural types.

Bug: v8:11954
Change-Id: I65a87cc98701a54f32500be192b3b6eef2ff6c8c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3257712Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77730}
parent d65a8d6c
......@@ -239,7 +239,7 @@ void AsmJsParser::DeclareGlobal(VarInfo* info, bool mutable_variable,
WasmInitExpr init) {
info->kind = VarKind::kGlobal;
info->type = type;
info->index = module_builder_->AddGlobal(vtype, true, std::move(init));
info->index = module_builder_->AddGlobal(vtype, true, init);
info->mutable_variable = mutable_variable;
}
......
......@@ -63,7 +63,10 @@ class InitExprInterface {
#define EMPTY_INTERFACE_FUNCTION(name, ...) \
V8_INLINE void name(FullDecoder* decoder, ##__VA_ARGS__) {}
INTERFACE_META_FUNCTIONS(EMPTY_INTERFACE_FUNCTION)
INTERFACE_NON_CONSTANT_FUNCTIONS(EMPTY_INTERFACE_FUNCTION)
#undef EMPTY_INTERFACE_FUNCTION
#define UNREACHABLE_INTERFACE_FUNCTION(name, ...) \
V8_INLINE void name(FullDecoder* decoder, ##__VA_ARGS__) { UNREACHABLE(); }
INTERFACE_NON_CONSTANT_FUNCTIONS(UNREACHABLE_INTERFACE_FUNCTION)
#undef EMPTY_INTERFACE_FUNCTION
#define DECLARE_INTERFACE_FUNCTION(name, ...) \
......
......@@ -49,7 +49,7 @@ ValueType WasmInitExpr::type(const WasmModule* module,
return ValueType::Rtt(immediate().heap_type, 0);
case kRttSub:
case kRttFreshSub: {
ValueType operand_type = operands()[0].type(module, enabled_features);
ValueType operand_type = (*operands())[0].type(module, enabled_features);
if (!operand_type.is_rtt()) return kWasmBottom;
if (operand_type.has_depth()) {
return ValueType::Rtt(immediate().heap_type, operand_type.depth() + 1);
......
......@@ -12,6 +12,7 @@
#include <memory>
#include "src/wasm/value-type.h"
#include "src/zone/zone-containers.h"
namespace v8 {
namespace internal {
......@@ -21,7 +22,7 @@ struct WasmModule;
class WasmFeatures;
// Representation of an initializer expression.
class WasmInitExpr {
class WasmInitExpr : public ZoneObject {
public:
enum Operator {
kNone,
......@@ -54,25 +55,26 @@ class WasmInitExpr {
HeapType::Representation heap_type;
};
WasmInitExpr() : kind_(kNone) { immediate_.i32_const = 0; }
explicit WasmInitExpr(int32_t v) : kind_(kI32Const) {
WasmInitExpr() : kind_(kNone), operands_(nullptr) {
immediate_.i32_const = 0;
}
explicit WasmInitExpr(int32_t v) : kind_(kI32Const), operands_(nullptr) {
immediate_.i32_const = v;
}
explicit WasmInitExpr(int64_t v) : kind_(kI64Const) {
explicit WasmInitExpr(int64_t v) : kind_(kI64Const), operands_(nullptr) {
immediate_.i64_const = v;
}
explicit WasmInitExpr(float v) : kind_(kF32Const) {
explicit WasmInitExpr(float v) : kind_(kF32Const), operands_(nullptr) {
immediate_.f32_const = v;
}
explicit WasmInitExpr(double v) : kind_(kF64Const) {
explicit WasmInitExpr(double v) : kind_(kF64Const), operands_(nullptr) {
immediate_.f64_const = v;
}
explicit WasmInitExpr(uint8_t v[kSimd128Size]) : kind_(kS128Const) {
explicit WasmInitExpr(uint8_t v[kSimd128Size])
: kind_(kS128Const), operands_(nullptr) {
memcpy(immediate_.s128_const.data(), v, kSimd128Size);
}
MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(WasmInitExpr);
static WasmInitExpr GlobalGet(uint32_t index) {
WasmInitExpr expr;
expr.kind_ = kGlobalGet;
......@@ -95,29 +97,25 @@ class WasmInitExpr {
}
static WasmInitExpr StructNewWithRtt(uint32_t index,
std::vector<WasmInitExpr> elements) {
WasmInitExpr expr;
expr.kind_ = kStructNewWithRtt;
ZoneVector<WasmInitExpr>* elements) {
WasmInitExpr expr(kStructNewWithRtt, elements);
expr.immediate_.index = index;
expr.operands_ = std::move(elements);
return expr;
}
static WasmInitExpr StructNew(uint32_t index,
std::vector<WasmInitExpr> elements) {
WasmInitExpr expr;
expr.kind_ = kStructNew;
ZoneVector<WasmInitExpr>* elements) {
WasmInitExpr expr(kStructNew, elements);
expr.immediate_.index = index;
expr.operands_ = std::move(elements);
return expr;
}
static WasmInitExpr StructNewDefaultWithRtt(uint32_t index,
static WasmInitExpr StructNewDefaultWithRtt(Zone* zone, uint32_t index,
WasmInitExpr rtt) {
WasmInitExpr expr;
expr.kind_ = kStructNewDefaultWithRtt;
WasmInitExpr expr(kStructNewDefaultWithRtt,
zone->New<ZoneVector<WasmInitExpr>>(
std::initializer_list<WasmInitExpr>{rtt}, zone));
expr.immediate_.index = index;
expr.operands_.push_back(std::move(rtt));
return expr;
}
......@@ -129,20 +127,16 @@ class WasmInitExpr {
}
static WasmInitExpr ArrayInit(uint32_t index,
std::vector<WasmInitExpr> elements) {
WasmInitExpr expr;
expr.kind_ = kArrayInit;
ZoneVector<WasmInitExpr>* elements) {
WasmInitExpr expr(kArrayInit, elements);
expr.immediate_.index = index;
expr.operands_ = std::move(elements);
return expr;
}
static WasmInitExpr ArrayInitStatic(uint32_t index,
std::vector<WasmInitExpr> elements) {
WasmInitExpr expr;
expr.kind_ = kArrayInitStatic;
ZoneVector<WasmInitExpr>* elements) {
WasmInitExpr expr(kArrayInitStatic, elements);
expr.immediate_.index = index;
expr.operands_ = std::move(elements);
return expr;
}
......@@ -153,25 +147,28 @@ class WasmInitExpr {
return expr;
}
static WasmInitExpr RttSub(uint32_t index, WasmInitExpr supertype) {
WasmInitExpr expr;
expr.kind_ = kRttSub;
static WasmInitExpr RttSub(Zone* zone, uint32_t index,
WasmInitExpr supertype) {
WasmInitExpr expr(
kRttSub, zone->New<ZoneVector<WasmInitExpr>>(
std::initializer_list<WasmInitExpr>{supertype}, zone));
expr.immediate_.index = index;
expr.operands_.push_back(std::move(supertype));
return expr;
}
static WasmInitExpr RttFreshSub(uint32_t index, WasmInitExpr supertype) {
WasmInitExpr expr;
expr.kind_ = kRttFreshSub;
static WasmInitExpr RttFreshSub(Zone* zone, uint32_t index,
WasmInitExpr supertype) {
WasmInitExpr expr(
kRttFreshSub,
zone->New<ZoneVector<WasmInitExpr>>(
std::initializer_list<WasmInitExpr>{supertype}, zone));
expr.immediate_.index = index;
expr.operands_.push_back(std::move(supertype));
return expr;
}
Immediate immediate() const { return immediate_; }
Operator kind() const { return kind_; }
const std::vector<WasmInitExpr>& operands() const { return operands_; }
const ZoneVector<WasmInitExpr>* operands() const { return operands_; }
bool operator==(const WasmInitExpr& other) const {
if (kind() != other.kind()) return false;
......@@ -199,16 +196,16 @@ class WasmInitExpr {
case kStructNewDefaultWithRtt:
case kStructNewDefault:
if (immediate().index != other.immediate().index) return false;
DCHECK_EQ(operands().size(), other.operands().size());
for (uint32_t i = 0; i < operands().size(); i++) {
DCHECK_EQ(operands()->size(), other.operands()->size());
for (uint32_t i = 0; i < operands()->size(); i++) {
if (operands()[i] != other.operands()[i]) return false;
}
return true;
case kArrayInit:
case kArrayInitStatic:
if (immediate().index != other.immediate().index) return false;
if (operands().size() != other.operands().size()) return false;
for (uint32_t i = 0; i < operands().size(); i++) {
if (operands()->size() != other.operands()->size()) return false;
for (uint32_t i = 0; i < operands()->size(); i++) {
if (operands()[i] != other.operands()[i]) return false;
}
return true;
......@@ -227,11 +224,15 @@ class WasmInitExpr {
const WasmFeatures& enabled_features) const;
private:
WasmInitExpr(Operator kind, const ZoneVector<WasmInitExpr>* operands)
: kind_(kind), operands_(operands) {}
Immediate immediate_;
Operator kind_;
std::vector<WasmInitExpr> operands_;
const ZoneVector<WasmInitExpr>* operands_;
};
ASSERT_TRIVIALLY_COPYABLE(WasmInitExpr);
} // namespace wasm
} // namespace internal
} // namespace v8
......
......@@ -355,7 +355,7 @@ uint32_t WasmModuleBuilder::AddTable(ValueType type, uint32_t min_size,
uint32_t WasmModuleBuilder::AddTable(ValueType type, uint32_t min_size,
uint32_t max_size, WasmInitExpr init) {
tables_.push_back({type, min_size, max_size, true, std::move(init)});
tables_.push_back({type, min_size, max_size, true, init});
return static_cast<uint32_t>(tables_.size() - 1);
}
......@@ -403,7 +403,7 @@ void WasmModuleBuilder::AddExport(base::Vector<const char> name,
uint32_t WasmModuleBuilder::AddExportedGlobal(ValueType type, bool mutability,
WasmInitExpr init,
base::Vector<const char> name) {
uint32_t index = AddGlobal(type, mutability, std::move(init));
uint32_t index = AddGlobal(type, mutability, init);
AddExport(name, kExternalGlobal, index);
return index;
}
......@@ -421,7 +421,7 @@ void WasmModuleBuilder::ExportImportedFunction(base::Vector<const char> name,
uint32_t WasmModuleBuilder::AddGlobal(ValueType type, bool mutability,
WasmInitExpr init) {
globals_.push_back({type, mutability, std::move(init)});
globals_.push_back({type, mutability, init});
return static_cast<uint32_t>(globals_.size() - 1);
}
......@@ -523,7 +523,7 @@ void WriteInitializerExpressionWithEnd(ZoneBuffer* buffer,
STATIC_ASSERT((kExprStructNewWithRtt >> 8) == kGCPrefix);
STATIC_ASSERT((kExprStructNewDefault >> 8) == kGCPrefix);
STATIC_ASSERT((kExprStructNewDefaultWithRtt >> 8) == kGCPrefix);
for (const WasmInitExpr& operand : init.operands()) {
for (const WasmInitExpr& operand : *init.operands()) {
WriteInitializerExpressionWithEnd(buffer, operand, kWasmBottom);
}
buffer->write_u8(kGCPrefix);
......@@ -551,7 +551,7 @@ void WriteInitializerExpressionWithEnd(ZoneBuffer* buffer,
case WasmInitExpr::kArrayInitStatic:
STATIC_ASSERT((kExprArrayInit >> 8) == kGCPrefix);
STATIC_ASSERT((kExprArrayInitStatic >> 8) == kGCPrefix);
for (const WasmInitExpr& operand : init.operands()) {
for (const WasmInitExpr& operand : *init.operands()) {
WriteInitializerExpressionWithEnd(buffer, operand, kWasmBottom);
}
buffer->write_u8(kGCPrefix);
......@@ -559,7 +559,7 @@ void WriteInitializerExpressionWithEnd(ZoneBuffer* buffer,
init.kind() == WasmInitExpr::kArrayInit ? kExprArrayInit
: kExprArrayInitStatic));
buffer->write_u32v(init.immediate().index);
buffer->write_u32v(static_cast<uint32_t>(init.operands().size() - 1));
buffer->write_u32v(static_cast<uint32_t>(init.operands()->size() - 1));
break;
case WasmInitExpr::kRttCanon:
STATIC_ASSERT((kExprRttCanon >> 8) == kGCPrefix);
......@@ -570,7 +570,7 @@ void WriteInitializerExpressionWithEnd(ZoneBuffer* buffer,
case WasmInitExpr::kRttSub:
case WasmInitExpr::kRttFreshSub:
// The operand to rtt.sub must be emitted first.
WriteInitializerExpressionWithEnd(buffer, init.operands()[0],
WriteInitializerExpressionWithEnd(buffer, (*init.operands())[0],
kWasmBottom);
STATIC_ASSERT((kExprRttSub >> 8) == kGCPrefix);
STATIC_ASSERT((kExprRttFreshSub >> 8) == kGCPrefix);
......
......@@ -273,7 +273,7 @@ class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject {
WasmInitExpr offset)
: type(type),
table_index(table_index),
offset(std::move(offset)),
offset(offset),
entries(zone),
status(kStatusActive) {
DCHECK(IsValidOffsetKind(offset.kind()));
......
......@@ -462,7 +462,8 @@ int GetNearestWasmFunction(const WasmModule* module, uint32_t byte_offset);
// Returns 0 if the type has no explicit supertype.
// The result is capped to {kV8MaxRttSubtypingDepth + 1}.
// Invalid cyclic hierarchies will return -1.
int GetSubtypingDepth(const WasmModule* module, uint32_t type_index);
V8_EXPORT_PRIVATE int GetSubtypingDepth(const WasmModule* module,
uint32_t type_index);
// Interface to the storage (wire bytes) of a wasm module.
// It is illegal for anyone receiving a ModuleWireBytes to store pointers based
......
......@@ -50,7 +50,7 @@ class WasmGCTester {
}
byte AddGlobal(ValueType type, bool mutability, WasmInitExpr init) {
return builder_.AddGlobal(type, mutability, std::move(init));
return builder_.AddGlobal(type, mutability, init);
}
byte DefineFunction(FunctionSig* sig, std::initializer_list<ValueType> locals,
......@@ -1425,7 +1425,8 @@ WASM_COMPILED_EXEC_TEST(RttFreshSub) {
const byte kRtt = tester.AddGlobal(
ValueType::Rtt(kType, 1), false,
WasmInitExpr::RttFreshSub(type_repr, WasmInitExpr::RttCanon(type_repr)));
WasmInitExpr::RttFreshSub(tester.zone(), type_repr,
WasmInitExpr::RttCanon(type_repr)));
// A struct allocated with a fresh RTT does not match other fresh RTTs
// created for the same type.
......@@ -2082,7 +2083,8 @@ WASM_COMPILED_EXEC_TEST(CastsBenchmark) {
WasmInitExpr::RttCanon(static_cast<HeapType::Representation>(SuperType)));
const byte RttSub = tester.AddGlobal(
ValueType::Rtt(SubType, 1), false,
WasmInitExpr::RttSub(static_cast<HeapType::Representation>(SubType),
WasmInitExpr::RttSub(tester.zone(),
static_cast<HeapType::Representation>(SubType),
WasmInitExpr::GlobalGet(RttSuper)));
const byte RttList = tester.AddGlobal(
ValueType::Rtt(ListType, 0), false,
......
......@@ -2297,7 +2297,8 @@ FunctionSig* GenerateSig(Zone* zone, DataRange* data, SigKind sig_kind,
return builder.Build();
}
WasmInitExpr GenerateInitExpr(WasmModuleBuilder* builder, ValueType type,
WasmInitExpr GenerateInitExpr(Zone* zone, WasmModuleBuilder* builder,
ValueType type,
uint32_t num_struct_and_array_types) {
switch (type.kind()) {
case kOptRef:
......@@ -2329,26 +2330,29 @@ WasmInitExpr GenerateInitExpr(WasmModuleBuilder* builder, ValueType type,
// We materialize all these types with a struct because they are all its
// supertypes.
DCHECK(builder->IsStructType(index));
std::vector<WasmInitExpr> elements;
ZoneVector<WasmInitExpr>* elements =
zone->New<ZoneVector<WasmInitExpr>>(zone);
int field_count = builder->GetStructType(index)->field_count();
for (int field_index = 0; field_index < field_count; field_index++) {
elements.push_back(GenerateInitExpr(
builder, builder->GetStructType(index)->field(field_index),
elements->push_back(GenerateInitExpr(
zone, builder, builder->GetStructType(index)->field(field_index),
num_struct_and_array_types));
}
return WasmInitExpr::StructNew(index, std::move(elements));
elements->push_back(WasmInitExpr::RttCanon(index));
return WasmInitExpr::StructNewWithRtt(index, elements);
}
DCHECK(type.has_index());
if (representation == HeapType::kFunc) {
return WasmInitExpr::RefFuncConst(index);
}
if (builder->IsArrayType(index)) {
std::vector<WasmInitExpr> elements;
elements.push_back(GenerateInitExpr(
builder, builder->GetArrayType(index)->element_type(),
ZoneVector<WasmInitExpr>* elements =
zone->New<ZoneVector<WasmInitExpr>>(zone);
elements->push_back(GenerateInitExpr(
zone, builder, builder->GetArrayType(index)->element_type(),
num_struct_and_array_types));
elements.push_back(WasmInitExpr::RttCanon(index));
return WasmInitExpr::ArrayInit(index, std::move(elements));
elements->push_back(WasmInitExpr::RttCanon(index));
return WasmInitExpr::ArrayInit(index, elements);
}
if (builder->IsSignature(index)) {
// Transform from signature index to function specific index.
......@@ -2460,7 +2464,7 @@ class WasmCompileFuzzer : public WasmExecutionFuzzer {
builder.AddGlobal(
type, mutability,
GenerateInitExpr(&builder, type,
GenerateInitExpr(zone, &builder, type,
static_cast<uint32_t>(num_structs + num_arrays)));
globals.push_back(type);
if (mutability) mutable_globals.push_back(static_cast<uint8_t>(i));
......
This diff is collapsed.
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