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