1/* 2 * Copyright (C) 2011, 2013 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 ValueRecovery_h 27#define ValueRecovery_h 28 29#include "DataFormat.h" 30#if ENABLE(JIT) 31#include "GPRInfo.h" 32#include "FPRInfo.h" 33#endif 34#include "JSCJSValue.h" 35#include "MacroAssembler.h" 36#include "VirtualRegister.h" 37 38namespace JSC { 39 40struct DumpContext; 41 42// Describes how to recover a given bytecode virtual register at a given 43// code point. 44enum ValueRecoveryTechnique { 45 // It's in a register. 46 InGPR, 47 UnboxedInt32InGPR, 48 UnboxedInt52InGPR, 49 UnboxedStrictInt52InGPR, 50 UnboxedBooleanInGPR, 51 UnboxedCellInGPR, 52#if USE(JSVALUE32_64) 53 InPair, 54#endif 55 InFPR, 56 // It's in the stack, but at a different location. 57 DisplacedInJSStack, 58 // It's in the stack, at a different location, and it's unboxed. 59 Int32DisplacedInJSStack, 60 Int52DisplacedInJSStack, 61 StrictInt52DisplacedInJSStack, 62 DoubleDisplacedInJSStack, 63 CellDisplacedInJSStack, 64 BooleanDisplacedInJSStack, 65 // It's an Arguments object. 66 ArgumentsThatWereNotCreated, 67 // It's a constant. 68 Constant, 69 // Don't know how to recover it. 70 DontKnow 71}; 72 73class ValueRecovery { 74public: 75 ValueRecovery() 76 : m_technique(DontKnow) 77 { 78 } 79 80 bool isSet() const { return m_technique != DontKnow; } 81 bool operator!() const { return !isSet(); } 82 83 static ValueRecovery inGPR(MacroAssembler::RegisterID gpr, DataFormat dataFormat) 84 { 85 ASSERT(dataFormat != DataFormatNone); 86#if USE(JSVALUE32_64) 87 ASSERT(dataFormat == DataFormatInt32 || dataFormat == DataFormatCell || dataFormat == DataFormatBoolean); 88#endif 89 ValueRecovery result; 90 if (dataFormat == DataFormatInt32) 91 result.m_technique = UnboxedInt32InGPR; 92 else if (dataFormat == DataFormatInt52) 93 result.m_technique = UnboxedInt52InGPR; 94 else if (dataFormat == DataFormatStrictInt52) 95 result.m_technique = UnboxedStrictInt52InGPR; 96 else if (dataFormat == DataFormatBoolean) 97 result.m_technique = UnboxedBooleanInGPR; 98 else if (dataFormat == DataFormatCell) 99 result.m_technique = UnboxedCellInGPR; 100 else 101 result.m_technique = InGPR; 102 result.m_source.gpr = gpr; 103 return result; 104 } 105 106#if USE(JSVALUE32_64) 107 static ValueRecovery inPair(MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR) 108 { 109 ValueRecovery result; 110 result.m_technique = InPair; 111 result.m_source.pair.tagGPR = tagGPR; 112 result.m_source.pair.payloadGPR = payloadGPR; 113 return result; 114 } 115#endif 116 117 static ValueRecovery inFPR(MacroAssembler::FPRegisterID fpr) 118 { 119 ValueRecovery result; 120 result.m_technique = InFPR; 121 result.m_source.fpr = fpr; 122 return result; 123 } 124 125 static ValueRecovery displacedInJSStack(VirtualRegister virtualReg, DataFormat dataFormat) 126 { 127 ValueRecovery result; 128 switch (dataFormat) { 129 case DataFormatInt32: 130 result.m_technique = Int32DisplacedInJSStack; 131 break; 132 133 case DataFormatInt52: 134 result.m_technique = Int52DisplacedInJSStack; 135 break; 136 137 case DataFormatStrictInt52: 138 result.m_technique = StrictInt52DisplacedInJSStack; 139 break; 140 141 case DataFormatDouble: 142 result.m_technique = DoubleDisplacedInJSStack; 143 break; 144 145 case DataFormatCell: 146 result.m_technique = CellDisplacedInJSStack; 147 break; 148 149 case DataFormatBoolean: 150 result.m_technique = BooleanDisplacedInJSStack; 151 break; 152 153 default: 154 ASSERT(dataFormat != DataFormatNone && dataFormat != DataFormatStorage); 155 result.m_technique = DisplacedInJSStack; 156 break; 157 } 158 result.m_source.virtualReg = virtualReg.offset(); 159 return result; 160 } 161 162 static ValueRecovery constant(JSValue value) 163 { 164 ValueRecovery result; 165 result.m_technique = Constant; 166 result.m_source.constant = JSValue::encode(value); 167 return result; 168 } 169 170 static ValueRecovery argumentsThatWereNotCreated() 171 { 172 ValueRecovery result; 173 result.m_technique = ArgumentsThatWereNotCreated; 174 return result; 175 } 176 177 ValueRecoveryTechnique technique() const { return m_technique; } 178 179 bool isConstant() const { return m_technique == Constant; } 180 181 bool isInRegisters() const 182 { 183 switch (m_technique) { 184 case InGPR: 185 case UnboxedInt32InGPR: 186 case UnboxedBooleanInGPR: 187 case UnboxedCellInGPR: 188 case UnboxedInt52InGPR: 189 case UnboxedStrictInt52InGPR: 190#if USE(JSVALUE32_64) 191 case InPair: 192#endif 193 case InFPR: 194 return true; 195 default: 196 return false; 197 } 198 } 199 200 MacroAssembler::RegisterID gpr() const 201 { 202 ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UnboxedInt52InGPR || m_technique == UnboxedStrictInt52InGPR || m_technique == UnboxedCellInGPR); 203 return m_source.gpr; 204 } 205 206#if USE(JSVALUE32_64) 207 MacroAssembler::RegisterID tagGPR() const 208 { 209 ASSERT(m_technique == InPair); 210 return m_source.pair.tagGPR; 211 } 212 213 MacroAssembler::RegisterID payloadGPR() const 214 { 215 ASSERT(m_technique == InPair); 216 return m_source.pair.payloadGPR; 217 } 218#endif 219 220 MacroAssembler::FPRegisterID fpr() const 221 { 222 ASSERT(m_technique == InFPR); 223 return m_source.fpr; 224 } 225 226 VirtualRegister virtualRegister() const 227 { 228 ASSERT(m_technique == DisplacedInJSStack || m_technique == Int32DisplacedInJSStack || m_technique == DoubleDisplacedInJSStack || m_technique == CellDisplacedInJSStack || m_technique == BooleanDisplacedInJSStack || m_technique == Int52DisplacedInJSStack || m_technique == StrictInt52DisplacedInJSStack); 229 return VirtualRegister(m_source.virtualReg); 230 } 231 232 ValueRecovery withLocalsOffset(int offset) const 233 { 234 switch (m_technique) { 235 case DisplacedInJSStack: 236 case Int32DisplacedInJSStack: 237 case DoubleDisplacedInJSStack: 238 case CellDisplacedInJSStack: 239 case BooleanDisplacedInJSStack: 240 case Int52DisplacedInJSStack: 241 case StrictInt52DisplacedInJSStack: { 242 ValueRecovery result; 243 result.m_technique = m_technique; 244 result.m_source.virtualReg = m_source.virtualReg + offset; 245 return result; 246 } 247 248 default: 249 return *this; 250 } 251 } 252 253 JSValue constant() const 254 { 255 ASSERT(m_technique == Constant); 256 return JSValue::decode(m_source.constant); 257 } 258 259 JSValue recover(ExecState*) const; 260 261#if ENABLE(JIT) 262 void dumpInContext(PrintStream& out, DumpContext* context) const; 263 void dump(PrintStream& out) const; 264#endif 265 266private: 267 ValueRecoveryTechnique m_technique; 268 union { 269 MacroAssembler::RegisterID gpr; 270 MacroAssembler::FPRegisterID fpr; 271#if USE(JSVALUE32_64) 272 struct { 273 MacroAssembler::RegisterID tagGPR; 274 MacroAssembler::RegisterID payloadGPR; 275 } pair; 276#endif 277 int virtualReg; 278 EncodedJSValue constant; 279 } m_source; 280}; 281 282} // namespace JSC 283 284#endif // ValueRecovery_h 285