Changeset 294794 in webkit


Ignore:
Timestamp:
May 25, 2022 6:32:59 AM (2 years ago)
Author:
commit-queue@webkit.org
Message:

[JSC][ARMv7] Support callee save FPRs

Patch by Geza Lore <Geza Lore> on 2022-05-25
https://bugs.webkit.org/show_bug.cgi?id=240376

Reviewed by Yusuke Suzuki.

ARMv7 FPRs d8-d15 (also referenced as s16-s32 and q4-q7) are callee save
in the host ABI, but currently JSC is unaware of this. This does not
currently cause problems as they are not used, but will be used by the
Wasm JITs.

In preparation for the 32-bit ports of the Wasm JITs, this patch:

  • Teaches JSC about callee save FPRs on ARMv7. d8-d15 are host ABI callee save, but only d8-d14 are VM callee save, i.e.: we treat d15 as a volatile register in JIT code. This is so we can use d15 as a macro assembler scratch register.
  • Changes offlineasm and MacroAssemblerARMv7 to use d15 as the FP scratch register. We do this so we can use the full range of d0-d7 as temporary, and in particular as Wasm argument/return registers.
  • To achieve the above, we need to modify RegisterAtOffsetList as GPRs and FPRs have different sizes on JSVALUE32_64 platforms
  • Adds the ARMv7 specific registers to RegisterSet::macroScratchRegisters()
  • assembler/ARMv7Registers.h:
  • assembler/MacroAssemblerARMv7.h:
  • b3/air/AirCode.cpp:

(JSC::B3::Air::Code::calleeSaveRegisterAtOffsetList const):
(JSC::B3::Air::Code::dump const):

  • b3/testb3_7.cpp:

(testInfiniteLoopDoesntCauseBadHoisting):

  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters):
(JSC::CodeBlock::calleeSaveSpaceAsVirtualRegisters):
(JSC::roundCalleeSaveSpaceAsVirtualRegisters): Deleted.

  • bytecode/ValueRecovery.h:

(JSC::ValueRecovery::calleeSaveGPRDisplacedInJSStack):
(JSC::ValueRecovery::calleeSaveRegDisplacedInJSStack): Deleted.

  • dfg/DFGOSREntry.cpp:

(JSC::DFG::prepareOSREntry):

  • dfg/DFGOSRExitCompilerCommon.cpp:

(JSC::DFG::calleeSaveSlot):

  • ftl/FTLOSRExitCompiler.cpp:

(JSC::FTL::compileStub):

  • interpreter/Interpreter.cpp:

(JSC::UnwindFunctor::copyCalleeSavesToEntryFrameCalleeSavesBuffer const):

  • jit/AssemblyHelpers.cpp:

(JSC::AssemblyHelpers::restoreCalleeSavesFromEntryFrameCalleeSavesBuffer):
(JSC::AssemblyHelpers::restoreCalleeSavesFromVMEntryFrameCalleeSavesBufferImpl):
(JSC::AssemblyHelpers::copyCalleeSavesToEntryFrameCalleeSavesBufferImpl):
(JSC::AssemblyHelpers::emitSave):
(JSC::AssemblyHelpers::emitRestore):
(JSC::AssemblyHelpers::emitSaveCalleeSavesFor):
(JSC::AssemblyHelpers::emitRestoreCalleeSavesFor):
(JSC::AssemblyHelpers::copyLLIntBaselineCalleeSavesFromFrameOrRegisterToEntryFrameCalleeSavesBuffer):
(JSC::AssemblyHelpers::emitSaveOrCopyLLIntBaselineCalleeSavesFor):

  • jit/CallFrameShuffleData.cpp:

(JSC::CallFrameShuffleData::setupCalleeSaveRegisters):

  • jit/CallFrameShuffler.h:

(JSC::CallFrameShuffler::snapshot const):

  • jit/CallFrameShuffler32_64.cpp:

(JSC::CallFrameShuffler::emitDisplace):

  • jit/FPRInfo.h:
  • jit/GPRInfo.h:
  • jit/RegisterAtOffsetList.cpp:

(JSC::RegisterAtOffsetList::RegisterAtOffsetList):

  • jit/RegisterAtOffsetList.h:

(JSC::RegisterAtOffsetList::registerCount const):
(JSC::RegisterAtOffsetList::sizeOfAreaInBytes const):
(JSC::RegisterAtOffsetList::adjustOffsets):
(JSC::RegisterAtOffsetList::size const): Deleted.
(JSC::RegisterAtOffsetList::at): Deleted.

  • jit/RegisterSet.cpp:

(JSC::RegisterSet::macroScratchRegisters):
(JSC::RegisterSet::vmCalleeSaveRegisters):

  • llint/LowLevelInterpreter.asm:
  • offlineasm/arm.rb:
  • wasm/js/JSToWasm.cpp:

(JSC::Wasm::createJSToWasmWrapper):

  • wasm/js/WasmToJS.cpp:

(JSC::Wasm::wasmToJS):

  • wasm/js/WebAssemblyFunction.cpp:

(JSC::WebAssemblyFunction::jsCallEntrypointSlow):

Canonical link: https://commits.webkit.org/250952@main

Location:
trunk/Source/JavaScriptCore
Files:
24 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/assembler/ARMv7Registers.h

    r254843 r294794  
    105105    macro(s14, "s14", 0, 0)                     \
    106106    macro(s15, "s15", 0, 0)                     \
    107     macro(s16, "s16", 0, 0)                     \
    108     macro(s17, "s17", 0, 0)                     \
    109     macro(s18, "s18", 0, 0)                     \
    110     macro(s19, "s19", 0, 0)                     \
    111     macro(s20, "s20", 0, 0)                     \
    112     macro(s21, "s21", 0, 0)                     \
    113     macro(s22, "s22", 0, 0)                     \
    114     macro(s23, "s23", 0, 0)                     \
    115     macro(s24, "s24", 0, 0)                     \
    116     macro(s25, "s25", 0, 0)                     \
    117     macro(s26, "s26", 0, 0)                     \
    118     macro(s27, "s27", 0, 0)                     \
    119     macro(s28, "s28", 0, 0)                     \
    120     macro(s29, "s29", 0, 0)                     \
    121     macro(s30, "s30", 0, 0)                     \
    122     macro(s31, "s31", 0, 0)
     107    macro(s16, "s16", 0, 1)                     \
     108    macro(s17, "s17", 0, 1)                     \
     109    macro(s18, "s18", 0, 1)                     \
     110    macro(s19, "s19", 0, 1)                     \
     111    macro(s20, "s20", 0, 1)                     \
     112    macro(s21, "s21", 0, 1)                     \
     113    macro(s22, "s22", 0, 1)                     \
     114    macro(s23, "s23", 0, 1)                     \
     115    macro(s24, "s24", 0, 1)                     \
     116    macro(s25, "s25", 0, 1)                     \
     117    macro(s26, "s26", 0, 1)                     \
     118    macro(s27, "s27", 0, 1)                     \
     119    macro(s28, "s28", 0, 1)                     \
     120    macro(s29, "s29", 0, 1)                     \
     121    macro(s30, "s30", 0, 1)                     \
     122    macro(s31, "s31", 0, 1)
    123123
    124124#if CPU(ARM_NEON) || CPU(ARM_VFP_V3_D32)
     
    132132    macro(d6,  "d6",  0, 0)                     \
    133133    macro(d7,  "d7",  0, 0)                     \
    134     macro(d8,  "d8",  0, 0)                     \
    135     macro(d9,  "d9",  0, 0)                     \
    136     macro(d10, "d10", 0, 0)                     \
    137     macro(d11, "d11", 0, 0)                     \
    138     macro(d12, "d12", 0, 0)                     \
    139     macro(d13, "d13", 0, 0)                     \
    140     macro(d14, "d14", 0, 0)                     \
    141     macro(d15, "d15", 0, 0)                     \
     134    macro(d8,  "d8",  0, 1)                     \
     135    macro(d9,  "d9",  0, 1)                     \
     136    macro(d10, "d10", 0, 1)                     \
     137    macro(d11, "d11", 0, 1)                     \
     138    macro(d12, "d12", 0, 1)                     \
     139    macro(d13, "d13", 0, 1)                     \
     140    macro(d14, "d14", 0, 1)                     \
     141    macro(d15, "d15", 0, 1)                     \
    142142    macro(d16, "d16", 0, 0)                     \
    143143    macro(d17, "d17", 0, 0)                     \
     
    166166    macro(d6,  "d6",  0, 0)                     \
    167167    macro(d7,  "d7",  0, 0)                     \
    168     macro(d8,  "d8",  0, 0)                     \
    169     macro(d9,  "d9",  0, 0)                     \
    170     macro(d10, "d10", 0, 0)                     \
    171     macro(d11, "d11", 0, 0)                     \
    172     macro(d12, "d12", 0, 0)                     \
    173     macro(d13, "d13", 0, 0)                     \
    174     macro(d14, "d14", 0, 0)                     \
    175     macro(d15, "d15", 0, 0)
     168    macro(d8,  "d8",  0, 1)                     \
     169    macro(d9,  "d9",  0, 1)                     \
     170    macro(d10, "d10", 0, 1)                     \
     171    macro(d11, "d11", 0, 1)                     \
     172    macro(d12, "d12", 0, 1)                     \
     173    macro(d13, "d13", 0, 1)                     \
     174    macro(d14, "d14", 0, 1)                     \
     175    macro(d15, "d15", 0, 1)
    176176#endif
    177177
     
    182182    macro(q2, "q2", 0, 0)                       \
    183183    macro(q3, "q3", 0, 0)                       \
    184     macro(q4, "q4", 0, 0)                       \
    185     macro(q5, "q5", 0, 0)                       \
    186     macro(q6, "q6", 0, 0)                       \
    187     macro(q7, "q7", 0, 0)                       \
     184    macro(q4, "q4", 0, 1)                       \
     185    macro(q5, "q5", 0, 1)                       \
     186    macro(q6, "q6", 0, 1)                       \
     187    macro(q7, "q7", 0, 1)                       \
    188188    macro(q8, "q8", 0, 0)                       \
    189189    macro(q9, "q9", 0, 0)                       \
  • trunk/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h

    r293087 r294794  
    4242    static constexpr size_t nearJumpRange = 16 * MB;
    4343
    44 private:
    4544    static constexpr RegisterID dataTempRegister = ARMRegisters::ip;
    4645    static constexpr RegisterID addressTempRegister = ARMRegisters::r6;
    4746
    48     static constexpr ARMRegisters::FPDoubleRegisterID fpTempRegister = ARMRegisters::d7;
     47    // d15 is host/C ABI callee save, but is volatile in the VM/JS ABI. We use
     48    // this as scratch register so we can use the full range of d0-d7 as
     49    // temporary, and in particular as Wasm argument/return register.
     50    static constexpr ARMRegisters::FPDoubleRegisterID fpTempRegister = ARMRegisters::d15;
     51private:
    4952    inline ARMRegisters::FPSingleRegisterID fpTempRegisterAsSingle() { return ARMRegisters::asSingle(fpTempRegister); }
    5053
  • trunk/Source/JavaScriptCore/b3/air/AirCode.cpp

    r292714 r294794  
    230230{
    231231    RegisterAtOffsetList result = m_uncorrectedCalleeSaveRegisterAtOffsetList;
    232     if (StackSlot* slot = m_calleeSaveStackSlot) {
    233         ptrdiff_t offset = slot->byteSize() + slot->offsetFromFP();
    234         for (size_t i = result.size(); i--;) {
    235             result.at(i) = RegisterAtOffset(
    236                 result.at(i).reg(),
    237                 result.at(i).offset() + offset);
    238         }
    239     }
     232    if (StackSlot* slot = m_calleeSaveStackSlot)
     233        result.adjustOffsets(slot->byteSize() + slot->offsetFromFP());
    240234    return result;
    241235}
     
    278272        out.print(tierName, "Call arg area size: ", m_callArgAreaSize, "\n");
    279273    RegisterAtOffsetList calleeSaveRegisters = this->calleeSaveRegisterAtOffsetList();
    280     if (calleeSaveRegisters.size())
     274    if (calleeSaveRegisters.registerCount())
    281275        out.print(tierName, "Callee saves: ", calleeSaveRegisters, "\n");
    282276}
  • trunk/Source/JavaScriptCore/b3/testb3_7.cpp

    r292475 r294794  
    15581558    // The patchpoint early ret() works because we don't have callee saves.
    15591559    auto code = compileProc(proc);
    1560     RELEASE_ASSERT(!proc.calleeSaveRegisterAtOffsetList().size());
     1560    RELEASE_ASSERT(!proc.calleeSaveRegisterAtOffsetList().registerCount());
    15611561    invoke<void>(*code, static_cast<uint64_t>(55)); // Shouldn't crash dereferncing 55.
    15621562}
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r293779 r294794  
    24632463
    24642464#if !ENABLE(C_LOOP)
    2465 static size_t roundCalleeSaveSpaceAsVirtualRegisters(size_t calleeSaveRegisters)
    2466 {
    2467 
    2468     return (WTF::roundUpToMultipleOf(sizeof(Register), calleeSaveRegisters * sizeof(CPURegister)) / sizeof(Register));
    2469 
    2470 }
    2471 
    24722465size_t CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters()
    24732466{
    2474     return roundCalleeSaveSpaceAsVirtualRegisters(numberOfLLIntBaselineCalleeSaveRegisters());
     2467    return WTF::roundUpToMultipleOf<sizeof(Register)>(numberOfLLIntBaselineCalleeSaveRegisters() * sizeof(CPURegister)) / sizeof(Register);
    24752468}
    24762469
    24772470size_t CodeBlock::calleeSaveSpaceAsVirtualRegisters(const RegisterAtOffsetList& calleeSaveRegisters)
    24782471{
    2479     return roundCalleeSaveSpaceAsVirtualRegisters(calleeSaveRegisters.size());
     2472    return WTF::roundUpToMultipleOf<sizeof(Register)>(calleeSaveRegisters.sizeOfAreaInBytes()) / sizeof(Register);
    24802473}
    24812474#endif
  • trunk/Source/JavaScriptCore/bytecode/ValueRecovery.h

    r284923 r294794  
    193193
    194194#if USE(JSVALUE32_64)
    195     static ValueRecovery calleeSaveRegDisplacedInJSStack(VirtualRegister virtualReg, bool inTag)
     195    static ValueRecovery calleeSaveGPRDisplacedInJSStack(VirtualRegister virtualReg, bool inTag)
    196196    {
    197197        ValueRecovery result;
  • trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp

    r293714 r294794  
    300300    RegisterSet dontSaveRegisters = RegisterSet(RegisterSet::stackRegisters());
    301301
    302     unsigned registerCount = registerSaveLocations->size();
     302    unsigned registerCount = registerSaveLocations->registerCount();
    303303    VMEntryRecord* record = vmEntryRecord(vm.topEntryFrame);
    304304    for (unsigned i = 0; i < registerCount; i++) {
  • trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp

    r293087 r294794  
    232232{
    233233    const RegisterAtOffsetList* calleeSaves = baselineCodeBlock->jitCode()->calleeSaveRegisters();
    234     for (unsigned i = 0; i < calleeSaves->size(); i++) {
     234    for (unsigned i = 0; i < calleeSaves->registerCount(); i++) {
    235235        RegisterAtOffset entry = calleeSaves->at(i);
    236236        if (entry.reg() != calleeSave)
  • trunk/Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp

    r293605 r294794  
    183183            exit.m_descriptor->m_values.size() + numMaterializations + maxMaterializationNumArguments) +
    184184        requiredScratchMemorySizeInBytes() +
    185         codeBlock->jitCode()->calleeSaveRegisters()->size() * sizeof(uint64_t));
     185        codeBlock->jitCode()->calleeSaveRegisters()->sizeOfAreaInBytes());
    186186    EncodedJSValue* scratch = scratchBuffer ? static_cast<EncodedJSValue*>(scratchBuffer->dataBuffer()) : nullptr;
    187187    EncodedJSValue* materializationPointers = scratch + exit.m_descriptor->m_values.size();
     
    453453        jit.move(CCallHelpers::TrustedImmPtr(unwindScratch), destBufferGPR);
    454454        CCallHelpers::CopySpooler spooler(CCallHelpers::CopySpooler::BufferRegs::AllowModification, jit, srcBufferGPR, destBufferGPR, GPRInfo::regT0, GPRInfo::regT1);
    455         for (unsigned i = codeBlock->jitCode()->calleeSaveRegisters()->size(); i--;) {
     455        for (unsigned i = codeBlock->jitCode()->calleeSaveRegisters()->registerCount(); i--;) {
    456456            RegisterAtOffset entry = codeBlock->jitCode()->calleeSaveRegisters()->at(i);
    457457            spooler.loadGPR(entry.offset());
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r293779 r294794  
    626626        CPURegister* frame = reinterpret_cast<CPURegister*>(m_callFrame->registers());
    627627
    628         unsigned registerCount = currentCalleeSaves->size();
     628        unsigned registerCount = currentCalleeSaves->registerCount();
    629629        VMEntryRecord* record = vmEntryRecord(m_vm.topEntryFrame);
    630630        for (unsigned i = 0; i < registerCount; i++) {
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp

    r293746 r294794  
    634634    RegisterAtOffsetList* allCalleeSaves = RegisterSet::vmCalleeSaveRegisterOffsets();
    635635    RegisterSet dontRestoreRegisters = RegisterSet::stackRegisters();
    636     unsigned registerCount = allCalleeSaves->size();
     636    unsigned registerCount = allCalleeSaves->registerCount();
    637637
    638638    GPRReg scratch = InvalidGPRReg;
     
    721721
    722722    RegisterAtOffsetList* allCalleeSaves = RegisterSet::vmCalleeSaveRegisterOffsets();
    723     unsigned registerCount = allCalleeSaves->size();
     723    unsigned registerCount = allCalleeSaves->registerCount();
    724724
    725725    LoadRegSpooler spooler(*this, entryFrameGPR);
     
    11101110    RegisterAtOffsetList* allCalleeSaves = RegisterSet::vmCalleeSaveRegisterOffsets();
    11111111    RegisterSet dontCopyRegisters = RegisterSet::stackRegisters();
    1112     unsigned registerCount = allCalleeSaves->size();
     1112    unsigned registerCount = allCalleeSaves->registerCount();
    11131113
    11141114    StoreRegSpooler spooler(*this, calleeSavesBuffer);
     
    12201220    StoreRegSpooler spooler(*this, framePointerRegister);
    12211221
    1222     size_t listSize = list.size();
     1222    size_t registerCount = list.registerCount();
    12231223    size_t i = 0;
    1224     for (; i < listSize; i++) {
     1224    for (; i < registerCount; i++) {
    12251225        auto entry = list.at(i);
    12261226        if (!entry.reg().isGPR())
     
    12301230    spooler.finalizeGPR();
    12311231
    1232     for (; i < listSize; i++)
     1232    for (; i < registerCount; i++)
    12331233        spooler.storeFPR(list.at(i));
    12341234    spooler.finalizeFPR();
     
    12391239    LoadRegSpooler spooler(*this, framePointerRegister);
    12401240
    1241     size_t listSize = list.size();
     1241    size_t registerCount = list.registerCount();
    12421242    size_t i = 0;
    1243     for (; i < listSize; i++) {
     1243    for (; i < registerCount; i++) {
    12441244        auto entry = list.at(i);
    12451245        if (!entry.reg().isGPR())
     
    12491249    spooler.finalizeGPR();
    12501250
    1251     for (; i < listSize; i++)
     1251    for (; i < registerCount; i++)
    12521252        spooler.loadFPR(list.at(i));
    12531253    spooler.finalizeFPR();
     
    12571257{
    12581258    RegisterSet dontSaveRegisters = RegisterSet(RegisterSet::stackRegisters());
    1259     unsigned registerCount = calleeSaves->size();
     1259    unsigned registerCount = calleeSaves->registerCount();
    12601260
    12611261    StoreRegSpooler spooler(*this, framePointerRegister);
     
    12831283{
    12841284    RegisterSet dontRestoreRegisters = RegisterSet(RegisterSet::stackRegisters());
    1285     unsigned registerCount = calleeSaves->size();
     1285    unsigned registerCount = calleeSaves->registerCount();
    12861286   
    12871287    LoadRegSpooler spooler(*this, framePointerRegister);
     
    13261326    const RegisterAtOffsetList* currentCalleeSaves = &RegisterAtOffsetList::llintBaselineCalleeSaveRegisters();
    13271327    RegisterSet dontCopyRegisters = RegisterSet::stackRegisters();
    1328     unsigned registerCount = allCalleeSaves->size();
     1328    unsigned registerCount = allCalleeSaves->registerCount();
    13291329
    13301330    unsigned i = 0;
     
    13741374    const RegisterAtOffsetList* calleeSaves = &RegisterAtOffsetList::llintBaselineCalleeSaveRegisters();
    13751375    RegisterSet dontSaveRegisters = RegisterSet(RegisterSet::stackRegisters());
    1376     unsigned registerCount = calleeSaves->size();
     1376    unsigned registerCount = calleeSaves->registerCount();
    13771377
    13781378    GPRReg dstBufferGPR = temp1;
  • trunk/Source/JavaScriptCore/jit/CallFrameShuffleData.cpp

    r290647 r294794  
    4040    RegisterSet calleeSaveRegisters { RegisterSet::vmCalleeSaveRegisters() };
    4141
    42     for (size_t i = 0; i < registerSaveLocations->size(); ++i) {
     42    for (size_t i = 0; i < registerSaveLocations->registerCount(); ++i) {
    4343        RegisterAtOffset entry { registerSaveLocations->at(i) };
    4444        if (!calleeSaveRegisters.get(entry.reg()))
     
    5353            = ValueRecovery::displacedInJSStack(saveSlot, DataFormatJS);
    5454#elif USE(JSVALUE32_64)
    55         // On 32-bit architectures, 2 callee saved registers may be packed into the same slot
    56         static_assert(!PayloadOffset || !TagOffset);
    57         static_assert(PayloadOffset == 4 || TagOffset == 4);
    58         bool inTag = (saveSlotIndexInCPURegisters & 1) == !!TagOffset;
    59         if (saveSlotIndexInCPURegisters < 0)
    60             saveSlotIndexInCPURegisters -= 1; // Round towards -inf
    61         VirtualRegister saveSlot { saveSlotIndexInCPURegisters / 2 };
    62         registers[entry.reg()]
    63             = ValueRecovery::calleeSaveRegDisplacedInJSStack(saveSlot, inTag);
     55        // On 32-bit architectures, 2 callee saved GPRs may be packed into the same slot
     56        if (entry.reg().isGPR()) {
     57            static_assert(!PayloadOffset || !TagOffset);
     58            static_assert(PayloadOffset == 4 || TagOffset == 4);
     59            bool inTag = (saveSlotIndexInCPURegisters & 1) == !!TagOffset;
     60            if (saveSlotIndexInCPURegisters < 0)
     61                saveSlotIndexInCPURegisters -= 1; // Round towards -inf
     62            VirtualRegister saveSlot { saveSlotIndexInCPURegisters / 2 };
     63            registers[entry.reg()] = ValueRecovery::calleeSaveGPRDisplacedInJSStack(saveSlot, inTag);
     64        } else {
     65            ASSERT(!(saveSlotIndexInCPURegisters & 1)); // Should be at an even offset
     66            VirtualRegister saveSlot { saveSlotIndexInCPURegisters / 2 };
     67            registers[entry.reg()] = ValueRecovery::displacedInJSStack(saveSlot, DataFormatDouble);
     68        }
    6469#endif
    6570    }
     
    7580        registers[reg] = ValueRecovery::inRegister(reg, DataFormatJS);
    7681#elif USE(JSVALUE32_64)
    77         registers[reg] = ValueRecovery::inRegister(reg, DataFormatInt32);
     82        registers[reg] = ValueRecovery::inRegister(reg, reg.isGPR() ? DataFormatInt32 : DataFormatDouble);
    7883#endif
    7984    }
  • trunk/Source/JavaScriptCore/jit/CallFrameShuffler.h

    r284923 r294794  
    120120#elif USE(JSVALUE32_64)
    121121            ValueRecovery recovery = cachedRecovery->recovery();
    122             if (recovery.technique() == DisplacedInJSStack) {
     122            if (reg.isGPR() && recovery.technique() == DisplacedInJSStack) {
    123123                JSValueRegs wantedJSValueReg = cachedRecovery->wantedJSValueRegs();
    124124                ASSERT(reg == wantedJSValueReg.payloadGPR() || reg == wantedJSValueReg.tagGPR());
    125125                bool inTag = reg == wantedJSValueReg.tagGPR();
    126                 data.registers[reg] = ValueRecovery::calleeSaveRegDisplacedInJSStack(recovery.virtualRegister(), inTag);
     126                data.registers[reg] = ValueRecovery::calleeSaveGPRDisplacedInJSStack(recovery.virtualRegister(), inTag);
    127127            } else
    128128                data.registers[reg] = recovery;
  • trunk/Source/JavaScriptCore/jit/CallFrameShuffler32_64.cpp

    r293087 r294794  
    184184    ASSERT(location.recovery().isInRegisters());
    185185    JSValueRegs wantedJSValueRegs { location.wantedJSValueRegs() };
    186     ASSERT(wantedJSValueRegs); // We don't support wanted FPRs on 32bit platforms
    187 
    188186    GPRReg wantedTagGPR { wantedJSValueRegs.tagGPR() };
    189187    GPRReg wantedPayloadGPR { wantedJSValueRegs.payloadGPR() };
    190    
     188    FPRReg wantedFPR { location.wantedFPR() };
     189
    191190    if (wantedTagGPR != InvalidGPRReg) {
    192191        ASSERT(!m_lockedRegisters.get(wantedTagGPR));
     
    209208    if (location.recovery().technique() == InPair
    210209        || location.recovery().isInGPR()) {
     210        ASSERT(wantedJSValueRegs); // We don't support wanted FPRs on 32bit platforms at the moment
    211211        GPRReg payloadGPR;
    212212        if (location.recovery().technique() == InPair)
     
    274274            RELEASE_ASSERT_NOT_REACHED();
    275275        }
     276        updateRecovery(location, ValueRecovery::inPair(wantedTagGPR, wantedPayloadGPR));
    276277    } else {
    277278        ASSERT(location.recovery().isInFPR());
    278         if (wantedTagGPR == InvalidGPRReg) {
    279             ASSERT(wantedPayloadGPR != InvalidGPRReg);
    280             m_lockedRegisters.set(wantedPayloadGPR);
    281             wantedTagGPR = getFreeGPR();
    282             m_lockedRegisters.clear(wantedPayloadGPR);
    283         }
    284         if (wantedPayloadGPR == InvalidGPRReg) {
    285             m_lockedRegisters.set(wantedTagGPR);
    286             wantedPayloadGPR = getFreeGPR();
    287             m_lockedRegisters.clear(wantedTagGPR);
    288         }
    289         m_jit.boxDouble(location.recovery().fpr(), wantedTagGPR, wantedPayloadGPR);
    290     }
    291     updateRecovery(location, ValueRecovery::inPair(wantedTagGPR, wantedPayloadGPR));
     279        if (wantedFPR != InvalidFPRReg) {
     280            m_jit.moveDouble(location.recovery().fpr(), wantedFPR);
     281            updateRecovery(location, ValueRecovery::inRegister(wantedFPR, DataFormatJS));
     282        } else {
     283            if (wantedTagGPR == InvalidGPRReg) {
     284                ASSERT(wantedPayloadGPR != InvalidGPRReg);
     285                m_lockedRegisters.set(wantedPayloadGPR);
     286                wantedTagGPR = getFreeGPR();
     287                m_lockedRegisters.clear(wantedPayloadGPR);
     288            }
     289            if (wantedPayloadGPR == InvalidGPRReg) {
     290                m_lockedRegisters.set(wantedTagGPR);
     291                wantedPayloadGPR = getFreeGPR();
     292                m_lockedRegisters.clear(wantedTagGPR);
     293            }
     294            m_jit.moveDoubleToInts(location.recovery().fpr(), wantedPayloadGPR, wantedTagGPR);
     295            updateRecovery(location, ValueRecovery::inPair(wantedTagGPR, wantedPayloadGPR));
     296        }
     297    }
    292298}
    293299
  • trunk/Source/JavaScriptCore/jit/FPRInfo.h

    r291946 r294794  
    107107public:
    108108    typedef FPRReg RegisterType;
    109     static constexpr unsigned numberOfRegisters = 6;
     109    static constexpr unsigned numberOfRegisters = 8;
    110110
    111111#if CPU(ARM_HARDFP)
     
    116116
    117117    // Temporary registers.
    118     // d7 is use by the MacroAssembler as fpTempRegister.
     118    // d8-d15 are callee saved, d15 is use by the MacroAssembler as fpTempRegister.
    119119    static constexpr FPRReg fpRegT0 = ARMRegisters::d0;
    120120    static constexpr FPRReg fpRegT1 = ARMRegisters::d1;
     
    123123    static constexpr FPRReg fpRegT4 = ARMRegisters::d4;
    124124    static constexpr FPRReg fpRegT5 = ARMRegisters::d5;
     125    static constexpr FPRReg fpRegT6 = ARMRegisters::d6;
     126    static constexpr FPRReg fpRegT7 = ARMRegisters::d7;
     127    static constexpr FPRReg fpRegCS0 = ARMRegisters::d8;
     128    static constexpr FPRReg fpRegCS1 = ARMRegisters::d9;
     129    static constexpr FPRReg fpRegCS2 = ARMRegisters::d10;
     130    static constexpr FPRReg fpRegCS3 = ARMRegisters::d11;
     131    static constexpr FPRReg fpRegCS4 = ARMRegisters::d12;
     132    static constexpr FPRReg fpRegCS5 = ARMRegisters::d13;
     133    static constexpr FPRReg fpRegCS6 = ARMRegisters::d14;
     134
    125135    // ARMv7 doesn't pass arguments in fp registers. The return
    126136    // value is also actually in integer registers, for now
     
    141151    static_assert(ARMRegisters::d4 == 4);
    142152    static_assert(ARMRegisters::d5 == 5);
     153    static_assert(ARMRegisters::d6 == 6);
     154    static_assert(ARMRegisters::d7 == 7);
    143155    static FPRReg toRegister(unsigned index)
    144156    {
  • trunk/Source/JavaScriptCore/jit/GPRInfo.h

    r293141 r294794  
    554554#if CPU(ARM_THUMB2)
    555555#define NUMBER_OF_ARGUMENT_REGISTERS 4u
    556 #define NUMBER_OF_CALLEE_SAVES_REGISTERS 2u
     556// Callee Saves includes r10, r11, and FP registers d8..d15, which are twice the size of a GPR
     557#define NUMBER_OF_CALLEE_SAVES_REGISTERS 18u
    557558
    558559class GPRInfo {
  • trunk/Source/JavaScriptCore/jit/RegisterAtOffsetList.cpp

    r287596 r294794  
    4040    : m_registers(registerSet.numberOfSetRegisters())
    4141{
    42     size_t numberOfRegisters = registerSet.numberOfSetRegisters();
    43     ptrdiff_t offset = 0;
    44    
     42    constexpr size_t sizeOfGPR = sizeof(CPURegister);
     43    constexpr size_t sizeOfFPR = sizeof(double);
     44
     45    size_t sizeOfAreaInBytes;
     46    {
     47#if USE(JSVALUE64)
     48        static_assert(sizeOfGPR == sizeOfFPR);
     49        size_t numberOfRegs = registerSet.numberOfSetRegisters();
     50        sizeOfAreaInBytes = numberOfRegs * sizeOfGPR;
     51#elif USE(JSVALUE32_64)
     52        static_assert(2 * sizeOfGPR == sizeOfFPR);
     53        size_t numberOfGPRs = registerSet.numberOfSetGPRs();
     54        size_t numberOfFPRs = registerSet.numberOfSetFPRs();
     55        if (numberOfFPRs)
     56            numberOfGPRs = WTF::roundUpToMultipleOf<2>(numberOfGPRs);
     57        sizeOfAreaInBytes = numberOfGPRs * sizeOfGPR + numberOfFPRs * sizeOfFPR;
     58        m_sizeOfAreaInBytes = sizeOfAreaInBytes; // Hold on to it to avoid having to re-compute it
     59#endif
     60    }
     61
     62    ptrdiff_t startOffset = 0;
    4563    if (offsetBaseType == FramePointerBased)
    46         offset = -(static_cast<ptrdiff_t>(numberOfRegisters) * sizeof(CPURegister));
     64        startOffset = -static_cast<ptrdiff_t>(sizeOfAreaInBytes);
    4765
     66    ptrdiff_t offset = startOffset;
    4867    unsigned index = 0;
     68
    4969    registerSet.forEach([&] (Reg reg) {
    50         m_registers[index] = RegisterAtOffset(reg, offset);
    51         offset += sizeof(CPURegister);
    52         ++index;
     70        size_t registerSize = reg.isGPR() ? sizeOfGPR : sizeOfFPR;
     71        offset = WTF::roundUpToMultipleOf(registerSize, offset);
     72        m_registers[index++] = RegisterAtOffset(reg, offset);
     73        offset += registerSize;
    5374    });
     75
     76    ASSERT(static_cast<size_t>(offset - startOffset) == sizeOfAreaInBytes);
    5477}
    5578
  • trunk/Source/JavaScriptCore/jit/RegisterAtOffsetList.h

    r287596 r294794  
    4545    void dump(PrintStream&) const;
    4646
    47     size_t size() const
     47    size_t registerCount() const { return m_registers.size(); }
     48    size_t sizeOfAreaInBytes() const
    4849    {
    49         return m_registers.size();
     50#if USE(JSVALUE64)
     51        static_assert(sizeof(CPURegister) == sizeof(double));
     52        return registerCount() * sizeof(CPURegister);
     53#elif USE(JSVALUE32_64)
     54        return m_sizeOfAreaInBytes;
     55#endif
    5056    }
    5157
     
    5561    }
    5662
    57     RegisterAtOffset& at(size_t index)
     63    void adjustOffsets(ptrdiff_t addend)
    5864    {
    59         return m_registers.at(index);
     65        // This preserves m_sizeOfAreaInBytes
     66        for (RegisterAtOffset &item : m_registers)
     67            item = RegisterAtOffset { item.reg(), item.offset() + addend };
    6068    }
    61    
     69
    6270    RegisterAtOffset* find(Reg) const;
    6371    unsigned indexOf(Reg) const; // Returns UINT_MAX if not found.
     
    6674    FixedVector<RegisterAtOffset>::const_iterator end() const { return m_registers.end(); }
    6775
     76
    6877    static const RegisterAtOffsetList& llintBaselineCalleeSaveRegisters(); // Registers and Offsets saved and used by the LLInt.
    6978    static const RegisterAtOffsetList& dfgCalleeSaveRegisters(); // Registers and Offsets saved and used by DFG.
     
    7180private:
    7281    FixedVector<RegisterAtOffset> m_registers;
     82#if USE(JSVALUE32_64) // On JSVALUE64, we can compute this cheaply
     83    size_t m_sizeOfAreaInBytes { 0 };
     84#endif
    7385};
    7486
  • trunk/Source/JavaScriptCore/jit/RegisterSet.cpp

    r293009 r294794  
    9595#elif CPU(ARM64) || CPU(RISCV64)
    9696    return RegisterSet(MacroAssembler::dataTempRegister, MacroAssembler::memoryTempRegister);
     97#elif CPU(ARM_THUMB2)
     98    RegisterSet result;
     99    result.set(MacroAssembler::dataTempRegister);
     100    result.set(MacroAssembler::addressTempRegister);
     101    result.set(MacroAssembler::fpTempRegister);
     102    return result;
    97103#elif CPU(MIPS)
    98104    RegisterSet result;
     
    153159    result.set(FPRInfo::fpRegCS6);
    154160    result.set(FPRInfo::fpRegCS7);
    155 #elif CPU(ARM_THUMB2) || CPU(MIPS)
     161#elif CPU(ARM_THUMB2)
     162    result.set(GPRInfo::regCS0);
     163    result.set(GPRInfo::regCS1);
     164    result.set(FPRInfo::fpRegCS0);
     165    result.set(FPRInfo::fpRegCS1);
     166    result.set(FPRInfo::fpRegCS2);
     167    result.set(FPRInfo::fpRegCS3);
     168    result.set(FPRInfo::fpRegCS4);
     169    result.set(FPRInfo::fpRegCS5);
     170    result.set(FPRInfo::fpRegCS6);
     171#elif CPU(MIPS)
    156172    result.set(GPRInfo::regCS0);
    157173    result.set(GPRInfo::regCS1);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r293041 r294794  
    757757    const CalleeSaveRegisterCount = 0
    758758elsif ARMv7
    759     const CalleeSaveRegisterCount = 7
     759    const CalleeSaveRegisterCount = 7 + 2 * 1 // 7 32-bit GPRs + 1 64-bit FPR
    760760elsif MIPS
    761761    const CalleeSaveRegisterCount = 3
     
    773773    if C_LOOP or C_LOOP_WIN or ARM64 or ARM64E or X86_64 or X86_64_WIN or RISCV64
    774774    elsif ARMv7
     775        emit "vpush.64 {d15}"
    775776        emit "push {r4-r6, r8-r11}"
    776777    elsif MIPS
     
    796797    elsif ARMv7
    797798        emit "pop {r4-r6, r8-r11}"
     799        emit "vpop.64 {d15}"
    798800    elsif MIPS
    799801        emit "lw $s0, 0($sp)"
     
    934936            storeq csr5, 40[entryFrame]
    935937            storeq csr6, 48[entryFrame]
    936         elsif ARMv7 or MIPS
     938        elsif ARMv7
     939            storep csr0, [entryFrame]
     940            storep csr1, 4[entryFrame]
     941            stored csfr0, 8[entryFrame]
     942            stored csfr1, 16[entryFrame]
     943            stored csfr2, 24[entryFrame]
     944            stored csfr3, 32[entryFrame]
     945            stored csfr4, 40[entryFrame]
     946            stored csfr5, 48[entryFrame]
     947            stored csfr6, 56[entryFrame]
     948        elsif MIPS
    937949            storep csr0, [entryFrame]
    938950            storep csr1, 4[entryFrame]
     
    10101022            loadq 40[temp], csr5
    10111023            loadq 48[temp], csr6
    1012         elsif ARMv7 or MIPS
     1024        elsif ARMv7
     1025            loadp [temp], csr0
     1026            loadp 4[temp], csr1
     1027            loadd 8[temp], csfr0
     1028            loadd 16[temp], csfr1
     1029            loadd 24[temp], csfr2
     1030            loadd 32[temp], csfr3
     1031            loadd 40[temp], csfr4
     1032            loadd 48[temp], csfr5
     1033            loadd 56[temp], csfr6
     1034        elsif MIPS
    10131035            loadp [temp], csr0
    10141036            loadp 4[temp], csr1
  • trunk/Source/JavaScriptCore/offlineasm/arm.rb

    r294787 r294794  
    4949# FPR conventions, to match the baseline JIT
    5050#
    51 # d0 => ft0, fa0, fr
    52 # d1 => ft1, fa1
    53 # d2 => ft2
    54 # d3 => ft3
    55 # d4 => ft4
    56 # d5 => ft5
    57 # d6 =>              (scratch)
    58 # d7 =>              (scratch)
     51#  d0 => ft0, fa0, fr
     52#  d1 => ft1, fa1
     53#  d2 => ft2
     54#  d3 => ft3
     55#  d4 => ft4
     56#  d5 => ft5
     57#  d6 => ft6
     58#  d7 => ft7
     59#  d8 => csfr0
     60#  d9 => csfr1
     61# d10 => csfr2
     62# d11 => csfr3
     63# d12 => csfr4
     64# d13 => csfr5
     65# d14 => csfr6
     66# d15 => scratch
    5967
    6068class Node
     
    7785ARM_EXTRA_GPRS = [SpecialRegister.new("r9"), SpecialRegister.new("r12"), SpecialRegister.new("r6")]
    7886ARM_EXTRA_FPRS = [SpecialRegister.new("d7")]
    79 ARM_SCRATCH_FPR = SpecialRegister.new("d6")
     87ARM_SCRATCH_FPR = SpecialRegister.new("d15")
    8088OS_DARWIN = ((RUBY_PLATFORM =~ /darwin/i) != nil)
    8189
     
    148156        when "ft5"
    149157            "d5"
     158        when "ft6"
     159            "d6"
     160        when "ft7"
     161            "d7"
     162        when "csfr0"
     163            "d8"
     164        when "csfr1"
     165            "d9"
     166        when "csfr2"
     167            "d10"
     168        when "csfr3"
     169            "d11"
     170        when "csfr4"
     171            "d12"
     172        when "csfr5"
     173            "d13"
     174        when "csfr6"
     175            "d14"
    150176        else
    151177            raise "Bad register #{name} for ARM at #{codeOriginString}"
  • trunk/Source/JavaScriptCore/wasm/js/JSToWasm.cpp

    r292773 r294794  
    198198    result->entrypoint.calleeSaveRegisters = registersToSpill;
    199199
    200     size_t totalFrameSize = registersToSpill.size() * sizeof(CPURegister);
     200    size_t totalFrameSize = registersToSpill.sizeOfAreaInBytes();
    201201    CallInformation wasmFrameConvention = wasmCallingConvention().callInformationFor(typeDefinition);
    202202    RegisterAtOffsetList savedResultRegisters = wasmFrameConvention.computeResultsOffsetList();
    203203    totalFrameSize += wasmFrameConvention.headerAndArgumentStackSizeInBytes;
    204     totalFrameSize += savedResultRegisters.size() * sizeof(CPURegister);
     204    totalFrameSize += savedResultRegisters.sizeOfAreaInBytes();
    205205
    206206    totalFrameSize = WTF::roundUpToMultipleOf(stackAlignmentBytes(), totalFrameSize);
  • trunk/Source/JavaScriptCore/wasm/js/WasmToJS.cpp

    r293510 r294794  
    8989    const unsigned numberOfRegsForCall = CallFrame::headerSizeInRegisters + numberOfParameters;
    9090    const unsigned numberOfBytesForCall = numberOfRegsForCall * sizeof(Register) - sizeof(CallerFrameAndPC);
    91     const unsigned stackOffset = WTF::roundUpToMultipleOf(stackAlignmentBytes(), std::max<unsigned>(numberOfBytesForCall, savedResultRegisters.size() * sizeof(CPURegister)));
     91    const unsigned stackOffset = WTF::roundUpToMultipleOf(stackAlignmentBytes(), std::max<unsigned>(numberOfBytesForCall, savedResultRegisters.sizeOfAreaInBytes()));
    9292    jit.subPtr(MacroAssembler::TrustedImm32(stackOffset), MacroAssembler::stackPointerRegister);
    9393    JIT::Address calleeFrame = CCallHelpers::Address(MacroAssembler::stackPointerRegister, -static_cast<ptrdiff_t>(sizeof(CallerFrameAndPC)));
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp

    r292773 r294794  
    194194    RegisterAtOffsetList savedResultRegisters = wasmCallInfo.computeResultsOffsetList();
    195195
    196     unsigned totalFrameSize = registersToSpill.size() * sizeof(CPURegister);
     196    unsigned totalFrameSize = registersToSpill.sizeOfAreaInBytes();
    197197    totalFrameSize += sizeof(CPURegister); // Slot for the VM's previous wasm instance.
    198198    totalFrameSize += wasmCallInfo.headerAndArgumentStackSizeInBytes;
    199     totalFrameSize += savedResultRegisters.size() * sizeof(CPURegister);
     199    totalFrameSize += savedResultRegisters.sizeOfAreaInBytes();
    200200
    201201    // FIXME: Optimize Wasm function call even if arguments include I64.
Note: See TracChangeset for help on using the changeset viewer.