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