| 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(value: 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(val: 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 | 
| 239 |  |