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