/* * 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. */ #ifndef AirSpecial_h #define AirSpecial_h #if ENABLE(B3_JIT) #include "AirInst.h" #include "B3SparseCollection.h" #include #include #include #include namespace JSC { namespace B3 { namespace Air { class Code; struct GenerationContext; class Special { WTF_MAKE_NONCOPYABLE(Special); WTF_MAKE_FAST_ALLOCATED; public: static const char* const dumpPrefix; Special(); virtual ~Special(); Code& code() const { return *m_code; } CString name() const; virtual void forEachArg(Inst&, const ScopedLambda&) = 0; virtual bool isValid(Inst&) = 0; virtual bool admitsStack(Inst&, unsigned argIndex) = 0; virtual Optional shouldTryAliasingDef(Inst&); // This gets called on for each Inst that uses this Special. Note that there is no way to // guarantee that a Special gets used from just one Inst, because Air might taildup late. So, // if you want to pass this information down to generate(), then you have to either: // // 1) Generate Air that starts with a separate Special per Patch Inst, and then merge // usedRegister sets. This is probably not great, but it optimizes for the common case that // Air didn't duplicate code or that such duplication didn't cause any interesting changes to // register assignment. // // 2) Have the Special maintain a HashMap. This works because the analysis // that feeds into this call is performed just before code generation and there is no way // for the Vector<>'s that contain the Insts to be reallocated. This allows generate() to // consult the HashMap. // // 3) Hybrid: you could use (1) and fire up a HashMap if you see multiple calls. // // Note that it's not possible to rely on reportUsedRegisters() being called in the same order // as generate(). If we could rely on that, then we could just have each Special instance // maintain a Vector of RegisterSet's and then process that vector in the right order in // generate(). But, the ordering difference is unlikely to change since it would harm the // performance of the liveness analysis. // // Currently, we do (1) for B3 stackmaps. virtual void reportUsedRegisters(Inst&, const RegisterSet&) = 0; virtual CCallHelpers::Jump generate(Inst&, CCallHelpers&, GenerationContext&) = 0; virtual const RegisterSet& extraEarlyClobberedRegs(Inst&) = 0; virtual const RegisterSet& extraClobberedRegs(Inst&) = 0; // By default, this returns true. virtual bool hasNonArgNonControlEffects(); void dump(PrintStream&) const; void deepDump(PrintStream&) const; protected: virtual void dumpImpl(PrintStream&) const = 0; virtual void deepDumpImpl(PrintStream&) const = 0; private: friend class Code; friend class SparseCollection; unsigned m_index { UINT_MAX }; Code* m_code { nullptr }; }; class DeepSpecialDump { public: DeepSpecialDump(const Special* special) : m_special(special) { } void dump(PrintStream& out) const { if (m_special) m_special->deepDump(out); else out.print(""); } private: const Special* m_special; }; inline DeepSpecialDump deepDump(const Special* special) { return DeepSpecialDump(special); } } } } // namespace JSC::B3::Air #endif // ENABLE(B3_JIT) #endif // AirSpecial_h