зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1290421: Throw ahead of time on statically known out-of-bounds; r=sunfish
MozReview-Commit-ID: Bj5MKn9w3vw --HG-- extra : rebase_source : e70fab6c482de3ceffaac876f3e6beee69f778a6
This commit is contained in:
Родитель
c8aa291733
Коммит
6abe4661c1
|
@ -698,6 +698,19 @@ class FunctionCompiler
|
|||
}
|
||||
|
||||
private:
|
||||
// False means we're sure to be out-of-bounds after this bounds check.
|
||||
bool maybeAddBoundsCheck(MDefinition* base, const MWasmMemoryAccess& access)
|
||||
{
|
||||
if (access.offset() > uint32_t(INT32_MAX)) {
|
||||
curBlock_->end(MWasmTrap::New(alloc(), Trap::OutOfBounds));
|
||||
curBlock_ = nullptr;
|
||||
return false;
|
||||
}
|
||||
if (!mg().usesSignal.forOOB)
|
||||
curBlock_->add(MWasmBoundsCheck::New(alloc(), base, access));
|
||||
return true;
|
||||
}
|
||||
|
||||
MDefinition* loadHeapPrivate(MDefinition* base, const MWasmMemoryAccess& access,
|
||||
bool isInt64 = false)
|
||||
{
|
||||
|
@ -708,8 +721,8 @@ class FunctionCompiler
|
|||
if (mg().isAsmJS()) {
|
||||
load = MAsmJSLoadHeap::New(alloc(), base, access);
|
||||
} else {
|
||||
if (!mg().usesSignal.forOOB)
|
||||
curBlock_->add(MWasmBoundsCheck::New(alloc(), base, access));
|
||||
if (!maybeAddBoundsCheck(base, access))
|
||||
return nullptr;
|
||||
load = MWasmLoad::New(alloc(), base, access, isInt64);
|
||||
}
|
||||
|
||||
|
@ -726,8 +739,8 @@ class FunctionCompiler
|
|||
if (mg().isAsmJS()) {
|
||||
store = MAsmJSStoreHeap::New(alloc(), base, access, v);
|
||||
} else {
|
||||
if (!mg().usesSignal.forOOB)
|
||||
curBlock_->add(MWasmBoundsCheck::New(alloc(), base, access));
|
||||
if (!maybeAddBoundsCheck(base, access))
|
||||
return;
|
||||
store = MWasmStore::New(alloc(), base, access, v);
|
||||
}
|
||||
|
||||
|
@ -1109,7 +1122,7 @@ class FunctionCompiler
|
|||
if (inDeadCode())
|
||||
return;
|
||||
|
||||
auto* ins = MAsmThrowUnreachable::New(alloc());
|
||||
auto* ins = MWasmTrap::New(alloc(), wasm::Trap::Unreachable);
|
||||
curBlock_->end(ins);
|
||||
curBlock_ = nullptr;
|
||||
}
|
||||
|
|
|
@ -11520,10 +11520,10 @@ CodeGenerator::visitAsmJSInterruptCheck(LAsmJSInterruptCheck* lir)
|
|||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitAsmThrowUnreachable(LAsmThrowUnreachable* lir)
|
||||
CodeGenerator::visitWasmTrap(LWasmTrap* lir)
|
||||
{
|
||||
MOZ_ASSERT(gen->compilingAsmJS());
|
||||
masm.jump(wasm::JumpTarget::Unreachable);
|
||||
masm.jump(wasm::JumpTarget(lir->mir()->trap()));
|
||||
}
|
||||
|
||||
typedef bool (*RecompileFn)(JSContext*);
|
||||
|
|
|
@ -415,7 +415,7 @@ class CodeGenerator final : public CodeGeneratorSpecific
|
|||
void visitInterruptCheck(LInterruptCheck* lir);
|
||||
void visitOutOfLineInterruptCheckImplicit(OutOfLineInterruptCheckImplicit* ins);
|
||||
void visitAsmJSInterruptCheck(LAsmJSInterruptCheck* lir);
|
||||
void visitAsmThrowUnreachable(LAsmThrowUnreachable* lir);
|
||||
void visitWasmTrap(LWasmTrap* lir);
|
||||
void visitRecompileCheck(LRecompileCheck* ins);
|
||||
void visitRotate(LRotate* ins);
|
||||
|
||||
|
|
|
@ -2530,9 +2530,9 @@ LIRGenerator::visitAsmJSInterruptCheck(MAsmJSInterruptCheck* ins)
|
|||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitAsmThrowUnreachable(MAsmThrowUnreachable* ins)
|
||||
LIRGenerator::visitWasmTrap(MWasmTrap* ins)
|
||||
{
|
||||
add(new(alloc()) LAsmThrowUnreachable, ins);
|
||||
add(new(alloc()) LWasmTrap, ins);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -191,7 +191,7 @@ class LIRGenerator : public LIRGeneratorSpecific
|
|||
void visitFunctionEnvironment(MFunctionEnvironment* ins);
|
||||
void visitInterruptCheck(MInterruptCheck* ins);
|
||||
void visitAsmJSInterruptCheck(MAsmJSInterruptCheck* ins);
|
||||
void visitAsmThrowUnreachable(MAsmThrowUnreachable* ins);
|
||||
void visitWasmTrap(MWasmTrap* ins);
|
||||
void visitAsmReinterpret(MAsmReinterpret* ins);
|
||||
void visitStoreSlot(MStoreSlot* ins);
|
||||
void visitFilterTypeSet(MFilterTypeSet* ins);
|
||||
|
|
|
@ -7738,18 +7738,28 @@ class MAsmJSInterruptCheck
|
|||
TRIVIAL_NEW_WRAPPERS
|
||||
};
|
||||
|
||||
// Directly jumps to the unreachable trap handler.
|
||||
class MAsmThrowUnreachable
|
||||
// Directly jumps to the indicated trap, leaving Wasm code and reporting a
|
||||
// runtime error.
|
||||
|
||||
class MWasmTrap
|
||||
: public MAryControlInstruction<0, 0>,
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
wasm::Trap trap_;
|
||||
|
||||
explicit MWasmTrap(wasm::Trap trap)
|
||||
: trap_(trap)
|
||||
{}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(AsmThrowUnreachable)
|
||||
INSTRUCTION_HEADER(WasmTrap)
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::None();
|
||||
}
|
||||
|
||||
wasm::Trap trap() const { return trap_; }
|
||||
};
|
||||
|
||||
// Checks if a value is JS_UNINITIALIZED_LEXICAL, bailout out if so, leaving
|
||||
|
|
|
@ -262,7 +262,6 @@ namespace jit {
|
|||
_(CallInstanceOf) \
|
||||
_(InterruptCheck) \
|
||||
_(AsmJSInterruptCheck) \
|
||||
_(AsmThrowUnreachable) \
|
||||
_(GetDOMProperty) \
|
||||
_(GetDOMMember) \
|
||||
_(SetDOMProperty) \
|
||||
|
@ -274,6 +273,7 @@ namespace jit {
|
|||
_(WasmBoundsCheck) \
|
||||
_(WasmLoad) \
|
||||
_(WasmStore) \
|
||||
_(WasmTrap) \
|
||||
_(WasmTruncateToInt32) \
|
||||
_(AsmJSNeg) \
|
||||
_(AsmJSUnsignedToDouble) \
|
||||
|
|
|
@ -2291,11 +2291,7 @@ CodeGeneratorARM::visitWasmBoundsCheck(LWasmBoundsCheck* ins)
|
|||
{
|
||||
MWasmBoundsCheck* mir = ins->mir();
|
||||
|
||||
uint32_t offset = mir->offset();
|
||||
if (offset > INT32_MAX) {
|
||||
masm.as_b(wasm::JumpTarget::OutOfBounds);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mir->offset() <= INT32_MAX);
|
||||
|
||||
if (!mir->isRedundant()) {
|
||||
// No guarantee that heapBase + endOffset can be properly encoded in
|
||||
|
@ -2348,11 +2344,7 @@ CodeGeneratorARM::emitWasmLoad(T* lir)
|
|||
MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI");
|
||||
|
||||
uint32_t offset = mir->offset();
|
||||
if (offset > INT32_MAX) {
|
||||
// This is unreachable because of bounds checks.
|
||||
masm.breakpoint();
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(offset <= INT32_MAX);
|
||||
|
||||
Register ptr = ToRegister(lir->ptr());
|
||||
Scalar::Type type = mir->accessType();
|
||||
|
@ -2419,11 +2411,7 @@ CodeGeneratorARM::emitWasmUnalignedLoad(T* lir)
|
|||
MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI");
|
||||
|
||||
uint32_t offset = mir->offset();
|
||||
if (offset > INT32_MAX) {
|
||||
// This is unreachable because of bounds checks.
|
||||
masm.breakpoint();
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(offset <= INT32_MAX);
|
||||
|
||||
Register ptr = ToRegister(lir->ptrCopy());
|
||||
if (offset)
|
||||
|
@ -2503,11 +2491,7 @@ CodeGeneratorARM::emitWasmStore(T* lir)
|
|||
MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI");
|
||||
|
||||
uint32_t offset = mir->offset();
|
||||
if (offset > INT32_MAX) {
|
||||
// This is unreachable because of bounds checks.
|
||||
masm.breakpoint();
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(offset <= INT32_MAX);
|
||||
|
||||
Register ptr = ToRegister(lir->ptr());
|
||||
unsigned byteSize = mir->byteSize();
|
||||
|
|
|
@ -1666,10 +1666,7 @@ CodeGeneratorMIPSShared::visitWasmBoundsCheck(LWasmBoundsCheck* ins)
|
|||
MWasmBoundsCheck* mir = ins->mir();
|
||||
|
||||
uint32_t offset = mir->offset();
|
||||
if (offset > INT32_MAX) {
|
||||
masm.jump(wasm::JumpTarget::OutOfBounds);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(offset <= INT32_MAX);
|
||||
|
||||
uint32_t endOffset = mir->endOffset();
|
||||
Register ptr = ToRegister(ins->ptr());
|
||||
|
@ -1693,11 +1690,7 @@ CodeGeneratorMIPSShared::visitWasmLoad(LWasmLoad* lir)
|
|||
MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI");
|
||||
|
||||
uint32_t offset = mir->offset();
|
||||
if (offset > INT32_MAX) {
|
||||
// This is unreachable because of bounds checks.
|
||||
masm.breakpoint();
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(offset <= INT32_MAX);
|
||||
|
||||
Register ptr = ToRegister(lir->ptr());
|
||||
|
||||
|
@ -1745,11 +1738,7 @@ CodeGeneratorMIPSShared::visitWasmStore(LWasmStore* lir)
|
|||
MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI");
|
||||
|
||||
uint32_t offset = mir->offset();
|
||||
if (offset > INT32_MAX) {
|
||||
// This is unreachable because of bounds checks.
|
||||
masm.breakpoint();
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(offset <= INT32_MAX);
|
||||
|
||||
Register ptr = ToRegister(lir->ptr());
|
||||
|
||||
|
|
|
@ -1404,13 +1404,17 @@ class LAsmJSInterruptCheck : public LInstructionHelper<0, 0, 0>
|
|||
}
|
||||
};
|
||||
|
||||
class LAsmThrowUnreachable : public LInstructionHelper<0, 0, 0>
|
||||
class LWasmTrap : public LInstructionHelper<0, 0, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(AsmThrowUnreachable);
|
||||
LIR_HEADER(WasmTrap);
|
||||
|
||||
LAsmThrowUnreachable()
|
||||
LWasmTrap()
|
||||
{ }
|
||||
|
||||
const MWasmTrap* mir() const {
|
||||
return mir_->toWasmTrap();
|
||||
}
|
||||
};
|
||||
|
||||
template<size_t Defs, size_t Ops>
|
||||
|
|
|
@ -369,7 +369,7 @@
|
|||
_(CallInstanceOf) \
|
||||
_(InterruptCheck) \
|
||||
_(AsmJSInterruptCheck) \
|
||||
_(AsmThrowUnreachable) \
|
||||
_(WasmTrap) \
|
||||
_(AsmReinterpret) \
|
||||
_(AsmReinterpretToI64) \
|
||||
_(AsmReinterpretFromI64) \
|
||||
|
|
|
@ -538,11 +538,7 @@ CodeGeneratorX64::emitWasmLoad(T* ins)
|
|||
Scalar::Type accessType = mir->accessType();
|
||||
MOZ_ASSERT(!Scalar::isSimdType(accessType), "SIMD NYI");
|
||||
MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI");
|
||||
|
||||
if (mir->offset() > INT32_MAX) {
|
||||
masm.jump(wasm::JumpTarget::OutOfBounds);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mir->offset() <= INT32_MAX);
|
||||
|
||||
const LAllocation* ptr = ins->ptr();
|
||||
Operand srcAddr = ptr->isBogus()
|
||||
|
@ -583,11 +579,7 @@ CodeGeneratorX64::emitWasmStore(T* ins)
|
|||
Scalar::Type accessType = mir->accessType();
|
||||
MOZ_ASSERT(!Scalar::isSimdType(accessType), "SIMD NYI");
|
||||
MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI");
|
||||
|
||||
if (mir->offset() > INT32_MAX) {
|
||||
masm.jump(wasm::JumpTarget::OutOfBounds);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mir->offset() <= INT32_MAX);
|
||||
|
||||
const LAllocation* value = ins->getOperand(ins->ValueIndex);
|
||||
const LAllocation* ptr = ins->ptr();
|
||||
|
|
|
@ -494,11 +494,9 @@ void
|
|||
CodeGeneratorX86Shared::visitWasmBoundsCheck(LWasmBoundsCheck* ins)
|
||||
{
|
||||
const MWasmBoundsCheck* mir = ins->mir();
|
||||
|
||||
MOZ_ASSERT(gen->needsBoundsCheckBranch(mir));
|
||||
if (mir->offset() > INT32_MAX) {
|
||||
masm.jump(wasm::JumpTarget::OutOfBounds);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mir->offset() <= INT32_MAX);
|
||||
|
||||
Register ptrReg = ToRegister(ins->ptr());
|
||||
maybeEmitWasmBoundsCheckBranch(mir, ptrReg, mir->isRedundant());
|
||||
|
@ -548,9 +546,8 @@ CodeGeneratorX86Shared::maybeEmitWasmBoundsCheckBranch(const MWasmMemoryAccess*
|
|||
|
||||
MOZ_ASSERT(mir->endOffset() >= 1,
|
||||
"need to subtract 1 to use JAE, see also AssemblerX86Shared::UpdateBoundsCheck");
|
||||
/*
|
||||
* TODO: See 1287224 Unify MWasmBoundsCheck::redunant_ and needsBoundsCheck
|
||||
*/
|
||||
|
||||
// TODO: See 1287224 Unify MWasmBoundsCheck::redunant_ and needsBoundsCheck
|
||||
if (!redundant) {
|
||||
uint32_t cmpOffset = masm.cmp32WithPatch(ptr, Imm32(1 - mir->endOffset())).offset();
|
||||
masm.j(Assembler::AboveOrEqual, wasm::JumpTarget::OutOfBounds);
|
||||
|
|
|
@ -500,12 +500,7 @@ CodeGeneratorX86::emitWasmLoad(T* ins)
|
|||
Scalar::Type accessType = mir->accessType();
|
||||
MOZ_ASSERT(!Scalar::isSimdType(accessType), "SIMD NYI");
|
||||
MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI");
|
||||
|
||||
if (mir->offset() > INT32_MAX) {
|
||||
// This is unreachable because of the bounds check.
|
||||
masm.breakpoint();
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mir->offset() <= INT32_MAX);
|
||||
|
||||
const LAllocation* ptr = ins->ptr();
|
||||
Operand srcAddr = ptr->isBogus()
|
||||
|
@ -539,12 +534,7 @@ CodeGeneratorX86::emitWasmStore(T* ins)
|
|||
Scalar::Type accessType = mir->accessType();
|
||||
MOZ_ASSERT(!Scalar::isSimdType(accessType), "SIMD NYI");
|
||||
MOZ_ASSERT(!mir->barrierBefore() && !mir->barrierAfter(), "atomics NYI");
|
||||
|
||||
if (mir->offset() > INT32_MAX) {
|
||||
// This is unreachable because of the bounds check.
|
||||
masm.breakpoint();
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mir->offset() <= INT32_MAX);
|
||||
|
||||
const LAllocation* ptr = ins->ptr();
|
||||
Operand dstAddr = ptr->isBogus()
|
||||
|
|
Загрузка…
Ссылка в новой задаче