Пример #1
0
// Generate a stub that is called immediately after the prologue when there is a
// stack overflow. This stub calls a C++ function to report the error and then
// jumps to the throw stub to pop the activation.
static bool
GenerateStackOverflowStub(ModuleGenerator& mg, Label* throwLabel)
{
    MacroAssembler& masm = mg.masm();

    masm.haltingAlign(CodeAlignment);
    Offsets offsets;
    offsets.begin = masm.currentOffset();
    masm.bind(masm.asmStackOverflowLabel());

    // If we reach here via the non-profiling prologue, WasmActivation::fp has
    // not been updated. To enable stack unwinding from C++, store to it now. If
    // we reached here via the profiling prologue, we'll just store the same
    // value again. Do not update AsmJSFrame::callerFP as it is not necessary in
    // the non-profiling case (there is no return path from this point) and, in
    // the profiling case, it is already correct.
    Register activation = ABIArgGenerator::NonArgReturnReg0;
    masm.loadWasmActivation(activation);
    masm.storePtr(masm.getStackPointer(), Address(activation, WasmActivation::offsetOfFP()));

    // Prepare the stack for calling C++.
    if (uint32_t d = StackDecrementForCall(ABIStackAlignment, sizeof(AsmJSFrame), ShadowStackSpace))
        masm.subFromStackPtr(Imm32(d));

    // No need to restore the stack; the throw stub pops everything.
    masm.assertStackAlignment(ABIStackAlignment);
    masm.call(SymbolicAddress::ReportOverRecursed);
    masm.jump(throwLabel);

    if (masm.oom())
        return false;

    offsets.end = masm.currentOffset();
    return mg.defineInlineStub(offsets);
}
Пример #2
0
// Generate a stub that is jumped to from an out-of-bounds heap access when
// there are throwing semantics. This stub calls a C++ function to report an
// error and then jumps to the throw stub to pop the activation.
static bool
GenerateConversionErrorStub(ModuleGenerator& mg, Label* throwLabel)
{
    MacroAssembler& masm = mg.masm();

    masm.haltingAlign(CodeAlignment);
    Offsets offsets;
    offsets.begin = masm.currentOffset();
    masm.bind(masm.asmOnConversionErrorLabel());

    // sp can be anything at this point, so ensure it is aligned when calling
    // into C++.  We unconditionally jump to throw so don't worry about restoring sp.
    masm.andToStackPtr(Imm32(~(ABIStackAlignment - 1)));

    // OnImpreciseConversion always throws.
    masm.assertStackAlignment(ABIStackAlignment);
    masm.call(SymbolicAddress::OnImpreciseConversion);
    masm.jump(throwLabel);

    if (masm.oom())
        return false;

    offsets.end = masm.currentOffset();
    return mg.defineInlineStub(offsets);
}
Пример #3
0
// If an exception is thrown, simply pop all frames (since asm.js does not
// contain try/catch). To do this:
//  1. Restore 'sp' to it's value right after the PushRegsInMask in GenerateEntry.
//  2. PopRegsInMask to restore the caller's non-volatile registers.
//  3. Return (to CallAsmJS).
static bool
GenerateThrowStub(ModuleGenerator& mg, Label* throwLabel)
{
    MacroAssembler& masm = mg.masm();

    masm.haltingAlign(CodeAlignment);
    Offsets offsets;
    offsets.begin = masm.currentOffset();
    masm.bind(throwLabel);

    // We are about to pop all frames in this WasmActivation. Set fp to null to
    // maintain the invariant that fp is either null or pointing to a valid
    // frame.
    Register scratch = ABIArgGenerator::NonArgReturnReg0;
    masm.loadWasmActivation(scratch);
    masm.storePtr(ImmWord(0), Address(scratch, WasmActivation::offsetOfFP()));

    masm.setFramePushed(FramePushedForEntrySP);
    masm.loadStackPtr(Address(scratch, WasmActivation::offsetOfEntrySP()));
    masm.Pop(scratch);
    masm.PopRegsInMask(NonVolatileRegs);
    MOZ_ASSERT(masm.framePushed() == 0);

    masm.mov(ImmWord(0), ReturnReg);
    masm.ret();

    if (masm.oom())
        return false;

    offsets.end = masm.currentOffset();
    return mg.defineInlineStub(offsets);
}