diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/jit/CallFrameShuffler64.cpp | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/jit/CallFrameShuffler64.cpp')
-rw-r--r-- | Source/JavaScriptCore/jit/CallFrameShuffler64.cpp | 369 |
1 files changed, 0 insertions, 369 deletions
diff --git a/Source/JavaScriptCore/jit/CallFrameShuffler64.cpp b/Source/JavaScriptCore/jit/CallFrameShuffler64.cpp deleted file mode 100644 index 2ef6ed111..000000000 --- a/Source/JavaScriptCore/jit/CallFrameShuffler64.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (C) 2015 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "CallFrameShuffler.h" - -#if ENABLE(JIT) && USE(JSVALUE64) - -#include "CCallHelpers.h" -#include "DataFormat.h" -#include "JSCInlines.h" - -namespace JSC { - -DataFormat CallFrameShuffler::emitStore( - CachedRecovery& cachedRecovery, MacroAssembler::Address address) -{ - ASSERT(!cachedRecovery.recovery().isInJSStack()); - - switch (cachedRecovery.recovery().technique()) { - case InGPR: - m_jit.storePtr(cachedRecovery.recovery().gpr(), address); - return DataFormatJS; - case UnboxedInt32InGPR: - m_jit.store32(cachedRecovery.recovery().gpr(), address.withOffset(PayloadOffset)); - return DataFormatInt32; - case UnboxedInt52InGPR: - m_jit.rshift64(MacroAssembler::TrustedImm32(JSValue::int52ShiftAmount), - cachedRecovery.recovery().gpr()); - FALLTHROUGH; - case UnboxedStrictInt52InGPR: - m_jit.storePtr(cachedRecovery.recovery().gpr(), address); - return DataFormatStrictInt52; - case UnboxedBooleanInGPR: - m_jit.storePtr(cachedRecovery.recovery().gpr(), address); - return DataFormatBoolean; - case UnboxedCellInGPR: - m_jit.storePtr(cachedRecovery.recovery().gpr(), address); - return DataFormatCell; - case UnboxedDoubleInFPR: - m_jit.storeDouble(cachedRecovery.recovery().fpr(), address); - return DataFormatDouble; - case InFPR: - m_jit.storeDouble(cachedRecovery.recovery().fpr(), address); - return DataFormatJS; - case Constant: - m_jit.storeTrustedValue(cachedRecovery.recovery().constant(), address); - return DataFormatJS; - default: - RELEASE_ASSERT_NOT_REACHED(); - } -} - -void CallFrameShuffler::emitBox(CachedRecovery& cachedRecovery) -{ - ASSERT(canBox(cachedRecovery)); - if (cachedRecovery.recovery().isConstant()) - return; - - if (cachedRecovery.recovery().isInGPR()) { - switch (cachedRecovery.recovery().dataFormat()) { - case DataFormatInt32: - if (verbose) - dataLog(" * Boxing ", cachedRecovery.recovery()); - m_jit.zeroExtend32ToPtr( - cachedRecovery.recovery().gpr(), - cachedRecovery.recovery().gpr()); - m_lockedRegisters.set(cachedRecovery.recovery().gpr()); - if (tryAcquireTagTypeNumber()) - m_jit.or64(m_tagTypeNumber, cachedRecovery.recovery().gpr()); - else { - // We have to do this the hard way - m_jit.or64(MacroAssembler::TrustedImm64(TagTypeNumber), - cachedRecovery.recovery().gpr()); - } - m_lockedRegisters.clear(cachedRecovery.recovery().gpr()); - cachedRecovery.setRecovery( - ValueRecovery::inGPR(cachedRecovery.recovery().gpr(), DataFormatJS)); - if (verbose) - dataLog(" into ", cachedRecovery.recovery(), "\n"); - return; - case DataFormatInt52: - if (verbose) - dataLog(" * Boxing ", cachedRecovery.recovery()); - m_jit.rshift64(MacroAssembler::TrustedImm32(JSValue::int52ShiftAmount), - cachedRecovery.recovery().gpr()); - cachedRecovery.setRecovery( - ValueRecovery::inGPR(cachedRecovery.recovery().gpr(), DataFormatStrictInt52)); - if (verbose) - dataLog(" into ", cachedRecovery.recovery(), "\n"); - FALLTHROUGH; - case DataFormatStrictInt52: { - if (verbose) - dataLog(" * Boxing ", cachedRecovery.recovery()); - FPRReg resultFPR = getFreeFPR(); - ASSERT(resultFPR != InvalidFPRReg); - m_jit.convertInt64ToDouble(cachedRecovery.recovery().gpr(), resultFPR); - updateRecovery(cachedRecovery, ValueRecovery::inFPR(resultFPR, DataFormatDouble)); - if (verbose) - dataLog(" into ", cachedRecovery.recovery(), "\n"); - break; - } - case DataFormatBoolean: - if (verbose) - dataLog(" * Boxing ", cachedRecovery.recovery()); - m_jit.add32(MacroAssembler::TrustedImm32(ValueFalse), - cachedRecovery.recovery().gpr()); - cachedRecovery.setRecovery( - ValueRecovery::inGPR(cachedRecovery.recovery().gpr(), DataFormatJS)); - if (verbose) - dataLog(" into ", cachedRecovery.recovery(), "\n"); - return; - default: - return; - } - } - - if (cachedRecovery.recovery().isInFPR()) { - if (cachedRecovery.recovery().dataFormat() == DataFormatDouble) { - if (verbose) - dataLog(" * Boxing ", cachedRecovery.recovery()); - GPRReg resultGPR = cachedRecovery.wantedJSValueRegs().gpr(); - if (resultGPR == InvalidGPRReg || m_registers[resultGPR]) - resultGPR = getFreeGPR(); - ASSERT(resultGPR != InvalidGPRReg); - m_jit.purifyNaN(cachedRecovery.recovery().fpr()); - m_jit.moveDoubleTo64(cachedRecovery.recovery().fpr(), resultGPR); - m_lockedRegisters.set(resultGPR); - if (tryAcquireTagTypeNumber()) - m_jit.sub64(m_tagTypeNumber, resultGPR); - else - m_jit.sub64(MacroAssembler::TrustedImm64(TagTypeNumber), resultGPR); - m_lockedRegisters.clear(resultGPR); - updateRecovery(cachedRecovery, ValueRecovery::inGPR(resultGPR, DataFormatJS)); - if (verbose) - dataLog(" into ", cachedRecovery.recovery(), "\n"); - return; - } - ASSERT(cachedRecovery.recovery().dataFormat() == DataFormatJS); - return; - } - - RELEASE_ASSERT_NOT_REACHED(); -} - -void CallFrameShuffler::emitLoad(CachedRecovery& cachedRecovery) -{ - if (!cachedRecovery.recovery().isInJSStack()) - return; - - if (verbose) - dataLog(" * Loading ", cachedRecovery.recovery(), " into "); - - VirtualRegister reg = cachedRecovery.recovery().virtualRegister(); - MacroAssembler::Address address { addressForOld(reg) }; - bool tryFPR { true }; - GPRReg resultGPR { cachedRecovery.wantedJSValueRegs().gpr() }; - - // If we want a GPR and it's available, that's better than loading - // into an FPR. - if (resultGPR != InvalidGPRReg && !m_registers[resultGPR] - && !m_lockedRegisters.get(resultGPR) && cachedRecovery.loadsIntoGPR()) - tryFPR = false; - - // Otherwise, we prefer loading into FPRs if possible - if (tryFPR && cachedRecovery.loadsIntoFPR()) { - FPRReg resultFPR { cachedRecovery.wantedFPR() }; - if (resultFPR == InvalidFPRReg || m_registers[resultFPR] || m_lockedRegisters.get(resultFPR)) - resultFPR = getFreeFPR(); - if (resultFPR != InvalidFPRReg) { - m_jit.loadDouble(address, resultFPR); - DataFormat dataFormat = DataFormatJS; - // We could be transforming a DataFormatCell into a - // DataFormatJS here - but that's OK. - if (cachedRecovery.recovery().dataFormat() == DataFormatDouble) - dataFormat = DataFormatDouble; - updateRecovery(cachedRecovery, - ValueRecovery::inFPR(resultFPR, dataFormat)); - if (verbose) - dataLog(cachedRecovery.recovery(), "\n"); - if (reg == newAsOld(dangerFrontier())) - updateDangerFrontier(); - return; - } - } - - ASSERT(cachedRecovery.loadsIntoGPR()); - if (resultGPR == InvalidGPRReg || m_registers[resultGPR] || m_lockedRegisters.get(resultGPR)) - resultGPR = getFreeGPR(); - ASSERT(resultGPR != InvalidGPRReg); - m_jit.loadPtr(address, resultGPR); - updateRecovery(cachedRecovery, - ValueRecovery::inGPR(resultGPR, cachedRecovery.recovery().dataFormat())); - if (verbose) - dataLog(cachedRecovery.recovery(), "\n"); - if (reg == newAsOld(dangerFrontier())) - updateDangerFrontier(); -} - -bool CallFrameShuffler::canLoad(CachedRecovery& cachedRecovery) -{ - if (!cachedRecovery.recovery().isInJSStack()) - return true; - - ASSERT(cachedRecovery.loadsIntoFPR() || cachedRecovery.loadsIntoGPR()); - - if (cachedRecovery.loadsIntoFPR() && getFreeFPR() != InvalidFPRReg) - return true; - - if (cachedRecovery.loadsIntoGPR() && getFreeGPR() != InvalidGPRReg) - return true; - - return false; -} - -void CallFrameShuffler::emitDisplace(CachedRecovery& cachedRecovery) -{ - Reg wantedReg; - if (!(wantedReg = Reg { cachedRecovery.wantedJSValueRegs().gpr() })) - wantedReg = Reg { cachedRecovery.wantedFPR() }; - ASSERT(wantedReg); - ASSERT(!m_lockedRegisters.get(wantedReg)); - - if (CachedRecovery* current = m_registers[wantedReg]) { - if (current == &cachedRecovery) { - if (verbose) - dataLog(" + ", wantedReg, " is OK\n"); - return; - } - // We could do a more complex thing by finding cycles - // etc. in that case. - // However, ending up in this situation will be super - // rare, and should actually be outright impossible for - // non-FTL tiers, since: - // (a) All doubles have been converted into JSValues with - // ValueRep nodes, so FPRs are initially free - // - // (b) The only recoveries with wanted registers are the - // callee (which always starts out in a register) and - // the callee-save registers - // - // (c) The callee-save registers are the first things we - // load (after the return PC), and they are loaded as JSValues - // - // (d) We prefer loading JSValues into FPRs if their - // wanted GPR is not available - // - // (e) If we end up spilling some registers with a - // target, we won't load them again before the very - // end of the algorithm - // - // Combined, this means that we will never load a recovery - // with a wanted GPR into any GPR other than its wanted - // GPR. The callee could however have been initially in - // one of the callee-save registers - but since the wanted - // GPR for the callee is always regT0, it will be the - // first one to be displaced, and we won't see it when - // handling any of the callee-save registers. - // - // Thus, the only way we could ever reach this path is in - // the FTL, when there is so much pressure that we - // absolutely need to load the callee-save registers into - // different GPRs initially but not enough pressure to - // then have to spill all of them. And even in that case, - // depending on the order in which B3 saves the - // callee-saves, we will probably still be safe. Anyway, - // the couple extra move instructions compared to an - // efficient cycle-based algorithm are not going to hurt - // us. - if (wantedReg.isFPR()) { - FPRReg tempFPR = getFreeFPR(); - if (verbose) - dataLog(" * Moving ", wantedReg, " into ", tempFPR, "\n"); - m_jit.moveDouble(wantedReg.fpr(), tempFPR); - updateRecovery(*current, - ValueRecovery::inFPR(tempFPR, current->recovery().dataFormat())); - } else { - GPRReg tempGPR = getFreeGPR(); - if (verbose) - dataLog(" * Moving ", wantedReg.gpr(), " into ", tempGPR, "\n"); - m_jit.move(wantedReg.gpr(), tempGPR); - updateRecovery(*current, - ValueRecovery::inGPR(tempGPR, current->recovery().dataFormat())); - } - } - ASSERT(!m_registers[wantedReg]); - - if (cachedRecovery.recovery().isConstant()) { - // We only care about callee saves for wanted FPRs, and those are never constants - ASSERT(wantedReg.isGPR()); - if (verbose) - dataLog(" * Loading ", cachedRecovery.recovery().constant(), " into ", wantedReg, "\n"); - m_jit.moveTrustedValue(cachedRecovery.recovery().constant(), JSValueRegs { wantedReg.gpr() }); - updateRecovery( - cachedRecovery, - ValueRecovery::inRegister(wantedReg, DataFormatJS)); - } else if (cachedRecovery.recovery().isInGPR()) { - if (verbose) - dataLog(" * Moving ", cachedRecovery.recovery(), " into ", wantedReg, "\n"); - if (wantedReg.isGPR()) - m_jit.move(cachedRecovery.recovery().gpr(), wantedReg.gpr()); - else - m_jit.move64ToDouble(cachedRecovery.recovery().gpr(), wantedReg.fpr()); - RELEASE_ASSERT(cachedRecovery.recovery().dataFormat() == DataFormatJS); - updateRecovery(cachedRecovery, - ValueRecovery::inRegister(wantedReg, DataFormatJS)); - } else { - ASSERT(cachedRecovery.recovery().isInFPR()); - if (cachedRecovery.recovery().dataFormat() == DataFormatDouble) { - // We only care about callee saves for wanted FPRs, and those are always DataFormatJS - ASSERT(wantedReg.isGPR()); - // This will automatically pick the wanted GPR - emitBox(cachedRecovery); - } else { - if (verbose) - dataLog(" * Moving ", cachedRecovery.recovery().fpr(), " into ", wantedReg, "\n"); - if (wantedReg.isGPR()) - m_jit.moveDoubleTo64(cachedRecovery.recovery().fpr(), wantedReg.gpr()); - else - m_jit.moveDouble(cachedRecovery.recovery().fpr(), wantedReg.fpr()); - RELEASE_ASSERT(cachedRecovery.recovery().dataFormat() == DataFormatJS); - updateRecovery(cachedRecovery, - ValueRecovery::inRegister(wantedReg, DataFormatJS)); - } - } - - ASSERT(m_registers[wantedReg] == &cachedRecovery); -} - -bool CallFrameShuffler::tryAcquireTagTypeNumber() -{ - if (m_tagTypeNumber != InvalidGPRReg) - return true; - - m_tagTypeNumber = getFreeGPR(); - - if (m_tagTypeNumber == InvalidGPRReg) - return false; - - m_lockedRegisters.set(m_tagTypeNumber); - m_jit.move(MacroAssembler::TrustedImm64(TagTypeNumber), m_tagTypeNumber); - return true; -} - -} // namespace JSC - -#endif // ENABLE(JIT) && USE(JSVALUE64) |