1/* 2 * Copyright (C) 2011, 2012, 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 Operands_h 27#define Operands_h 28 29#include "CallFrame.h" 30#include "JSObject.h" 31#include "VirtualRegister.h" 32 33#include <wtf/PrintStream.h> 34#include <wtf/Vector.h> 35 36namespace JSC { 37 38template<typename T> struct OperandValueTraits; 39 40template<typename T> 41struct OperandValueTraits { 42 static T defaultValue() { return T(); } 43 static bool isEmptyForDump(const T& value) { return !value; } 44}; 45 46enum OperandKind { ArgumentOperand, LocalOperand }; 47 48enum OperandsLikeTag { OperandsLike }; 49 50template<typename T, typename Traits = OperandValueTraits<T>> 51class Operands { 52public: 53 Operands() { } 54 55 explicit Operands(size_t numArguments, size_t numLocals) 56 { 57 m_arguments.fill(Traits::defaultValue(), numArguments); 58 m_locals.fill(Traits::defaultValue(), numLocals); 59 } 60 61 template<typename U, typename OtherTraits> 62 explicit Operands(OperandsLikeTag, const Operands<U, OtherTraits>& other) 63 { 64 m_arguments.fill(Traits::defaultValue(), other.numberOfArguments()); 65 m_locals.fill(Traits::defaultValue(), other.numberOfLocals()); 66 } 67 68 size_t numberOfArguments() const { return m_arguments.size(); } 69 size_t numberOfLocals() const { return m_locals.size(); } 70 71 T& argument(size_t idx) { return m_arguments[idx]; } 72 const T& argument(size_t idx) const { return m_arguments[idx]; } 73 74 T& local(size_t idx) { return m_locals[idx]; } 75 const T& local(size_t idx) const { return m_locals[idx]; } 76 77 template<OperandKind operandKind> 78 size_t sizeFor() const 79 { 80 if (operandKind == ArgumentOperand) 81 return numberOfArguments(); 82 return numberOfLocals(); 83 } 84 template<OperandKind operandKind> 85 T& atFor(size_t idx) 86 { 87 if (operandKind == ArgumentOperand) 88 return argument(idx); 89 return local(idx); 90 } 91 template<OperandKind operandKind> 92 const T& atFor(size_t idx) const 93 { 94 if (operandKind == ArgumentOperand) 95 return argument(idx); 96 return local(idx); 97 } 98 99 void ensureLocals(size_t size) 100 { 101 if (size <= m_locals.size()) 102 return; 103 104 size_t oldSize = m_locals.size(); 105 m_locals.resize(size); 106 for (size_t i = oldSize; i < m_locals.size(); ++i) 107 m_locals[i] = Traits::defaultValue(); 108 } 109 110 void setLocal(size_t idx, const T& value) 111 { 112 ensureLocals(idx + 1); 113 114 m_locals[idx] = value; 115 } 116 117 T getLocal(size_t idx) 118 { 119 if (idx >= m_locals.size()) 120 return Traits::defaultValue(); 121 return m_locals[idx]; 122 } 123 124 void setArgumentFirstTime(size_t idx, const T& value) 125 { 126 ASSERT(m_arguments[idx] == Traits::defaultValue()); 127 argument(idx) = value; 128 } 129 130 void setLocalFirstTime(size_t idx, const T& value) 131 { 132 ASSERT(idx >= m_locals.size() || m_locals[idx] == Traits::defaultValue()); 133 setLocal(idx, value); 134 } 135 136 T& operand(int operand) 137 { 138 if (operandIsArgument(operand)) { 139 int argument = VirtualRegister(operand).toArgument(); 140 return m_arguments[argument]; 141 } 142 143 return m_locals[VirtualRegister(operand).toLocal()]; 144 } 145 146 T& operand(VirtualRegister virtualRegister) 147 { 148 return operand(virtualRegister.offset()); 149 } 150 151 const T& operand(int operand) const { return const_cast<const T&>(const_cast<Operands*>(this)->operand(operand)); } 152 153 bool hasOperand(int operand) const 154 { 155 if (operandIsArgument(operand)) 156 return true; 157 return static_cast<size_t>(VirtualRegister(operand).toLocal()) < numberOfLocals(); 158 } 159 bool hasOperand(VirtualRegister reg) const 160 { 161 return hasOperand(reg.offset()); 162 } 163 164 void setOperand(int operand, const T& value) 165 { 166 if (operandIsArgument(operand)) { 167 int argument = VirtualRegister(operand).toArgument(); 168 m_arguments[argument] = value; 169 return; 170 } 171 172 setLocal(VirtualRegister(operand).toLocal(), value); 173 } 174 175 void setOperand(VirtualRegister virtualRegister, const T& value) 176 { 177 setOperand(virtualRegister.offset(), value); 178 } 179 180 size_t size() const { return numberOfArguments() + numberOfLocals(); } 181 const T& at(size_t index) const 182 { 183 if (index < numberOfArguments()) 184 return m_arguments[index]; 185 return m_locals[index - numberOfArguments()]; 186 } 187 T& at(size_t index) 188 { 189 if (index < numberOfArguments()) 190 return m_arguments[index]; 191 return m_locals[index - numberOfArguments()]; 192 } 193 const T& operator[](size_t index) const { return at(index); } 194 T& operator[](size_t index) { return at(index); } 195 196 bool isArgument(size_t index) const { return index < numberOfArguments(); } 197 bool isVariable(size_t index) const { return !isArgument(index); } 198 int argumentForIndex(size_t index) const 199 { 200 return index; 201 } 202 int variableForIndex(size_t index) const 203 { 204 return index - m_arguments.size(); 205 } 206 int operandForIndex(size_t index) const 207 { 208 if (index < numberOfArguments()) 209 return virtualRegisterForArgument(index).offset(); 210 return virtualRegisterForLocal(index - numberOfArguments()).offset(); 211 } 212 size_t indexForOperand(int operand) const 213 { 214 if (operandIsArgument(operand)) 215 return static_cast<size_t>(VirtualRegister(operand).toArgument()); 216 return static_cast<size_t>(VirtualRegister(operand).toLocal()) + numberOfArguments(); 217 } 218 size_t indexForOperand(VirtualRegister reg) const 219 { 220 return indexForOperand(reg.offset()); 221 } 222 223 void setOperandFirstTime(int operand, const T& value) 224 { 225 if (operandIsArgument(operand)) { 226 setArgumentFirstTime(VirtualRegister(operand).toArgument(), value); 227 return; 228 } 229 230 setLocalFirstTime(VirtualRegister(operand).toLocal(), value); 231 } 232 233 void fill(T value) 234 { 235 for (size_t i = 0; i < m_arguments.size(); ++i) 236 m_arguments[i] = value; 237 for (size_t i = 0; i < m_locals.size(); ++i) 238 m_locals[i] = value; 239 } 240 241 void clear() 242 { 243 fill(Traits::defaultValue()); 244 } 245 246 bool operator==(const Operands& other) const 247 { 248 ASSERT(numberOfArguments() == other.numberOfArguments()); 249 ASSERT(numberOfLocals() == other.numberOfLocals()); 250 251 return m_arguments == other.m_arguments && m_locals == other.m_locals; 252 } 253 254 void dumpInContext(PrintStream& out, DumpContext* context) const; 255 256 void dump(PrintStream& out) const 257 { 258 dumpInContext(out, 0); 259 } 260 261private: 262 Vector<T, 8> m_arguments; 263 Vector<T, 16> m_locals; 264}; 265 266} // namespace JSC 267 268#endif // Operands_h 269 270