initial import
[vuplus_webkit] / Source / JavaScriptCore / 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 SlotVisitor;
34
35     class MarkedArgumentBuffer {
36         WTF_MAKE_NONCOPYABLE(MarkedArgumentBuffer);
37     private:
38         static const unsigned inlineCapacity = 8;
39         typedef Vector<Register, inlineCapacity> VectorType;
40         typedef HashSet<MarkedArgumentBuffer*> ListSet;
41
42     public:
43         typedef VectorType::iterator iterator;
44         typedef VectorType::const_iterator const_iterator;
45
46         // Constructor for a read-write list, to which you may append values.
47         // FIXME: Remove all clients of this API, then remove this API.
48         MarkedArgumentBuffer()
49             : m_isUsingInlineBuffer(true)
50             , m_markSet(0)
51 #ifndef NDEBUG
52             , m_isReadOnly(false)
53 #endif
54         {
55             m_buffer = m_vector.data();
56             m_size = 0;
57         }
58
59         // Constructor for a read-only list whose data has already been allocated elsewhere.
60         MarkedArgumentBuffer(Register* buffer, size_t size)
61             : m_buffer(buffer)
62             , m_size(size)
63             , m_isUsingInlineBuffer(true)
64             , m_markSet(0)
65 #ifndef NDEBUG
66             , m_isReadOnly(true)
67 #endif
68         {
69         }
70
71         void initialize(WriteBarrier<Unknown>* buffer, size_t size)
72         {
73             ASSERT(!m_markSet);
74             ASSERT(isEmpty());
75
76             m_buffer = reinterpret_cast<Register*>(buffer);
77             m_size = size;
78 #ifndef NDEBUG
79             m_isReadOnly = true;
80 #endif
81         }
82
83         ~MarkedArgumentBuffer()
84         {
85             if (m_markSet)
86                 m_markSet->remove(this);
87         }
88
89         size_t size() const { return m_size; }
90         bool isEmpty() const { return !m_size; }
91
92         JSValue at(size_t i) const
93         {
94             if (i < m_size)
95                 return m_buffer[i].jsValue();
96             return jsUndefined();
97         }
98
99         void clear()
100         {
101             m_vector.clear();
102             m_buffer = 0;
103             m_size = 0;
104         }
105
106         void append(JSValue v)
107         {
108             ASSERT(!m_isReadOnly);
109
110             if (m_isUsingInlineBuffer && m_size < inlineCapacity) {
111                 m_vector.uncheckedAppend(v);
112                 ++m_size;
113             } else {
114                 // Putting this case all in one function measurably improves
115                 // the performance of the fast "just append to inline buffer" case.
116                 slowAppend(v);
117                 ++m_size;
118                 m_isUsingInlineBuffer = false;
119             }
120         }
121
122         void removeLast()
123         { 
124             ASSERT(m_size);
125             m_size--;
126             m_vector.removeLast();
127         }
128
129         JSValue last() 
130         {
131             ASSERT(m_size);
132             return m_buffer[m_size - 1].jsValue();
133         }
134         
135         iterator begin() { return m_buffer; }
136         iterator end() { return m_buffer + m_size; }
137
138         const_iterator begin() const { return m_buffer; }
139         const_iterator end() const { return m_buffer + m_size; }
140
141         static void markLists(HeapRootVisitor&, ListSet&);
142
143     private:
144         void slowAppend(JSValue);
145         
146         Register* m_buffer;
147         size_t m_size;
148         bool m_isUsingInlineBuffer;
149
150         VectorType m_vector;
151         ListSet* m_markSet;
152 #ifndef NDEBUG
153         bool m_isReadOnly;
154 #endif
155
156     private:
157         // Prohibits new / delete, which would break GC.
158         friend class JSGlobalData;
159         
160         void* operator new(size_t size)
161         {
162             return fastMalloc(size);
163         }
164         void operator delete(void* p)
165         {
166             fastFree(p);
167         }
168
169         void* operator new[](size_t);
170         void operator delete[](void*);
171
172         void* operator new(size_t, void*);
173         void operator delete(void*, size_t);
174     };
175
176     class ArgList {
177         friend class JIT;
178     public:
179         typedef JSValue* iterator;
180         typedef const JSValue* const_iterator;
181
182         ArgList()
183             : m_args(0)
184             , m_argCount(0)
185         {
186         }
187         
188         ArgList(ExecState* exec)
189             : m_args(reinterpret_cast<JSValue*>(&exec[exec->hostThisRegister() + 1]))
190             , m_argCount(exec->argumentCount())
191         {
192         }
193         
194         ArgList(JSValue* args, unsigned argCount)
195             : m_args(args)
196             , m_argCount(argCount)
197         {
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