/*
- * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
#include "CallFrame.h"
#include "JSObject.h"
-#include "ScopeChain.h"
+#include "VirtualRegister.h"
+
+#include <wtf/PrintStream.h>
#include <wtf/Vector.h>
namespace JSC {
-// argument 0 is 'this'.
-inline bool operandIsArgument(int operand) { return operand < 0; }
-inline int operandToArgument(int operand) { return -operand + CallFrame::thisArgumentOffset(); }
-inline int argumentToOperand(int argument) { return -argument + CallFrame::thisArgumentOffset(); }
-
template<typename T> struct OperandValueTraits;
template<typename T>
struct OperandValueTraits {
static T defaultValue() { return T(); }
- static void dump(const T& value, FILE* out) { value.dump(out); }
+ static bool isEmptyForDump(const T& value) { return !value; }
};
-template<typename T, typename Traits = OperandValueTraits<T> >
+enum OperandKind { ArgumentOperand, LocalOperand };
+
+enum OperandsLikeTag { OperandsLike };
+
+template<typename T, typename Traits = OperandValueTraits<T>>
class Operands {
public:
Operands() { }
m_locals.fill(Traits::defaultValue(), 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& 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)
{
if (size <= m_locals.size())
T& operand(int operand)
{
if (operandIsArgument(operand)) {
- int argument = operandToArgument(operand);
+ int argument = VirtualRegister(operand).toArgument();
return m_arguments[argument];
}
-
- return m_locals[operand];
+
+ 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)); }
+ 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 = operandToArgument(operand);
+ int argument = VirtualRegister(operand).toArgument();
m_arguments[argument] = value;
return;
}
- setLocal(operand, value);
+ setLocal(VirtualRegister(operand).toLocal(), value);
}
- void clear()
+ 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();
+ }
+ 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] = Traits::defaultValue();
+ m_arguments[i] = value;
for (size_t i = 0; i < m_locals.size(); ++i)
- m_locals[i] = Traits::defaultValue();
+ 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
+ {
+ dumpInContext(out, 0);
}
private:
Vector<T, 16> m_locals;
};
-template<typename T, typename Traits>
-void dumpOperands(Operands<T, Traits>& operands, FILE* out)
-{
- for (size_t argument = 0; argument < operands.numberOfArguments(); ++argument) {
- if (argument)
- fprintf(out, " ");
- Traits::dump(operands.argument(argument), out);
- }
- fprintf(out, " : ");
- for (size_t local = 0; local < operands.numberOfLocals(); ++local) {
- if (local)
- fprintf(out, " ");
- Traits::dump(operands.local(local), out);
- }
-}
-
} // namespace JSC
#endif // Operands_h