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