Bug 1790626 - wasm: Manually serialize/deserialize PackedType to prepare for it not being POD. r=yury

PackedType will store a pointer to *TypeDef in a later commit, making it
non-cacheable POD. We therefore need to specially handle it in serialization.
This commit starts preparing for that.

Differential Revision: https://phabricator.services.mozilla.com/D157386
This commit is contained in:
Ryan Hunt 2022-10-18 22:28:13 +00:00
Родитель 99578d6774
Коммит 17d79988c0
5 изменённых файлов: 95 добавлений и 45 удалений

Просмотреть файл

@ -614,9 +614,6 @@ struct TableDesc {
uint32_t initialLength; uint32_t initialLength;
Maybe<uint32_t> maximumLength; Maybe<uint32_t> maximumLength;
WASM_CHECK_CACHEABLE_POD(elemType, isImportedOrExported, isAsmJS,
globalDataOffset, initialLength, maximumLength);
TableDesc() = default; TableDesc() = default;
TableDesc(RefType elemType, uint32_t initialLength, TableDesc(RefType elemType, uint32_t initialLength,
Maybe<uint32_t> maximumLength, bool isAsmJS, Maybe<uint32_t> maximumLength, bool isAsmJS,
@ -629,8 +626,6 @@ struct TableDesc {
maximumLength(maximumLength) {} maximumLength(maximumLength) {}
}; };
WASM_DECLARE_CACHEABLE_POD(TableDesc);
using TableDescVector = Vector<TableDesc, 0, SystemAllocPolicy>; using TableDescVector = Vector<TableDesc, 0, SystemAllocPolicy>;
} // namespace wasm } // namespace wasm

Просмотреть файл

@ -412,16 +412,56 @@ CoderResult CodeShareableBytes(Coder<mode>& coder,
return CodePodVector(coder, &item->bytes); return CodePodVector(coder, &item->bytes);
} }
// WasmValType.h
template <CoderMode mode>
CoderResult CodeValType(Coder<mode>& coder, CoderArg<mode, ValType> item) {
if constexpr (mode == MODE_DECODE) {
return coder.readBytes((void*)item, sizeof(ValType));
} else {
return coder.writeBytes((const void*)item, sizeof(ValType));
}
}
CoderResult CodeFieldType(Coder<MODE_DECODE>& coder, FieldType* item) {
return coder.readBytes((void*)item, sizeof(FieldType));
}
template <CoderMode mode>
CoderResult CodeFieldType(Coder<mode>& coder, const FieldType* item) {
STATIC_ASSERT_ENCODING_OR_SIZING;
return coder.writeBytes((const void*)item, sizeof(FieldType));
}
CoderResult CodeRefType(Coder<MODE_DECODE>& coder, RefType* item) {
return coder.readBytes((void*)item, sizeof(RefType));
}
template <CoderMode mode>
CoderResult CodeRefType(Coder<mode>& coder, const RefType* item) {
STATIC_ASSERT_ENCODING_OR_SIZING;
return coder.writeBytes((const void*)item, sizeof(RefType));
}
// WasmValue.h
template <CoderMode mode>
CoderResult CodeLitVal(Coder<mode>& coder, CoderArg<mode, LitVal> item) {
MOZ_TRY(CodeValType(coder, &item->type_));
MOZ_TRY(CodePod(coder, &item->cell_));
return Ok();
}
// WasmInitExpr.h // WasmInitExpr.h
template <CoderMode mode> template <CoderMode mode>
CoderResult CodeInitExpr(Coder<mode>& coder, CoderArg<mode, InitExpr> item) { CoderResult CodeInitExpr(Coder<mode>& coder, CoderArg<mode, InitExpr> item) {
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::InitExpr, 80); WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::InitExpr, 80);
MOZ_TRY(CodePod(coder, &item->kind_)); MOZ_TRY(CodePod(coder, &item->kind_));
MOZ_TRY(CodePod(coder, &item->type_)); MOZ_TRY(CodeValType(coder, &item->type_));
switch (item->kind_) { switch (item->kind_) {
case InitExprKind::Literal: case InitExprKind::Literal:
MOZ_TRY(CodePod(coder, &item->literal_)); MOZ_TRY(CodeLitVal(coder, &item->literal_));
break; break;
case InitExprKind::Variable: case InitExprKind::Variable:
MOZ_TRY(CodePodVector(coder, &item->bytecode_)); MOZ_TRY(CodePodVector(coder, &item->bytecode_));
@ -437,21 +477,40 @@ CoderResult CodeInitExpr(Coder<mode>& coder, CoderArg<mode, InitExpr> item) {
template <CoderMode mode> template <CoderMode mode>
CoderResult CodeFuncType(Coder<mode>& coder, CoderArg<mode, FuncType> item) { CoderResult CodeFuncType(Coder<mode>& coder, CoderArg<mode, FuncType> item) {
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::FuncType, 208); WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::FuncType, 208);
MOZ_TRY(CodePodVector(coder, &item->results_)); MOZ_TRY((CodeVector<mode, ValType, &CodeValType<mode>>(coder, &item->args_)));
MOZ_TRY(CodePodVector(coder, &item->args_)); MOZ_TRY(
(CodeVector<mode, ValType, &CodeValType<mode>>(coder, &item->results_)));
MOZ_TRY(CodePod(coder, &item->immediateTypeId_)); MOZ_TRY(CodePod(coder, &item->immediateTypeId_));
return Ok(); return Ok();
} }
template <CoderMode mode>
CoderResult CodeStructField(Coder<mode>& coder,
CoderArg<mode, StructField> item) {
MOZ_TRY(CodeFieldType(coder, &item->type));
MOZ_TRY(CodePod(coder, &item->offset));
MOZ_TRY(CodePod(coder, &item->isMutable));
return Ok();
}
template <CoderMode mode> template <CoderMode mode>
CoderResult CodeStructType(Coder<mode>& coder, CoderResult CodeStructType(Coder<mode>& coder,
CoderArg<mode, StructType> item) { CoderArg<mode, StructType> item) {
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::StructType, 48); WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::StructType, 48);
MOZ_TRY(CodePodVector(coder, &item->fields_)); MOZ_TRY((CodeVector<mode, StructField, &CodeStructField<mode>>(
coder, &item->fields_)));
MOZ_TRY(CodePod(coder, &item->size_)); MOZ_TRY(CodePod(coder, &item->size_));
return Ok(); return Ok();
} }
template <CoderMode mode>
CoderResult CodeArrayType(Coder<mode>& coder, CoderArg<mode, ArrayType> item) {
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::ArrayType, 48);
MOZ_TRY(CodeFieldType(coder, &item->elementType_));
MOZ_TRY(CodePod(coder, &item->isMutable_));
return Ok();
}
template <CoderMode mode> template <CoderMode mode>
CoderResult CodeTypeDef(Coder<mode>& coder, CoderArg<mode, TypeDef> item) { CoderResult CodeTypeDef(Coder<mode>& coder, CoderArg<mode, TypeDef> item) {
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::TypeDef, 216); WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::TypeDef, 216);
@ -477,7 +536,10 @@ CoderResult CodeTypeDef(Coder<mode>& coder, CoderArg<mode, TypeDef> item) {
break; break;
} }
case TypeDefKind::Array: { case TypeDefKind::Array: {
MOZ_TRY(CodePod(coder, &item->arrayType_)); if constexpr (mode == MODE_DECODE) {
new (&item->arrayType_) ArrayType();
}
MOZ_TRY(CodeArrayType(coder, &item->arrayType_));
break; break;
} }
case TypeDefKind::None: { case TypeDefKind::None: {
@ -525,7 +587,8 @@ CoderResult CodeGlobalDesc(Coder<mode>& coder,
template <CoderMode mode> template <CoderMode mode>
CoderResult CodeTagType(Coder<mode>& coder, CoderArg<mode, TagType> item) { CoderResult CodeTagType(Coder<mode>& coder, CoderArg<mode, TagType> item) {
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::TagType, 168); WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::TagType, 168);
MOZ_TRY(CodePodVector(coder, &item->argTypes_)); MOZ_TRY(
(CodeVector<mode, ValType, &CodeValType<mode>>(coder, &item->argTypes_)));
MOZ_TRY(CodePodVector(coder, &item->argOffsets_)); MOZ_TRY(CodePodVector(coder, &item->argOffsets_));
MOZ_TRY(CodePod(coder, &item->size_)); MOZ_TRY(CodePod(coder, &item->size_));
return Ok(); return Ok();
@ -548,7 +611,7 @@ CoderResult CodeElemSegment(Coder<mode>& coder,
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::ElemSegment, 184); WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::ElemSegment, 184);
MOZ_TRY(CodePod(coder, &item->kind)); MOZ_TRY(CodePod(coder, &item->kind));
MOZ_TRY(CodePod(coder, &item->tableIndex)); MOZ_TRY(CodePod(coder, &item->tableIndex));
MOZ_TRY(CodePod(coder, &item->elemType)); MOZ_TRY(CodeRefType(coder, &item->elemType));
MOZ_TRY((CodeMaybe<mode, InitExpr, &CodeInitExpr<mode>>( MOZ_TRY((CodeMaybe<mode, InitExpr, &CodeInitExpr<mode>>(
coder, &item->offsetIfActive))); coder, &item->offsetIfActive)));
MOZ_TRY(CodePodVector(coder, &item->elemFuncIndices)); MOZ_TRY(CodePodVector(coder, &item->elemFuncIndices));
@ -575,6 +638,18 @@ CoderResult CodeCustomSection(Coder<mode>& coder,
return Ok(); return Ok();
} }
template <CoderMode mode>
CoderResult CodeTableDesc(Coder<mode>& coder, CoderArg<mode, TableDesc> item) {
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::TableDesc, 48);
MOZ_TRY(CodeRefType(coder, &item->elemType));
MOZ_TRY(CodePod(coder, &item->isImportedOrExported));
MOZ_TRY(CodePod(coder, &item->isAsmJS));
MOZ_TRY(CodePod(coder, &item->globalDataOffset));
MOZ_TRY(CodePod(coder, &item->initialLength));
MOZ_TRY(CodePod(coder, &item->maximumLength));
return Ok();
}
// WasmCodegenTypes.h // WasmCodegenTypes.h
template <CoderMode mode> template <CoderMode mode>
@ -805,7 +880,8 @@ CoderResult CodeMetadata(Coder<mode>& coder,
MOZ_TRY((CodePod(coder, &item->typeIdsOffsetStart))); MOZ_TRY((CodePod(coder, &item->typeIdsOffsetStart)));
MOZ_TRY((CodeVector<mode, GlobalDesc, &CodeGlobalDesc<mode>>( MOZ_TRY((CodeVector<mode, GlobalDesc, &CodeGlobalDesc<mode>>(
coder, &item->globals))); coder, &item->globals)));
MOZ_TRY(CodePodVector(coder, &item->tables)); MOZ_TRY((
CodeVector<mode, TableDesc, &CodeTableDesc<mode>>(coder, &item->tables)));
MOZ_TRY((CodeVector<mode, TagDesc, &CodeTagDesc<mode>>(coder, &item->tags))); MOZ_TRY((CodeVector<mode, TagDesc, &CodeTagDesc<mode>>(coder, &item->tags)));
MOZ_TRY(CodePod(coder, &item->moduleName)); MOZ_TRY(CodePod(coder, &item->moduleName));
MOZ_TRY(CodePodVector(coder, &item->funcNames)); MOZ_TRY(CodePodVector(coder, &item->funcNames));

Просмотреть файл

@ -217,12 +217,8 @@ struct StructField {
FieldType type; FieldType type;
uint32_t offset; uint32_t offset;
bool isMutable; bool isMutable;
WASM_CHECK_CACHEABLE_POD(type, offset, isMutable);
}; };
WASM_DECLARE_CACHEABLE_POD(StructField);
using StructFieldVector = Vector<StructField, 0, SystemAllocPolicy>; using StructFieldVector = Vector<StructField, 0, SystemAllocPolicy>;
class StructType { class StructType {
@ -300,9 +296,8 @@ class ArrayType {
FieldType elementType_; // field type FieldType elementType_; // field type
bool isMutable_; // mutability bool isMutable_; // mutability
WASM_CHECK_CACHEABLE_POD(elementType_, isMutable_);
public: public:
ArrayType() : isMutable_(false) {}
ArrayType(FieldType elementType, bool isMutable) ArrayType(FieldType elementType, bool isMutable)
: elementType_(elementType), isMutable_(isMutable) {} : elementType_(elementType), isMutable_(isMutable) {}

Просмотреть файл

@ -57,8 +57,6 @@ union PackedTypeCode {
PackedRepr pointerTag_ : PointerTagBits; PackedRepr pointerTag_ : PointerTagBits;
}; };
WASM_CHECK_CACHEABLE_POD(bits_);
public: public:
static constexpr uint32_t NoTypeCode = (1 << TypeCodeBits) - 1; static constexpr uint32_t NoTypeCode = (1 << TypeCodeBits) - 1;
static constexpr uint32_t NoTypeIndex = (1 << TypeIndexBits) - 1; static constexpr uint32_t NoTypeIndex = (1 << TypeIndexBits) - 1;
@ -162,11 +160,7 @@ union PackedTypeCode {
} }
}; };
WASM_DECLARE_CACHEABLE_POD(PackedTypeCode);
static_assert(sizeof(PackedTypeCode) == sizeof(uint32_t), "packed"); static_assert(sizeof(PackedTypeCode) == sizeof(uint32_t), "packed");
static_assert(std::is_pod_v<PackedTypeCode>,
"must be POD to be simply serialized/deserialized");
// An enum that describes the representation classes for tables; The table // An enum that describes the representation classes for tables; The table
// element type is mapped into this by Table::repr(). // element type is mapped into this by Table::repr().
@ -188,8 +182,6 @@ class RefType {
private: private:
PackedTypeCode ptc_; PackedTypeCode ptc_;
WASM_CHECK_CACHEABLE_POD(ptc_);
#ifdef DEBUG #ifdef DEBUG
bool isValid() const { bool isValid() const {
switch (ptc_.typeCode()) { switch (ptc_.typeCode()) {
@ -265,8 +257,6 @@ class RefType {
bool operator!=(const RefType& that) const { return ptc_ != that.ptc_; } bool operator!=(const RefType& that) const { return ptc_ != that.ptc_; }
}; };
WASM_DECLARE_CACHEABLE_POD(RefType);
class FieldTypeTraits { class FieldTypeTraits {
public: public:
enum Kind { enum Kind {
@ -415,8 +405,6 @@ class PackedType : public T {
protected: protected:
PackedTypeCode tc_; PackedTypeCode tc_;
WASM_CHECK_CACHEABLE_POD(tc_);
explicit PackedType(TypeCode c) : tc_(PackedTypeCode::pack(c)) { explicit PackedType(TypeCode c) : tc_(PackedTypeCode::pack(c)) {
MOZ_ASSERT(c != AbstractReferenceTypeIndexCode); MOZ_ASSERT(c != AbstractReferenceTypeIndexCode);
MOZ_ASSERT(isValid()); MOZ_ASSERT(isValid());
@ -692,9 +680,6 @@ class PackedType : public T {
using ValType = PackedType<ValTypeTraits>; using ValType = PackedType<ValTypeTraits>;
using FieldType = PackedType<FieldTypeTraits>; using FieldType = PackedType<FieldTypeTraits>;
WASM_DECLARE_CACHEABLE_POD(ValType);
WASM_DECLARE_CACHEABLE_POD(FieldType);
// The dominant use of this data type is for locals and args, and profiling // The dominant use of this data type is for locals and args, and profiling
// with ZenGarden and Tanks suggests an initial size of 16 minimises heap // with ZenGarden and Tanks suggests an initial size of 16 minimises heap
// allocation, both in terms of blocks and bytes. // allocation, both in terms of blocks and bytes.

Просмотреть файл

@ -276,21 +276,18 @@ class LitVal {
Cell() : v128_() {} Cell() : v128_() {}
~Cell() = default; ~Cell() = default;
WASM_CHECK_CACHEABLE_POD(i32_, i64_, f32_, f64_, v128_);
WASM_ALLOW_NON_CACHEABLE_POD_FIELD(
ref_,
"The pointer value in ref_ is guaranteed to always be null in a "
"LitVal.");
}; };
protected: protected:
ValType type_; ValType type_;
Cell cell_; Cell cell_;
// We check the fields of cell_ here instead of in the union to avoid a
// template issue. In addition, Cell is only cacheable POD when used in
// LitVal and not Val, so checking here makes sense.
WASM_CHECK_CACHEABLE_POD(type_, cell_.i32_, cell_.i64_, cell_.f32_,
cell_.f64_, cell_.v128_);
WASM_ALLOW_NON_CACHEABLE_POD_FIELD(
cell_.ref_,
"The pointer value in ref_ is guaranteed to always be null in a LitVal.");
public: public:
LitVal() : type_(ValType()), cell_{} {} LitVal() : type_(ValType()), cell_{} {}
@ -369,9 +366,11 @@ class LitVal {
MOZ_ASSERT(type_ == ValType::V128); MOZ_ASSERT(type_ == ValType::V128);
return cell_.v128_; return cell_.v128_;
} }
WASM_DECLARE_FRIEND_SERIALIZE(LitVal);
}; };
WASM_DECLARE_CACHEABLE_POD(LitVal); WASM_DECLARE_CACHEABLE_POD(LitVal::Cell);
// A Val is a LitVal that can contain (non-null) pointers to GC things. All Vals // A Val is a LitVal that can contain (non-null) pointers to GC things. All Vals
// must be used with the rooting APIs as they may contain JS objects. // must be used with the rooting APIs as they may contain JS objects.