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