mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 08:18:41 +09:00
1352506 - Ion: Automatically call gen->setPerformsCall() if a LIR instruction performs a call
1352506: Remove dead code in the backtracking allocator; 1352506: Automatically setPerformsCall for LIR call instructions. 1352506: Don't conflate need for overrecursed check and static alignment in MIRGenerator;
This commit is contained in:
parent
75adae3c46
commit
64d22a5bb6
11 changed files with 121 additions and 81 deletions
|
|
@ -588,18 +588,11 @@ BacktrackingAllocator::buildLivenessInfo()
|
|||
if (!callRanges.insert(callRange))
|
||||
return false;
|
||||
}
|
||||
DebugOnly<bool> hasDoubleDef = false;
|
||||
DebugOnly<bool> hasFloat32Def = false;
|
||||
for (size_t i = 0; i < ins->numDefs(); i++) {
|
||||
LDefinition* def = ins->getDef(i);
|
||||
if (def->isBogusTemp())
|
||||
continue;
|
||||
#ifdef DEBUG
|
||||
if (def->type() == LDefinition::DOUBLE)
|
||||
hasDoubleDef = true;
|
||||
if (def->type() == LDefinition::FLOAT32)
|
||||
hasFloat32Def = true;
|
||||
#endif
|
||||
|
||||
CodePosition from = outputOf(*ins);
|
||||
|
||||
if (def->policy() == LDefinition::MUST_REUSE_INPUT) {
|
||||
|
|
@ -644,8 +637,7 @@ BacktrackingAllocator::buildLivenessInfo()
|
|||
}
|
||||
}
|
||||
|
||||
CodePosition to =
|
||||
ins->isCall() ? outputOf(*ins) : outputOf(*ins).next();
|
||||
CodePosition to = ins->isCall() ? outputOf(*ins) : outputOf(*ins).next();
|
||||
|
||||
if (!vreg(temp).addInitialRange(alloc(), from, to))
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -1179,6 +1179,18 @@ class LCallInstructionHelper : public LInstructionHelper<Defs, Operands, Temps>
|
|||
}
|
||||
};
|
||||
|
||||
template <size_t Defs, size_t Temps>
|
||||
class LBinaryCallInstructionHelper : public LCallInstructionHelper<Defs, 2, Temps>
|
||||
{
|
||||
public:
|
||||
const LAllocation* lhs() {
|
||||
return this->getOperand(0);
|
||||
}
|
||||
const LAllocation* rhs() {
|
||||
return this->getOperand(1);
|
||||
}
|
||||
};
|
||||
|
||||
class LRecoverInfo : public TempObject
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -3636,10 +3636,9 @@ LIRGenerator::visitGetNameCache(MGetNameCache* ins)
|
|||
{
|
||||
MOZ_ASSERT(ins->envObj()->type() == MIRType::Object);
|
||||
|
||||
// Set the performs-call flag so that we don't omit the overrecursed check.
|
||||
// This is necessary because the cache can attach a scripted getter stub
|
||||
// that calls this script recursively.
|
||||
gen->setPerformsCall();
|
||||
// Emit an overrecursed check: this is necessary because the cache can
|
||||
// attach a scripted getter stub that calls this script recursively.
|
||||
gen->setNeedsOverrecursedCheck();
|
||||
|
||||
LGetNameCache* lir = new(alloc()) LGetNameCache(useRegister(ins->envObj()));
|
||||
defineBox(lir, ins);
|
||||
|
|
@ -3654,6 +3653,24 @@ LIRGenerator::visitCallGetIntrinsicValue(MCallGetIntrinsicValue* ins)
|
|||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitGetPropSuperCache(MGetPropSuperCache* ins)
|
||||
{
|
||||
MDefinition* obj = ins->object();
|
||||
MDefinition* receiver = ins->receiver();
|
||||
MDefinition* id = ins->idval();
|
||||
|
||||
gen->setNeedsOverrecursedCheck();
|
||||
|
||||
bool useConstId = id->type() == MIRType::String || id->type() == MIRType::Symbol;
|
||||
|
||||
auto* lir = new(alloc()) LGetPropSuperCacheV(useRegister(obj),
|
||||
useBoxOrTyped(receiver),
|
||||
useBoxOrTypedOrConstant(id, useConstId));
|
||||
defineBox(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitGetPropertyCache(MGetPropertyCache* ins)
|
||||
{
|
||||
|
|
@ -3666,10 +3683,9 @@ LIRGenerator::visitGetPropertyCache(MGetPropertyCache* ins)
|
|||
id->type() == MIRType::Value);
|
||||
|
||||
if (ins->monitoredResult()) {
|
||||
// Set the performs-call flag so that we don't omit the overrecursed
|
||||
// check. This is necessary because the cache can attach a scripted
|
||||
// getter stub that calls this script recursively.
|
||||
gen->setPerformsCall();
|
||||
// Emit an overrecursed check: this is necessary because the cache can
|
||||
// attach a scripted getter stub that calls this script recursively.
|
||||
gen->setNeedsOverrecursedCheck();
|
||||
}
|
||||
|
||||
// If this is a GETPROP, the id is a constant string. Allow passing it as a
|
||||
|
|
@ -3933,10 +3949,9 @@ LIRGenerator::visitSetPropertyCache(MSetPropertyCache* ins)
|
|||
bool useConstId = id->type() == MIRType::String || id->type() == MIRType::Symbol;
|
||||
bool useConstValue = IsNonNurseryConstant(ins->value());
|
||||
|
||||
// Set the performs-call flag so that we don't omit the overrecursed check.
|
||||
// This is necessary because the cache can attach a scripted setter stub
|
||||
// that calls this script recursively.
|
||||
gen->setPerformsCall();
|
||||
// Emit an overrecursed check: this is necessary because the cache can
|
||||
// attach a scripted setter stub that calls this script recursively.
|
||||
gen->setNeedsOverrecursedCheck();
|
||||
|
||||
// If the index might be an integer, we need some extra temp registers for
|
||||
// the dense and typed array element stubs.
|
||||
|
|
@ -4117,8 +4132,30 @@ LIRGenerator::visitIn(MIn* ins)
|
|||
MOZ_ASSERT(lhs->type() == MIRType::Value);
|
||||
MOZ_ASSERT(rhs->type() == MIRType::Object);
|
||||
|
||||
LIn* lir = new(alloc()) LIn(useBoxAtStart(lhs), useRegisterAtStart(rhs));
|
||||
defineReturn(lir, ins);
|
||||
LInCache* lir = new(alloc()) LInCache(useBoxOrTyped(lhs), useRegister(rhs), temp());
|
||||
define(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
void
|
||||
LIRGenerator::visitHasOwnCache(MHasOwnCache* ins)
|
||||
{
|
||||
MDefinition* value = ins->value();
|
||||
MOZ_ASSERT(value->type() == MIRType::Object || value->type() == MIRType::Value);
|
||||
|
||||
MDefinition* id = ins->idval();
|
||||
MOZ_ASSERT(id->type() == MIRType::String ||
|
||||
id->type() == MIRType::Symbol ||
|
||||
id->type() == MIRType::Int32 ||
|
||||
id->type() == MIRType::Value);
|
||||
|
||||
// Emit an overrecursed check: this is necessary because the cache can
|
||||
// attach a scripted getter stub that calls this script recursively.
|
||||
gen->setNeedsOverrecursedCheck();
|
||||
|
||||
LHasOwnCache* lir = new(alloc()) LHasOwnCache(useBoxOrTyped(value), useBoxOrTyped(id));
|
||||
|
||||
define(lir, ins);
|
||||
assignSafepoint(lir, ins);
|
||||
}
|
||||
|
||||
|
|
@ -4386,7 +4423,6 @@ LIRGenerator::visitWasmStackArg(MWasmStackArg* ins)
|
|||
void
|
||||
LIRGenerator::visitWasmCall(MWasmCall* ins)
|
||||
{
|
||||
gen->setPerformsCall();
|
||||
|
||||
LAllocation* args = gen->allocate<LAllocation>(ins->numOperands());
|
||||
if (!args) {
|
||||
|
|
@ -4633,8 +4669,11 @@ LIRGenerator::visitInstruction(MInstruction* ins)
|
|||
return false;
|
||||
ins->accept(this);
|
||||
|
||||
if (ins->possiblyCalls())
|
||||
gen->setPerformsCall();
|
||||
if (ins->possiblyCalls()) {
|
||||
gen->setNeedsStaticStackAlignment();
|
||||
gen->setNeedsOverrecursedCheck();
|
||||
}
|
||||
|
||||
|
||||
if (ins->resumePoint())
|
||||
updateResumeState(ins);
|
||||
|
|
|
|||
|
|
@ -6139,6 +6139,10 @@ class MMod : public MBinaryArithInstruction
|
|||
unsigned_ == ins->toMod()->isUnsigned();
|
||||
}
|
||||
|
||||
bool possiblyCalls() const override {
|
||||
return type() == MIRType::Double;
|
||||
}
|
||||
|
||||
ALLOW_CLONE(MMod)
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -141,12 +141,19 @@ class MIRGenerator
|
|||
uint32_t minWasmHeapLength() const {
|
||||
return minWasmHeapLength_;
|
||||
}
|
||||
void setPerformsCall() {
|
||||
performsCall_ = true;
|
||||
void setNeedsOverrecursedCheck() {
|
||||
needsOverrecursedCheck_ = true;
|
||||
}
|
||||
bool performsCall() const {
|
||||
return performsCall_;
|
||||
bool needsOverrecursedCheck() const {
|
||||
return needsOverrecursedCheck_;
|
||||
}
|
||||
void setNeedsStaticStackAlignment() {
|
||||
needsStaticStackAlignment_ = true;
|
||||
}
|
||||
bool needsStaticStackAlignment() const {
|
||||
return needsOverrecursedCheck_;
|
||||
}
|
||||
|
||||
|
||||
bool modifiesFrameArguments() const {
|
||||
return modifiesFrameArguments_;
|
||||
|
|
@ -176,7 +183,8 @@ class MIRGenerator
|
|||
mozilla::Atomic<bool, mozilla::Relaxed> cancelBuild_;
|
||||
|
||||
uint32_t wasmMaxStackArgBytes_;
|
||||
bool performsCall_;
|
||||
bool needsOverrecursedCheck_;
|
||||
bool needsStaticStackAlignment_;
|
||||
|
||||
// Keep track of whether frame arguments are modified during execution.
|
||||
// RegAlloc needs to know this as spilling values back to their register
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ MIRGenerator::MIRGenerator(CompileCompartment* compartment, const JitCompileOpti
|
|||
pauseBuild_(nullptr),
|
||||
cancelBuild_(false),
|
||||
wasmMaxStackArgBytes_(0),
|
||||
performsCall_(false),
|
||||
needsOverrecursedCheck_(false),
|
||||
needsStaticStackAlignment_(false),
|
||||
modifiesFrameArguments_(false),
|
||||
instrumentedProfiling_(false),
|
||||
instrumentedProfilingIsCached_(false),
|
||||
|
|
|
|||
|
|
@ -776,7 +776,8 @@ CodeGeneratorARM::visitSoftModI(LSoftModI* ins)
|
|||
Label done;
|
||||
|
||||
// Save the lhs in case we end up with a 0 that should be a -0.0 because lhs < 0.
|
||||
MOZ_ASSERT(callTemp.code() > r3.code() && callTemp.code() < r12.code());
|
||||
MOZ_ASSERT(callTemp != lhs);
|
||||
MOZ_ASSERT(callTemp != rhs);
|
||||
masm.ma_mov(lhs, callTemp);
|
||||
|
||||
|
||||
|
|
@ -812,6 +813,8 @@ CodeGeneratorARM::visitSoftModI(LSoftModI* ins)
|
|||
masm.callWithABI(wasm::SymbolicAddress::aeabi_idivmod);
|
||||
else
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, __aeabi_idivmod));
|
||||
MOZ_ASSERT(r1 != output);
|
||||
masm.move32(r1, output);
|
||||
|
||||
// If X%Y == 0 and X < 0, then we *actually* wanted to return -0.0
|
||||
if (mir->canBeNegativeDividend()) {
|
||||
|
|
@ -820,7 +823,7 @@ CodeGeneratorARM::visitSoftModI(LSoftModI* ins)
|
|||
} else {
|
||||
MOZ_ASSERT(mir->fallible());
|
||||
// See if X < 0
|
||||
masm.as_cmp(r1, Imm8(0));
|
||||
masm.as_cmp(output, Imm8(0));
|
||||
masm.ma_b(&done, Assembler::NotEqual);
|
||||
masm.as_cmp(callTemp, Imm8(0));
|
||||
bailoutIf(Assembler::Signed, ins->snapshot());
|
||||
|
|
@ -2874,9 +2877,7 @@ CodeGeneratorARM::visitSoftUDivOrMod(LSoftUDivOrMod* ins)
|
|||
|
||||
MOZ_ASSERT(lhs == r0);
|
||||
MOZ_ASSERT(rhs == r1);
|
||||
MOZ_ASSERT(ins->mirRaw()->isDiv() || ins->mirRaw()->isMod());
|
||||
MOZ_ASSERT_IF(ins->mirRaw()->isDiv(), output == r0);
|
||||
MOZ_ASSERT_IF(ins->mirRaw()->isMod(), output == r1);
|
||||
MOZ_ASSERT(output == r0);
|
||||
|
||||
Label done;
|
||||
MDiv* div = ins->mir()->isDiv() ? ins->mir()->toDiv() : nullptr;
|
||||
|
|
@ -2892,6 +2893,10 @@ CodeGeneratorARM::visitSoftUDivOrMod(LSoftUDivOrMod* ins)
|
|||
masm.callWithABI(wasm::SymbolicAddress::aeabi_uidivmod);
|
||||
else
|
||||
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void*, __aeabi_uidivmod));
|
||||
if (mod) {
|
||||
MOZ_ASSERT(output == r0, "output should not be r1 for mod");
|
||||
masm.move32(r1, output);
|
||||
}
|
||||
|
||||
// uidivmod returns the quotient in r0, and the remainder in r1.
|
||||
if (div && !div->canTruncateRemainder()) {
|
||||
|
|
|
|||
|
|
@ -189,29 +189,15 @@ class LUDivOrModI64 : public LCallInstructionHelper<INT64_PIECES, INT64_PIECES*2
|
|||
};
|
||||
|
||||
// LSoftDivI is a software divide for ARM cores that don't support a hardware
|
||||
// divide instruction.
|
||||
//
|
||||
// It is implemented as a proper C function so it trashes r0, r1, r2 and r3.
|
||||
// The call also trashes lr, and has the ability to trash ip. The function also
|
||||
// takes two arguments (dividend in r0, divisor in r1). The LInstruction gets
|
||||
// encoded such that the divisor and dividend are passed in their apropriate
|
||||
// registers and end their life at the start of the instruction by the use of
|
||||
// useFixedAtStart. The result is returned in r0 and the other three registers
|
||||
// that can be trashed are marked as temps. For the time being, the link
|
||||
// register is not marked as trashed because we never allocate to the link
|
||||
// register. The FP registers are not trashed.
|
||||
class LSoftDivI : public LBinaryMath<3>
|
||||
// divide instruction, implemented as a C++ native call.
|
||||
class LSoftDivI : public LBinaryCallInstructionHelper<1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(SoftDivI);
|
||||
|
||||
LSoftDivI(const LAllocation& lhs, const LAllocation& rhs,
|
||||
const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) {
|
||||
LSoftDivI(const LAllocation& lhs, const LAllocation& rhs) {
|
||||
setOperand(0, lhs);
|
||||
setOperand(1, rhs);
|
||||
setTemp(0, temp1);
|
||||
setTemp(1, temp2);
|
||||
setTemp(2, temp3);
|
||||
}
|
||||
|
||||
MDiv* mir() const {
|
||||
|
|
@ -267,25 +253,21 @@ class LModI : public LBinaryMath<1>
|
|||
}
|
||||
};
|
||||
|
||||
class LSoftModI : public LBinaryMath<4>
|
||||
class LSoftModI : public LBinaryCallInstructionHelper<1, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(SoftModI);
|
||||
|
||||
LSoftModI(const LAllocation& lhs, const LAllocation& rhs,
|
||||
const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3,
|
||||
const LDefinition& callTemp)
|
||||
const LDefinition& temp)
|
||||
{
|
||||
setOperand(0, lhs);
|
||||
setOperand(1, rhs);
|
||||
setTemp(0, temp1);
|
||||
setTemp(1, temp2);
|
||||
setTemp(2, temp3);
|
||||
setTemp(3, callTemp);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LDefinition* callTemp() {
|
||||
return getTemp(3);
|
||||
return getTemp(0);
|
||||
}
|
||||
|
||||
MMod* mir() const {
|
||||
|
|
@ -464,18 +446,14 @@ class LUMod : public LBinaryMath<0>
|
|||
}
|
||||
};
|
||||
|
||||
class LSoftUDivOrMod : public LBinaryMath<3>
|
||||
class LSoftUDivOrMod : public LBinaryCallInstructionHelper<1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(SoftUDivOrMod);
|
||||
|
||||
LSoftUDivOrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp1,
|
||||
const LDefinition& temp2, const LDefinition& temp3) {
|
||||
LSoftUDivOrMod(const LAllocation& lhs, const LAllocation& rhs) {
|
||||
setOperand(0, lhs);
|
||||
setOperand(1, rhs);
|
||||
setTemp(0, temp1);
|
||||
setTemp(1, temp2);
|
||||
setTemp(2, temp3);
|
||||
}
|
||||
|
||||
MInstruction* mir() {
|
||||
|
|
@ -580,8 +558,7 @@ class LWasmTruncateToInt64 : public LCallInstructionHelper<INT64_PIECES, 1, 0>
|
|||
public:
|
||||
LIR_HEADER(WasmTruncateToInt64);
|
||||
|
||||
LWasmTruncateToInt64(const LAllocation& in)
|
||||
{
|
||||
LWasmTruncateToInt64(const LAllocation& in) {
|
||||
setOperand(0, in);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -350,11 +350,11 @@ LIRGeneratorARM::lowerDivI(MDiv* div)
|
|||
return;
|
||||
}
|
||||
|
||||
LSoftDivI* lir = new(alloc()) LSoftDivI(useFixedAtStart(div->lhs(), r0), useFixedAtStart(div->rhs(), r1),
|
||||
tempFixed(r1), tempFixed(r2), tempFixed(r3));
|
||||
LSoftDivI* lir = new(alloc()) LSoftDivI(useFixedAtStart(div->lhs(), r0),
|
||||
useFixedAtStart(div->rhs(), r1));
|
||||
if (div->fallible())
|
||||
assignSnapshot(lir, Bailout_DoubleOutput);
|
||||
defineFixed(lir, div, LAllocation(AnyRegister(r0)));
|
||||
defineReturn(lir, div);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -402,12 +402,12 @@ LIRGeneratorARM::lowerModI(MMod* mod)
|
|||
return;
|
||||
}
|
||||
|
||||
LSoftModI* lir = new(alloc()) LSoftModI(useFixedAtStart(mod->lhs(), r0), useFixedAtStart(mod->rhs(), r1),
|
||||
tempFixed(r0), tempFixed(r2), tempFixed(r3),
|
||||
temp(LDefinition::GENERAL));
|
||||
LSoftModI* lir = new(alloc()) LSoftModI(useFixedAtStart(mod->lhs(), r0),
|
||||
useFixedAtStart(mod->rhs(), r1),
|
||||
temp());
|
||||
if (mod->fallible())
|
||||
assignSnapshot(lir, Bailout_DoubleOutput);
|
||||
defineFixed(lir, mod, LAllocation(AnyRegister(r1)));
|
||||
defineReturn(lir, mod);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ CodeGeneratorShared::CodeGeneratorShared(MIRGenerator* gen, LIRGraph* graph, Mac
|
|||
static_assert(!SupportsSimd, "we need padding so that local slots are SIMD-aligned and "
|
||||
"the stack must be kept SIMD-aligned too.");
|
||||
|
||||
if (gen->performsCall()) {
|
||||
if (gen->needsStaticStackAlignment()) {
|
||||
// An MWasmCall does not align the stack pointer at calls sites but
|
||||
// instead relies on the a priori stack adjustment. This must be the
|
||||
// last adjustment of frameDepth_.
|
||||
|
|
@ -1471,7 +1471,7 @@ CodeGeneratorShared::omitOverRecursedCheck() const
|
|||
// stack overflow check. Note that the actual number here is somewhat
|
||||
// arbitrary, and codegen actually uses small bounded amounts of
|
||||
// additional stack space in some cases too.
|
||||
return frameSize() < 64 && !gen->performsCall();
|
||||
return frameSize() < 64 && !gen->needsOverrecursedCheck();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -64,7 +64,8 @@ LIRGeneratorShared::define(details::LInstructionFixedDefsTempsHelper<1, X>* lir,
|
|||
}
|
||||
|
||||
template <size_t X, size_t Y> void
|
||||
LIRGeneratorShared::defineFixed(LInstructionHelper<1, X, Y>* lir, MDefinition* mir, const LAllocation& output)
|
||||
LIRGeneratorShared::defineFixed(LInstructionHelper<1, X, Y>* lir, MDefinition* mir,
|
||||
const LAllocation& output)
|
||||
{
|
||||
LDefinition::Type type = LDefinition::TypeFrom(mir->type());
|
||||
|
||||
|
|
@ -233,6 +234,7 @@ LIRGeneratorShared::defineReturn(LInstruction* lir, MDefinition* mir)
|
|||
lir->setMir(mir);
|
||||
|
||||
MOZ_ASSERT(lir->isCall());
|
||||
gen->setNeedsStaticStackAlignment();
|
||||
|
||||
uint32_t vreg = getVirtualRegister();
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue