Пример #1
0
void ValueRep::emitRestore(AssemblyHelpers& jit, Reg reg) const
{
    if (reg.isGPR()) {
        switch (kind()) {
        case LateRegister:
        case Register:
            if (isGPR())
                jit.move(gpr(), reg.gpr());
            else
                jit.moveDoubleTo64(fpr(), reg.gpr());
            break;
        case Stack:
            jit.load64(AssemblyHelpers::Address(GPRInfo::callFrameRegister, offsetFromFP()), reg.gpr());
            break;
        case Constant:
            jit.move(AssemblyHelpers::TrustedImm64(value()), reg.gpr());
            break;
        default:
            RELEASE_ASSERT_NOT_REACHED();
            break;
        }
        return;
    }

    switch (kind()) {
    case LateRegister:
    case Register:
        if (isGPR())
            jit.move64ToDouble(gpr(), reg.fpr());
        else
            jit.moveDouble(fpr(), reg.fpr());
        break;
    case Stack:
        jit.loadDouble(AssemblyHelpers::Address(GPRInfo::callFrameRegister, offsetFromFP()), reg.fpr());
        break;
    case Constant:
        jit.move(AssemblyHelpers::TrustedImm64(value()), jit.scratchRegister());
        jit.move64ToDouble(jit.scratchRegister(), reg.fpr());
        break;
    default:
        RELEASE_ASSERT_NOT_REACHED();
        break;
    }
}
static void generateRegisterRestoration(AssemblyHelpers& jit)
{
#if ENABLE(FTL_JIT)
    RegisterSet toSave = registersToPreserve();
    ptrdiff_t offset = registerPreservationOffset();
    
    ASSERT(!toSave.get(GPRInfo::regT4));

    // We need to place the stack pointer back to where the caller thought they left it.
    // But also, in order to recover the registers, we need to figure out how big the
    // arguments area is.
    
    jit.load32(
        AssemblyHelpers::Address(
            AssemblyHelpers::stackPointerRegister,
            (JSStack::ArgumentCount - JSStack::CallerFrameAndPCSize) * sizeof(Register) + PayloadOffset),
        GPRInfo::regT4);
    
    jit.move(GPRInfo::regT4, GPRInfo::regT2);
    jit.lshift32(AssemblyHelpers::TrustedImm32(3), GPRInfo::regT2);
    
    jit.addPtr(AssemblyHelpers::TrustedImm32(offset), AssemblyHelpers::stackPointerRegister);
    jit.addPtr(AssemblyHelpers::stackPointerRegister, GPRInfo::regT2);
    
    // We saved things at:
    //
    //     adjSP + (JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + NumArgs) * 8
    //
    // Where:
    //
    //     adjSP = origSP - offset
    //
    // regT2 now points at:
    //
    //     origSP + NumArgs * 8
    //   = adjSP + offset + NumArgs * 8
    // 
    // So if we subtract offset and then add JSStack::CallFrameHeaderSize and subtract
    // JSStack::CallerFrameAndPCSize, we'll get the thing we want.
    ptrdiff_t currentOffset = -offset + sizeof(Register) * (
        JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize);
    jit.loadPtr(AssemblyHelpers::Address(GPRInfo::regT2, currentOffset), GPRInfo::regT1);
    
    for (GPRReg gpr = AssemblyHelpers::firstRegister(); gpr <= AssemblyHelpers::lastRegister(); gpr = static_cast<GPRReg>(gpr + 1)) {
        if (!toSave.get(gpr))
            continue;
        currentOffset += sizeof(Register);
        jit.load64(AssemblyHelpers::Address(GPRInfo::regT2, currentOffset), gpr);
    }
    for (FPRReg fpr = AssemblyHelpers::firstFPRegister(); fpr <= AssemblyHelpers::lastFPRegister(); fpr = static_cast<FPRReg>(fpr + 1)) {
        if (!toSave.get(fpr))
            continue;
        currentOffset += sizeof(Register);
        jit.loadDouble(AssemblyHelpers::Address(GPRInfo::regT2, currentOffset), fpr);
    }
    
    // Thunks like this rely on the ArgumentCount being intact. Pay it forward.
    jit.store32(
        GPRInfo::regT4,
        AssemblyHelpers::Address(
            AssemblyHelpers::stackPointerRegister,
            (JSStack::ArgumentCount - JSStack::CallerFrameAndPCSize) * sizeof(Register) + PayloadOffset));
    
    if (!ASSERT_DISABLED) {
        AssemblyHelpers::Jump ok = jit.branchPtr(
            AssemblyHelpers::Above, GPRInfo::regT1, AssemblyHelpers::TrustedImmPtr(static_cast<size_t>(0x1000)));
        jit.abortWithReason(RPWUnreasonableJumpTarget);
        ok.link(&jit);
    }
    
    jit.jump(GPRInfo::regT1);
#else // ENABLE(FTL_JIT)
    UNUSED_PARAM(jit);
    UNREACHABLE_FOR_PLATFORM();
#endif // ENABLE(FTL_JIT)
}