зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1607440 - Introduce the Opcode abstraction. r=bbouvier
The `Opcode` wraps an `Op`, and if the `Op` is a prefix it also carries the secondary opcode bits. Implicit constructors from `Op`, `MiscOp`, etc to `Opcode`, ensures that this will be pretty painless to use. Differential Revision: https://phabricator.services.mozilla.com/D58940 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
15cf5c2afd
Коммит
6fa8ac7e16
|
@ -169,9 +169,7 @@ class WasmToken {
|
|||
int64_t sint_;
|
||||
FloatLiteralKind floatLiteralKind_;
|
||||
ValType valueType_;
|
||||
Op op_;
|
||||
MiscOp miscOp_;
|
||||
ThreadOp threadOp_;
|
||||
Opcode opcode_;
|
||||
U() : index_(0) {}
|
||||
} u;
|
||||
|
||||
|
@ -211,30 +209,26 @@ class WasmToken {
|
|||
MOZ_ASSERT(kind_ == ValueType || kind_ == Const);
|
||||
u.valueType_ = valueType;
|
||||
}
|
||||
explicit WasmToken(Kind kind, Op op, const char16_t* begin,
|
||||
explicit WasmToken(Kind kind, Opcode op, const char16_t* begin,
|
||||
const char16_t* end)
|
||||
: kind_(kind), begin_(begin), end_(end) {
|
||||
MOZ_ASSERT(begin != end);
|
||||
MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode ||
|
||||
kind_ == ComparisonOpcode || kind_ == ConversionOpcode ||
|
||||
kind_ == Load || kind_ == Store);
|
||||
u.op_ = op;
|
||||
}
|
||||
explicit WasmToken(Kind kind, MiscOp op, const char16_t* begin,
|
||||
const char16_t* end)
|
||||
: kind_(kind), begin_(begin), end_(end) {
|
||||
MOZ_ASSERT(begin != end);
|
||||
MOZ_ASSERT(kind_ == ExtraConversionOpcode);
|
||||
u.miscOp_ = op;
|
||||
}
|
||||
explicit WasmToken(Kind kind, ThreadOp op, const char16_t* begin,
|
||||
const char16_t* end)
|
||||
: kind_(kind), begin_(begin), end_(end) {
|
||||
MOZ_ASSERT(begin != end);
|
||||
MOZ_ASSERT(kind_ == AtomicCmpXchg || kind_ == AtomicLoad ||
|
||||
kind_ == AtomicRMW || kind_ == AtomicStore || kind_ == Wait ||
|
||||
kind_ == Wake || kind_ == Fence);
|
||||
u.threadOp_ = op;
|
||||
#ifdef DEBUG
|
||||
if (op.isOp()) {
|
||||
MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode ||
|
||||
kind_ == ComparisonOpcode || kind_ == ConversionOpcode ||
|
||||
kind_ == Load || kind_ == Store);
|
||||
} else if (op.isMisc()) {
|
||||
MOZ_ASSERT(kind_ == ExtraConversionOpcode);
|
||||
} else if (op.isThread()) {
|
||||
MOZ_ASSERT(kind_ == AtomicCmpXchg || kind_ == AtomicLoad ||
|
||||
kind_ == AtomicRMW || kind_ == AtomicStore || kind_ == Wait ||
|
||||
kind_ == Wake || kind_ == Fence);
|
||||
} else {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
#endif
|
||||
u.opcode_ = op;
|
||||
}
|
||||
explicit WasmToken(const char16_t* begin)
|
||||
: kind_(Error), begin_(begin), end_(begin), u{} {}
|
||||
|
@ -276,17 +270,17 @@ class WasmToken {
|
|||
MOZ_ASSERT(kind_ == UnaryOpcode || kind_ == BinaryOpcode ||
|
||||
kind_ == ComparisonOpcode || kind_ == ConversionOpcode ||
|
||||
kind_ == Load || kind_ == Store);
|
||||
return u.op_;
|
||||
return u.opcode_.asOp();
|
||||
}
|
||||
MiscOp miscOp() const {
|
||||
MOZ_ASSERT(kind_ == ExtraConversionOpcode);
|
||||
return u.miscOp_;
|
||||
return u.opcode_.asMisc();
|
||||
}
|
||||
ThreadOp threadOp() const {
|
||||
MOZ_ASSERT(kind_ == AtomicCmpXchg || kind_ == AtomicLoad ||
|
||||
kind_ == AtomicRMW || kind_ == AtomicStore || kind_ == Wait ||
|
||||
kind_ == Wake);
|
||||
return u.threadOp_;
|
||||
return u.opcode_.asThread();
|
||||
}
|
||||
bool isOpcode() const {
|
||||
switch (kind_) {
|
||||
|
|
|
@ -202,6 +202,61 @@ struct ShareableBytes : ShareableBase<ShareableBytes> {
|
|||
typedef RefPtr<ShareableBytes> MutableBytes;
|
||||
typedef RefPtr<const ShareableBytes> SharedBytes;
|
||||
|
||||
// The Opcode compactly and safely represents the primary opcode plus any
|
||||
// extension, with convenient predicates and accessors.
|
||||
|
||||
class Opcode {
|
||||
uint32_t bits_;
|
||||
|
||||
public:
|
||||
MOZ_IMPLICIT Opcode(Op op) : bits_(uint32_t(op)) {
|
||||
static_assert(size_t(Op::Limit) == 256, "fits");
|
||||
MOZ_ASSERT(size_t(op) < size_t(Op::Limit));
|
||||
}
|
||||
MOZ_IMPLICIT Opcode(MiscOp op)
|
||||
: bits_((uint32_t(op) << 8) | uint32_t(Op::MiscPrefix)) {
|
||||
static_assert(size_t(MiscOp::Limit) <= 0xFFFFFF, "fits");
|
||||
MOZ_ASSERT(size_t(op) < size_t(MiscOp::Limit));
|
||||
}
|
||||
MOZ_IMPLICIT Opcode(ThreadOp op)
|
||||
: bits_((uint32_t(op) << 8) | uint32_t(Op::ThreadPrefix)) {
|
||||
static_assert(size_t(ThreadOp::Limit) <= 0xFFFFFF, "fits");
|
||||
MOZ_ASSERT(size_t(op) < size_t(ThreadOp::Limit));
|
||||
}
|
||||
MOZ_IMPLICIT Opcode(MozOp op)
|
||||
: bits_((uint32_t(op) << 8) | uint32_t(Op::MozPrefix)) {
|
||||
static_assert(size_t(MozOp::Limit) <= 0xFFFFFF, "fits");
|
||||
MOZ_ASSERT(size_t(op) < size_t(MozOp::Limit));
|
||||
}
|
||||
|
||||
bool isOp() const { return bits_ < uint32_t(Op::FirstPrefix); }
|
||||
bool isMisc() const { return (bits_ & 255) == uint32_t(Op::MiscPrefix); }
|
||||
bool isThread() const { return (bits_ & 255) == uint32_t(Op::ThreadPrefix); }
|
||||
bool isMoz() const { return (bits_ & 255) == uint32_t(Op::MozPrefix); }
|
||||
|
||||
Op asOp() const {
|
||||
MOZ_ASSERT(isOp());
|
||||
return Op(bits_);
|
||||
}
|
||||
MiscOp asMisc() const {
|
||||
MOZ_ASSERT(isMisc());
|
||||
return MiscOp(bits_ >> 8);
|
||||
}
|
||||
ThreadOp asThread() const {
|
||||
MOZ_ASSERT(isThread());
|
||||
return ThreadOp(bits_ >> 8);
|
||||
}
|
||||
MozOp asMoz() const {
|
||||
MOZ_ASSERT(isMoz());
|
||||
return MozOp(bits_ >> 8);
|
||||
}
|
||||
|
||||
uint32_t bits() const { return bits_; }
|
||||
|
||||
bool operator==(const Opcode& that) const { return bits_ == that.bits_; }
|
||||
bool operator!=(const Opcode& that) const { return bits_ != that.bits_; }
|
||||
};
|
||||
|
||||
// A PackedTypeCode represents a TypeCode paired with a refTypeIndex (valid only
|
||||
// for TypeCode::Ref). PackedTypeCode is guaranteed to be POD. The TypeCode
|
||||
// spans the full range of type codes including the specialized AnyRef, FuncRef,
|
||||
|
|
|
@ -441,6 +441,18 @@ class Encoder {
|
|||
MOZ_ASSERT(size_t(op) < size_t(MozOp::Limit));
|
||||
return writeFixedU8(uint8_t(Op::MozPrefix)) && writeVarU32(uint32_t(op));
|
||||
}
|
||||
MOZ_MUST_USE bool writeOp(Opcode opcode) {
|
||||
// The Opcode constructor has asserted that `opcode` is meaningful, so no
|
||||
// further correctness checking is necessary here.
|
||||
uint32_t bits = opcode.bits();
|
||||
if (!writeFixedU8(bits & 255)) {
|
||||
return false;
|
||||
}
|
||||
if (opcode.isOp()) {
|
||||
return true;
|
||||
}
|
||||
return writeVarU32(bits >> 8);
|
||||
}
|
||||
|
||||
// Fixed-length encodings that allow back-patching.
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче