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