コード例 #1
0
ファイル: RegisterSet.cpp プロジェクト: TigerLau1985/webkit
RegisterSet RegisterSet::reservedHardwareRegisters()
{
#if CPU(ARM64)
    return RegisterSet(ARM64Registers::lr);
#else
    return RegisterSet();
#endif
}
コード例 #2
0
ファイル: RegisterSet.cpp プロジェクト: TigerLau1985/webkit
RegisterSet RegisterSet::runtimeRegisters()
{
#if USE(JSVALUE64)
    return RegisterSet(GPRInfo::tagTypeNumberRegister, GPRInfo::tagMaskRegister);
#else
    return RegisterSet();
#endif
}
コード例 #3
0
ファイル: RegisterSet.cpp プロジェクト: ekapujiw2002/webkit
RegisterSet RegisterSet::macroScratchRegisters()
{
#if CPU(X86_64)
    return RegisterSet(MacroAssembler::s_scratchRegister);
#elif CPU(ARM64)
    return RegisterSet(MacroAssembler::dataTempRegister, MacroAssembler::memoryTempRegister);
#else
    return RegisterSet();
#endif
}
コード例 #4
0
ファイル: RegisterSet.cpp プロジェクト: jeff-jenness/webkit
RegisterSet RegisterSet::reservedHardwareRegisters()
{
#if CPU(ARM64)
#if PLATFORM(IOS)
    return RegisterSet(ARM64Registers::x18, ARM64Registers::lr);
#else
    return RegisterSet(ARM64Registers::lr);
#endif // PLATFORM(IOS)
#else
    return RegisterSet();
#endif
}
コード例 #5
0
ファイル: RegisterSet.cpp プロジェクト: jeff-jenness/webkit
RegisterSet RegisterSet::macroScratchRegisters()
{
#if CPU(X86_64)
    return RegisterSet(MacroAssembler::s_scratchRegister);
#elif CPU(ARM64)
    return RegisterSet(MacroAssembler::dataTempRegister, MacroAssembler::memoryTempRegister);
#elif CPU(MIPS)
    RegisterSet result;
    result.set(MacroAssembler::immTempRegister);
    result.set(MacroAssembler::dataTempRegister);
    result.set(MacroAssembler::addrTempRegister);
    result.set(MacroAssembler::cmpTempRegister);
    return result;
#else
    return RegisterSet();
#endif
}
コード例 #6
0
ファイル: FTLJITCode.cpp プロジェクト: sailei1/webkit
RegisterSet JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBlock*, CallSiteIndex callSiteIndex)
{
    for (OSRExit& exit : osrExit) {
        if (exit.m_exceptionHandlerCallSiteIndex.bits() == callSiteIndex.bits()) {
            RELEASE_ASSERT(exit.m_isExceptionHandler);
            return stackmaps.records[exit.m_stackmapRecordIndex].usedRegisterSet();
        }
    }
    return RegisterSet();
}
コード例 #7
0
ファイル: bitcoin-tx.cpp プロジェクト: RichardW35/bitcoin
static void MutateTx(CMutableTransaction& tx, const std::string& command,
                     const std::string& commandVal)
{
    std::unique_ptr<Secp256k1Init> ecc;

    if (command == "nversion")
        MutateTxVersion(tx, commandVal);
    else if (command == "locktime")
        MutateTxLocktime(tx, commandVal);
    else if (command == "replaceable") {
        MutateTxRBFOptIn(tx, commandVal);
    }

    else if (command == "delin")
        MutateTxDelInput(tx, commandVal);
    else if (command == "in")
        MutateTxAddInput(tx, commandVal);

    else if (command == "delout")
        MutateTxDelOutput(tx, commandVal);
    else if (command == "outaddr")
        MutateTxAddOutAddr(tx, commandVal);
    else if (command == "outpubkey") {
        ecc.reset(new Secp256k1Init());
        MutateTxAddOutPubKey(tx, commandVal);
    } else if (command == "outmultisig") {
        ecc.reset(new Secp256k1Init());
        MutateTxAddOutMultiSig(tx, commandVal);
    } else if (command == "outscript")
        MutateTxAddOutScript(tx, commandVal);
    else if (command == "outdata")
        MutateTxAddOutData(tx, commandVal);

    else if (command == "sign") {
        ecc.reset(new Secp256k1Init());
        MutateTxSign(tx, commandVal);
    }

    else if (command == "load")
        RegisterLoad(commandVal);

    else if (command == "set")
        RegisterSet(commandVal);

    else
        throw std::runtime_error("unknown command");
}
コード例 #8
0
//IFX_ETHSW_HANDLE handle;
static int __init IFX_ETHSW_Switch_API_testModule_Init(void)
{
    //printk("Init IFX_ETHSW_Switch_API_testModule successfully.\n");

    IFX_ETHSW_HANDLE handle;

    handle = ifx_ethsw_kopen("/dev/switch/0");
    switch (g_cmd)
    {
        case 1: CfgGet(handle); break;
        case 2: CfgSet(handle); break;
        case 3: PortCfgGet(handle); break;
        case 4: PortCfgSet(handle); break;
        case 5: PortLinkCfgGet(handle); break;
        case 6: PortLinkCfgSet(handle); break;
        case 7: PortRedirectGet(handle); break;
        case 8: PortRedirectSet(handle); break;
        case 9: MAC_tableRead(handle); break;
        case 10: MAC_tableAdd(handle); break;
        case 11: MAC_tableRemove(handle); break;
        case 12: MAC_TableClear(handle); break;
        case 13: VLAN_IdCreate(handle); break;
        case 14: VLAN_IdDelete(handle); break;
        case 15: VLAN_IdGet(handle); break;
        case 16: VLAN_PortMemberAdd(handle); break;
        case 17: VLAN_PortMemberRemove(handle); break;
        case 18: VLAN_PortCfgGet(handle); break;
        case 19: VLAN_PortCfgSet(handle); break;
        case 20: VLAN_ReservedAdd(handle); break;
        case 21: VLAN_ReservedRemove(handle); break;
        case 22: MDIO_DataRead(handle); break;
        case 23: MDIO_DataWrite(handle); break;
        case 24: RegisterGet(handle); break;
        case 25: RegisterSet(handle); break;
        default: help();  break;
    }
    ifx_ethsw_kclose(handle);

    return IFX_SUCCESS;
}
コード例 #9
0
static RegisterSet usedRegistersFor(const StackMaps::Record& record)
{
    if (Options::assumeAllRegsInFTLICAreLive())
        return RegisterSet::allRegisters();
    return RegisterSet(record.usedRegisterSet(), RegisterSet::calleeSaveRegisters());
}
コード例 #10
0
ファイル: DFGOSREntry.cpp プロジェクト: LuXiong/webkit
SUPPRESS_ASAN
void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIndex)
{
    ASSERT(JITCode::isOptimizingJIT(codeBlock->jitType()));
    ASSERT(codeBlock->alternative());
    ASSERT(codeBlock->alternative()->jitType() == JITCode::BaselineJIT);
    ASSERT(!codeBlock->jitCodeMap());

    if (!Options::useOSREntryToDFG())
        return 0;

    if (Options::verboseOSR()) {
        dataLog(
            "DFG OSR in ", *codeBlock->alternative(), " -> ", *codeBlock,
            " from bc#", bytecodeIndex, "\n");
    }
    
    VM* vm = &exec->vm();

    sanitizeStackForVM(vm);
    
    if (bytecodeIndex)
        codeBlock->ownerScriptExecutable()->setDidTryToEnterInLoop(true);
    
    if (codeBlock->jitType() != JITCode::DFGJIT) {
        RELEASE_ASSERT(codeBlock->jitType() == JITCode::FTLJIT);
        
        // When will this happen? We could have:
        //
        // - An exit from the FTL JIT into the baseline JIT followed by an attempt
        //   to reenter. We're fine with allowing this to fail. If it happens
        //   enough we'll just reoptimize. It basically means that the OSR exit cost
        //   us dearly and so reoptimizing is the right thing to do.
        //
        // - We have recursive code with hot loops. Consider that foo has a hot loop
        //   that calls itself. We have two foo's on the stack, lets call them foo1
        //   and foo2, with foo1 having called foo2 from foo's hot loop. foo2 gets
        //   optimized all the way into the FTL. Then it returns into foo1, and then
        //   foo1 wants to get optimized. It might reach this conclusion from its
        //   hot loop and attempt to OSR enter. And we'll tell it that it can't. It
        //   might be worth addressing this case, but I just think this case will
        //   be super rare. For now, if it does happen, it'll cause some compilation
        //   thrashing.
        
        if (Options::verboseOSR())
            dataLog("    OSR failed because the target code block is not DFG.\n");
        return 0;
    }
    
    JITCode* jitCode = codeBlock->jitCode()->dfg();
    OSREntryData* entry = jitCode->osrEntryDataForBytecodeIndex(bytecodeIndex);
    
    if (!entry) {
        if (Options::verboseOSR())
            dataLogF("    OSR failed because the entrypoint was optimized out.\n");
        return 0;
    }
    
    ASSERT(entry->m_bytecodeIndex == bytecodeIndex);
    
    // The code below checks if it is safe to perform OSR entry. It may find
    // that it is unsafe to do so, for any number of reasons, which are documented
    // below. If the code decides not to OSR then it returns 0, and it's the caller's
    // responsibility to patch up the state in such a way as to ensure that it's
    // both safe and efficient to continue executing baseline code for now. This
    // should almost certainly include calling either codeBlock->optimizeAfterWarmUp()
    // or codeBlock->dontOptimizeAnytimeSoon().
    
    // 1) Verify predictions. If the predictions are inconsistent with the actual
    //    values, then OSR entry is not possible at this time. It's tempting to
    //    assume that we could somehow avoid this case. We can certainly avoid it
    //    for first-time loop OSR - that is, OSR into a CodeBlock that we have just
    //    compiled. Then we are almost guaranteed that all of the predictions will
    //    check out. It would be pretty easy to make that a hard guarantee. But
    //    then there would still be the case where two call frames with the same
    //    baseline CodeBlock are on the stack at the same time. The top one
    //    triggers compilation and OSR. In that case, we may no longer have
    //    accurate value profiles for the one deeper in the stack. Hence, when we
    //    pop into the CodeBlock that is deeper on the stack, we might OSR and
    //    realize that the predictions are wrong. Probably, in most cases, this is
    //    just an anomaly in the sense that the older CodeBlock simply went off
    //    into a less-likely path. So, the wisest course of action is to simply not
    //    OSR at this time.
    
    for (size_t argument = 0; argument < entry->m_expectedValues.numberOfArguments(); ++argument) {
        if (argument >= exec->argumentCountIncludingThis()) {
            if (Options::verboseOSR()) {
                dataLogF("    OSR failed because argument %zu was not passed, expected ", argument);
                entry->m_expectedValues.argument(argument).dump(WTF::dataFile());
                dataLogF(".\n");
            }
            return 0;
        }
        
        JSValue value;
        if (!argument)
            value = exec->thisValue();
        else
            value = exec->argument(argument - 1);
        
        if (!entry->m_expectedValues.argument(argument).validate(value)) {
            if (Options::verboseOSR()) {
                dataLog(
                    "    OSR failed because argument ", argument, " is ", value,
                    ", expected ", entry->m_expectedValues.argument(argument), ".\n");
            }
            return 0;
        }
    }
    
    for (size_t local = 0; local < entry->m_expectedValues.numberOfLocals(); ++local) {
        int localOffset = virtualRegisterForLocal(local).offset();
        if (entry->m_localsForcedDouble.get(local)) {
            if (!exec->registers()[localOffset].asanUnsafeJSValue().isNumber()) {
                if (Options::verboseOSR()) {
                    dataLog(
                        "    OSR failed because variable ", localOffset, " is ",
                        exec->registers()[localOffset].asanUnsafeJSValue(), ", expected number.\n");
                }
                return 0;
            }
            continue;
        }
        if (entry->m_localsForcedAnyInt.get(local)) {
            if (!exec->registers()[localOffset].asanUnsafeJSValue().isAnyInt()) {
                if (Options::verboseOSR()) {
                    dataLog(
                        "    OSR failed because variable ", localOffset, " is ",
                        exec->registers()[localOffset].asanUnsafeJSValue(), ", expected ",
                        "machine int.\n");
                }
                return 0;
            }
            continue;
        }
        if (!entry->m_expectedValues.local(local).validate(exec->registers()[localOffset].asanUnsafeJSValue())) {
            if (Options::verboseOSR()) {
                dataLog(
                    "    OSR failed because variable ", localOffset, " is ",
                    exec->registers()[localOffset].asanUnsafeJSValue(), ", expected ",
                    entry->m_expectedValues.local(local), ".\n");
            }
            return 0;
        }
    }

    // 2) Check the stack height. The DFG JIT may require a taller stack than the
    //    baseline JIT, in some cases. If we can't grow the stack, then don't do
    //    OSR right now. That's the only option we have unless we want basic block
    //    boundaries to start throwing RangeErrors. Although that would be possible,
    //    it seems silly: you'd be diverting the program to error handling when it
    //    would have otherwise just kept running albeit less quickly.
    
    unsigned frameSizeForCheck = jitCode->common.requiredRegisterCountForExecutionAndExit();
    if (!vm->interpreter->stack().ensureCapacityFor(&exec->registers()[virtualRegisterForLocal(frameSizeForCheck - 1).offset()])) {
        if (Options::verboseOSR())
            dataLogF("    OSR failed because stack growth failed.\n");
        return 0;
    }
    
    if (Options::verboseOSR())
        dataLogF("    OSR should succeed.\n");

    // At this point we're committed to entering. We will do some work to set things up,
    // but we also rely on our caller recognizing that when we return a non-null pointer,
    // that means that we're already past the point of no return and we must succeed at
    // entering.
    
    // 3) Set up the data in the scratch buffer and perform data format conversions.

    unsigned frameSize = jitCode->common.frameRegisterCount;
    unsigned baselineFrameSize = entry->m_expectedValues.numberOfLocals();
    unsigned maxFrameSize = std::max(frameSize, baselineFrameSize);

    Register* scratch = bitwise_cast<Register*>(vm->scratchBufferForSize(sizeof(Register) * (2 + JSStack::CallFrameHeaderSize + maxFrameSize))->dataBuffer());
    
    *bitwise_cast<size_t*>(scratch + 0) = frameSize;
    
    void* targetPC = codeBlock->jitCode()->executableAddressAtOffset(entry->m_machineCodeOffset);
    if (Options::verboseOSR())
        dataLogF("    OSR using target PC %p.\n", targetPC);
    RELEASE_ASSERT(targetPC);
    *bitwise_cast<void**>(scratch + 1) = targetPC;
    
    Register* pivot = scratch + 2 + JSStack::CallFrameHeaderSize;
    
    for (int index = -JSStack::CallFrameHeaderSize; index < static_cast<int>(baselineFrameSize); ++index) {
        VirtualRegister reg(-1 - index);
        
        if (reg.isLocal()) {
            if (entry->m_localsForcedDouble.get(reg.toLocal())) {
                *bitwise_cast<double*>(pivot + index) = exec->registers()[reg.offset()].asanUnsafeJSValue().asNumber();
                continue;
            }
            
            if (entry->m_localsForcedAnyInt.get(reg.toLocal())) {
                *bitwise_cast<int64_t*>(pivot + index) = exec->registers()[reg.offset()].asanUnsafeJSValue().asAnyInt() << JSValue::int52ShiftAmount;
                continue;
            }
        }
        
        pivot[index] = exec->registers()[reg.offset()].asanUnsafeJSValue();
    }
    
    // 4) Reshuffle those registers that need reshuffling.
    Vector<JSValue> temporaryLocals(entry->m_reshufflings.size());
    for (unsigned i = entry->m_reshufflings.size(); i--;)
        temporaryLocals[i] = pivot[VirtualRegister(entry->m_reshufflings[i].fromOffset).toLocal()].asanUnsafeJSValue();
    for (unsigned i = entry->m_reshufflings.size(); i--;)
        pivot[VirtualRegister(entry->m_reshufflings[i].toOffset).toLocal()] = temporaryLocals[i];
    
    // 5) Clear those parts of the call frame that the DFG ain't using. This helps GC on
    //    some programs by eliminating some stale pointer pathologies.
    for (unsigned i = frameSize; i--;) {
        if (entry->m_machineStackUsed.get(i))
            continue;
        pivot[i] = JSValue();
    }

    // 6) Copy our callee saves to buffer.
#if NUMBER_OF_CALLEE_SAVES_REGISTERS > 0
    RegisterAtOffsetList* registerSaveLocations = codeBlock->calleeSaveRegisters();
    RegisterAtOffsetList* allCalleeSaves = vm->getAllCalleeSaveRegisterOffsets();
    RegisterSet dontSaveRegisters = RegisterSet(RegisterSet::stackRegisters(), RegisterSet::allFPRs());

    unsigned registerCount = registerSaveLocations->size();
    VMEntryRecord* record = vmEntryRecord(vm->topVMEntryFrame);
    for (unsigned i = 0; i < registerCount; i++) {
        RegisterAtOffset currentEntry = registerSaveLocations->at(i);
        if (dontSaveRegisters.get(currentEntry.reg()))
            continue;
        RegisterAtOffset* calleeSavesEntry = allCalleeSaves->find(currentEntry.reg());
        
        *(bitwise_cast<intptr_t*>(pivot - 1) - currentEntry.offsetAsIndex()) = record->calleeSaveRegistersBuffer[calleeSavesEntry->offsetAsIndex()];
    }
#endif
    
    // 7) Fix the call frame to have the right code block.
    
    *bitwise_cast<CodeBlock**>(pivot - 1 - JSStack::CodeBlock) = codeBlock;
    
    if (Options::verboseOSR())
        dataLogF("    OSR returning data buffer %p.\n", scratch);
    return scratch;
}
コード例 #11
0
void MacroAssembler::atomic_cas64(Register memval_lo, Register memval_hi, Register result, Register oldval_lo, Register oldval_hi, Register newval_lo, Register newval_hi, Register base, int offset) {
  if (VM_Version::supports_ldrexd()) {
    Label loop;
    assert_different_registers(memval_lo, memval_hi, result, oldval_lo,
                               oldval_hi, newval_lo, newval_hi, base);
    assert(memval_hi == memval_lo + 1 && memval_lo < R9, "cmpxchg_long: illegal registers");
    assert(oldval_hi == oldval_lo + 1 && oldval_lo < R9, "cmpxchg_long: illegal registers");
    assert(newval_hi == newval_lo + 1 && newval_lo < R9, "cmpxchg_long: illegal registers");
    assert(result != R10, "cmpxchg_long: illegal registers");
    assert(base != R10, "cmpxchg_long: illegal registers");

    mov(result, 0);
    bind(loop);
    ldrexd(memval_lo, Address(base, offset));
    cmp(memval_lo, oldval_lo);
    cmp(memval_hi, oldval_hi, eq);
    strexd(result, newval_lo, Address(base, offset), eq);
    rsbs(result, result, 1, eq);
    b(loop, eq);
  } else if (VM_Version::supports_kuser_cmpxchg64()) {
    // On armv5 platforms we must use the Linux kernel helper
    // function for atomic cas64 operations since ldrexd/strexd is
    // not supported.
    //
    // This is a special routine at a fixed address 0xffff0f60
    //
    // input:
    //  r0 = (long long *)oldval, r1 = (long long *)newval,
    //  r2 = ptr, lr = return adress
    // output:
    //  r0 = 0 carry set on success
    //  r0 != 0 carry clear on failure
    //
    // r3, and flags are clobbered
    //
    Label done;
    Label loop;

    if (result != R12) {
      push(R12);
    }
    push(RegisterSet(R10) | RegisterSet(LR));
    mov(R10, SP);         // Save SP

    bic(SP, SP, StackAlignmentInBytes - 1);  // align stack
    push(RegisterSet(oldval_lo, oldval_hi));
    push(RegisterSet(newval_lo, newval_hi));

    if ((offset != 0) || (base != R12)) {
      add(R12, base, offset);
    }
    push(RegisterSet(R0, R3));
    bind(loop);
    ldrd(memval_lo, Address(R12)); //current
    ldrd(oldval_lo, Address(SP, 24));
    cmp(memval_lo, oldval_lo);
    cmp(memval_hi, oldval_hi, eq);
    pop(RegisterSet(R0, R3), ne);
    mov(result, 0, ne);
    b(done, ne);
    // Setup for kernel call
    mov(R2, R12);
    add(R0, SP, 24);            // R0 == &oldval_lo
    add(R1, SP, 16);            // R1 == &newval_lo
    mvn(R3, 0xf000);            // call kernel helper at 0xffff0f60
    mov(LR, PC);
    sub(PC, R3, 0x9f);
    b(loop, cc);                 // if Carry clear then oldval != current
                                 // try again. Otherwise, return oldval
    // Here on success
    pop(RegisterSet(R0, R3));
    mov(result, 1);
    ldrd(memval_lo, Address(SP, 8));
    bind(done);
    pop(RegisterSet(newval_lo, newval_hi));
    pop(RegisterSet(oldval_lo, oldval_hi));
    mov(SP, R10);                 // restore SP
    pop(RegisterSet(R10) | RegisterSet(LR));
    if (result != R12) {
      pop(R12);
    }
  } else {
    stop("Atomic cmpxchg64 unsupported on this platform");
  }
}
コード例 #12
0
void MacroAssembler::atomic_cas_bool(Register oldval, Register newval, Register base, int offset, Register tmpreg) {
  if (VM_Version::supports_ldrex()) {
    Register tmp_reg;
    if (tmpreg == noreg) {
      push(LR);
      tmp_reg = LR;
    } else {
      tmp_reg = tmpreg;
    }
    assert_different_registers(tmp_reg, oldval, newval, base);
    Label loop;
    bind(loop);
    ldrex(tmp_reg, Address(base, offset));
    subs(tmp_reg, tmp_reg, oldval);
    strex(tmp_reg, newval, Address(base, offset), eq);
    cmp(tmp_reg, 1, eq);
    b(loop, eq);
    cmp(tmp_reg, 0);
    if (tmpreg == noreg) {
      pop(tmp_reg);
    }
  } else if (VM_Version::supports_kuser_cmpxchg32()) {
    // On armv5 platforms we must use the Linux kernel helper
    // function for atomic cas operations since ldrex/strex is
    // not supported.
    //
    // This is a special routine at a fixed address 0xffff0fc0 with
    // with these arguments and results
    //
    // input:
    //  r0 = oldval, r1 = newval, r2 = ptr, lr = return adress
    // output:
    //  r0 = 0 carry set on success
    //  r0 != 0 carry clear on failure
    //
    // r3, ip and flags are clobbered
    //

    Label loop;

    push(RegisterSet(R0, R3) | RegisterSet(R12) | RegisterSet(LR));

    Register tmp_reg = LR; // ignore the argument

    assert_different_registers(tmp_reg, oldval, newval, base);

    // Shuffle registers for kernel call
    if (oldval != R0) {
      if (newval == R0) {
        mov(tmp_reg, newval);
        newval = tmp_reg;
      }
      if (base == R0) {
        mov(tmp_reg, base);
        base = tmp_reg;
      }
      mov(R0, oldval);
    }
    if(newval != R1) {
      if(base == R1) {
        if(newval == R2) {
          mov(tmp_reg, base);
          base = tmp_reg;
        }
        else {
          mov(R2, base);
          base = R2;
        }
      }
      mov(R1, newval);
    }
    if (base != R2)
      mov(R2, base);

    if (offset != 0)
      add(R2, R2, offset);

    mvn(R3, 0xf000);
    mov(LR, PC);
    sub(PC, R3, 0x3f);
    cmp (R0, 0);

    pop(RegisterSet(R0, R3) | RegisterSet(R12) | RegisterSet(LR));
  } else {
    // Should never run on a platform so old that it does not have kernel helper
    stop("Atomic cmpxchg32 unsupported on this platform");
  }
}
コード例 #13
0
void MacroAssembler::atomic_cas(Register temp1, Register temp2, Register oldval, Register newval, Register base, int offset) {
  if (temp1 != R0) {
    // try to read the previous value directly in R0
    if (temp2 == R0) {
      // R0 declared free
      temp2 = temp1;
      temp1 = R0;
    } else if ((oldval != R0) && (newval != R0) && (base != R0)) {
      // free, and scratched on return
      temp1 = R0;
    }
  }
  if (VM_Version::supports_ldrex()) {
    Label loop;
    assert_different_registers(temp1, temp2, oldval, newval, base);

    bind(loop);
    ldrex(temp1, Address(base, offset));
    cmp(temp1, oldval);
    strex(temp2, newval, Address(base, offset), eq);
    cmp(temp2, 1, eq);
    b(loop, eq);
    if (temp1 != R0) {
      mov(R0, temp1);
    }
  } else if (VM_Version::supports_kuser_cmpxchg32()) {
    // On armv5 platforms we must use the Linux kernel helper
    // function for atomic cas operations since ldrex/strex is
    // not supported.
    //
    // This is a special routine at a fixed address 0xffff0fc0
    //
    // input:
    //  r0 = oldval, r1 = newval, r2 = ptr, lr = return adress
    // output:
    //  r0 = 0 carry set on success
    //  r0 != 0 carry clear on failure
    //
    // r3, ip and flags are clobbered
    //
    Label done;
    Label loop;

    push(RegisterSet(R1, R4) | RegisterSet(R12) | RegisterSet(LR));

    if ( oldval != R0 || newval != R1 || base != R2 ) {
      push(oldval);
      push(newval);
      push(base);
      pop(R2);
      pop(R1);
      pop(R0);
    }

    if (offset != 0) {
      add(R2, R2, offset);
    }

    mov(R4, R0);
    bind(loop);
    ldr(R0, Address(R2));
    cmp(R0, R4);
    b(done, ne);
    mvn(R12, 0xf000);
    mov(LR, PC);
    sub(PC, R12, 0x3f);
    b(loop, cc);
    mov(R0, R4);
    bind(done);

    pop(RegisterSet(R1, R4) | RegisterSet(R12) | RegisterSet(LR));
  } else {
    // Should never run on a platform so old that it does not have kernel helper
    stop("Atomic cmpxchg32 unsupported on this platform");
  }
}
コード例 #14
0
ファイル: RegisterSet.cpp プロジェクト: TigerLau1985/webkit
RegisterSet RegisterSet::registersToNotSaveForCall()
{
    return RegisterSet(RegisterSet::vmCalleeSaveRegisters(), RegisterSet::stackRegisters(), RegisterSet::reservedHardwareRegisters());
}
コード例 #15
0
ファイル: RegisterSet.cpp プロジェクト: TigerLau1985/webkit
RegisterSet RegisterSet::stubUnavailableRegisters()
{
    return RegisterSet(specialRegisters(), vmCalleeSaveRegisters());
}
コード例 #16
0
ファイル: RegisterSet.cpp プロジェクト: TigerLau1985/webkit
RegisterSet RegisterSet::specialRegisters()
{
    return RegisterSet(
        stackRegisters(), reservedHardwareRegisters(), runtimeRegisters());
}
コード例 #17
0
ファイル: RegisterSet.cpp プロジェクト: TigerLau1985/webkit
RegisterSet RegisterSet::stackRegisters()
{
    return RegisterSet(
        MacroAssembler::stackPointerRegister,
        MacroAssembler::framePointerRegister);
}