JavaScriptCore:
[WebKit-https.git] / JavaScriptCore / kjs / ArgList.h
1 /*
2  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2003, 2007, 2008 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 "JSImmediate.h"
26 #include "Register.h"
27
28 #include <wtf/HashSet.h>
29 #include <wtf/Noncopyable.h>
30 #include <wtf/Vector.h>
31
32 namespace KJS {
33
34     class JSValue;
35     
36     class ArgList : Noncopyable {
37     private:
38         static const unsigned inlineCapacity = 8;
39         typedef Vector<Register, inlineCapacity> VectorType;
40         typedef HashSet<ArgList*> 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         ArgList()
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.
59         ArgList(Register* buffer, size_t size)
60             : m_buffer(buffer)
61             , m_size(size)
62             , m_markSet(0)
63 #ifndef NDEBUG
64             , m_isReadOnly(true)
65 #endif
66         {
67         }
68
69         ~ArgList()
70         {
71             if (m_markSet)
72                 m_markSet->remove(this);
73         }
74
75         size_t size() const { return m_size; }
76         bool isEmpty() const { return !m_size; }
77
78         JSValue* at(ExecState* exec, size_t i) const
79         {
80             if (i < m_size)
81                 return m_buffer[i].jsValue(exec);
82             return jsUndefined();
83         }
84
85         void clear()
86         {
87             m_vector.clear();
88             m_buffer = 0;
89             m_size = 0;
90         }
91
92         void append(JSValue* v)
93         {
94             ASSERT(!m_isReadOnly);
95             
96             if (m_size < inlineCapacity) {
97                 m_vector.uncheckedAppend(v);
98                 ++m_size;
99             } else {
100                 // Putting this case all in one function measurably improves
101                 // the performance of the fast "just append to inline buffer" case.
102                 slowAppend(v);
103                 ++m_size;
104             }
105         }
106
107         void getSlice(int startIndex, ArgList& result) const;
108
109         iterator begin() { return m_buffer; }
110         iterator end() { return m_buffer + m_size; }
111
112         const_iterator begin() const { return m_buffer; }
113         const_iterator end() const { return m_buffer + m_size; }
114
115         static void markLists(ListSet&);
116
117     private:
118         void slowAppend(JSValue*);
119         
120         Register* m_buffer;
121         size_t m_size;
122
123         VectorType m_vector;
124         ListSet* m_markSet;
125 #ifndef NDEBUG
126         bool m_isReadOnly;
127 #endif
128
129     private:
130         // Prohibits new / delete, which would break GC.
131         friend class JSGlobalData;
132         
133         void* ArgList::operator new(size_t size)
134         {
135             return fastMalloc(size);
136         }
137         void operator delete(void*);
138
139         void* operator new[](size_t);
140         void operator delete[](void*);
141
142         void* operator new(size_t, void*);
143         void operator delete(void*, size_t);
144     };
145
146 } // namespace KJS
147
148 #endif // ArgList_h