| /* |
| * Copyright (C) 2011, 2012, 2013, 2015 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #ifndef Operands_h |
| #define Operands_h |
| |
| #include "CallFrame.h" |
| #include "JSObject.h" |
| #include "VirtualRegister.h" |
| |
| #include <wtf/PrintStream.h> |
| #include <wtf/Vector.h> |
| |
| namespace JSC { |
| |
| template<typename T> struct OperandValueTraits; |
| |
| template<typename T> |
| struct OperandValueTraits { |
| static T defaultValue() { return T(); } |
| static bool isEmptyForDump(const T& value) { return !value; } |
| }; |
| |
| enum OperandKind { ArgumentOperand, LocalOperand }; |
| |
| enum OperandsLikeTag { OperandsLike }; |
| |
| template<typename T, typename Traits = OperandValueTraits<T>> |
| class Operands { |
| public: |
| Operands() { } |
| |
| explicit Operands(size_t numArguments, size_t numLocals, const T& initialValue = Traits::defaultValue()) |
| { |
| m_arguments.fill(initialValue, numArguments); |
| m_locals.fill(initialValue, numLocals); |
| } |
| |
| template<typename U, typename OtherTraits> |
| explicit Operands(OperandsLikeTag, const Operands<U, OtherTraits>& other) |
| { |
| m_arguments.fill(Traits::defaultValue(), other.numberOfArguments()); |
| m_locals.fill(Traits::defaultValue(), other.numberOfLocals()); |
| } |
| |
| size_t numberOfArguments() const { return m_arguments.size(); } |
| size_t numberOfLocals() const { return m_locals.size(); } |
| |
| T& argument(size_t idx) { return m_arguments[idx]; } |
| const T& argument(size_t idx) const { return m_arguments[idx]; } |
| |
| T& local(size_t idx) { return m_locals[idx]; } |
| const T& local(size_t idx) const { return m_locals[idx]; } |
| |
| template<OperandKind operandKind> |
| size_t sizeFor() const |
| { |
| if (operandKind == ArgumentOperand) |
| return numberOfArguments(); |
| return numberOfLocals(); |
| } |
| template<OperandKind operandKind> |
| T& atFor(size_t idx) |
| { |
| if (operandKind == ArgumentOperand) |
| return argument(idx); |
| return local(idx); |
| } |
| template<OperandKind operandKind> |
| const T& atFor(size_t idx) const |
| { |
| if (operandKind == ArgumentOperand) |
| return argument(idx); |
| return local(idx); |
| } |
| |
| void ensureLocals(size_t size, const T& ensuredValue = Traits::defaultValue()) |
| { |
| if (size <= m_locals.size()) |
| return; |
| |
| size_t oldSize = m_locals.size(); |
| m_locals.resize(size); |
| for (size_t i = oldSize; i < m_locals.size(); ++i) |
| m_locals[i] = ensuredValue; |
| } |
| |
| void setLocal(size_t idx, const T& value) |
| { |
| ensureLocals(idx + 1); |
| |
| m_locals[idx] = value; |
| } |
| |
| T getLocal(size_t idx) |
| { |
| if (idx >= m_locals.size()) |
| return Traits::defaultValue(); |
| return m_locals[idx]; |
| } |
| |
| void setArgumentFirstTime(size_t idx, const T& value) |
| { |
| ASSERT(m_arguments[idx] == Traits::defaultValue()); |
| argument(idx) = value; |
| } |
| |
| void setLocalFirstTime(size_t idx, const T& value) |
| { |
| ASSERT(idx >= m_locals.size() || m_locals[idx] == Traits::defaultValue()); |
| setLocal(idx, value); |
| } |
| |
| T& operand(int operand) |
| { |
| if (operandIsArgument(operand)) { |
| int argument = VirtualRegister(operand).toArgument(); |
| return m_arguments[argument]; |
| } |
| |
| return m_locals[VirtualRegister(operand).toLocal()]; |
| } |
| |
| T& operand(VirtualRegister virtualRegister) |
| { |
| return operand(virtualRegister.offset()); |
| } |
| |
| const T& operand(int operand) const { return const_cast<const T&>(const_cast<Operands*>(this)->operand(operand)); } |
| const T& operand(VirtualRegister operand) const { return const_cast<const T&>(const_cast<Operands*>(this)->operand(operand)); } |
| |
| bool hasOperand(int operand) const |
| { |
| if (operandIsArgument(operand)) |
| return true; |
| return static_cast<size_t>(VirtualRegister(operand).toLocal()) < numberOfLocals(); |
| } |
| bool hasOperand(VirtualRegister reg) const |
| { |
| return hasOperand(reg.offset()); |
| } |
| |
| void setOperand(int operand, const T& value) |
| { |
| if (operandIsArgument(operand)) { |
| int argument = VirtualRegister(operand).toArgument(); |
| m_arguments[argument] = value; |
| return; |
| } |
| |
| setLocal(VirtualRegister(operand).toLocal(), value); |
| } |
| |
| void setOperand(VirtualRegister virtualRegister, const T& value) |
| { |
| setOperand(virtualRegister.offset(), value); |
| } |
| |
| size_t size() const { return numberOfArguments() + numberOfLocals(); } |
| const T& at(size_t index) const |
| { |
| if (index < numberOfArguments()) |
| return m_arguments[index]; |
| return m_locals[index - numberOfArguments()]; |
| } |
| T& at(size_t index) |
| { |
| if (index < numberOfArguments()) |
| return m_arguments[index]; |
| return m_locals[index - numberOfArguments()]; |
| } |
| const T& operator[](size_t index) const { return at(index); } |
| T& operator[](size_t index) { return at(index); } |
| |
| bool isArgument(size_t index) const { return index < numberOfArguments(); } |
| bool isVariable(size_t index) const { return !isArgument(index); } |
| int argumentForIndex(size_t index) const |
| { |
| return index; |
| } |
| int variableForIndex(size_t index) const |
| { |
| return index - m_arguments.size(); |
| } |
| int operandForIndex(size_t index) const |
| { |
| if (index < numberOfArguments()) |
| return virtualRegisterForArgument(index).offset(); |
| return virtualRegisterForLocal(index - numberOfArguments()).offset(); |
| } |
| VirtualRegister virtualRegisterForIndex(size_t index) const |
| { |
| return VirtualRegister(operandForIndex(index)); |
| } |
| size_t indexForOperand(int operand) const |
| { |
| if (operandIsArgument(operand)) |
| return static_cast<size_t>(VirtualRegister(operand).toArgument()); |
| return static_cast<size_t>(VirtualRegister(operand).toLocal()) + numberOfArguments(); |
| } |
| size_t indexForOperand(VirtualRegister reg) const |
| { |
| return indexForOperand(reg.offset()); |
| } |
| |
| void setOperandFirstTime(int operand, const T& value) |
| { |
| if (operandIsArgument(operand)) { |
| setArgumentFirstTime(VirtualRegister(operand).toArgument(), value); |
| return; |
| } |
| |
| setLocalFirstTime(VirtualRegister(operand).toLocal(), value); |
| } |
| |
| void fill(T value) |
| { |
| for (size_t i = 0; i < m_arguments.size(); ++i) |
| m_arguments[i] = value; |
| for (size_t i = 0; i < m_locals.size(); ++i) |
| m_locals[i] = value; |
| } |
| |
| void clear() |
| { |
| fill(Traits::defaultValue()); |
| } |
| |
| bool operator==(const Operands& other) const |
| { |
| ASSERT(numberOfArguments() == other.numberOfArguments()); |
| ASSERT(numberOfLocals() == other.numberOfLocals()); |
| |
| return m_arguments == other.m_arguments && m_locals == other.m_locals; |
| } |
| |
| void dumpInContext(PrintStream& out, DumpContext* context) const; |
| void dump(PrintStream& out) const; |
| |
| private: |
| Vector<T, 8> m_arguments; |
| Vector<T, 16> m_locals; |
| }; |
| |
| } // namespace JSC |
| |
| #endif // Operands_h |
| |