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

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

@ -412,16 +412,56 @@ CoderResult CodeShareableBytes(Coder<mode>& coder,
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
template <CoderMode mode>
CoderResult CodeInitExpr(Coder<mode>& coder, CoderArg<mode, InitExpr> item) {
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::InitExpr, 80);
MOZ_TRY(CodePod(coder, &item->kind_));
MOZ_TRY(CodePod(coder, &item->type_));
MOZ_TRY(CodeValType(coder, &item->type_));
switch (item->kind_) {
case InitExprKind::Literal:
MOZ_TRY(CodePod(coder, &item->literal_));
MOZ_TRY(CodeLitVal(coder, &item->literal_));
break;
case InitExprKind::Variable:
MOZ_TRY(CodePodVector(coder, &item->bytecode_));
@ -437,21 +477,40 @@ CoderResult CodeInitExpr(Coder<mode>& coder, CoderArg<mode, InitExpr> item) {
template <CoderMode mode>
CoderResult CodeFuncType(Coder<mode>& coder, CoderArg<mode, FuncType> item) {
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::FuncType, 208);
MOZ_TRY(CodePodVector(coder, &item->results_));
MOZ_TRY(CodePodVector(coder, &item->args_));
MOZ_TRY((CodeVector<mode, ValType, &CodeValType<mode>>(coder, &item->args_)));
MOZ_TRY(
(CodeVector<mode, ValType, &CodeValType<mode>>(coder, &item->results_)));
MOZ_TRY(CodePod(coder, &item->immediateTypeId_));
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>
CoderResult CodeStructType(Coder<mode>& coder,
CoderArg<mode, StructType> item) {
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_));
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>
CoderResult CodeTypeDef(Coder<mode>& coder, CoderArg<mode, TypeDef> item) {
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::TypeDef, 216);
@ -477,7 +536,10 @@ CoderResult CodeTypeDef(Coder<mode>& coder, CoderArg<mode, TypeDef> item) {
break;
}
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;
}
case TypeDefKind::None: {
@ -525,7 +587,8 @@ CoderResult CodeGlobalDesc(Coder<mode>& coder,
template <CoderMode mode>
CoderResult CodeTagType(Coder<mode>& coder, CoderArg<mode, TagType> item) {
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(CodePod(coder, &item->size_));
return Ok();
@ -548,7 +611,7 @@ CoderResult CodeElemSegment(Coder<mode>& coder,
WASM_VERIFY_SERIALIZATION_FOR_SIZE(wasm::ElemSegment, 184);
MOZ_TRY(CodePod(coder, &item->kind));
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>>(
coder, &item->offsetIfActive)));
MOZ_TRY(CodePodVector(coder, &item->elemFuncIndices));
@ -575,6 +638,18 @@ CoderResult CodeCustomSection(Coder<mode>& coder,
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
template <CoderMode mode>
@ -805,7 +880,8 @@ CoderResult CodeMetadata(Coder<mode>& coder,
MOZ_TRY((CodePod(coder, &item->typeIdsOffsetStart)));
MOZ_TRY((CodeVector<mode, GlobalDesc, &CodeGlobalDesc<mode>>(
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(CodePod(coder, &item->moduleName));
MOZ_TRY(CodePodVector(coder, &item->funcNames));

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

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

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

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

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

@ -276,21 +276,18 @@ class LitVal {
Cell() : v128_() {}
~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:
ValType type_;
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:
LitVal() : type_(ValType()), cell_{} {}
@ -369,9 +366,11 @@ class LitVal {
MOZ_ASSERT(type_ == ValType::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
// must be used with the rooting APIs as they may contain JS objects.