]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/ArgList.h
ef7809fe8fc5682162e22cfb3e213aa86c230033
[apple/javascriptcore.git] / runtime / ArgList.h
1 /*
2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2007, 2008, 2009 Apple Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 */
21
22 #ifndef ArgList_h
23 #define ArgList_h
24
25 #include "CallFrame.h"
26 #include "Register.h"
27 #include "WriteBarrier.h"
28 #include <wtf/HashSet.h>
29 #include <wtf/Vector.h>
30
31 namespace JSC {
32
33 class MarkStack;
34 typedef MarkStack SlotVisitor;
35
36 class MarkedArgumentBuffer {
37 WTF_MAKE_NONCOPYABLE(MarkedArgumentBuffer);
38 private:
39 static const unsigned inlineCapacity = 8;
40 typedef Vector<Register, inlineCapacity> VectorType;
41 typedef HashSet<MarkedArgumentBuffer*> ListSet;
42
43 public:
44 typedef VectorType::iterator iterator;
45 typedef VectorType::const_iterator const_iterator;
46
47 // Constructor for a read-write list, to which you may append values.
48 // FIXME: Remove all clients of this API, then remove this API.
49 MarkedArgumentBuffer()
50 : m_isUsingInlineBuffer(true)
51 , m_markSet(0)
52 #ifndef NDEBUG
53 , m_isReadOnly(false)
54 #endif
55 {
56 m_buffer = m_vector.data();
57 m_size = 0;
58 }
59
60 // Constructor for a read-only list whose data has already been allocated elsewhere.
61 MarkedArgumentBuffer(Register* buffer, size_t size)
62 : m_buffer(buffer)
63 , m_size(size)
64 , m_isUsingInlineBuffer(true)
65 , m_markSet(0)
66 #ifndef NDEBUG
67 , m_isReadOnly(true)
68 #endif
69 {
70 }
71
72 void initialize(WriteBarrier<Unknown>* buffer, size_t size)
73 {
74 ASSERT(!m_markSet);
75 ASSERT(isEmpty());
76
77 m_buffer = reinterpret_cast<Register*>(buffer);
78 m_size = size;
79 #ifndef NDEBUG
80 m_isReadOnly = true;
81 #endif
82 }
83
84 ~MarkedArgumentBuffer()
85 {
86 if (m_markSet)
87 m_markSet->remove(this);
88 }
89
90 size_t size() const { return m_size; }
91 bool isEmpty() const { return !m_size; }
92
93 JSValue at(size_t i) const
94 {
95 if (i < m_size)
96 return m_buffer[i].jsValue();
97 return jsUndefined();
98 }
99
100 void clear()
101 {
102 m_vector.clear();
103 m_buffer = 0;
104 m_size = 0;
105 }
106
107 void append(JSValue v)
108 {
109 ASSERT(!m_isReadOnly);
110
111 #if ENABLE(JSC_ZOMBIES)
112 ASSERT(!v.isZombie());
113 #endif
114
115 if (m_isUsingInlineBuffer && m_size < inlineCapacity) {
116 m_vector.uncheckedAppend(v);
117 ++m_size;
118 } else {
119 // Putting this case all in one function measurably improves
120 // the performance of the fast "just append to inline buffer" case.
121 slowAppend(v);
122 ++m_size;
123 m_isUsingInlineBuffer = false;
124 }
125 }
126
127 void removeLast()
128 {
129 ASSERT(m_size);
130 m_size--;
131 m_vector.removeLast();
132 }
133
134 JSValue last()
135 {
136 ASSERT(m_size);
137 return m_buffer[m_size - 1].jsValue();
138 }
139
140 iterator begin() { return m_buffer; }
141 iterator end() { return m_buffer + m_size; }
142
143 const_iterator begin() const { return m_buffer; }
144 const_iterator end() const { return m_buffer + m_size; }
145
146 static void markLists(HeapRootVisitor&, ListSet&);
147
148 private:
149 void slowAppend(JSValue);
150
151 Register* m_buffer;
152 size_t m_size;
153 bool m_isUsingInlineBuffer;
154
155 VectorType m_vector;
156 ListSet* m_markSet;
157 #ifndef NDEBUG
158 bool m_isReadOnly;
159 #endif
160
161 private:
162 // Prohibits new / delete, which would break GC.
163 friend class JSGlobalData;
164
165 void* operator new(size_t size)
166 {
167 return fastMalloc(size);
168 }
169 void operator delete(void* p)
170 {
171 fastFree(p);
172 }
173
174 void* operator new[](size_t);
175 void operator delete[](void*);
176
177 void* operator new(size_t, void*);
178 void operator delete(void*, size_t);
179 };
180
181 class ArgList {
182 friend class JIT;
183 public:
184 typedef JSValue* iterator;
185 typedef const JSValue* const_iterator;
186
187 ArgList()
188 : m_args(0)
189 , m_argCount(0)
190 {
191 }
192
193 ArgList(ExecState* exec)
194 : m_args(reinterpret_cast<JSValue*>(&exec[exec->hostThisRegister() + 1]))
195 , m_argCount(exec->argumentCount())
196 {
197 }
198
199 ArgList(JSValue* args, unsigned argCount)
200 : m_args(args)
201 , m_argCount(argCount)
202 {
203 #if ENABLE(JSC_ZOMBIES)
204 for (size_t i = 0; i < argCount; i++)
205 ASSERT(!m_args[i].isZombie());
206 #endif
207 }
208
209 ArgList(Register* args, int argCount)
210 : m_args(reinterpret_cast<JSValue*>(args))
211 , m_argCount(argCount)
212 {
213 ASSERT(argCount >= 0);
214 }
215
216 ArgList(const MarkedArgumentBuffer& args)
217 : m_args(reinterpret_cast<JSValue*>(const_cast<Register*>(args.begin())))
218 , m_argCount(args.size())
219 {
220 }
221
222 JSValue at(size_t idx) const
223 {
224 if (idx < m_argCount)
225 return m_args[idx];
226 return jsUndefined();
227 }
228
229 bool isEmpty() const { return !m_argCount; }
230
231 size_t size() const { return m_argCount; }
232
233 iterator begin() { return m_args; }
234 iterator end() { return m_args + m_argCount; }
235
236 const_iterator begin() const { return m_args; }
237 const_iterator end() const { return m_args + m_argCount; }
238
239 void getSlice(int startIndex, ArgList& result) const;
240 private:
241 JSValue* m_args;
242 size_t m_argCount;
243 };
244
245 } // namespace JSC
246
247 #endif // ArgList_h