Home | History | Annotate | Download | only in dfg
      1 /*
      2  * Copyright (C) 2011 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef DFGGenerationInfo_h
     27 #define DFGGenerationInfo_h
     28 
     29 #if ENABLE(DFG_JIT)
     30 
     31 #include <dfg/DFGJITCompiler.h>
     32 
     33 namespace JSC { namespace DFG {
     34 
     35 // === DataFormat ===
     36 //
     37 // This enum tracks the current representation in which a value is being held.
     38 // Values may be unboxed primitives (int32, double, or cell), or boxed as a JSValue.
     39 // For boxed values, we may know the type of boxing that has taken place.
     40 // (May also need bool, array, object, string types!)
     41 enum DataFormat {
     42     DataFormatNone = 0,
     43     DataFormatInteger = 1,
     44     DataFormatDouble = 2,
     45     DataFormatCell = 3,
     46     DataFormatJS = 8,
     47     DataFormatJSInteger = DataFormatJS | DataFormatInteger,
     48     DataFormatJSDouble = DataFormatJS | DataFormatDouble,
     49     DataFormatJSCell = DataFormatJS | DataFormatCell,
     50 };
     51 
     52 // === GenerationInfo ===
     53 //
     54 // This class is used to track the current status of a live values during code generation.
     55 // Can provide information as to whether a value is in machine registers, and if so which,
     56 // whether a value has been spilled to the RegsiterFile, and if so may be able to provide
     57 // details of the format in memory (all values are spilled in a boxed form, but we may be
     58 // able to track the type of box), and tracks how many outstanding uses of a value remain,
     59 // so that we know when the value is dead and the machine registers associated with it
     60 // may be released.
     61 class GenerationInfo {
     62 public:
     63     GenerationInfo()
     64         : m_nodeIndex(NoNode)
     65         , m_useCount(0)
     66         , m_registerFormat(DataFormatNone)
     67         , m_spillFormat(DataFormatNone)
     68         , m_canFill(false)
     69     {
     70     }
     71 
     72     void initConstant(NodeIndex nodeIndex, uint32_t useCount)
     73     {
     74         m_nodeIndex = nodeIndex;
     75         m_useCount = useCount;
     76         m_registerFormat = DataFormatNone;
     77         m_spillFormat = DataFormatNone;
     78         m_canFill = true;
     79     }
     80     void initInteger(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
     81     {
     82         m_nodeIndex = nodeIndex;
     83         m_useCount = useCount;
     84         m_registerFormat = DataFormatInteger;
     85         m_spillFormat = DataFormatNone;
     86         m_canFill = false;
     87         u.gpr = gpr;
     88     }
     89     void initJSValue(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr, DataFormat format = DataFormatJS)
     90     {
     91         ASSERT(format & DataFormatJS);
     92 
     93         m_nodeIndex = nodeIndex;
     94         m_useCount = useCount;
     95         m_registerFormat = format;
     96         m_spillFormat = DataFormatNone;
     97         m_canFill = false;
     98         u.gpr = gpr;
     99     }
    100     void initCell(NodeIndex nodeIndex, uint32_t useCount, GPRReg gpr)
    101     {
    102         m_nodeIndex = nodeIndex;
    103         m_useCount = useCount;
    104         m_registerFormat = DataFormatCell;
    105         m_spillFormat = DataFormatNone;
    106         m_canFill = false;
    107         u.gpr = gpr;
    108     }
    109     void initDouble(NodeIndex nodeIndex, uint32_t useCount, FPRReg fpr)
    110     {
    111         m_nodeIndex = nodeIndex;
    112         m_useCount = useCount;
    113         m_registerFormat = DataFormatDouble;
    114         m_spillFormat = DataFormatNone;
    115         m_canFill = false;
    116         u.fpr = fpr;
    117     }
    118     void initNone(NodeIndex nodeIndex, uint32_t useCount)
    119     {
    120         m_nodeIndex = nodeIndex;
    121         m_useCount = useCount;
    122         m_registerFormat = DataFormatNone;
    123         m_spillFormat = DataFormatNone;
    124         m_canFill = false;
    125     }
    126 
    127     // Get the index of the node that produced this value.
    128     NodeIndex nodeIndex() { return m_nodeIndex; }
    129 
    130     // Mark the value as having been used (decrement the useCount).
    131     // Returns true if this was the last use of the value, and any
    132     // associated machine registers may be freed.
    133     bool use()
    134     {
    135         return !--m_useCount;
    136     }
    137 
    138     // Used to check the operands of operations to see if they are on
    139     // their last use; in some cases it may be safe to reuse the same
    140     // machine register for the result of the operation.
    141     bool canReuse()
    142     {
    143         ASSERT(m_useCount);
    144         return m_useCount == 1;
    145     }
    146 
    147     // Get the format of the value in machine registers (or 'none').
    148     DataFormat registerFormat() { return m_registerFormat; }
    149     // Get the format of the value as it is spilled in the RegisterFile (or 'none').
    150     DataFormat spillFormat() { return m_spillFormat; }
    151 
    152     // Get the machine resister currently holding the value.
    153     GPRReg gpr() { ASSERT(m_registerFormat && m_registerFormat != DataFormatDouble); return u.gpr; }
    154     FPRReg fpr() { ASSERT(m_registerFormat == DataFormatDouble); return u.fpr; }
    155 
    156     // Check whether a value needs spilling in order to free up any associated machine registers.
    157     bool needsSpill()
    158     {
    159         // This should only be called on values that are currently in a register.
    160         ASSERT(m_registerFormat != DataFormatNone);
    161         // Constants do not need spilling, nor do values that have already been
    162         // spilled to the RegisterFile.
    163         return !m_canFill;
    164     }
    165 
    166     // Called when a VirtualRegister is being spilled to the RegisterFile for the first time.
    167     void spill(DataFormat spillFormat)
    168     {
    169         // We shouldn't be spill values that don't need spilling.
    170         ASSERT(!m_canFill);
    171         ASSERT(m_spillFormat == DataFormatNone);
    172         // We should only be spilling values that are currently in machine registers.
    173         ASSERT(m_registerFormat != DataFormatNone);
    174         // We only spill values that have been boxed as a JSValue; otherwise the GC
    175         // would need a way to distinguish cell pointers from numeric primitives.
    176         ASSERT(spillFormat & DataFormatJS);
    177 
    178         m_registerFormat = DataFormatNone;
    179         m_spillFormat = spillFormat;
    180         m_canFill = true;
    181     }
    182 
    183     // Called on values that don't need spilling (constants and values that have
    184     // already been spilled), to mark them as no longer being in machine registers.
    185     void setSpilled()
    186     {
    187         // Should only be called on values that don't need spilling, and are currently in registers.
    188         ASSERT(m_canFill && m_registerFormat != DataFormatNone);
    189         m_registerFormat = DataFormatNone;
    190     }
    191 
    192     // Record that this value is filled into machine registers,
    193     // tracking which registers, and what format the value has.
    194     void fillJSValue(GPRReg gpr, DataFormat format = DataFormatJS)
    195     {
    196         ASSERT(format & DataFormatJS);
    197         m_registerFormat = format;
    198         u.gpr = gpr;
    199     }
    200     void fillInteger(GPRReg gpr)
    201     {
    202         m_registerFormat = DataFormatInteger;
    203         u.gpr = gpr;
    204     }
    205     void fillDouble(FPRReg fpr)
    206     {
    207         m_registerFormat = DataFormatDouble;
    208         u.fpr = fpr;
    209     }
    210 
    211 #ifndef NDEBUG
    212     bool alive()
    213     {
    214         return m_useCount;
    215     }
    216 #endif
    217 
    218 private:
    219     // The index of the node whose result is stored in this virtual register.
    220     // FIXME: Can we remove this? - this is currently only used when collecting
    221     // snapshots of the RegisterBank for SpeculationCheck/EntryLocation. Could
    222     // investigate storing NodeIndex as the name in RegsiterBank, instead of
    223     // VirtualRegister.
    224     NodeIndex m_nodeIndex;
    225     uint32_t m_useCount;
    226     DataFormat m_registerFormat;
    227     DataFormat m_spillFormat;
    228     bool m_canFill;
    229     union {
    230         GPRReg gpr;
    231         FPRReg fpr;
    232     } u;
    233 };
    234 
    235 } } // namespace JSC::DFG
    236 
    237 #endif
    238 #endif
    239