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