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:
Dmitry Bezhetskov 2020-10-01 11:24:30 +00:00
Родитель 116a97dbec
Коммит 5bc9230be0
21 изменённых файлов: 347 добавлений и 58 удалений

Просмотреть файл

@ -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));
}