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