mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1229399: Implement write/readVarU32 and use it for locals/globals; r=luke
This commit is contained in:
parent
c848138c5a
commit
5746c4ca9e
@ -2696,20 +2696,24 @@ class MOZ_STACK_CLASS FunctionValidator
|
||||
}
|
||||
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool writeU8(uint8_t u) {
|
||||
return encoder().writeU8(u);
|
||||
bool writeU8(uint8_t u8) {
|
||||
return encoder().writeU8(u8);
|
||||
}
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool writeU32(uint32_t u) {
|
||||
return encoder().writeU32(u);
|
||||
bool writeVarU32(uint32_t u32) {
|
||||
return encoder().writeVarU32(u32);
|
||||
}
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool writeI32(int32_t u) {
|
||||
return encoder().writeI32(u);
|
||||
bool writeU32(uint32_t u32) {
|
||||
return encoder().writeU32(u32);
|
||||
}
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool writeInt32Lit(int32_t i) {
|
||||
return writeOp(Expr::I32Literal) && encoder().writeI32(i);
|
||||
bool writeI32(int32_t i32) {
|
||||
return encoder().writeI32(i32);
|
||||
}
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
bool writeInt32Lit(int32_t i32) {
|
||||
return writeOp(Expr::I32Literal) && encoder().writeI32(i32);
|
||||
}
|
||||
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
@ -3406,7 +3410,7 @@ SetLocal(FunctionValidator& f, Expr exprStmt, NumLit lit)
|
||||
{
|
||||
return f.writeOp(exprStmt) &&
|
||||
f.writeOp(Expr::SetLocal) &&
|
||||
f.writeU32(f.numLocals()) &&
|
||||
f.writeVarU32(f.numLocals()) &&
|
||||
f.writeLit(lit);
|
||||
}
|
||||
|
||||
@ -3509,7 +3513,7 @@ CheckVarRef(FunctionValidator& f, ParseNode* varRef, Type* type)
|
||||
if (!f.writeOp(Expr::GetLocal))
|
||||
return false;
|
||||
MOZ_ASSERT(local->type != ValType::I64, "no int64 in asm.js");
|
||||
if (!f.writeU32(local->slot))
|
||||
if (!f.writeVarU32(local->slot))
|
||||
return false;
|
||||
*type = Type::var(local->type);
|
||||
return true;
|
||||
@ -3524,7 +3528,7 @@ CheckVarRef(FunctionValidator& f, ParseNode* varRef, Type* type)
|
||||
case ModuleValidator::Global::Variable: {
|
||||
*type = global->varOrConstType();
|
||||
return f.writeOp(Expr::LoadGlobal) &&
|
||||
f.writeU32(global->varOrConstGlobalDataOffset()) &&
|
||||
f.writeVarU32(global->varOrConstGlobalDataOffset()) &&
|
||||
f.writeU8(uint8_t(global->isConst()));
|
||||
}
|
||||
case ModuleValidator::Global::Function:
|
||||
@ -3815,25 +3819,19 @@ CheckAssignName(FunctionValidator& f, ParseNode* lhs, ParseNode* rhs, Type* type
|
||||
{
|
||||
RootedPropertyName name(f.cx(), lhs->name());
|
||||
|
||||
size_t opcodeAt;
|
||||
size_t indexAt;
|
||||
if (!f.tempOp(&opcodeAt) || !f.temp32(&indexAt))
|
||||
return false;
|
||||
|
||||
Type rhsType;
|
||||
if (!CheckExpr(f, rhs, &rhsType))
|
||||
return false;
|
||||
|
||||
if (const FunctionValidator::Local* lhsVar = f.lookupLocal(name)) {
|
||||
if (!f.writeOp(Expr::SetLocal) || !f.writeVarU32(lhsVar->slot))
|
||||
return false;
|
||||
|
||||
Type rhsType;
|
||||
if (!CheckExpr(f, rhs, &rhsType))
|
||||
return false;
|
||||
|
||||
if (!(rhsType <= lhsVar->type)) {
|
||||
return f.failf(lhs, "%s is not a subtype of %s",
|
||||
rhsType.toChars(), Type::var(lhsVar->type).toChars());
|
||||
}
|
||||
|
||||
MOZ_ASSERT(lhsVar->type != ValType::I64, "no int64 in asm.js");
|
||||
|
||||
f.patchOp(opcodeAt, Expr::SetLocal);
|
||||
f.patch32(indexAt, lhsVar->slot);
|
||||
*type = rhsType;
|
||||
return true;
|
||||
}
|
||||
@ -3842,13 +3840,16 @@ CheckAssignName(FunctionValidator& f, ParseNode* lhs, ParseNode* rhs, Type* type
|
||||
if (global->which() != ModuleValidator::Global::Variable)
|
||||
return f.failName(lhs, "'%s' is not a mutable variable", name);
|
||||
|
||||
if (!(rhsType <= global->varOrConstType())) {
|
||||
return f.failf(lhs, "%s is not a subtype of %s",
|
||||
rhsType.toChars(), global->varOrConstType().toChars());
|
||||
}
|
||||
if (!f.writeOp(Expr::StoreGlobal) || !f.writeVarU32(global->varOrConstGlobalDataOffset()))
|
||||
return false;
|
||||
|
||||
f.patchOp(opcodeAt, Expr::StoreGlobal);
|
||||
f.patch32(indexAt, global->varOrConstGlobalDataOffset());
|
||||
Type rhsType;
|
||||
if (!CheckExpr(f, rhs, &rhsType))
|
||||
return false;
|
||||
|
||||
Type globType = global->varOrConstType();
|
||||
if (!(rhsType <= globType))
|
||||
return f.failf(lhs, "%s is not a subtype of %s", rhsType.toChars(), globType.toChars());
|
||||
*type = rhsType;
|
||||
return true;
|
||||
}
|
||||
|
@ -398,7 +398,7 @@ class Encoder
|
||||
done_(false)
|
||||
{}
|
||||
|
||||
bool init(UniqueBytecode bytecode) {
|
||||
bool init(UniqueBytecode bytecode = UniqueBytecode()) {
|
||||
if (bytecode) {
|
||||
bytecode_ = mozilla::Move(bytecode);
|
||||
bytecode_->clear();
|
||||
@ -417,6 +417,19 @@ class Encoder
|
||||
return mozilla::Move(bytecode_);
|
||||
}
|
||||
|
||||
MOZ_WARN_UNUSED_RESULT bool
|
||||
writeVarU32(uint32_t i) {
|
||||
do {
|
||||
uint8_t byte = i & 0x7F;
|
||||
i >>= 7;
|
||||
if (i != 0)
|
||||
byte |= 0x80;
|
||||
if (!writeU8(byte))
|
||||
return false;
|
||||
} while(i != 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_WARN_UNUSED_RESULT bool
|
||||
writeU8(uint8_t i, size_t* offset = nullptr) { return write<uint8_t>(i, offset); }
|
||||
MOZ_WARN_UNUSED_RESULT bool
|
||||
@ -546,6 +559,26 @@ class Decoder
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_WARN_UNUSED_RESULT bool readVarU32(uint32_t* decoded) {
|
||||
*decoded = 0;
|
||||
uint8_t byte;
|
||||
uint32_t shift = 0;
|
||||
do {
|
||||
if (!readU8(&byte))
|
||||
return false;
|
||||
if (!(byte & 0x80)) {
|
||||
*decoded |= uint32_t(byte & 0x7F) << shift;
|
||||
return true;
|
||||
}
|
||||
*decoded |= uint32_t(byte & 0x7F) << shift;
|
||||
shift += 7;
|
||||
} while (shift != 28);
|
||||
if (!readU8(&byte) || (byte & 0xF0))
|
||||
return false;
|
||||
*decoded |= uint32_t(byte) << 28;
|
||||
return true;
|
||||
}
|
||||
|
||||
// The infallible unpacking API should be used when we are sure that the
|
||||
// bytecode is well-formed.
|
||||
uint8_t uncheckedReadU8 () { return uncheckedRead<uint8_t>(); }
|
||||
@ -567,6 +600,25 @@ class Decoder
|
||||
v[i] = uncheckedReadF32();
|
||||
return jit::SimdConstant::CreateX4(v[0], v[1], v[2], v[3]);
|
||||
}
|
||||
|
||||
uint32_t uncheckedReadVarU32() {
|
||||
uint32_t decoded = 0;
|
||||
uint32_t shift = 0;
|
||||
uint8_t byte;
|
||||
do {
|
||||
byte = uncheckedReadU8();
|
||||
if (!(byte & 0x80)) {
|
||||
decoded |= uint32_t(byte & 0x7F) << shift;
|
||||
return decoded;
|
||||
}
|
||||
decoded |= uint32_t(byte & 0x7F) << shift;
|
||||
shift += 7;
|
||||
} while (shift != 28);
|
||||
byte = uncheckedReadU8();
|
||||
MOZ_ASSERT(!(byte & 0xF0));
|
||||
decoded |= uint32_t(byte) << 28;
|
||||
return decoded;
|
||||
}
|
||||
};
|
||||
|
||||
// Source coordinates for a call site. As they're read sequentially, we
|
||||
|
@ -1170,6 +1170,7 @@ class FunctionCompiler
|
||||
|
||||
uint8_t readU8() { return decoder_.uncheckedReadU8(); }
|
||||
uint32_t readU32() { return decoder_.uncheckedReadU32(); }
|
||||
uint32_t readVarU32() { return decoder_.uncheckedReadVarU32(); }
|
||||
int32_t readI32() { return decoder_.uncheckedReadI32(); }
|
||||
float readF32() { return decoder_.uncheckedReadF32(); }
|
||||
double readF64() { return decoder_.uncheckedReadF64(); }
|
||||
@ -1330,7 +1331,7 @@ EmitLiteral(FunctionCompiler& f, ValType type, MDefinition**def)
|
||||
static bool
|
||||
EmitGetLocal(FunctionCompiler& f, const DebugOnly<MIRType>& type, MDefinition** def)
|
||||
{
|
||||
uint32_t slot = f.readU32();
|
||||
uint32_t slot = f.readVarU32();
|
||||
*def = f.getLocalDef(slot);
|
||||
MOZ_ASSERT_IF(*def, (*def)->type() == type);
|
||||
return true;
|
||||
@ -1339,7 +1340,7 @@ EmitGetLocal(FunctionCompiler& f, const DebugOnly<MIRType>& type, MDefinition**
|
||||
static bool
|
||||
EmitLoadGlobal(FunctionCompiler& f, MIRType type, MDefinition** def)
|
||||
{
|
||||
uint32_t globalDataOffset = f.readU32();
|
||||
uint32_t globalDataOffset = f.readVarU32();
|
||||
bool isConst = bool(f.readU8());
|
||||
*def = f.loadGlobalVar(globalDataOffset, isConst, type);
|
||||
return true;
|
||||
@ -1429,7 +1430,7 @@ EmitStoreWithCoercion(FunctionCompiler& f, Scalar::Type rhsType, Scalar::Type vi
|
||||
static bool
|
||||
EmitSetLocal(FunctionCompiler& f, ValType type, MDefinition** def)
|
||||
{
|
||||
uint32_t slot = f.readU32();
|
||||
uint32_t slot = f.readVarU32();
|
||||
MDefinition* expr;
|
||||
if (!EmitExpr(f, type, &expr))
|
||||
return false;
|
||||
@ -1441,7 +1442,7 @@ EmitSetLocal(FunctionCompiler& f, ValType type, MDefinition** def)
|
||||
static bool
|
||||
EmitStoreGlobal(FunctionCompiler& f, ValType type, MDefinition**def)
|
||||
{
|
||||
uint32_t globalDataOffset = f.readU32();
|
||||
uint32_t globalDataOffset = f.readVarU32();
|
||||
MDefinition* expr;
|
||||
if (!EmitExpr(f, type, &expr))
|
||||
return false;
|
||||
|
@ -86,6 +86,7 @@ UNIFIED_SOURCES += [
|
||||
'testUbiNode.cpp',
|
||||
'testUncaughtError.cpp',
|
||||
'testUTF8.cpp',
|
||||
'testWasmLEB128.cpp',
|
||||
'testWeakMap.cpp',
|
||||
'testXDR.cpp',
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user