diff --git a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp index c1b40dbebdb1..b38a38675125 100644 --- a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp +++ b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp @@ -1654,6 +1654,136 @@ CodeGeneratorMIPSShared::visitAsmJSCall(LAsmJSCall* ins) emitAsmJSCall(ins); } +void +CodeGeneratorMIPSShared::visitWasmBoundsCheck(LWasmBoundsCheck* ins) +{ + MWasmBoundsCheck* mir = ins->mir(); + + uint32_t offset = mir->offset(); + if (offset > INT32_MAX) { + masm.jump(wasm::JumpTarget::OutOfBounds); + return; + } + + uint32_t endOffset = mir->endOffset(); + Register ptr = ToRegister(ins->ptr()); + + masm.move32(Imm32(endOffset), SecondScratchReg); + masm.addPtr(ptr, SecondScratchReg); + + // Detect unsigned overflow. + masm.ma_b(SecondScratchReg, ptr, wasm::JumpTarget::OutOfBounds, Assembler::LessThan); + + BufferOffset bo = masm.ma_BoundsCheck(ScratchRegister); + masm.ma_b(SecondScratchReg, ScratchRegister, wasm::JumpTarget::OutOfBounds, Assembler::Above); + masm.append(wasm::BoundsCheck(bo.getOffset())); +} + +void +CodeGeneratorMIPSShared::visitWasmLoad(LWasmLoad* lir) +{ + const MWasmLoad* mir = lir->mir(); + + 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; + } + + Register ptr = ToRegister(lir->ptr()); + + // Maybe add the offset. + if (offset) { + Register ptrPlusOffset = ToRegister(lir->ptrCopy()); + masm.addPtr(Imm32(offset), ptrPlusOffset); + ptr = ptrPlusOffset; + } else { + MOZ_ASSERT(lir->ptrCopy()->isBogusTemp()); + } + + unsigned byteSize = mir->byteSize(); + bool isSigned; + bool isFloat = false; + + switch (mir->accessType()) { + case Scalar::Int8: isSigned = true; break; + case Scalar::Uint8: isSigned = false; break; + case Scalar::Int16: isSigned = true; break; + case Scalar::Uint16: isSigned = false; break; + case Scalar::Int32: isSigned = true; break; + case Scalar::Uint32: isSigned = false; break; + case Scalar::Float64: isFloat = true; break; + case Scalar::Float32: isFloat = true; break; + default: MOZ_CRASH("unexpected array type"); + } + + if (isFloat) { + if (byteSize == 4) { + masm.loadFloat32(BaseIndex(HeapReg, ptr, TimesOne), ToFloatRegister(lir->output())); + } else + masm.loadDouble(BaseIndex(HeapReg, ptr, TimesOne), ToFloatRegister(lir->output())); + } else { + masm.ma_load(ToRegister(lir->output()), BaseIndex(HeapReg, ptr, TimesOne), + static_cast(8 * byteSize), isSigned ? SignExtend : ZeroExtend); + } +} + +void +CodeGeneratorMIPSShared::visitWasmStore(LWasmStore* lir) +{ + const MWasmStore* mir = lir->mir(); + + 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; + } + + Register ptr = ToRegister(lir->ptr()); + + // Maybe add the offset. + if (offset) { + Register ptrPlusOffset = ToRegister(lir->ptrCopy()); + masm.addPtr(Imm32(offset), ptrPlusOffset); + ptr = ptrPlusOffset; + } else { + MOZ_ASSERT(lir->ptrCopy()->isBogusTemp()); + } + + unsigned byteSize = mir->byteSize(); + bool isSigned; + bool isFloat = false; + + switch (mir->accessType()) { + case Scalar::Int8: isSigned = true; break; + case Scalar::Uint8: isSigned = false; break; + case Scalar::Int16: isSigned = true; break; + case Scalar::Uint16: isSigned = false; break; + case Scalar::Int32: isSigned = true; break; + case Scalar::Uint32: isSigned = false; break; + case Scalar::Int64: isSigned = true; break; + case Scalar::Float64: isFloat = true; break; + case Scalar::Float32: isFloat = true; break; + default: MOZ_CRASH("unexpected array type"); + } + + if (isFloat) { + if (byteSize == 4) { + masm.storeFloat32(ToFloatRegister(lir->value()), BaseIndex(HeapReg, ptr, TimesOne)); + } else + masm.storeDouble(ToFloatRegister(lir->value()), BaseIndex(HeapReg, ptr, TimesOne)); + } else { + masm.ma_store(ToRegister(lir->value()), BaseIndex(HeapReg, ptr, TimesOne), + static_cast(8 * byteSize), isSigned ? SignExtend : ZeroExtend); + } +} + void CodeGeneratorMIPSShared::visitAsmJSLoadHeap(LAsmJSLoadHeap* ins) { diff --git a/js/src/jit/mips-shared/CodeGenerator-mips-shared.h b/js/src/jit/mips-shared/CodeGenerator-mips-shared.h index 00648dda1969..1dddfc407c68 100644 --- a/js/src/jit/mips-shared/CodeGenerator-mips-shared.h +++ b/js/src/jit/mips-shared/CodeGenerator-mips-shared.h @@ -193,6 +193,9 @@ class CodeGeneratorMIPSShared : public CodeGeneratorShared void visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins); void visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins); void visitAsmJSCall(LAsmJSCall* ins); + void visitWasmBoundsCheck(LWasmBoundsCheck* ins); + void visitWasmLoad(LWasmLoad* ins); + void visitWasmStore(LWasmStore* ins); void visitAsmJSLoadHeap(LAsmJSLoadHeap* ins); void visitAsmJSStoreHeap(LAsmJSStoreHeap* ins); void visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins);