e7b3e241fb4f13beb1b566ade73932d869df6d28
[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 template<typename T, typename Traits = OperandValueTraits<T> >
52 class Operands {
53 public:
54     Operands() { }
55     
56     explicit Operands(size_t numArguments, size_t numLocals)
57     {
58         m_arguments.fill(Traits::defaultValue(), numArguments);
59         m_locals.fill(Traits::defaultValue(), numLocals);
60     }
61     
62     size_t numberOfArguments() const { return m_arguments.size(); }
63     size_t numberOfLocals() const { return m_locals.size(); }
64     
65     T& argument(size_t idx) { return m_arguments[idx]; }
66     const T& argument(size_t idx) const { return m_arguments[idx]; }
67     
68     T& local(size_t idx) { return m_locals[idx]; }
69     const T& local(size_t idx) const { return m_locals[idx]; }
70     
71     template<OperandKind operandKind>
72     size_t sizeFor() const
73     {
74         if (operandKind == ArgumentOperand)
75             return numberOfArguments();
76         return numberOfLocals();
77     }
78     template<OperandKind operandKind>
79     T& atFor(size_t idx)
80     {
81         if (operandKind == ArgumentOperand)
82             return argument(idx);
83         return local(idx);
84     }
85     template<OperandKind operandKind>
86     const T& atFor(size_t idx) const
87     {
88         if (operandKind == ArgumentOperand)
89             return argument(idx);
90         return local(idx);
91     }
92     
93     void ensureLocals(size_t size)
94     {
95         if (size <= m_locals.size())
96             return;
97
98         size_t oldSize = m_locals.size();
99         m_locals.resize(size);
100         for (size_t i = oldSize; i < m_locals.size(); ++i)
101             m_locals[i] = Traits::defaultValue();
102     }
103     
104     void setLocal(size_t idx, const T& value)
105     {
106         ensureLocals(idx + 1);
107         
108         m_locals[idx] = value;
109     }
110     
111     T getLocal(size_t idx)
112     {
113         if (idx >= m_locals.size())
114             return Traits::defaultValue();
115         return m_locals[idx];
116     }
117     
118     void setArgumentFirstTime(size_t idx, const T& value)
119     {
120         ASSERT(m_arguments[idx] == Traits::defaultValue());
121         argument(idx) = value;
122     }
123     
124     void setLocalFirstTime(size_t idx, const T& value)
125     {
126         ASSERT(idx >= m_locals.size() || m_locals[idx] == Traits::defaultValue());
127         setLocal(idx, value);
128     }
129     
130     T& operand(int operand)
131     {
132         if (operandIsArgument(operand)) {
133             int argument = operandToArgument(operand);
134             return m_arguments[argument];
135         }
136         
137         return m_locals[operand];
138     }
139     
140     const T& operand(int operand) const { return const_cast<const T&>(const_cast<Operands*>(this)->operand(operand)); }
141     
142     bool hasOperand(int operand) const
143     {
144         if (operandIsArgument(operand))
145             return true;
146         return static_cast<size_t>(operand) < numberOfLocals();
147     }
148     
149     void setOperand(int operand, const T& value)
150     {
151         if (operandIsArgument(operand)) {
152             int argument = operandToArgument(operand);
153             m_arguments[argument] = value;
154             return;
155         }
156         
157         setLocal(operand, value);
158     }
159     
160     size_t size() const { return numberOfArguments() + numberOfLocals(); }
161     const T& at(size_t index) const
162     {
163         if (index < numberOfArguments())
164             return m_arguments[index];
165         return m_locals[index - numberOfArguments()];
166     }
167     T& at(size_t index)
168     {
169         if (index < numberOfArguments())
170             return m_arguments[index];
171         return m_locals[index - numberOfArguments()];
172     }
173     const T& operator[](size_t index) const { return at(index); }
174     T& operator[](size_t index) { return at(index); }
175
176     bool isArgument(size_t index) const { return index < numberOfArguments(); }
177     bool isVariable(size_t index) const { return !isArgument(index); }
178     int argumentForIndex(size_t index) const
179     {
180         return index;
181     }
182     int variableForIndex(size_t index) const
183     {
184         return index - m_arguments.size();
185     }
186     int operandForIndex(size_t index) const
187     {
188         if (index < numberOfArguments())
189             return argumentToOperand(index);
190         return index - numberOfArguments();
191     }
192     
193     void setOperandFirstTime(int operand, const T& value)
194     {
195         if (operandIsArgument(operand)) {
196             setArgumentFirstTime(operandToArgument(operand), value);
197             return;
198         }
199         
200         setLocalFirstTime(operand, value);
201     }
202     
203     void clear()
204     {
205         for (size_t i = 0; i < m_arguments.size(); ++i)
206             m_arguments[i] = Traits::defaultValue();
207         for (size_t i = 0; i < m_locals.size(); ++i)
208             m_locals[i] = Traits::defaultValue();
209     }
210     
211 private:
212     Vector<T, 8> m_arguments;
213     Vector<T, 16> m_locals;
214 };
215
216 template<typename T, typename Traits>
217 void dumpOperands(const Operands<T, Traits>& operands, PrintStream& out)
218 {
219     for (size_t argument = operands.numberOfArguments(); argument--;) {
220         if (argument != operands.numberOfArguments() - 1)
221             out.printf(" ");
222         out.print("arg", argument, ":");
223         Traits::dump(operands.argument(argument), out);
224     }
225     out.printf(" : ");
226     for (size_t local = 0; local < operands.numberOfLocals(); ++local) {
227         if (local)
228             out.printf(" ");
229         out.print("r", local, ":");
230         Traits::dump(operands.local(local), out);
231     }
232 }
233
234 } // namespace JSC
235
236 #endif // Operands_h
237