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