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