зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1639153 - Part 6.6: Add tls dependency for truncate i32. r=lth
We generate builtin call for MTruncateToInt32 operation for floating points types, so we need to add a tls dependency. I inserted NYI for arm64 because Ion doesn't support arm64. Differential Revision: https://phabricator.services.mozilla.com/D89550
This commit is contained in:
Родитель
116a97dbec
Коммит
5bc9230be0
|
@ -2381,6 +2381,16 @@ void LIRGenerator::visitWasmTruncateToInt32(MWasmTruncateToInt32* ins) {
|
|||
}
|
||||
}
|
||||
|
||||
void LIRGenerator::visitWasmBuiltinTruncateToInt32(
|
||||
MWasmBuiltinTruncateToInt32* truncate) {
|
||||
mozilla::DebugOnly<MDefinition*> opd = truncate->input();
|
||||
MOZ_ASSERT(opd->type() == MIRType::Double || opd->type() == MIRType::Float32);
|
||||
|
||||
// May call into JS::ToInt32() on the slow OOL path.
|
||||
gen->setNeedsStaticStackAlignment();
|
||||
lowerWasmBuiltinTruncateToInt32(truncate);
|
||||
}
|
||||
|
||||
void LIRGenerator::visitWasmBoxValue(MWasmBoxValue* ins) {
|
||||
LWasmBoxValue* lir = new (alloc()) LWasmBoxValue(useBox(ins->input()));
|
||||
define(lir, ins);
|
||||
|
|
|
@ -4455,6 +4455,41 @@ class MTruncateToInt32 : public MUnaryInstruction, public ToInt32Policy::Data {
|
|||
ALLOW_CLONE(MTruncateToInt32)
|
||||
};
|
||||
|
||||
// It is like MTruncateToInt32 but with tls dependency.
|
||||
class MWasmBuiltinTruncateToInt32 : public MAryInstruction<2>,
|
||||
public ToInt32Policy::Data {
|
||||
wasm::BytecodeOffset bytecodeOffset_;
|
||||
|
||||
MWasmBuiltinTruncateToInt32(
|
||||
MDefinition* def, MDefinition* tls,
|
||||
wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset())
|
||||
: MAryInstruction(classOpcode), bytecodeOffset_(bytecodeOffset) {
|
||||
initOperand(0, def);
|
||||
initOperand(1, tls);
|
||||
setResultType(MIRType::Int32);
|
||||
setMovable();
|
||||
|
||||
// Guard unless the conversion is known to be non-effectful & non-throwing.
|
||||
if (MTruncateToInt32::mightHaveSideEffects(def)) {
|
||||
setGuard();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(WasmBuiltinTruncateToInt32)
|
||||
NAMED_OPERANDS((0, input), (1, tls))
|
||||
TRIVIAL_NEW_WRAPPERS
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
}
|
||||
AliasSet getAliasSet() const override { return AliasSet::None(); }
|
||||
|
||||
wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
|
||||
|
||||
ALLOW_CLONE(MWasmBuiltinTruncateToInt32)
|
||||
};
|
||||
|
||||
// Converts a primitive (either typed or untyped) to a BigInt. If the input is
|
||||
// not primitive at runtime, a bailout occurs.
|
||||
class MToBigInt : public MUnaryInstruction, public ToBigIntPolicy::Data {
|
||||
|
|
|
@ -2443,6 +2443,11 @@ void MacroAssembler::outOfLineTruncateSlow(FloatRegister src, Register dest,
|
|||
bool widenFloatToDouble,
|
||||
bool compilingWasm,
|
||||
wasm::BytecodeOffset callOffset) {
|
||||
if (compilingWasm) {
|
||||
Push(WasmTlsReg);
|
||||
}
|
||||
int32_t framePushedAfterTls = framePushed();
|
||||
|
||||
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) || \
|
||||
defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
|
||||
ScratchDoubleScope fpscratch(*this);
|
||||
|
@ -2467,9 +2472,11 @@ void MacroAssembler::outOfLineTruncateSlow(FloatRegister src, Register dest,
|
|||
MOZ_ASSERT(src.isDouble());
|
||||
|
||||
if (compilingWasm) {
|
||||
int32_t tlsOffset = framePushed() - framePushedAfterTls;
|
||||
setupWasmABICall();
|
||||
passABIArg(src, MoveOp::DOUBLE);
|
||||
callWithABI(callOffset, wasm::SymbolicAddress::ToInt32, mozilla::Nothing());
|
||||
callWithABI(callOffset, wasm::SymbolicAddress::ToInt32,
|
||||
mozilla::Some(tlsOffset));
|
||||
} else {
|
||||
setupUnalignedABICall(dest);
|
||||
passABIArg(src, MoveOp::DOUBLE);
|
||||
|
@ -2488,6 +2495,10 @@ void MacroAssembler::outOfLineTruncateSlow(FloatRegister src, Register dest,
|
|||
#else
|
||||
MOZ_CRASH("MacroAssembler platform hook: outOfLineTruncateSlow");
|
||||
#endif
|
||||
|
||||
if (compilingWasm) {
|
||||
Pop(WasmTlsReg);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::convertDoubleToInt(FloatRegister src, Register output,
|
||||
|
@ -3136,31 +3147,20 @@ CodeOffset MacroAssembler::callWithABI(wasm::BytecodeOffset bytecode,
|
|||
MoveOp::Type result) {
|
||||
MOZ_ASSERT(wasm::NeedsBuiltinThunk(imm));
|
||||
|
||||
// We clobber WasmTlsReg below in the loadWasmTlsRegFromFrame(), but Ion
|
||||
// assumes it is non-volatile, so preserve it manually.
|
||||
Push(WasmTlsReg);
|
||||
|
||||
uint32_t stackAdjust;
|
||||
callWithABIPre(&stackAdjust, /* callFromWasm = */ true);
|
||||
|
||||
// The TLS register is used in builtin thunks and must be set, by ABI:
|
||||
// reload it after passing arguments, which might have used it at spill
|
||||
// points when placing arguments.
|
||||
|
||||
// The TLS register is used in builtin thunks and must be set, by ABI.
|
||||
if (tlsOffset) {
|
||||
// Account for stackAdjust and Push(WasmTlsReg).
|
||||
*tlsOffset += stackAdjust + sizeof(void*);
|
||||
loadPtr(Address(getStackPointer(), *tlsOffset), WasmTlsReg);
|
||||
loadPtr(Address(getStackPointer(), *tlsOffset + stackAdjust), WasmTlsReg);
|
||||
} else {
|
||||
loadWasmTlsRegFromFrame();
|
||||
MOZ_CRASH("This can be only for an unsupported architecture.");
|
||||
}
|
||||
CodeOffset raOffset = call(
|
||||
wasm::CallSiteDesc(bytecode.offset(), wasm::CallSite::Symbolic), imm);
|
||||
|
||||
callWithABIPost(stackAdjust, result, /* callFromWasm = */ true);
|
||||
|
||||
Pop(WasmTlsReg);
|
||||
|
||||
return raOffset;
|
||||
}
|
||||
|
||||
|
|
|
@ -1195,11 +1195,23 @@ void CodeGenerator::visitTruncateDToInt32(LTruncateDToInt32* ins) {
|
|||
ins->mir());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitWasmBuiltinTruncateDToInt32(
|
||||
LWasmBuiltinTruncateDToInt32* ins) {
|
||||
emitTruncateDouble(ToFloatRegister(ins->getOperand(0)),
|
||||
ToRegister(ins->getDef(0)), ins->mir());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitTruncateFToInt32(LTruncateFToInt32* ins) {
|
||||
emitTruncateFloat32(ToFloatRegister(ins->input()), ToRegister(ins->output()),
|
||||
ins->mir());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitWasmBuiltinTruncateFToInt32(
|
||||
LWasmBuiltinTruncateFToInt32* ins) {
|
||||
emitTruncateFloat32(ToFloatRegister(ins->getOperand(0)),
|
||||
ToRegister(ins->getDef(0)), ins->mir());
|
||||
}
|
||||
|
||||
static const uint32_t FrameSizes[] = {128, 256, 512, 1024};
|
||||
|
||||
FrameSizeClass FrameSizeClass::FromDepth(uint32_t frameDepth) {
|
||||
|
|
|
@ -262,6 +262,25 @@ void LIRGeneratorARM::lowerForBitAndAndBranch(LBitAndAndBranch* baab,
|
|||
add(baab, mir);
|
||||
}
|
||||
|
||||
void LIRGeneratorARM::lowerWasmBuiltinTruncateToInt32(
|
||||
MWasmBuiltinTruncateToInt32* ins) {
|
||||
MDefinition* opd = ins->input();
|
||||
MOZ_ASSERT(opd->type() == MIRType::Double || opd->type() == MIRType::Float32);
|
||||
|
||||
if (opd->type() == MIRType::Double) {
|
||||
define(new (alloc()) LWasmBuiltinTruncateDToInt32(
|
||||
useRegister(opd), useFixedAtStart(ins->tls(), WasmTlsReg),
|
||||
LDefinition::BogusTemp()),
|
||||
ins);
|
||||
return;
|
||||
}
|
||||
|
||||
define(new (alloc()) LWasmBuiltinTruncateFToInt32(
|
||||
useRegister(opd), useFixedAtStart(ins->tls(), WasmTlsReg),
|
||||
LDefinition::BogusTemp()),
|
||||
ins);
|
||||
}
|
||||
|
||||
void LIRGeneratorARM::lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition,
|
||||
LBlock* block, size_t lirIndex) {
|
||||
MDefinition* operand = phi->getOperand(inputPosition);
|
||||
|
|
|
@ -69,6 +69,7 @@ class LIRGeneratorARM : public LIRGeneratorShared {
|
|||
void lowerWasmBuiltinTruncateToInt64(MWasmBuiltinTruncateToInt64* ins);
|
||||
void lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction* mir,
|
||||
MDefinition* lhs, MDefinition* rhs);
|
||||
void lowerWasmBuiltinTruncateToInt32(MWasmBuiltinTruncateToInt32* ins);
|
||||
void lowerTruncateDToInt32(MTruncateToInt32* ins);
|
||||
void lowerTruncateFToInt32(MTruncateToInt32* ins);
|
||||
void lowerDivI(MDiv* div);
|
||||
|
|
|
@ -1162,11 +1162,21 @@ void CodeGenerator::visitTruncateDToInt32(LTruncateDToInt32* ins) {
|
|||
ins->mir());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitWasmBuiltinTruncateDToInt32(
|
||||
LWasmBuiltinTruncateDToInt32* lir) {
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
void CodeGenerator::visitTruncateFToInt32(LTruncateFToInt32* ins) {
|
||||
emitTruncateFloat32(ToFloatRegister(ins->input()), ToRegister(ins->output()),
|
||||
ins->mir());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitWasmBuiltinTruncateFToInt32(
|
||||
LWasmBuiltinTruncateFToInt32* lir) {
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
FrameSizeClass FrameSizeClass::FromDepth(uint32_t frameDepth) {
|
||||
return FrameSizeClass::None();
|
||||
}
|
||||
|
|
|
@ -186,6 +186,11 @@ void LIRGeneratorARM64::lowerForBitAndAndBranch(LBitAndAndBranch* baab,
|
|||
add(baab, mir);
|
||||
}
|
||||
|
||||
void LIRGeneratorARM64::lowerWasmBuiltinTruncateToInt32(
|
||||
MWasmBuiltinTruncateToInt32* ins) {
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
void LIRGeneratorARM64::lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition,
|
||||
LBlock* block, size_t lirIndex) {
|
||||
lowerTypedPhiInput(phi, inputPosition, block, lirIndex);
|
||||
|
|
|
@ -72,6 +72,7 @@ class LIRGeneratorARM64 : public LIRGeneratorShared {
|
|||
void lowerWasmBuiltinTruncateToInt64(MWasmBuiltinTruncateToInt64* ins);
|
||||
void lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction* mir,
|
||||
MDefinition* lhs, MDefinition* rhs);
|
||||
void lowerWasmBuiltinTruncateToInt32(MWasmBuiltinTruncateToInt32* ins);
|
||||
void lowerTruncateDToInt32(MTruncateToInt32* ins);
|
||||
void lowerTruncateFToInt32(MTruncateToInt32* ins);
|
||||
void lowerDivI(MDiv* div);
|
||||
|
|
|
@ -1130,6 +1130,16 @@ void CodeGenerator::visitTruncateFToInt32(LTruncateFToInt32* ins) {
|
|||
ins->mir());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitWasmBuiltinTruncateDToInt32(
|
||||
LWasmBuiltinTruncateDToInt32* lir) {
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
void CodeGenerator::visitWasmBuiltinTruncateFToInt32(
|
||||
LWasmBuiltinTruncateFToInt32* lir) {
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
void CodeGenerator::visitWasmTruncateToInt32(LWasmTruncateToInt32* lir) {
|
||||
auto input = ToFloatRegister(lir->input());
|
||||
auto output = ToRegister(lir->output());
|
||||
|
|
|
@ -180,6 +180,11 @@ void LIRGeneratorMIPSShared::lowerForBitAndAndBranch(LBitAndAndBranch* baab,
|
|||
add(baab, mir);
|
||||
}
|
||||
|
||||
void LIRGeneratorMIPSShared::lowerWasmBuiltinTruncateToInt32(
|
||||
MWasmBuiltinTruncateToInt32* ins) {
|
||||
MOZ_CRASH("NYI");
|
||||
}
|
||||
|
||||
void LIRGeneratorMIPSShared::lowerForShift(LInstructionHelper<1, 2, 0>* ins,
|
||||
MDefinition* mir, MDefinition* lhs,
|
||||
MDefinition* rhs) {
|
||||
|
|
|
@ -55,6 +55,7 @@ class LIRGeneratorMIPSShared : public LIRGeneratorShared {
|
|||
|
||||
void lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction* mir,
|
||||
MDefinition* lhs, MDefinition* rhs);
|
||||
void lowerWasmBuiltinTruncateToInt32(MWasmBuiltinTruncateToInt32* ins);
|
||||
void lowerDivI(MDiv* div);
|
||||
void lowerModI(MMod* mod);
|
||||
void lowerMulI(MMul* mul, MDefinition* lhs, MDefinition* rhs);
|
||||
|
|
|
@ -78,6 +78,9 @@ class LIRGeneratorNone : public LIRGeneratorShared {
|
|||
void lowerWasmBuiltinTruncateToInt64(MWasmBuiltinTruncateToInt64* ins) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
void lowerWasmBuiltinTruncateToInt32(MWasmBuiltinTruncateToInt32* ins) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
void lowerDivI(MDiv*) { MOZ_CRASH(); }
|
||||
void lowerModI(MMod*) { MOZ_CRASH(); }
|
||||
void lowerDivI64(MDiv*) { MOZ_CRASH(); }
|
||||
|
|
|
@ -886,15 +886,18 @@ class OutOfLineTruncateSlow : public OutOfLineCodeBase<CodeGeneratorShared> {
|
|||
Register dest_;
|
||||
bool widenFloatToDouble_;
|
||||
wasm::BytecodeOffset bytecodeOffset_;
|
||||
bool preserveTls_;
|
||||
|
||||
public:
|
||||
OutOfLineTruncateSlow(
|
||||
FloatRegister src, Register dest, bool widenFloatToDouble = false,
|
||||
wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset())
|
||||
wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset(),
|
||||
bool preserveTls = false)
|
||||
: src_(src),
|
||||
dest_(dest),
|
||||
widenFloatToDouble_(widenFloatToDouble),
|
||||
bytecodeOffset_(bytecodeOffset) {}
|
||||
bytecodeOffset_(bytecodeOffset),
|
||||
preserveTls_(preserveTls) {}
|
||||
|
||||
void accept(CodeGeneratorShared* codegen) override {
|
||||
codegen->visitOutOfLineTruncateSlow(this);
|
||||
|
@ -902,32 +905,43 @@ class OutOfLineTruncateSlow : public OutOfLineCodeBase<CodeGeneratorShared> {
|
|||
FloatRegister src() const { return src_; }
|
||||
Register dest() const { return dest_; }
|
||||
bool widenFloatToDouble() const { return widenFloatToDouble_; }
|
||||
bool preserveTls() const { return preserveTls_; }
|
||||
wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
|
||||
};
|
||||
|
||||
OutOfLineCode* CodeGeneratorShared::oolTruncateDouble(
|
||||
FloatRegister src, Register dest, MInstruction* mir,
|
||||
wasm::BytecodeOffset bytecodeOffset) {
|
||||
wasm::BytecodeOffset bytecodeOffset, bool preserveTls) {
|
||||
MOZ_ASSERT_IF(IsCompilingWasm(), bytecodeOffset.isValid());
|
||||
|
||||
OutOfLineTruncateSlow* ool = new (alloc())
|
||||
OutOfLineTruncateSlow(src, dest, /* float32 */ false, bytecodeOffset);
|
||||
OutOfLineTruncateSlow* ool = new (alloc()) OutOfLineTruncateSlow(
|
||||
src, dest, /* float32 */ false, bytecodeOffset, preserveTls);
|
||||
addOutOfLineCode(ool, mir);
|
||||
return ool;
|
||||
}
|
||||
|
||||
void CodeGeneratorShared::emitTruncateDouble(FloatRegister src, Register dest,
|
||||
MTruncateToInt32* mir) {
|
||||
OutOfLineCode* ool = oolTruncateDouble(src, dest, mir, mir->bytecodeOffset());
|
||||
MInstruction* mir) {
|
||||
MOZ_ASSERT(mir->isTruncateToInt32() || mir->isWasmBuiltinTruncateToInt32());
|
||||
wasm::BytecodeOffset bytecodeOffset =
|
||||
mir->isTruncateToInt32()
|
||||
? mir->toTruncateToInt32()->bytecodeOffset()
|
||||
: mir->toWasmBuiltinTruncateToInt32()->bytecodeOffset();
|
||||
OutOfLineCode* ool = oolTruncateDouble(src, dest, mir, bytecodeOffset);
|
||||
|
||||
masm.branchTruncateDoubleMaybeModUint32(src, dest, ool->entry());
|
||||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
void CodeGeneratorShared::emitTruncateFloat32(FloatRegister src, Register dest,
|
||||
MTruncateToInt32* mir) {
|
||||
OutOfLineTruncateSlow* ool = new (alloc()) OutOfLineTruncateSlow(
|
||||
src, dest, /* float32 */ true, mir->bytecodeOffset());
|
||||
MInstruction* mir) {
|
||||
MOZ_ASSERT(mir->isTruncateToInt32() || mir->isWasmBuiltinTruncateToInt32());
|
||||
wasm::BytecodeOffset bytecodeOffset =
|
||||
mir->isTruncateToInt32()
|
||||
? mir->toTruncateToInt32()->bytecodeOffset()
|
||||
: mir->toWasmBuiltinTruncateToInt32()->bytecodeOffset();
|
||||
OutOfLineTruncateSlow* ool = new (alloc())
|
||||
OutOfLineTruncateSlow(src, dest, /* float32 */ true, bytecodeOffset);
|
||||
addOutOfLineCode(ool, mir);
|
||||
|
||||
masm.branchTruncateFloat32MaybeModUint32(src, dest, ool->entry());
|
||||
|
|
|
@ -279,11 +279,10 @@ class CodeGeneratorShared : public LElementVisitor {
|
|||
|
||||
OutOfLineCode* oolTruncateDouble(
|
||||
FloatRegister src, Register dest, MInstruction* mir,
|
||||
wasm::BytecodeOffset callOffset = wasm::BytecodeOffset());
|
||||
void emitTruncateDouble(FloatRegister src, Register dest,
|
||||
MTruncateToInt32* mir);
|
||||
void emitTruncateFloat32(FloatRegister src, Register dest,
|
||||
MTruncateToInt32* mir);
|
||||
wasm::BytecodeOffset callOffset = wasm::BytecodeOffset(),
|
||||
bool preserveTls = false);
|
||||
void emitTruncateDouble(FloatRegister src, Register dest, MInstruction* mir);
|
||||
void emitTruncateFloat32(FloatRegister src, Register dest, MInstruction* mir);
|
||||
|
||||
void emitPreBarrier(Register elements, const LAllocation* index);
|
||||
void emitPreBarrier(Address address);
|
||||
|
|
|
@ -3156,6 +3156,27 @@ class LTruncateDToInt32 : public LInstructionHelper<1, 1, 1> {
|
|||
MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); }
|
||||
};
|
||||
|
||||
// Convert a double to a truncated int32 with tls offset because we need it for
|
||||
// the slow ool path.
|
||||
class LWasmBuiltinTruncateDToInt32 : public LInstructionHelper<1, 2, 1> {
|
||||
public:
|
||||
LIR_HEADER(WasmBuiltinTruncateDToInt32)
|
||||
|
||||
LWasmBuiltinTruncateDToInt32(const LAllocation& in, const LAllocation& tls,
|
||||
const LDefinition& temp)
|
||||
: LInstructionHelper(classOpcode) {
|
||||
setOperand(0, in);
|
||||
setOperand(1, tls);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LDefinition* tempFloat() { return getTemp(0); }
|
||||
|
||||
MWasmBuiltinTruncateToInt32* mir() const {
|
||||
return mir_->toWasmBuiltinTruncateToInt32();
|
||||
}
|
||||
};
|
||||
|
||||
// Convert a float32 to a truncated int32.
|
||||
// Input: floating-point register
|
||||
// Output: 32-bit integer
|
||||
|
@ -3174,6 +3195,27 @@ class LTruncateFToInt32 : public LInstructionHelper<1, 1, 1> {
|
|||
MTruncateToInt32* mir() const { return mir_->toTruncateToInt32(); }
|
||||
};
|
||||
|
||||
// Convert a float32 to a truncated int32 with tls offset because we need it for
|
||||
// the slow ool path.
|
||||
class LWasmBuiltinTruncateFToInt32 : public LInstructionHelper<1, 2, 1> {
|
||||
public:
|
||||
LIR_HEADER(WasmBuiltinTruncateFToInt32)
|
||||
|
||||
LWasmBuiltinTruncateFToInt32(const LAllocation& in, const LAllocation& tls,
|
||||
const LDefinition& temp)
|
||||
: LInstructionHelper(classOpcode) {
|
||||
setOperand(0, in);
|
||||
setOperand(1, tls);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LDefinition* tempFloat() { return getTemp(0); }
|
||||
|
||||
MWasmBuiltinTruncateToInt32* mir() const {
|
||||
return mir_->toWasmBuiltinTruncateToInt32();
|
||||
}
|
||||
};
|
||||
|
||||
class LWasmTruncateToInt32 : public LInstructionHelper<1, 1, 0> {
|
||||
public:
|
||||
LIR_HEADER(WasmTruncateToInt32)
|
||||
|
|
|
@ -578,6 +578,22 @@ void CodeGenerator::visitTruncateDToInt32(LTruncateDToInt32* ins) {
|
|||
emitTruncateDouble(input, output, ins->mir());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitWasmBuiltinTruncateDToInt32(
|
||||
LWasmBuiltinTruncateDToInt32* lir) {
|
||||
FloatRegister input = ToFloatRegister(lir->getOperand(0));
|
||||
Register output = ToRegister(lir->getDef(0));
|
||||
|
||||
emitTruncateDouble(input, output, lir->mir());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitWasmBuiltinTruncateFToInt32(
|
||||
LWasmBuiltinTruncateFToInt32* lir) {
|
||||
FloatRegister input = ToFloatRegister(lir->getOperand(0));
|
||||
Register output = ToRegister(lir->getDef(0));
|
||||
|
||||
emitTruncateFloat32(input, output, lir->mir());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitTruncateFToInt32(LTruncateFToInt32* ins) {
|
||||
FloatRegister input = ToFloatRegister(ins->input());
|
||||
Register output = ToRegister(ins->output());
|
||||
|
|
|
@ -450,6 +450,25 @@ void LIRGeneratorX86Shared::lowerPowOfTwoI(MPow* mir) {
|
|||
define(lir, mir);
|
||||
}
|
||||
|
||||
void LIRGeneratorX86Shared::lowerWasmBuiltinTruncateToInt32(
|
||||
MWasmBuiltinTruncateToInt32* ins) {
|
||||
MDefinition* opd = ins->input();
|
||||
MOZ_ASSERT(opd->type() == MIRType::Double || opd->type() == MIRType::Float32);
|
||||
|
||||
LDefinition maybeTemp =
|
||||
Assembler::HasSSE3() ? LDefinition::BogusTemp() : tempDouble();
|
||||
if (opd->type() == MIRType::Double) {
|
||||
define(new (alloc()) LWasmBuiltinTruncateDToInt32(
|
||||
useRegister(opd), useFixed(ins->tls(), WasmTlsReg), maybeTemp),
|
||||
ins);
|
||||
return;
|
||||
}
|
||||
|
||||
define(new (alloc()) LWasmBuiltinTruncateFToInt32(
|
||||
useRegister(opd), useFixed(ins->tls(), WasmTlsReg), maybeTemp),
|
||||
ins);
|
||||
}
|
||||
|
||||
void LIRGeneratorX86Shared::lowerTruncateDToInt32(MTruncateToInt32* ins) {
|
||||
MDefinition* opd = ins->input();
|
||||
MOZ_ASSERT(opd->type() == MIRType::Double);
|
||||
|
|
|
@ -46,6 +46,7 @@ class LIRGeneratorX86Shared : public LIRGeneratorShared {
|
|||
void lowerUMod(MMod* mod);
|
||||
void lowerUrshD(MUrsh* mir);
|
||||
void lowerPowOfTwoI(MPow* mir);
|
||||
void lowerWasmBuiltinTruncateToInt32(MWasmBuiltinTruncateToInt32* ins);
|
||||
void lowerTruncateDToInt32(MTruncateToInt32* ins);
|
||||
void lowerTruncateFToInt32(MTruncateToInt32* ins);
|
||||
void lowerCompareExchangeTypedArrayElement(
|
||||
|
|
|
@ -508,27 +508,55 @@ namespace js {
|
|||
namespace jit {
|
||||
|
||||
class OutOfLineTruncate : public OutOfLineCodeBase<CodeGeneratorX86> {
|
||||
LTruncateDToInt32* ins_;
|
||||
LInstruction* ins_;
|
||||
|
||||
public:
|
||||
explicit OutOfLineTruncate(LTruncateDToInt32* ins) : ins_(ins) {}
|
||||
explicit OutOfLineTruncate(LInstruction* ins) : ins_(ins) {
|
||||
MOZ_ASSERT(ins_->isTruncateDToInt32() ||
|
||||
ins_->isWasmBuiltinTruncateDToInt32());
|
||||
}
|
||||
|
||||
void accept(CodeGeneratorX86* codegen) override {
|
||||
codegen->visitOutOfLineTruncate(this);
|
||||
}
|
||||
LTruncateDToInt32* ins() const { return ins_; }
|
||||
|
||||
LAllocation* input() { return ins_->getOperand(0); }
|
||||
LDefinition* output() { return ins_->getDef(0); }
|
||||
LDefinition* tempFloat() { return ins_->getTemp(0); }
|
||||
|
||||
wasm::BytecodeOffset bytecodeOffset() const {
|
||||
if (ins_->isTruncateDToInt32()) {
|
||||
return ins_->toTruncateDToInt32()->mir()->bytecodeOffset();
|
||||
}
|
||||
|
||||
return ins_->toWasmBuiltinTruncateDToInt32()->mir()->bytecodeOffset();
|
||||
}
|
||||
};
|
||||
|
||||
class OutOfLineTruncateFloat32 : public OutOfLineCodeBase<CodeGeneratorX86> {
|
||||
LTruncateFToInt32* ins_;
|
||||
LInstruction* ins_;
|
||||
|
||||
public:
|
||||
explicit OutOfLineTruncateFloat32(LTruncateFToInt32* ins) : ins_(ins) {}
|
||||
explicit OutOfLineTruncateFloat32(LInstruction* ins) : ins_(ins) {
|
||||
MOZ_ASSERT(ins_->isTruncateFToInt32() ||
|
||||
ins_->isWasmBuiltinTruncateFToInt32());
|
||||
}
|
||||
|
||||
void accept(CodeGeneratorX86* codegen) override {
|
||||
codegen->visitOutOfLineTruncateFloat32(this);
|
||||
}
|
||||
LTruncateFToInt32* ins() const { return ins_; }
|
||||
|
||||
LAllocation* input() { return ins_->getOperand(0); }
|
||||
LDefinition* output() { return ins_->getDef(0); }
|
||||
LDefinition* tempFloat() { return ins_->getTemp(0); }
|
||||
|
||||
wasm::BytecodeOffset bytecodeOffset() const {
|
||||
if (ins_->isTruncateFToInt32()) {
|
||||
return ins_->toTruncateDToInt32()->mir()->bytecodeOffset();
|
||||
}
|
||||
|
||||
return ins_->toWasmBuiltinTruncateFToInt32()->mir()->bytecodeOffset();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace jit
|
||||
|
@ -545,6 +573,18 @@ void CodeGenerator::visitTruncateDToInt32(LTruncateDToInt32* ins) {
|
|||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitWasmBuiltinTruncateDToInt32(
|
||||
LWasmBuiltinTruncateDToInt32* lir) {
|
||||
FloatRegister input = ToFloatRegister(lir->getOperand(0));
|
||||
Register output = ToRegister(lir->getDef(0));
|
||||
|
||||
OutOfLineTruncate* ool = new (alloc()) OutOfLineTruncate(lir);
|
||||
addOutOfLineCode(ool, lir->mir());
|
||||
|
||||
masm.branchTruncateDoubleMaybeModUint32(input, output, ool->entry());
|
||||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitTruncateFToInt32(LTruncateFToInt32* ins) {
|
||||
FloatRegister input = ToFloatRegister(ins->input());
|
||||
Register output = ToRegister(ins->output());
|
||||
|
@ -556,10 +596,21 @@ void CodeGenerator::visitTruncateFToInt32(LTruncateFToInt32* ins) {
|
|||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
void CodeGenerator::visitWasmBuiltinTruncateFToInt32(
|
||||
LWasmBuiltinTruncateFToInt32* lir) {
|
||||
FloatRegister input = ToFloatRegister(lir->getOperand(0));
|
||||
Register output = ToRegister(lir->getDef(0));
|
||||
|
||||
OutOfLineTruncateFloat32* ool = new (alloc()) OutOfLineTruncateFloat32(lir);
|
||||
addOutOfLineCode(ool, lir->mir());
|
||||
|
||||
masm.branchTruncateFloat32MaybeModUint32(input, output, ool->entry());
|
||||
masm.bind(ool->rejoin());
|
||||
}
|
||||
|
||||
void CodeGeneratorX86::visitOutOfLineTruncate(OutOfLineTruncate* ool) {
|
||||
LTruncateDToInt32* ins = ool->ins();
|
||||
FloatRegister input = ToFloatRegister(ins->input());
|
||||
Register output = ToRegister(ins->output());
|
||||
FloatRegister input = ToFloatRegister(ool->input());
|
||||
Register output = ToRegister(ool->output());
|
||||
|
||||
Label fail;
|
||||
|
||||
|
@ -584,7 +635,7 @@ void CodeGeneratorX86::visitOutOfLineTruncate(OutOfLineTruncate* ool) {
|
|||
masm.addl(Imm32(sizeof(double)), esp);
|
||||
masm.jump(&fail);
|
||||
} else {
|
||||
FloatRegister temp = ToFloatRegister(ins->tempFloat());
|
||||
FloatRegister temp = ToFloatRegister(ool->tempFloat());
|
||||
|
||||
// Try to convert doubles representing integers within 2^32 of a signed
|
||||
// integer, by adding/subtracting 2^32 and then trying to convert to int32.
|
||||
|
@ -622,13 +673,20 @@ void CodeGeneratorX86::visitOutOfLineTruncate(OutOfLineTruncate* ool) {
|
|||
|
||||
masm.bind(&fail);
|
||||
{
|
||||
if (gen->compilingWasm()) {
|
||||
masm.Push(WasmTlsReg);
|
||||
}
|
||||
int32_t framePushedAfterTls = masm.framePushed();
|
||||
|
||||
saveVolatile(output);
|
||||
|
||||
if (gen->compilingWasm()) {
|
||||
masm.setupWasmABICall();
|
||||
masm.passABIArg(input, MoveOp::DOUBLE);
|
||||
masm.callWithABI(ins->mir()->bytecodeOffset(),
|
||||
wasm::SymbolicAddress::ToInt32, mozilla::Nothing());
|
||||
|
||||
int32_t tlsOffset = masm.framePushed() - framePushedAfterTls;
|
||||
masm.callWithABI(ool->bytecodeOffset(), wasm::SymbolicAddress::ToInt32,
|
||||
mozilla::Some(tlsOffset));
|
||||
} else {
|
||||
masm.setupUnalignedABICall(output);
|
||||
masm.passABIArg(input, MoveOp::DOUBLE);
|
||||
|
@ -638,6 +696,10 @@ void CodeGeneratorX86::visitOutOfLineTruncate(OutOfLineTruncate* ool) {
|
|||
masm.storeCallInt32Result(output);
|
||||
|
||||
restoreVolatile(output);
|
||||
|
||||
if (gen->compilingWasm()) {
|
||||
masm.Pop(WasmTlsReg);
|
||||
}
|
||||
}
|
||||
|
||||
masm.jump(ool->rejoin());
|
||||
|
@ -645,9 +707,8 @@ void CodeGeneratorX86::visitOutOfLineTruncate(OutOfLineTruncate* ool) {
|
|||
|
||||
void CodeGeneratorX86::visitOutOfLineTruncateFloat32(
|
||||
OutOfLineTruncateFloat32* ool) {
|
||||
LTruncateFToInt32* ins = ool->ins();
|
||||
FloatRegister input = ToFloatRegister(ins->input());
|
||||
Register output = ToRegister(ins->output());
|
||||
FloatRegister input = ToFloatRegister(ool->input());
|
||||
Register output = ToRegister(ool->output());
|
||||
|
||||
Label fail;
|
||||
|
||||
|
@ -674,7 +735,7 @@ void CodeGeneratorX86::visitOutOfLineTruncateFloat32(
|
|||
masm.addl(Imm32(sizeof(uint64_t)), esp);
|
||||
masm.jump(&fail);
|
||||
} else {
|
||||
FloatRegister temp = ToFloatRegister(ins->tempFloat());
|
||||
FloatRegister temp = ToFloatRegister(ool->tempFloat());
|
||||
|
||||
// Try to convert float32 representing integers within 2^32 of a signed
|
||||
// integer, by adding/subtracting 2^32 and then trying to convert to int32.
|
||||
|
@ -712,6 +773,11 @@ void CodeGeneratorX86::visitOutOfLineTruncateFloat32(
|
|||
|
||||
masm.bind(&fail);
|
||||
{
|
||||
if (gen->compilingWasm()) {
|
||||
masm.Push(WasmTlsReg);
|
||||
}
|
||||
int32_t framePushedAfterTls = masm.framePushed();
|
||||
|
||||
saveVolatile(output);
|
||||
|
||||
masm.Push(input);
|
||||
|
@ -726,8 +792,9 @@ void CodeGeneratorX86::visitOutOfLineTruncateFloat32(
|
|||
masm.passABIArg(input.asDouble(), MoveOp::DOUBLE);
|
||||
|
||||
if (gen->compilingWasm()) {
|
||||
masm.callWithABI(ins->mir()->bytecodeOffset(),
|
||||
wasm::SymbolicAddress::ToInt32, mozilla::Nothing());
|
||||
int32_t tlsOffset = masm.framePushed() - framePushedAfterTls;
|
||||
masm.callWithABI(ool->bytecodeOffset(), wasm::SymbolicAddress::ToInt32,
|
||||
mozilla::Some(tlsOffset));
|
||||
} else {
|
||||
masm.callWithABI(BitwiseCast<void*, int32_t (*)(double)>(JS::ToInt32),
|
||||
MoveOp::GENERAL, CheckUnsafeCallWithABI::DontCheckOther);
|
||||
|
@ -737,6 +804,10 @@ void CodeGeneratorX86::visitOutOfLineTruncateFloat32(
|
|||
masm.Pop(input);
|
||||
|
||||
restoreVolatile(output);
|
||||
|
||||
if (gen->compilingWasm()) {
|
||||
masm.Pop(WasmTlsReg);
|
||||
}
|
||||
}
|
||||
|
||||
masm.jump(ool->rejoin());
|
||||
|
|
|
@ -450,13 +450,13 @@ class FunctionCompiler {
|
|||
// Do this for Int32 only since Int64 is not subject to the same
|
||||
// issues.
|
||||
//
|
||||
// Note the offsets passed to MTruncateToInt32 are wrong here, but
|
||||
// it doesn't matter: they're not codegen'd to calls since inputs
|
||||
// Note the offsets passed to MWasmBuiltinTruncateToInt32 are wrong here,
|
||||
// but it doesn't matter: they're not codegen'd to calls since inputs
|
||||
// already are int32.
|
||||
auto* lhs2 = MTruncateToInt32::New(alloc(), lhs);
|
||||
auto* lhs2 = createTruncateToInt32(lhs);
|
||||
curBlock_->add(lhs2);
|
||||
lhs = lhs2;
|
||||
auto* rhs2 = MTruncateToInt32::New(alloc(), rhs);
|
||||
auto* rhs2 = createTruncateToInt32(rhs);
|
||||
curBlock_->add(rhs2);
|
||||
rhs = rhs2;
|
||||
}
|
||||
|
@ -479,6 +479,14 @@ class FunctionCompiler {
|
|||
return ins;
|
||||
}
|
||||
|
||||
MInstruction* createTruncateToInt32(MDefinition* op) {
|
||||
if (op->type() == MIRType::Double || op->type() == MIRType::Float32) {
|
||||
return MWasmBuiltinTruncateToInt32::New(alloc(), op, tlsPointer_);
|
||||
}
|
||||
|
||||
return MTruncateToInt32::New(alloc(), op);
|
||||
}
|
||||
|
||||
MDefinition* mod(MDefinition* lhs, MDefinition* rhs, MIRType type,
|
||||
bool unsignd) {
|
||||
if (inDeadCode()) {
|
||||
|
@ -487,10 +495,10 @@ class FunctionCompiler {
|
|||
bool trapOnError = !env().isAsmJS();
|
||||
if (!unsignd && type == MIRType::Int32) {
|
||||
// See block comment in div().
|
||||
auto* lhs2 = MTruncateToInt32::New(alloc(), lhs);
|
||||
auto* lhs2 = createTruncateToInt32(lhs);
|
||||
curBlock_->add(lhs2);
|
||||
lhs = lhs2;
|
||||
auto* rhs2 = MTruncateToInt32::New(alloc(), rhs);
|
||||
auto* rhs2 = createTruncateToInt32(rhs);
|
||||
curBlock_->add(rhs2);
|
||||
rhs = rhs2;
|
||||
}
|
||||
|
@ -2208,11 +2216,13 @@ MDefinition* FunctionCompiler::unary<MToFloat32>(MDefinition* op) {
|
|||
}
|
||||
|
||||
template <>
|
||||
MDefinition* FunctionCompiler::unary<MTruncateToInt32>(MDefinition* op) {
|
||||
MDefinition* FunctionCompiler::unary<MWasmBuiltinTruncateToInt32>(
|
||||
MDefinition* op) {
|
||||
if (inDeadCode()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto* ins = MTruncateToInt32::New(alloc(), op, bytecodeOffset());
|
||||
auto* ins = MWasmBuiltinTruncateToInt32::New(alloc(), op, tlsPointer_,
|
||||
bytecodeOffset());
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
|
@ -2764,7 +2774,7 @@ static bool EmitConversionWithType(FunctionCompiler& f, ValType operandType,
|
|||
static bool EmitTruncate(FunctionCompiler& f, ValType operandType,
|
||||
ValType resultType, bool isUnsigned,
|
||||
bool isSaturating) {
|
||||
MDefinition* input;
|
||||
MDefinition* input = nullptr;
|
||||
if (!f.iter().readConversion(operandType, resultType, &input)) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2778,7 +2788,12 @@ static bool EmitTruncate(FunctionCompiler& f, ValType operandType,
|
|||
}
|
||||
if (resultType == ValType::I32) {
|
||||
if (f.env().isAsmJS()) {
|
||||
f.iter().setResult(f.unary<MTruncateToInt32>(input));
|
||||
if (input && (input->type() == MIRType::Double ||
|
||||
input->type() == MIRType::Float32)) {
|
||||
f.iter().setResult(f.unary<MWasmBuiltinTruncateToInt32>(input));
|
||||
} else {
|
||||
f.iter().setResult(f.unary<MTruncateToInt32>(input));
|
||||
}
|
||||
} else {
|
||||
f.iter().setResult(f.truncate<MWasmTruncateToInt32>(input, flags));
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче