WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
more
blah.patch (text/plain), 27.59 KB, created by
Filip Pizlo
on 2016-03-01 20:28:14 PST
(
hide
)
Description:
more
Filename:
MIME Type:
Creator:
Filip Pizlo
Created:
2016-03-01 20:28:14 PST
Size:
27.59 KB
patch
obsolete
>Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 197410) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,33 @@ >+2016-03-01 Filip Pizlo <fpizlo@apple.com> >+ >+ Need a short description (OOPS!). >+ Need the bug URL (OOPS!). >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * b3/air/AirEmitShuffle.h: >+ (JSC::B3::Air::ShufflePair::ShufflePair): Deleted. >+ (JSC::B3::Air::ShufflePair::src): Deleted. >+ (JSC::B3::Air::ShufflePair::dst): Deleted. >+ (JSC::B3::Air::ShufflePair::width): Deleted. >+ * b3/air/AirInst.cpp: >+ (JSC::B3::Air::Inst::addShufflePair): >+ (JSC::B3::Air::Inst::hasArgEffects): >+ * b3/air/AirInst.h: >+ * b3/air/AirInstInlines.h: >+ (JSC::B3::Air::Inst::forEachDefWithExtraClobberedRegs): >+ (JSC::B3::Air::Inst::forEachShufflePair): >+ (JSC::B3::Air::Inst::reportUsedRegisters): >+ * b3/air/AirIteratedRegisterCoalescing.cpp: >+ * b3/air/AirShufflePair.cpp: Added. >+ (JSC::B3::Air::ShufflePair::dump): >+ * b3/air/AirShufflePair.h: Added. >+ (JSC::B3::Air::ShufflePair::ShufflePair): >+ (JSC::B3::Air::ShufflePair::src): >+ (JSC::B3::Air::ShufflePair::dst): >+ (JSC::B3::Air::ShufflePair::width): >+ * jit/JITOperations.h: >+ > 2016-03-01 Skachkov Oleksandr <gskachkov@gmail.com> > > [ES6] Arrow function. Some not used byte code is emited >Index: Source/JavaScriptCore/b3/air/AirEmitShuffle.h >=================================================================== >--- Source/JavaScriptCore/b3/air/AirEmitShuffle.h (revision 197410) >+++ Source/JavaScriptCore/b3/air/AirEmitShuffle.h (working copy) >@@ -30,6 +30,7 @@ > > #include "AirArg.h" > #include "AirInst.h" >+#include "AirShufflePair.h" > #include <wtf/Vector.h> > > namespace JSC { namespace B3 { >@@ -38,34 +39,6 @@ class Value; > > namespace Air { > >-class ShufflePair { >-public: >- ShufflePair() >- { >- } >- >- ShufflePair(const Arg& src, const Arg& dst, Arg::Width width) >- : m_src(src) >- , m_dst(dst) >- , m_width(width) >- { >- } >- >- const Arg& src() const { return m_src; } >- const Arg& dst() const { return m_dst; } >- >- // The width determines the kind of move we do. You can only choose Width32 or Width64 right now. >- // For GP, it picks between Move32 and Move. For FP, it picks between MoveFloat and MoveDouble. >- Arg::Width width() const { return m_width; } >- >- void dump(PrintStream&) const; >- >-private: >- Arg m_src; >- Arg m_dst; >- Arg::Width m_width { Arg::Width8 }; >-}; >- > // Create a Shuffle instruction. > Inst createShuffle(Value* origin, const Vector<ShufflePair>&); > >Index: Source/JavaScriptCore/b3/air/AirInst.cpp >=================================================================== >--- Source/JavaScriptCore/b3/air/AirInst.cpp (revision 197410) >+++ Source/JavaScriptCore/b3/air/AirInst.cpp (working copy) >@@ -34,6 +34,18 @@ > > namespace JSC { namespace B3 { namespace Air { > >+void Inst::addShufflePair(const ShufflePair& pair) >+{ >+ if (opcode == Nop) >+ opcode = Shuffle; >+ else >+ RELEASE_ASSERT(opcode == Shuffle); >+ >+ args.append(pair.src()); >+ args.append(pair.dst()); >+ args.append(Arg::widthArg(pair.width())); >+} >+ > bool Inst::hasArgEffects() > { > bool result = false; >Index: Source/JavaScriptCore/b3/air/AirInst.h >=================================================================== >--- Source/JavaScriptCore/b3/air/AirInst.h (revision 197410) >+++ Source/JavaScriptCore/b3/air/AirInst.h (working copy) >@@ -30,6 +30,7 @@ > > #include "AirArg.h" > #include "AirOpcode.h" >+#include "AirShufflePair.h" > #include "CCallHelpers.h" > > namespace JSC { >@@ -146,6 +147,14 @@ public: > template<typename Thing, typename Functor> > static void forEachDefWithExtraClobberedRegs(Inst* prevInst, Inst* nextInst, const Functor&); > >+ template<typename Functor> >+ bool forEachShufflePair(const Functor&); >+ >+ template<typename ShuffleCallback, typename FallbackCallback> >+ void forEachShufflePair(const ShuffleCallback&, const FallbackCallback&); >+ >+ void addShufflePair(const ShufflePair&); >+ > // Use this to report which registers are live. This should be done just before codegen. Note > // that for efficiency, reportUsedRegisters() only works for the Patch opcode. > void reportUsedRegisters(const RegisterSet&); >Index: Source/JavaScriptCore/b3/air/AirInstInlines.h >=================================================================== >--- Source/JavaScriptCore/b3/air/AirInstInlines.h (revision 197410) >+++ Source/JavaScriptCore/b3/air/AirInstInlines.h (working copy) >@@ -153,6 +153,43 @@ inline void Inst::forEachDefWithExtraClo > } > } > >+template<typename Functor> >+bool Inst::forEachShufflePair(const Functor& functor) >+{ >+ switch (opcode) { >+ case Move: >+ functor(ShufflePair(args[0], args[1], Arg::conservativeWidth(Arg::GP))); >+ return true; >+ case Move32: >+ functor(ShufflePair(args[0], args[1], Arg::Width32)); >+ return true; >+ case MoveDouble: >+ functor(ShufflePair(args[0], args[1], Arg::Width64)); >+ return true; >+ case MoveFloat: >+ functor(ShufflePair(args[0], args[1], Arg::Width32)); >+ return true; >+ case Shuffle: >+ for (unsigned i = 0; i + 2 < args.size(); i += 3) { >+ Arg src = args[i + 0]; >+ Arg dest = args[i + 1]; >+ Arg width = args[i + 2]; >+ functor(src, dest, width.width()); >+ } >+ return true; >+ default: >+ return false; >+ } >+} >+ >+template<typename ShuffleCallback, typename FallbackCallback> >+void Inst::forEachShufflePair( >+ const ShuffleCallback& shuffleCallback, const FallbackCallback& fallbackCallback) >+{ >+ if (!forEachShufflePair(shuffleCallback)) >+ fallbackCallback(); >+} >+ > inline void Inst::reportUsedRegisters(const RegisterSet& usedRegisters) > { > ASSERT(opcode == Patch); >Index: Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp >=================================================================== >--- Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp (revision 197410) >+++ Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp (working copy) >@@ -751,9 +751,25 @@ public: > // This tells you if a Move will be coalescable if the src and dst end up matching. This method > // relies on an analysis that is invalidated by register allocation, so you it's only meaningful to > // call this *before* replacing the Tmp's in this Inst with registers or spill slots. >- bool mayBeCoalescable(const Inst& inst) const >+ bool mayBeCoalescableMove(const Inst& inst) const > { >- return mayBeCoalescableImpl(inst, &m_tmpWidth); >+ return mayBeCoalescableMoveImpl(inst, &m_tmpWidth); >+ } >+ >+ bool mayBeCoalescableShufflePair(const Inst& inst, unsigned index) const >+ { >+ return mayBeCoalescable( >+ inst.args[index + 2].width(), inst.args[index + 0], inst.args[index + 1]); >+ } >+ >+ bool mayBeCoalescable(Arg::Width width, const Arg& src, const Arg& dest) >+ { >+ return mayBeCoalescableImpl(width, src, dest, &m_tmpWidth); >+ } >+ >+ bool mayBeCoalescable(const ShufflePair& pair) >+ { >+ return mayBeCoalescableImpl(pair, &m_tmpWidth); > } > > bool isUselessMove(const Inst& inst) const >@@ -761,6 +777,22 @@ public: > return mayBeCoalescableImpl(inst, nullptr) && inst.args[0].tmp() == inst.args[1].tmp(); > } > >+ bool isUselessShufflePair(const Inst& inst, unsigned index) const >+ { >+ return isUselessMove( >+ inst.args[index + 2].width(), inst.args[index + 0], inst.args[index + 1]); >+ } >+ >+ bool isUselessMove(Arg::Width width, const Arg& src, const Arg& dest) >+ { >+ return mayBeCoalescableImpl(width, src, dest, nullptr) && src.tmp() == dest.tmp(); >+ } >+ >+ bool isUselessShufflePair(const ShufflePair& pair) const >+ { >+ return mayBeCoalescableImpl(pair, nullptr) && pair.src().tmp() == pair.dst().tmp(); >+ } >+ > Tmp getAliasWhenSpilling(Tmp tmp) const > { > ASSERT_WITH_MESSAGE(!m_spilledTmps.isEmpty(), "This function is only valid for coalescing during spilling."); >@@ -941,47 +973,62 @@ private: > }); > }); > >- if (prevInst && mayBeCoalescable(*prevInst)) { >- // We do not want the Use() of this move to interfere with the Def(), even if it is live >- // after the Move. If we were to add the interference edge, it would be impossible to >- // coalesce the Move even if the two Tmp never interfere anywhere. >- Tmp defTmp; >- Tmp useTmp; >- prevInst->forEachTmp([&defTmp, &useTmp] (Tmp& argTmp, Arg::Role role, Arg::Type, Arg::Width) { >- if (Arg::isLateDef(role)) >- defTmp = argTmp; >- else { >- ASSERT(Arg::isEarlyUse(role)); >- useTmp = argTmp; >- } >- }); >- ASSERT(defTmp); >- ASSERT(useTmp); >- >- unsigned nextMoveIndex = m_coalescingCandidates.size(); >- m_coalescingCandidates.append({ AbsoluteTmpMapper<type>::absoluteIndex(useTmp), AbsoluteTmpMapper<type>::absoluteIndex(defTmp) }); >- >- unsigned newIndexInWorklist = m_worklistMoves.addMove(); >- ASSERT_UNUSED(newIndexInWorklist, newIndexInWorklist == nextMoveIndex); >+ if (prevInst) { >+ // This code path attempts to handle coalescable instructions. It handles both Moves and >+ // Shuffles. The trick is to ensure that the definitions in a Move don't interfere with >+ // the sources, so if we detect a coalescing opportunity we also avoid taking the usual >+ // interference path by doing the interference calculation manually and returning early. >+ >+ auto addCoalescableMove = [&] (Tmp srcTmp, Tmp destTmp) { >+ unsigned srcIndex = AbsoluteTmpMapper<type>::absoluteIndex(srcTmp); >+ unsigned destIndex = AbsoluteTmpMapper<type>::absoluteIndex(destTmp); >+ >+ unsigned nextMoveIndex = m_coalescingCandidates.size(); >+ m_coalescingCandidates.append({ srcIndex, destIndex }); >+ >+ unsigned newIndexInWorklist = m_worklistMoves.addMove(); >+ ASSERT_UNUSED(newIndexInWorklist, newIndexInWorklist == nextMoveIndex); >+ >+ ASSERT(nextMoveIndex <= m_activeMoves.size()); >+ m_activeMoves.ensureSize(nextMoveIndex + 1); > >- ASSERT(nextMoveIndex <= m_activeMoves.size()); >- m_activeMoves.ensureSize(nextMoveIndex + 1); >+ m_moveList[srcIndex].add(nextMoveIndex); >+ m_moveList[destIndex].add(nextMoveIndex); >+ }; >+ >+ bool didHandle = prevInst->forEachShufflePair( >+ [&] (const ShufflePair& pair) { >+ if (mayBeCoalescable(pair)) { >+ Tmp srcTmp = pair.src().tmp(); >+ Tmp dstTmp = pair.dst().tmp(); >+ >+ addCoalescableMove(srcTmp, dstTmp); >+ >+ // Conservatively, dest would interfere with everything live. But in this >+ // case it only interferes with all live variables except srcTmp. >+ for (Tmp liveTmp : localCalc.live()) { >+ if (liveTmp != srcTmp) >+ addEdge(dstTmp, liveTmp); >+ } >+ return; >+ } > >- for (const Arg& arg : prevInst->args) { >- auto& list = m_moveList[AbsoluteTmpMapper<type>::absoluteIndex(arg.tmp())]; >- list.add(nextMoveIndex); >- } >+ // If the destination is a tmp, it needs to interfere with everything live. >+ if (dst.isTmp()) { >+ for (Tmp liveTmp : localCalc.live()) >+ addEdge(pair.dst().tmp(), liveTmp); >+ } >+ }); > >- for (const Tmp& liveTmp : localCalc.live()) { >- if (liveTmp != useTmp) >- addEdge(defTmp, liveTmp); >+ if (didHandle) { >+ // The next instruction could have early clobbers or early def's. Consider those >+ // now. >+ addEdges(nullptr, nextInst, localCalc.live()); >+ return; > } >+ } > >- // The next instruction could have early clobbers or early def's. We need to consider >- // those now. >- addEdges(nullptr, nextInst, localCalc.live()); >- } else >- addEdges(prevInst, nextInst, localCalc.live()); >+ addEdges(prevInst, nextInst, localCalc.live()); > } > > void buildLowPriorityMoveList() >@@ -1037,13 +1084,18 @@ private: > > // Calling this without a tmpWidth will perform a more conservative coalescing analysis that assumes > // that Move32's are not coalescable. >- static bool mayBeCoalescableImpl(const Inst& inst, TmpWidth* tmpWidth) >+ static bool mayBeCoalescableMoveImpl(const Inst& inst, TmpWidth* tmpWidth) > { >+ Arg::Width width; >+ > switch (type) { > case Arg::GP: > switch (inst.opcode) { > case Move: >+ width = Arg::conservativeWidth(type); >+ break; > case Move32: >+ width = Arg::Width32; > break; > default: > return false; >@@ -1052,7 +1104,10 @@ private: > case Arg::FP: > switch (inst.opcode) { > case MoveFloat: >+ width = Arg::Width32; >+ break; > case MoveDouble: >+ width = Arg::Width64; > break; > default: > return false; >@@ -1062,29 +1117,56 @@ private: > > ASSERT_WITH_MESSAGE(inst.args.size() == 2, "We assume coalecable moves only have two arguments in a few places."); > >- if (!inst.args[0].isTmp() || !inst.args[1].isTmp()) >+ return mayBeCoalescableImpl(width, inst.args[0], inst.args[1], tmpWidth); >+ } >+ >+ static bool mayBeCoalescableImpl( >+ Arg::Width width, const Arg& src, const Arg& dest, TmpWidth* tmpWidth) >+ { >+ if (!src.isTmp() || !dest.isTmp()) > return false; > >- ASSERT(inst.args[0].type() == type); >- ASSERT(inst.args[1].type() == type); >+ if (!src.isType(type)) >+ return false; > >- // We can coalesce a Move32 so long as either of the following holds: >- // - The input is already zero-filled. >- // - The output only cares about the low 32 bits. >- // >- // Note that the input property requires an analysis over ZDef's, so it's only valid so long >- // as the input gets a register. We don't know if the input gets a register, but we do know >- // that if it doesn't get a register then we will still emit this Move32. >- if (inst.opcode == Move32) { >- if (!tmpWidth) >- return false; >+ ASSERT(width == Width32 || width == Width64); >+ ASSERT(src.type() == dest.type()); > >- if (tmpWidth->defWidth(inst.args[0].tmp()) > Arg::Width32 >- && tmpWidth->useWidth(inst.args[1].tmp()) > Arg::Width32) >- return false; >- } >- >- return true; >+ if (type == Arg::FP) >+ return true; >+ >+ if (width == Arg::conservativeWidth(type)) >+ return true; >+ >+ if (!tmpWidth) >+ return false; >+ >+ return tmpWidth->defWidth(src) <= Arg::Width32 >+ || tmpWidth->useWidth(dest) <= Arg::Width32; >+ } >+ >+ static bool mayBeCoalescableImpl(const ShufflePair& pair, TmpWidth* tmpWidth) >+ { >+ if (!pair.src().isTmp() || !pair.dst().isTmp()) >+ return false; >+ >+ if (!pair.src().isType(type)) >+ return false; >+ >+ ASSERT(pair.width() == Width32 || pair.width() == Width64); >+ ASSERT(pair.src().type() == pair.dst().type()); >+ >+ if (type == Arg::FP) >+ return true; >+ >+ if (pair.width() == Arg::conservativeWidth(type)) >+ return true; >+ >+ if (!tmpWidth) >+ return false; >+ >+ return tmpWidth->defWidth(pair.src()) <= Arg::Width32 >+ || tmpWidth->useWidth(pair.dst()) <= Arg::Width32; > } > > void selectSpill() >@@ -1375,9 +1457,9 @@ private: > for (unsigned instIndex = 0; instIndex < block->size(); ++instIndex) { > Inst& inst = block->at(instIndex); > >- // The mayBeCoalescable() method will change its mind for some operations after we >- // complete register allocation. So, we record this before starting. >- bool mayBeCoalescable = allocator.mayBeCoalescable(inst); >+ // The mayBeCoalescableMove() method will change its mind for some operations after >+ // we complete register allocation. So, we record this before starting. >+ bool mayBeCoalescableMove = allocator.mayBeCoalescableMove(inst); > > // Move32 is cheaper if we know that it's equivalent to a Move. It's > // equivalent if the destination's high bits are not observable or if the source's high >@@ -1390,6 +1472,25 @@ private: > inst.opcode = Move32; > } > >+ // All of the stuff we do for Moves also applies to Shuffles. >+ BitVector coalescableShufflePairs; >+ if (inst.opcode == Shuffle) { >+ for (unsigned i = 0; i < inst.args.size(); i += 3) { >+ Arg src = inst.args[i + 0]; >+ Arg dest = inst.args[i + 1]; >+ Arg::Width width = inst.args[i + 2].width(); >+ >+ if (allocator.mayBeCoalescableShufflePair(inst, i)) >+ coalescableShufflePairs.set(i); >+ >+ if (type == Arg::GP && src.isTmp() && dest.isTmp() && src.isGP() >+ && width == Width64 >+ && (m_tmpWidth.useWidth(dest) <= Arg::Width32 >+ || m_tmpWidth.defWidth(src) <= Arg::Width32)) >+ inst.args[i + 2] = Arg::widthArg(Arg::Width32); >+ } >+ } >+ > inst.forEachTmpFast([&] (Tmp& tmp) { > if (tmp.isReg() || tmp.isGP() == (type != Arg::GP)) > return; >@@ -1410,11 +1511,29 @@ private: > if (mayBeCoalescable && inst.args[0].isTmp() && inst.args[1].isTmp() > && inst.args[0].tmp() == inst.args[1].tmp()) > inst = Inst(); >- } > >+ if (inst.opcode == Shuffle) { >+ Inst::ArgList newArgs; >+ for (unsigned i = 0; i < inst.args.size(); i += 3) { >+ Arg src = inst.args[i + 0]; >+ Arg dest = inst.args[i + 1]; >+ Arg::Width width = inst.args[i + 2]; >+ if (coalescableShufflePairs.get(i) >+ && src.isTmp() && dest.isTmp() && src.tmp() == dest.tmp()) >+ continue; >+ >+ newArgs.append(src); >+ newArgs.append(dest); >+ newArgs.append(Arg::widthArg(width)); >+ } >+ >+ inst.args = WTFMove(newArgs); >+ } >+ } >+ > // Remove all the useless moves we created in this block. > block->insts().removeAllMatching([&] (const Inst& inst) { >- return !inst; >+ return !inst || (inst.opcode == Shuffle && inst.args.isEmpty()); > }); > } > } >@@ -1442,6 +1561,62 @@ private: > for (unsigned instIndex = 0; instIndex < block->size(); ++instIndex) { > Inst& inst = block->at(instIndex); > >+ // The Shuffle instruction requires some special care. The TmpWidth analysis will >+ // say that a shuffle pair only stores 32-bits into the destination if the source >+ // only had 32 bits worth of non-zero bits. Same for the source: it will only claim >+ // to read 32 bits from the source if only 32 bits of the destination are read. This >+ // happens on a per-pair basis. We also happen to know that Shuffle admits stack >+ // everywhere, which makes spilling easier. >+ // >+ // Note that it's OK for this to fall through for not GP, since we handle Shuffle >+ // just fine if we don't have to handle the width special cases. >+ if (inst.opcode == Shuffle && type) { >+ for (unsigned i = 0; i < inst.args.size(); i += 3) { >+ Arg src = inst.args[i + 0]; >+ Arg dest = inst.args[i + 1]; >+ Arg::Width width = inst.args[i + 2].width(); >+ >+ // This excludes everything except mem->mem pairs, which we gracefully >+ // ignore down below. >+ if (!src.isType(type) || !dest.isType(type)) >+ return; >+ >+ bool forceWidth32IfDidSpill = false; >+ bool didSpill = false; >+ >+ if (type == GP && width == Arg::Width64) { >+ if ((src.isTmp() && m_tmpWidth.useWidth(dest.tmp()) <= Arg::Width32) >+ || (dest.isTmp() && m_tmpWidth.defWidth(src.tmp()) <= Arg::Width32)) >+ forceWidth32IfDidSpill = true; >+ } >+ >+ auto handleTmp = [&] (Arg& arg) { >+ if (!arg.isTmp()) >+ return; >+ if (arg.isReg()) >+ return; >+ auto stackSlotEntry = stackSlots.find(arg.tmp()); >+ if (stackSlotEntry == stackSlots.end()) >+ return; >+ stackSlotEntry->value->ensureSize( >+ forceWidth32IfDidSpill ? 4 : Arg::bytes(width)); >+ arg = Arg::stack(stackSlotEntry->value); >+ didSpill = true; >+ }; >+ >+ handleTmp(src); >+ handleTmp(dest); >+ >+ if (didSpill && forceWidth32IfDidSpill) >+ width = Arg::Width32; >+ >+ inst.args[i + 0] = src; >+ inst.args[i + 1] = dest; >+ inst.args[i + 2] = Arg::widthArg(width); >+ } >+ continue; >+ } >+ > // The TmpWidth analysis will say that a Move only stores 32 bits into the destination, > // if the source only had 32 bits worth of non-zero bits. Same for the source: it will > // only claim to read 32 bits from the source if only 32 bits of the destination are >Index: Source/JavaScriptCore/b3/air/AirShufflePair.cpp >=================================================================== >--- Source/JavaScriptCore/b3/air/AirShufflePair.cpp (revision 0) >+++ Source/JavaScriptCore/b3/air/AirShufflePair.cpp (working copy) >@@ -0,0 +1,41 @@ >+/* >+ * Copyright (C) 2016 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 "AirShufflePair.h" >+ >+#if ENABLE(B3_JIT) >+ >+namespace JSC { namespace B3 { namespace Air { >+ >+void ShufflePair::dump(PrintStream& out) const >+{ >+ out.print(width(), ":", src(), "=>", dst()); >+} >+ >+} } } // namespace JSC::B3::Air >+ >+#endif // ENABLE(B3_JIT) >+ >Index: Source/JavaScriptCore/b3/air/AirShufflePair.h >=================================================================== >--- Source/JavaScriptCore/b3/air/AirShufflePair.h (revision 0) >+++ Source/JavaScriptCore/b3/air/AirShufflePair.h (working copy) >@@ -0,0 +1,68 @@ >+/* >+ * Copyright (C) 2016 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. >+ */ >+ >+#ifndef AirShufflePair_h >+#define AirShufflePair_h >+ >+#if ENABLE(B3_JIT) >+ >+#include "AirArg.h" >+ >+namespace JSC { namespace B3 { namespace Air { >+ >+class ShufflePair { >+public: >+ ShufflePair() >+ { >+ } >+ >+ ShufflePair(const Arg& src, const Arg& dst, Arg::Width width) >+ : m_src(src) >+ , m_dst(dst) >+ , m_width(width) >+ { >+ } >+ >+ const Arg& src() const { return m_src; } >+ const Arg& dst() const { return m_dst; } >+ >+ // The width determines the kind of move we do. You can only choose Width32 or Width64 right now. >+ // For GP, it picks between Move32 and Move. For FP, it picks between MoveFloat and MoveDouble. >+ Arg::Width width() const { return m_width; } >+ >+ void dump(PrintStream&) const; >+ >+private: >+ Arg m_src; >+ Arg m_dst; >+ Arg::Width m_width { Arg::Width8 }; >+}; >+ >+} } } // namespace JSC::B3::Air >+ >+#endif // ENABLE(B3_JIT) >+ >+#endif // AirShufflePair_h >+
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 154405
:
271683
|
271710
|
271719
|
272036
| 272628