mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 998490 - OdinMonkey: simplify stack-overflow exit stub (r=sunfish)
--HG-- extra : rebase_source : a9fdec79fcf136ef296173f08ae8908ee46019f9
This commit is contained in:
parent
b7df0d287a
commit
0e10a5f610
@ -2029,8 +2029,6 @@ class FunctionCompiler
|
||||
if (!newBlock(/* pred = */ nullptr, &curBlock_, fn_))
|
||||
return false;
|
||||
|
||||
curBlock_->add(MAsmJSCheckOverRecursed::New(alloc(), &m_.stackOverflowLabel()));
|
||||
|
||||
for (ABIArgTypeIter i = argTypes; !i.done(); i++) {
|
||||
MAsmJSParameter *ins = MAsmJSParameter::New(alloc(), *i, i.mirType());
|
||||
curBlock_->add(ins);
|
||||
@ -5470,8 +5468,8 @@ GenerateCode(ModuleCompiler &m, ModuleCompiler::Func &func, MIRGenerator &mir, L
|
||||
|
||||
m.masm().bind(func.code());
|
||||
|
||||
ScopedJSDeletePtr<CodeGenerator> codegen(jit::GenerateCode(&mir, &lir, &m.masm()));
|
||||
if (!codegen)
|
||||
ScopedJSDeletePtr<CodeGenerator> codegen(js_new<CodeGenerator>(&mir, &lir, &m.masm()));
|
||||
if (!codegen || !codegen->generateAsmJS(&m.stackOverflowLabel()))
|
||||
return m.fail(nullptr, "internal codegen failure (probably out of memory)");
|
||||
|
||||
if (!m.collectAccesses(mir))
|
||||
@ -6739,30 +6737,37 @@ GenerateStackOverflowExit(ModuleCompiler &m, Label *throwLabel)
|
||||
masm.align(CodeAlignment);
|
||||
masm.bind(&m.stackOverflowLabel());
|
||||
|
||||
#if defined(JS_CODEGEN_X86)
|
||||
// Ensure that at least one slot is pushed for passing 'cx' below.
|
||||
masm.push(Imm32(0));
|
||||
#endif
|
||||
// The overflow check always occurs before the initial function-specific
|
||||
// stack-size adjustment. See CodeGenerator::generateAsmJSPrologue.
|
||||
masm.setFramePushed(AlignmentMidPrologue - AlignmentAtPrologue);
|
||||
|
||||
// We know that StackPointer is word-aligned, but nothing past that. Thus,
|
||||
// we must align StackPointer dynamically. Don't worry about restoring
|
||||
// StackPointer since throwLabel will clobber StackPointer immediately.
|
||||
masm.andPtr(Imm32(~(StackAlignment - 1)), StackPointer);
|
||||
if (ShadowStackSpace)
|
||||
masm.subPtr(Imm32(ShadowStackSpace), StackPointer);
|
||||
MIRTypeVector argTypes(m.cx());
|
||||
argTypes.infallibleAppend(MIRType_Pointer); // cx
|
||||
|
||||
// Prepare the arguments for the call to js_ReportOverRecursed.
|
||||
#if defined(JS_CODEGEN_X86)
|
||||
LoadAsmJSActivationIntoRegister(masm, eax);
|
||||
LoadJSContextFromActivation(masm, eax, eax);
|
||||
masm.storePtr(eax, Address(StackPointer, 0));
|
||||
#else
|
||||
LoadAsmJSActivationIntoRegister(masm, IntArgReg0);
|
||||
LoadJSContextFromActivation(masm, IntArgReg0, IntArgReg0);
|
||||
#endif
|
||||
unsigned stackDec = StackDecrementForCall(masm, argTypes);
|
||||
masm.reserveStack(stackDec);
|
||||
|
||||
ABIArgMIRTypeIter i(argTypes);
|
||||
|
||||
Register scratch = ABIArgGenerator::NonArgReturnVolatileReg0;
|
||||
LoadAsmJSActivationIntoRegister(masm, scratch);
|
||||
|
||||
// argument 0: cx
|
||||
if (i->kind() == ABIArg::GPR) {
|
||||
LoadJSContextFromActivation(masm, scratch, i->gpr());
|
||||
} else {
|
||||
LoadJSContextFromActivation(masm, scratch, scratch);
|
||||
masm.storePtr(scratch, Address(StackPointer, i->offsetFromArgBase()));
|
||||
}
|
||||
i++;
|
||||
|
||||
JS_ASSERT(i.done());
|
||||
|
||||
AssertStackAlignment(masm);
|
||||
masm.call(AsmJSImm_ReportOverRecursed);
|
||||
masm.jump(throwLabel);
|
||||
|
||||
// Don't worry about restoring the stack; throwLabel will pop everything.
|
||||
masm.jump(throwLabel);
|
||||
return !masm.oom();
|
||||
}
|
||||
|
||||
|
@ -2748,17 +2748,6 @@ class CheckOverRecursedFailure : public OutOfLineCodeBase<CodeGenerator>
|
||||
}
|
||||
};
|
||||
|
||||
bool
|
||||
CodeGenerator::omitOverRecursedCheck() const
|
||||
{
|
||||
// If the current function makes no calls (which means it isn't recursive)
|
||||
// and it uses only a small amount of stack space, it doesn't need a
|
||||
// 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();
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitCheckOverRecursed(LCheckOverRecursed *lir)
|
||||
{
|
||||
@ -6202,7 +6191,7 @@ CodeGenerator::visitRestPar(LRestPar *lir)
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::generateAsmJS()
|
||||
CodeGenerator::generateAsmJS(Label *stackOverflowLabel)
|
||||
{
|
||||
IonSpew(IonSpew_Codegen, "# Emitting asm.js code");
|
||||
|
||||
@ -6215,7 +6204,7 @@ CodeGenerator::generateAsmJS()
|
||||
// parameters have been useFixed()ed to these ABI-specified positions.
|
||||
// Thus, there is nothing special to do in the prologue except (possibly)
|
||||
// bump the stack.
|
||||
if (!generatePrologue())
|
||||
if (!generateAsmJSPrologue(stackOverflowLabel))
|
||||
return false;
|
||||
if (!generateBody())
|
||||
return false;
|
||||
@ -8297,20 +8286,6 @@ CodeGenerator::visitAsmJSVoidReturn(LAsmJSVoidReturn *lir)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitAsmJSCheckOverRecursed(LAsmJSCheckOverRecursed *lir)
|
||||
{
|
||||
// If we don't push anything on the stack, skip the check.
|
||||
if (omitOverRecursedCheck())
|
||||
return true;
|
||||
|
||||
masm.branchPtr(Assembler::AboveOrEqual,
|
||||
AsmJSAbsoluteAddress(AsmJSImm_StackLimit),
|
||||
StackPointer,
|
||||
lir->mir()->onError());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::emitAssertRangeI(const Range *r, Register input)
|
||||
{
|
||||
|
@ -53,7 +53,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
|
||||
public:
|
||||
bool generate();
|
||||
bool generateAsmJS();
|
||||
bool generateAsmJS(Label *stackOverflowLabel);
|
||||
bool link(JSContext *cx, types::CompilerConstraintList *constraints);
|
||||
|
||||
bool visitLabel(LLabel *lir);
|
||||
@ -294,7 +294,6 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
|
||||
bool visitCheckOverRecursed(LCheckOverRecursed *lir);
|
||||
bool visitCheckOverRecursedFailure(CheckOverRecursedFailure *ool);
|
||||
bool visitAsmJSCheckOverRecursed(LAsmJSCheckOverRecursed *lir);
|
||||
|
||||
bool visitCheckOverRecursedPar(LCheckOverRecursedPar *lir);
|
||||
bool visitCheckOverRecursedFailurePar(CheckOverRecursedFailurePar *ool);
|
||||
@ -447,8 +446,6 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
bool emitAssertRangeI(const Range *r, Register input);
|
||||
bool emitAssertRangeD(const Range *r, FloatRegister input, FloatRegister temp);
|
||||
|
||||
bool omitOverRecursedCheck() const;
|
||||
|
||||
Vector<CodeOffsetLabel, 0, IonAllocPolicy> ionScriptLabels_;
|
||||
#ifdef DEBUG
|
||||
bool branchIfInvalidated(Register temp, Label *invalidated);
|
||||
|
@ -1628,29 +1628,22 @@ GenerateLIR(MIRGenerator *mir)
|
||||
}
|
||||
|
||||
CodeGenerator *
|
||||
GenerateCode(MIRGenerator *mir, LIRGraph *lir, MacroAssembler *maybeMasm)
|
||||
GenerateCode(MIRGenerator *mir, LIRGraph *lir)
|
||||
{
|
||||
CodeGenerator *codegen = js_new<CodeGenerator>(mir, lir, maybeMasm);
|
||||
CodeGenerator *codegen = js_new<CodeGenerator>(mir, lir);
|
||||
if (!codegen)
|
||||
return nullptr;
|
||||
|
||||
if (mir->compilingAsmJS()) {
|
||||
if (!codegen->generateAsmJS()) {
|
||||
js_delete(codegen);
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
if (!codegen->generate()) {
|
||||
js_delete(codegen);
|
||||
return nullptr;
|
||||
}
|
||||
if (!codegen->generate()) {
|
||||
js_delete(codegen);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return codegen;
|
||||
}
|
||||
|
||||
CodeGenerator *
|
||||
CompileBackEnd(MIRGenerator *mir, MacroAssembler *maybeMasm)
|
||||
CompileBackEnd(MIRGenerator *mir)
|
||||
{
|
||||
if (!OptimizeMIR(mir))
|
||||
return nullptr;
|
||||
@ -1659,7 +1652,7 @@ CompileBackEnd(MIRGenerator *mir, MacroAssembler *maybeMasm)
|
||||
if (!lir)
|
||||
return nullptr;
|
||||
|
||||
return GenerateCode(mir, lir, maybeMasm);
|
||||
return GenerateCode(mir, lir);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -149,8 +149,8 @@ class CodeGenerator;
|
||||
|
||||
bool OptimizeMIR(MIRGenerator *mir);
|
||||
LIRGraph *GenerateLIR(MIRGenerator *mir);
|
||||
CodeGenerator *GenerateCode(MIRGenerator *mir, LIRGraph *lir, MacroAssembler *maybeMasm = nullptr);
|
||||
CodeGenerator *CompileBackEnd(MIRGenerator *mir, MacroAssembler *maybeMasm = nullptr);
|
||||
CodeGenerator *GenerateCode(MIRGenerator *mir, LIRGraph *lir);
|
||||
CodeGenerator *CompileBackEnd(MIRGenerator *mir);
|
||||
|
||||
void AttachFinishedCompilations(JSContext *cx);
|
||||
void FinishOffThreadBuilder(IonBuilder *builder);
|
||||
|
@ -5995,16 +5995,6 @@ class LAsmJSCall MOZ_FINAL : public LInstruction
|
||||
}
|
||||
};
|
||||
|
||||
class LAsmJSCheckOverRecursed : public LInstructionHelper<0, 0, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(AsmJSCheckOverRecursed)
|
||||
|
||||
MAsmJSCheckOverRecursed *mir() const {
|
||||
return mir_->toAsmJSCheckOverRecursed();
|
||||
}
|
||||
};
|
||||
|
||||
class LAssertRangeI : public LInstructionHelper<0, 1, 0>
|
||||
{
|
||||
public:
|
||||
|
@ -292,7 +292,6 @@
|
||||
_(AsmJSVoidReturn) \
|
||||
_(AsmJSPassStackArg) \
|
||||
_(AsmJSCall) \
|
||||
_(AsmJSCheckOverRecursed) \
|
||||
_(InterruptCheckPar) \
|
||||
_(RecompileCheck) \
|
||||
_(AssertRangeI) \
|
||||
|
@ -3502,12 +3502,6 @@ LIRGenerator::visitAsmJSCall(MAsmJSCall *ins)
|
||||
return defineReturn(lir, ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitAsmJSCheckOverRecursed(MAsmJSCheckOverRecursed *ins)
|
||||
{
|
||||
return add(new(alloc()) LAsmJSCheckOverRecursed(), ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitSetDOMProperty(MSetDOMProperty *ins)
|
||||
{
|
||||
|
@ -254,7 +254,6 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
bool visitAsmJSVoidReturn(MAsmJSVoidReturn *ins);
|
||||
bool visitAsmJSPassStackArg(MAsmJSPassStackArg *ins);
|
||||
bool visitAsmJSCall(MAsmJSCall *ins);
|
||||
bool visitAsmJSCheckOverRecursed(MAsmJSCheckOverRecursed *ins);
|
||||
bool visitSetDOMProperty(MSetDOMProperty *ins);
|
||||
bool visitGetDOMProperty(MGetDOMProperty *ins);
|
||||
bool visitGetDOMMember(MGetDOMMember *ins);
|
||||
|
@ -10040,20 +10040,6 @@ class MAsmJSCall MOZ_FINAL : public MInstruction
|
||||
}
|
||||
};
|
||||
|
||||
// The asm.js version doesn't use the bail mechanism: instead it throws and
|
||||
// exception by jumping to the given label.
|
||||
class MAsmJSCheckOverRecursed : public MNullaryInstruction
|
||||
{
|
||||
Label *onError_;
|
||||
MAsmJSCheckOverRecursed(Label *onError) : onError_(onError) {}
|
||||
public:
|
||||
INSTRUCTION_HEADER(AsmJSCheckOverRecursed);
|
||||
static MAsmJSCheckOverRecursed *New(TempAllocator &alloc, Label *onError) {
|
||||
return new(alloc) MAsmJSCheckOverRecursed(onError);
|
||||
}
|
||||
Label *onError() const { return onError_; }
|
||||
};
|
||||
|
||||
#undef INSTRUCTION_HEADER
|
||||
|
||||
// Implement opcode casts now that the compiler can see the inheritance.
|
||||
|
@ -210,7 +210,6 @@ namespace jit {
|
||||
_(AsmJSVoidReturn) \
|
||||
_(AsmJSPassStackArg) \
|
||||
_(AsmJSCall) \
|
||||
_(AsmJSCheckOverRecursed) \
|
||||
_(CheckOverRecursedPar) \
|
||||
_(NewCallObjectPar) \
|
||||
_(NewPar) \
|
||||
|
@ -321,7 +321,6 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
||||
UNSAFE_OP(AsmJSPassStackArg)
|
||||
UNSAFE_OP(AsmJSParameter)
|
||||
UNSAFE_OP(AsmJSCall)
|
||||
UNSAFE_OP(AsmJSCheckOverRecursed)
|
||||
DROP_OP(RecompileCheck)
|
||||
|
||||
// It looks like this could easily be made safe:
|
||||
|
@ -40,16 +40,34 @@ CodeGeneratorARM::CodeGeneratorARM(MIRGenerator *gen, LIRGraph *graph, MacroAsse
|
||||
bool
|
||||
CodeGeneratorARM::generatePrologue()
|
||||
{
|
||||
if (gen->compilingAsmJS()) {
|
||||
masm.Push(lr);
|
||||
// Note that this automatically sets MacroAssembler::framePushed().
|
||||
masm.reserveStack(frameDepth_);
|
||||
} else {
|
||||
// Note that this automatically sets MacroAssembler::framePushed().
|
||||
masm.reserveStack(frameSize());
|
||||
masm.checkStackAlignment();
|
||||
JS_ASSERT(!gen->compilingAsmJS());
|
||||
|
||||
// Note that this automatically sets MacroAssembler::framePushed().
|
||||
masm.reserveStack(frameSize());
|
||||
masm.checkStackAlignment();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorARM::generateAsmJSPrologue(Label *stackOverflowLabel)
|
||||
{
|
||||
JS_ASSERT(gen->compilingAsmJS());
|
||||
|
||||
masm.Push(lr);
|
||||
|
||||
// The asm.js over-recursed handler wants to be able to assume that SP
|
||||
// points to the return address, so perform the check after pushing lr but
|
||||
// before pushing frameDepth.
|
||||
if (!omitOverRecursedCheck()) {
|
||||
masm.branchPtr(Assembler::AboveOrEqual,
|
||||
AsmJSAbsoluteAddress(AsmJSImm_StackLimit),
|
||||
StackPointer,
|
||||
stackOverflowLabel);
|
||||
}
|
||||
|
||||
// Note that this automatically sets MacroAssembler::framePushed().
|
||||
masm.reserveStack(frameDepth_);
|
||||
masm.checkStackAlignment();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ class CodeGeneratorARM : public CodeGeneratorShared
|
||||
|
||||
protected:
|
||||
bool generatePrologue();
|
||||
bool generateAsmJSPrologue(Label *stackOverflowLabel);
|
||||
bool generateEpilogue();
|
||||
bool generateOutOfLineCode();
|
||||
|
||||
|
@ -776,6 +776,17 @@ CodeGeneratorShared::visitOutOfLineTruncateSlow(OutOfLineTruncateSlow *ool)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorShared::omitOverRecursedCheck() const
|
||||
{
|
||||
// If the current function makes no calls (which means it isn't recursive)
|
||||
// and it uses only a small amount of stack space, it doesn't need a
|
||||
// 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();
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorShared::emitPreBarrier(Register base, const LAllocation *index, MIRType type)
|
||||
{
|
||||
|
@ -435,6 +435,8 @@ class CodeGeneratorShared : public LInstructionVisitor
|
||||
|
||||
bool visitOutOfLineTruncateSlow(OutOfLineTruncateSlow *ool);
|
||||
|
||||
bool omitOverRecursedCheck() const;
|
||||
|
||||
public:
|
||||
bool callTraceLIR(uint32_t blockIndex, LInstruction *lir, const char *bailoutName = nullptr);
|
||||
|
||||
|
@ -39,12 +39,34 @@ CodeGeneratorX86Shared::CodeGeneratorX86Shared(MIRGenerator *gen, LIRGraph *grap
|
||||
bool
|
||||
CodeGeneratorX86Shared::generatePrologue()
|
||||
{
|
||||
JS_ASSERT(!gen->compilingAsmJS());
|
||||
|
||||
// Note that this automatically sets MacroAssembler::framePushed().
|
||||
masm.reserveStack(frameSize());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86Shared::generateAsmJSPrologue(Label *stackOverflowLabel)
|
||||
{
|
||||
JS_ASSERT(gen->compilingAsmJS());
|
||||
|
||||
// The asm.js over-recursed handler wants to be able to assume that SP
|
||||
// points to the return address, so perform the check before pushing
|
||||
// frameDepth.
|
||||
if (!omitOverRecursedCheck()) {
|
||||
masm.branchPtr(Assembler::AboveOrEqual,
|
||||
AsmJSAbsoluteAddress(AsmJSImm_StackLimit),
|
||||
StackPointer,
|
||||
stackOverflowLabel);
|
||||
}
|
||||
|
||||
// Note that this automatically sets MacroAssembler::framePushed().
|
||||
masm.reserveStack(frameSize());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGeneratorX86Shared::generateEpilogue()
|
||||
{
|
||||
|
@ -78,6 +78,7 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
|
||||
|
||||
protected:
|
||||
bool generatePrologue();
|
||||
bool generateAsmJSPrologue(Label *stackOverflowLabe);
|
||||
bool generateEpilogue();
|
||||
bool generateOutOfLineCode();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user