1/* 2 * Copyright (C) 2012 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 DFGVariableEvent_h 27#define DFGVariableEvent_h 28 29#if ENABLE(DFG_JIT) 30 31#include "DFGCommon.h" 32#include "DFGMinifiedID.h" 33#include "DataFormat.h" 34#include "MacroAssembler.h" 35#include <stdio.h> 36 37namespace JSC { namespace DFG { 38 39enum VariableEventKind { 40 // Marks the beginning of a checkpoint. If you interpret the variable 41 // events starting at a Reset point then you'll get everything you need. 42 Reset, 43 44 // Node births. Points in the code where a node becomes relevant for OSR. 45 // It may be the point where it is actually born (i.e. assigned) or it may 46 // be a later point, if it's only later in the sequence of instructions 47 // that we start to care about this node. 48 BirthToFill, 49 BirthToSpill, 50 51 // Events related to how a node is represented. 52 Fill, 53 Spill, 54 55 // Death of a node - after this we no longer care about this node. 56 Death, 57 58 // A MovHintEvent means that a node is being associated with a bytecode operand, 59 // but that it has not been stored into that operand. 60 MovHintEvent, 61 62 // A SetLocalEvent means that a node's value has been stored into the stack. 63 SetLocalEvent, 64 65 // Used to indicate an uninitialized VariableEvent. Don't use for other 66 // purposes. 67 InvalidEventKind 68}; 69 70union VariableRepresentation { 71 MacroAssembler::RegisterID gpr; 72 MacroAssembler::FPRegisterID fpr; 73#if USE(JSVALUE32_64) 74 struct { 75 MacroAssembler::RegisterID tagGPR; 76 MacroAssembler::RegisterID payloadGPR; 77 } pair; 78#endif 79 int32_t virtualReg; 80}; 81 82class VariableEvent { 83public: 84 VariableEvent() 85 : m_kind(InvalidEventKind) 86 { 87 } 88 89 static VariableEvent reset() 90 { 91 VariableEvent event; 92 event.m_kind = Reset; 93 return event; 94 } 95 96 static VariableEvent fillGPR(VariableEventKind kind, MinifiedID id, MacroAssembler::RegisterID gpr, DataFormat dataFormat) 97 { 98 ASSERT(kind == BirthToFill || kind == Fill); 99 ASSERT(dataFormat != DataFormatDouble); 100#if USE(JSVALUE32_64) 101 ASSERT(!(dataFormat & DataFormatJS)); 102#endif 103 VariableEvent event; 104 event.m_which.id = id.bits(); 105 event.m_representation.gpr = gpr; 106 event.m_kind = kind; 107 event.m_dataFormat = dataFormat; 108 return event; 109 } 110 111#if USE(JSVALUE32_64) 112 static VariableEvent fillPair(VariableEventKind kind, MinifiedID id, MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR) 113 { 114 ASSERT(kind == BirthToFill || kind == Fill); 115 VariableEvent event; 116 event.m_which.id = id.bits(); 117 event.m_representation.pair.tagGPR = tagGPR; 118 event.m_representation.pair.payloadGPR = payloadGPR; 119 event.m_kind = kind; 120 event.m_dataFormat = DataFormatJS; 121 return event; 122 } 123#endif // USE(JSVALUE32_64) 124 125 static VariableEvent fillFPR(VariableEventKind kind, MinifiedID id, MacroAssembler::FPRegisterID fpr) 126 { 127 ASSERT(kind == BirthToFill || kind == Fill); 128 VariableEvent event; 129 event.m_which.id = id.bits(); 130 event.m_representation.fpr = fpr; 131 event.m_kind = kind; 132 event.m_dataFormat = DataFormatDouble; 133 return event; 134 } 135 136 static VariableEvent spill(VariableEventKind kind, MinifiedID id, VirtualRegister virtualRegister, DataFormat format) 137 { 138 ASSERT(kind == BirthToSpill || kind == Spill); 139 VariableEvent event; 140 event.m_which.id = id.bits(); 141 event.m_representation.virtualReg = virtualRegister.offset(); 142 event.m_kind = kind; 143 event.m_dataFormat = format; 144 return event; 145 } 146 147 static VariableEvent death(MinifiedID id) 148 { 149 VariableEvent event; 150 event.m_which.id = id.bits(); 151 event.m_kind = Death; 152 return event; 153 } 154 155 static VariableEvent setLocal( 156 VirtualRegister bytecodeReg, VirtualRegister machineReg, DataFormat format) 157 { 158 VariableEvent event; 159 event.m_which.virtualReg = machineReg.offset(); 160 event.m_representation.virtualReg = bytecodeReg.offset(); 161 event.m_kind = SetLocalEvent; 162 event.m_dataFormat = format; 163 return event; 164 } 165 166 static VariableEvent movHint(MinifiedID id, VirtualRegister bytecodeReg) 167 { 168 VariableEvent event; 169 event.m_which.id = id.bits(); 170 event.m_representation.virtualReg = bytecodeReg.offset(); 171 event.m_kind = MovHintEvent; 172 return event; 173 } 174 175 VariableEventKind kind() const 176 { 177 return static_cast<VariableEventKind>(m_kind); 178 } 179 180 MinifiedID id() const 181 { 182 ASSERT(m_kind == BirthToFill || m_kind == Fill 183 || m_kind == BirthToSpill || m_kind == Spill 184 || m_kind == Death || m_kind == MovHintEvent); 185 return MinifiedID::fromBits(m_which.id); 186 } 187 188 DataFormat dataFormat() const 189 { 190 ASSERT(m_kind == BirthToFill || m_kind == Fill 191 || m_kind == BirthToSpill || m_kind == Spill 192 || m_kind == SetLocalEvent); 193 return static_cast<DataFormat>(m_dataFormat); 194 } 195 196 MacroAssembler::RegisterID gpr() const 197 { 198 ASSERT(m_kind == BirthToFill || m_kind == Fill); 199 ASSERT(m_dataFormat); 200 ASSERT(m_dataFormat != DataFormatDouble); 201#if USE(JSVALUE32_64) 202 ASSERT(!(m_dataFormat & DataFormatJS)); 203#endif 204 return m_representation.gpr; 205 } 206 207#if USE(JSVALUE32_64) 208 MacroAssembler::RegisterID tagGPR() const 209 { 210 ASSERT(m_kind == BirthToFill || m_kind == Fill); 211 ASSERT(m_dataFormat & DataFormatJS); 212 return m_representation.pair.tagGPR; 213 } 214 MacroAssembler::RegisterID payloadGPR() const 215 { 216 ASSERT(m_kind == BirthToFill || m_kind == Fill); 217 ASSERT(m_dataFormat & DataFormatJS); 218 return m_representation.pair.payloadGPR; 219 } 220#endif // USE(JSVALUE32_64) 221 222 MacroAssembler::FPRegisterID fpr() const 223 { 224 ASSERT(m_kind == BirthToFill || m_kind == Fill); 225 ASSERT(m_dataFormat == DataFormatDouble); 226 return m_representation.fpr; 227 } 228 229 VirtualRegister spillRegister() const 230 { 231 ASSERT(m_kind == BirthToSpill || m_kind == Spill); 232 return VirtualRegister(m_representation.virtualReg); 233 } 234 235 VirtualRegister bytecodeRegister() const 236 { 237 ASSERT(m_kind == SetLocalEvent || m_kind == MovHintEvent); 238 return VirtualRegister(m_representation.virtualReg); 239 } 240 241 VirtualRegister machineRegister() const 242 { 243 ASSERT(m_kind == SetLocalEvent); 244 return VirtualRegister(m_which.virtualReg); 245 } 246 247 const VariableRepresentation& variableRepresentation() const { return m_representation; } 248 249 void dump(PrintStream&) const; 250 251private: 252 void dumpFillInfo(const char* name, PrintStream&) const; 253 void dumpSpillInfo(const char* name, PrintStream&) const; 254 255 union { 256 int virtualReg; 257 uintptr_t id; 258 } m_which; 259 260 // For BirthToFill, Fill: 261 // - The GPR or FPR, or a GPR pair. 262 // For BirthToSpill, Spill: 263 // - The virtual register. 264 // For MovHintEvent, SetLocalEvent: 265 // - The bytecode operand. 266 // For Death: 267 // - Unused. 268 VariableRepresentation m_representation; 269 270 int8_t m_kind; 271 int8_t m_dataFormat; 272}; 273 274} } // namespace JSC::DFG 275 276#endif // ENABLE(DFG_JIT) 277 278#endif // DFGVariableEvent_h 279 280