]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/ArgList.h
JavaScriptCore-721.26.tar.gz
[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 "Register.h"
26 #include <wtf/HashSet.h>
27 #include <wtf/Noncopyable.h>
28 #include <wtf/Vector.h>
29
30 namespace JSC {
31
32 class MarkStack;
33
34 class MarkedArgumentBuffer : public Noncopyable {
35 private:
36 static const unsigned inlineCapacity = 8;
37 typedef Vector<Register, inlineCapacity> VectorType;
38 typedef HashSet<MarkedArgumentBuffer*> ListSet;
39
40 public:
41 typedef VectorType::iterator iterator;
42 typedef VectorType::const_iterator const_iterator;
43
44 // Constructor for a read-write list, to which you may append values.
45 // FIXME: Remove all clients of this API, then remove this API.
46 MarkedArgumentBuffer()
47 : m_isUsingInlineBuffer(true)
48 , m_markSet(0)
49 #ifndef NDEBUG
50 , m_isReadOnly(false)
51 #endif
52 {
53 m_buffer = m_vector.data();
54 m_size = 0;
55 }
56
57 // Constructor for a read-only list whose data has already been allocated elsewhere.
58 MarkedArgumentBuffer(Register* buffer, size_t size)
59 : m_buffer(buffer)
60 , m_size(size)
61 , m_isUsingInlineBuffer(true)
62 , m_markSet(0)
63 #ifndef NDEBUG
64 , m_isReadOnly(true)
65 #endif
66 {
67 }
68
69 void initialize(Register* buffer, size_t size)
70 {
71 ASSERT(!m_markSet);
72 ASSERT(isEmpty());
73
74 m_buffer = buffer;
75 m_size = size;
76 #ifndef NDEBUG
77 m_isReadOnly = true;
78 #endif
79 }
80
81 ~MarkedArgumentBuffer()
82 {
83 if (m_markSet)
84 m_markSet->remove(this);
85 }
86
87 size_t size() const { return m_size; }
88 bool isEmpty() const { return !m_size; }
89
90 JSValue at(size_t i) const
91 {
92 if (i < m_size)
93 return m_buffer[i].jsValue();
94 return jsUndefined();
95 }
96
97 void clear()
98 {
99 m_vector.clear();
100 m_buffer = 0;
101 m_size = 0;
102 }
103
104 void append(JSValue v)
105 {
106 ASSERT(!m_isReadOnly);
107
108 #if ENABLE(JSC_ZOMBIES)
109 ASSERT(!v.isZombie());
110 #endif
111
112 if (m_isUsingInlineBuffer && m_size < inlineCapacity) {
113 m_vector.uncheckedAppend(v);
114 ++m_size;
115 } else {
116 // Putting this case all in one function measurably improves
117 // the performance of the fast "just append to inline buffer" case.
118 slowAppend(v);
119 ++m_size;
120 m_isUsingInlineBuffer = false;
121 }
122 }
123
124 void removeLast()
125 {
126 ASSERT(m_size);
127 m_size--;
128 m_vector.removeLast();
129 }
130
131 JSValue last()
132 {
133 ASSERT(m_size);
134 return m_buffer[m_size - 1].jsValue();
135 }
136
137 iterator begin() { return m_buffer; }
138 iterator end() { return m_buffer + m_size; }
139
140 const_iterator begin() const { return m_buffer; }
141 const_iterator end() const { return m_buffer + m_size; }
142
143 static void markLists(MarkStack&, ListSet&);
144
145 private:
146 void slowAppend(JSValue);
147
148 Register* m_buffer;
149 size_t m_size;
150 bool m_isUsingInlineBuffer;
151
152 VectorType m_vector;
153 ListSet* m_markSet;
154 #ifndef NDEBUG
155 bool m_isReadOnly;
156 #endif
157
158 private:
159 // Prohibits new / delete, which would break GC.
160 friend class JSGlobalData;
161
162 void* operator new(size_t size)
163 {
164 return fastMalloc(size);
165 }
166 void operator delete(void* p)
167 {
168 fastFree(p);
169 }
170
171 void* operator new[](size_t);
172 void operator delete[](void*);
173
174 void* operator new(size_t, void*);
175 void operator delete(void*, size_t);
176 };
177
178 class ArgList {
179 friend class JIT;
180 public:
181 typedef JSValue* iterator;
182 typedef const JSValue* const_iterator;
183
184 ArgList()
185 : m_args(0)
186 , m_argCount(0)
187 {
188 }
189
190 ArgList(JSValue* args, unsigned argCount)
191 : m_args(args)
192 , m_argCount(argCount)
193 {
194 #if ENABLE(JSC_ZOMBIES)
195 for (size_t i = 0; i < argCount; i++)
196 ASSERT(!m_args[i].isZombie());
197 #endif
198 }
199
200 ArgList(Register* args, int argCount)
201 : m_args(reinterpret_cast<JSValue*>(args))
202 , m_argCount(argCount)
203 {
204 ASSERT(argCount >= 0);
205 }
206
207 ArgList(const MarkedArgumentBuffer& args)
208 : m_args(reinterpret_cast<JSValue*>(const_cast<Register*>(args.begin())))
209 , m_argCount(args.size())
210 {
211 }
212
213 JSValue at(size_t idx) const
214 {
215 if (idx < m_argCount)
216 return m_args[idx];
217 return jsUndefined();
218 }
219
220 bool isEmpty() const { return !m_argCount; }
221
222 size_t size() const { return m_argCount; }
223
224 iterator begin() { return m_args; }
225 iterator end() { return m_args + m_argCount; }
226
227 const_iterator begin() const { return m_args; }
228 const_iterator end() const { return m_args + m_argCount; }
229
230 void getSlice(int startIndex, ArgList& result) const;
231 private:
232 JSValue* m_args;
233 size_t m_argCount;
234 };
235
236 } // namespace JSC
237
238 #endif // ArgList_h