1/* 2 * Copyright (C) 2011, 2013, 2014 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 DFGValueSource_h 27#define DFGValueSource_h 28 29#if ENABLE(DFG_JIT) 30 31#include "DFGCommon.h" 32#include "DFGFlushFormat.h" 33#include "DFGMinifiedID.h" 34#include "DataFormat.h" 35#include "SpeculatedType.h" 36#include "ValueRecovery.h" 37 38namespace JSC { namespace DFG { 39 40enum ValueSourceKind { 41 SourceNotSet, 42 ValueInJSStack, 43 Int32InJSStack, 44 Int52InJSStack, 45 CellInJSStack, 46 BooleanInJSStack, 47 DoubleInJSStack, 48 ArgumentsSource, 49 SourceIsDead, 50 HaveNode 51}; 52 53static inline ValueSourceKind dataFormatToValueSourceKind(DataFormat dataFormat) 54{ 55 switch (dataFormat) { 56 case DataFormatInt32: 57 return Int32InJSStack; 58 case DataFormatInt52: 59 return Int52InJSStack; 60 case DataFormatDouble: 61 return DoubleInJSStack; 62 case DataFormatBoolean: 63 return BooleanInJSStack; 64 case DataFormatCell: 65 return CellInJSStack; 66 case DataFormatDead: 67 return SourceIsDead; 68 case DataFormatArguments: 69 return ArgumentsSource; 70 default: 71 RELEASE_ASSERT(dataFormat & DataFormatJS); 72 return ValueInJSStack; 73 } 74} 75 76static inline DataFormat valueSourceKindToDataFormat(ValueSourceKind kind) 77{ 78 switch (kind) { 79 case ValueInJSStack: 80 return DataFormatJS; 81 case Int32InJSStack: 82 return DataFormatInt32; 83 case Int52InJSStack: 84 return DataFormatInt52; 85 case CellInJSStack: 86 return DataFormatCell; 87 case BooleanInJSStack: 88 return DataFormatBoolean; 89 case DoubleInJSStack: 90 return DataFormatDouble; 91 case ArgumentsSource: 92 return DataFormatArguments; 93 case SourceIsDead: 94 return DataFormatDead; 95 default: 96 return DataFormatNone; 97 } 98} 99 100static inline bool isInJSStack(ValueSourceKind kind) 101{ 102 DataFormat format = valueSourceKindToDataFormat(kind); 103 return format != DataFormatNone && format < DataFormatOSRMarker; 104} 105 106// Can this value be recovered without having to look at register allocation state or 107// DFG node liveness? 108static inline bool isTriviallyRecoverable(ValueSourceKind kind) 109{ 110 return valueSourceKindToDataFormat(kind) != DataFormatNone; 111} 112 113class ValueSource { 114public: 115 ValueSource() 116 : m_kind(SourceNotSet) 117 { 118 } 119 120 explicit ValueSource(ValueSourceKind valueSourceKind) 121 : m_kind(valueSourceKind) 122 { 123 ASSERT(kind() == ArgumentsSource || kind() == SourceIsDead || kind() == ArgumentsSource); 124 } 125 126 explicit ValueSource(MinifiedID id) 127 : m_kind(HaveNode) 128 , m_value(id.bits()) 129 { 130 ASSERT(!!id); 131 ASSERT(kind() == HaveNode); 132 } 133 134 ValueSource(ValueSourceKind valueSourceKind, VirtualRegister where) 135 : m_kind(valueSourceKind) 136 , m_value(static_cast<intptr_t>(where.offset())) 137 { 138 ASSERT(kind() != SourceNotSet); 139 ASSERT(kind() != HaveNode); 140 } 141 142 static ValueSource forFlushFormat(VirtualRegister where, FlushFormat format) 143 { 144 switch (format) { 145 case DeadFlush: 146 case ConflictingFlush: 147 return ValueSource(SourceIsDead); 148 case FlushedJSValue: 149 return ValueSource(ValueInJSStack, where); 150 case FlushedDouble: 151 return ValueSource(DoubleInJSStack, where); 152 case FlushedInt32: 153 return ValueSource(Int32InJSStack, where); 154 case FlushedInt52: 155 return ValueSource(Int52InJSStack, where); 156 case FlushedCell: 157 return ValueSource(CellInJSStack, where); 158 case FlushedBoolean: 159 return ValueSource(BooleanInJSStack, where); 160 case FlushedArguments: 161 return ValueSource(ArgumentsSource); 162 } 163 RELEASE_ASSERT_NOT_REACHED(); 164 return ValueSource(); 165 } 166 167 static ValueSource forDataFormat(VirtualRegister where, DataFormat dataFormat) 168 { 169 return ValueSource(dataFormatToValueSourceKind(dataFormat), where); 170 } 171 172 bool isSet() const 173 { 174 return kind() != SourceNotSet; 175 } 176 177 bool operator!() const { return !isSet(); } 178 179 ValueSourceKind kind() const 180 { 181 return m_kind; 182 } 183 184 bool isInJSStack() const { return JSC::DFG::isInJSStack(kind()); } 185 bool isTriviallyRecoverable() const { return JSC::DFG::isTriviallyRecoverable(kind()); } 186 187 DataFormat dataFormat() const 188 { 189 return valueSourceKindToDataFormat(kind()); 190 } 191 192 ValueRecovery valueRecovery() const 193 { 194 ASSERT(isTriviallyRecoverable()); 195 switch (kind()) { 196 case SourceIsDead: 197 return ValueRecovery::constant(jsUndefined()); 198 199 case ArgumentsSource: 200 return ValueRecovery::argumentsThatWereNotCreated(); 201 202 default: 203 return ValueRecovery::displacedInJSStack(virtualRegister(), dataFormat()); 204 } 205 } 206 207 MinifiedID id() const 208 { 209 ASSERT(kind() == HaveNode); 210 return MinifiedID::fromBits(m_value); 211 } 212 213 VirtualRegister virtualRegister() const 214 { 215 ASSERT(isInJSStack()); 216 return VirtualRegister(m_value); 217 } 218 219 void dump(PrintStream&) const; 220 void dumpInContext(PrintStream&, DumpContext*) const; 221 222private: 223 ValueSourceKind m_kind; 224 uintptr_t m_value; 225}; 226 227} } // namespace JSC::DFG 228 229#endif // ENABLE(DFG_JIT) 230 231#endif // DFGValueSource_h 232 233