Merge remote-tracking branch 'redux/master' into sh4-pool
[tamarin-stm.git] / core / VectorClass-impl.h
blobe4a9e84b610ad00ff615aed6d853e069941c418a
1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is [Open Source Virtual Machine.].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2004-2006
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Adobe AS3 Team
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 #ifndef __avmplus_VectorClass_impl__
42 #define __avmplus_VectorClass_impl__
44 namespace avmplus
46 // ----------------------------
48 Atom TypedVectorClassBase::call(int argc, Atom* argv)
50 Toplevel* toplevel = this->toplevel();
51 AvmCore* core = toplevel->core();
53 if (argc != 1)
54 toplevel->throwArgumentError(kCoerceArgumentCountError, core->toErrorString(argc));
56 Traits* itraits = ivtable()->traits;
57 if (AvmCore::istype(argv[1], itraits))
58 return argv[1];
60 if (!AvmCore::isObject(argv[1]))
61 toplevel->throwTypeError(kCheckTypeFailedError, core->atomToErrorString(argv[1]), core->toErrorString(itraits));
63 ScriptObject* so_args = AvmCore::atomToScriptObject(argv[1]);
64 uint32_t len = so_args->getLengthProperty();
65 return createAndInitVectorFromObject(so_args, len);
68 void TypedVectorClassBase::_forEach(Atom thisAtom, ScriptObject* callback, Atom thisObject)
70 return ArrayClass::generic_forEach(toplevel(), thisAtom, callback, thisObject);
73 bool TypedVectorClassBase::_every(Atom thisAtom, ScriptObject* callback, Atom thisObject)
75 return ArrayClass::generic_every(toplevel(), thisAtom, callback, thisObject);
78 bool TypedVectorClassBase::_some(Atom thisAtom, ScriptObject* callback, Atom thisObject)
80 return ArrayClass::generic_some(toplevel(), thisAtom, callback, thisObject);
83 Atom TypedVectorClassBase::_sort(Atom thisAtom, ArrayObject* args)
85 return ArrayClass::generic_sort(toplevel(), thisAtom, args);
88 // ----------------------------
90 template<class OBJ>
91 TypedVectorClass<OBJ>::TypedVectorClass(VTable* vtable)
92 : TypedVectorClassBase(vtable)
94 setPrototypePtr(toplevel()->objectClass->construct());
97 template<class OBJ>
98 OBJ* TypedVectorClass<OBJ>::newVector(uint32_t length, bool fixed)
100 OBJ* v = (OBJ*)OBJ::create(gc(), ivtable(), prototypePtr());
101 v->m_vecClass = this;
102 if (length > 0)
103 v->set_length(length);
104 v->m_fixed = fixed;
105 return v;
108 template<class OBJ>
109 Atom TypedVectorClass<OBJ>::createAndInitVectorFromObject(ScriptObject* so_args, uint32_t len)
111 OBJ* v = newVector();
112 v->_spliceHelper_so(0, len, 0, so_args, 0);
113 return v->atom();
116 template<class OBJ>
117 Atom TypedVectorClass<OBJ>::constructImpl(int argc, Atom* argv)
119 uint32_t len = 0;
120 bool fixed = false;
121 if (argc > 0)
123 len = AvmCore::toUInt32(argv[1]);
124 if (argc > 1)
126 fixed = AvmCore::boolean(argv[2]) != 0;
127 if (argc > 2)
129 vtable->init->argcError(argc);
133 OBJ* v = newVector(len, fixed);
134 return v->atom();
137 // ----------------------------
139 VectorBaseObject::VectorBaseObject(VTable* ivtable, ScriptObject* delegate)
140 : ScriptObject(ivtable, delegate)
141 , m_vecClass(NULL)
142 , m_fixed(false)
146 VectorBaseObject* VectorBaseObject::_newVector()
148 AvmAssert(m_vecClass != NULL);
149 Atom args[1] = { nullObjectAtom };
150 return (VectorBaseObject*)AvmCore::atomToScriptObject(m_vecClass->construct(0, args));
153 void FASTCALL VectorBaseObject::throwFixedError() const
155 toplevel()->throwRangeError(kVectorFixedError);
158 Atom VectorBaseObject::_mapImpl(ScriptObject* callback, Atom thisObject, VectorBaseObject* r, uint32_t len)
160 AvmCore* core = this->core();
161 if (callback)
163 ScriptObject* d = this;
164 for (uint32_t i = 0; i < len; i++)
166 // If thisObject is null, the call function will substitute the global object
167 // args are modified in place by callee
168 Atom args[4] = {
169 thisObject,
170 d->getUintProperty(i), // element
171 core->uintToAtom(i), // index
172 this->atom()
174 Atom result = callback->call(3, args);
175 r->setUintProperty(i, result);
178 return r->atom();
181 Atom VectorBaseObject::_filterImpl(ScriptObject* callback, Atom thisObject, VectorBaseObject* r, uint32_t len)
183 AvmCore* core = this->core();
184 if (callback)
186 ScriptObject* d = this;
187 for (uint32_t i = 0, k = 0; i < len; i++)
189 // If thisObject is null, the call function will substitute the global object
190 // args are modified in place by callee
191 Atom element = d->getUintProperty(i);
192 Atom args[4] = {
193 thisObject,
194 element,
195 core->uintToAtom(i), // index
196 this->atom()
198 Atom result = callback->call(3, args);
199 if (result == trueAtom)
200 r->setUintProperty(k++, element);
203 return r->atom();
206 // ----------------------------
208 template<class TLIST>
209 TypedVectorObject<TLIST>::TypedVectorObject(VTable* ivtable, ScriptObject* delegate)
210 : VectorBaseObject(ivtable, delegate)
211 , m_list(ivtable->gc(), 0)
215 template<class TLIST>
216 bool TypedVectorObject<TLIST>::hasAtomProperty(Atom name) const
218 uint32_t index;
219 VectorIndexStatus status = getVectorIndex(name, index);
220 if (status == kValidNumber)
222 return index < m_list.length();
224 else if (status == kInvalidNumber)
226 return false;
228 else // status == kNotNumber
230 return ScriptObject::hasAtomProperty(name);
234 template<class TLIST>
235 void TypedVectorObject<TLIST>::setAtomProperty(Atom name, Atom value)
237 uint32_t index;
238 VectorIndexStatus status = getVectorIndex(name, index);
239 if (status == kValidNumber)
241 setUintProperty(index, value);
243 else
245 toplevel()->throwReferenceError(kWriteSealedError, core()->string(name), traits());
249 template<class TLIST>
250 Atom TypedVectorObject<TLIST>::getAtomProperty(Atom name) const
252 uint32_t index;
253 VectorIndexStatus status = getVectorIndex(name, index);
254 if (status == kValidNumber)
256 return getUintProperty(index);
258 else if (status == kInvalidNumber)
260 // Not a valid indexed name - has a decimal part
261 toplevel()->throwReferenceError(kReadSealedError, core()->string(name), traits());
262 return undefinedAtom; // not reached
264 else // status == kNotNumber
266 // Check the prototype chain - that will throw if there is no match
267 return getAtomPropertyFromProtoChain(name, getDelegate(), traits());
271 template<class TLIST>
272 /*virtual*/ uint32_t TypedVectorObject<TLIST>::getLength() const
274 return get_length();
277 template<class TLIST>
278 /*virtual*/ void TypedVectorObject<TLIST>::setLength(uint32_t length)
280 set_length(length);
283 template<class TLIST>
284 void TypedVectorObject<TLIST>::set_length(uint32_t newLength)
286 checkFixed();
287 // this is what the old code did, so we'll do it too: set the capacity explicitly if we grow
288 if (newLength > m_list.capacity())
290 m_list.set_capacity(newLength);
292 m_list.set_length(newLength);
295 template<class TLIST>
296 Atom TypedVectorObject<TLIST>::nextName(int index)
298 AvmAssert(index > 0);
299 if (uint32_t(index) <= m_list.length())
301 return core()->intToAtom(index-1);
303 else
305 return nullStringAtom;
309 template<class TLIST>
310 Atom TypedVectorObject<TLIST>::nextValue(int index)
312 AvmAssert(index > 0);
313 if (uint32_t(index) <= m_list.length())
315 return getUintProperty(index-1);
317 else
319 return undefinedAtom;
323 template<class TLIST>
324 int TypedVectorObject<TLIST>::nextNameIndex(int index)
326 if (uint32_t(index) < m_list.length())
328 return index + 1;
330 else
332 return 0;
336 template<class TLIST>
337 Atom TypedVectorObject<TLIST>::_map(ScriptObject* callback, Atom thisObject)
339 TypedVectorObject<TLIST>* r = (TypedVectorObject<TLIST>*)_newVector();
340 uint32_t const len = m_list.length();
341 r->set_length(len);
342 return _mapImpl(callback, thisObject, r, len);
345 template<class TLIST>
346 Atom TypedVectorObject<TLIST>::_filter(ScriptObject* callback, Atom thisObject)
348 TypedVectorObject<TLIST>* r = (TypedVectorObject<TLIST>*)_newVector();
349 uint32_t const len = m_list.length();
350 return _filterImpl(callback, thisObject, r, len);
353 template<class TLIST>
354 void TypedVectorObject<TLIST>::_spliceHelper_so(uint32_t insertPoint, uint32_t insertCount, uint32_t deleteCount, ScriptObject* so_args, uint32_t offset)
356 AvmAssert(!AvmCore::istype(so_args->atom(), vtable->traits));
358 // NB: so_args could be any kind of object, but in practice,
359 // it's almost always an ArrayObject; it might be profitable
360 // to sniff for that case and optimize appropriately.
362 // passing NULL for args inserts the proper space, but leaves the inserted entries empty
363 m_list.splice(insertPoint, insertCount, deleteCount, NULL);
364 for (uint32_t i = 0; i < insertCount; i++)
366 typename TLIST::OPAQUE_TYPE value;
367 atomToValue(so_args->getUintProperty(i+offset), value);
368 m_list.set(insertPoint+i, (typename TLIST::TYPE)value);
372 template<class TLIST>
373 void TypedVectorObject<TLIST>::_spliceHelper(uint32_t insertPoint, uint32_t insertCount, uint32_t deleteCount, Atom args, uint32_t offset)
375 if (AvmCore::istype(args, vtable->traits))
377 TypedVectorObject<TLIST>* vec_args = (TypedVectorObject<TLIST>*)AvmCore::atomToScriptObject(args);
378 m_list.splice(insertPoint, insertCount, deleteCount, vec_args->m_list, offset);
380 else if (AvmCore::isObject(args))
382 ScriptObject* so_args = AvmCore::atomToScriptObject(args);
383 _spliceHelper_so(insertPoint, insertCount, deleteCount, so_args, offset);
385 else
387 AvmAssert(insertCount == 0);
388 m_list.splice(insertPoint, 0, deleteCount, NULL);
392 template<class TLIST>
393 void TypedVectorObject<TLIST>::_splice(uint32_t insertPoint, uint32_t insertCount, uint32_t deleteCount, const Atom* argv)
395 // passing NULL for args inserts the proper space, but leaves the inserted entries empty
396 m_list.splice(insertPoint, insertCount, deleteCount, NULL);
397 for (uint32_t i = 0; i < insertCount; i++)
399 typename TLIST::OPAQUE_TYPE value;
400 atomToValue(argv[i], value);
401 m_list.set(insertPoint+i, (typename TLIST::TYPE)value);
405 template<class TLIST>
406 uint32_t TypedVectorObject<TLIST>::AS3_push(Atom* argv, int argc)
408 checkFixed();
409 _splice(m_list.length(), argc, 0, argv);
410 return m_list.length();
413 template<class TLIST>
414 typename TLIST::TYPE TypedVectorObject<TLIST>::AS3_pop()
416 checkFixed();
417 return m_list.isEmpty() ?
418 (typename TLIST::TYPE)TypedVectorConstants<typename TLIST::OPAQUE_TYPE>::undefinedValue() :
419 m_list.removeLast();
422 template<class TLIST>
423 typename TLIST::TYPE TypedVectorObject<TLIST>::AS3_shift()
425 checkFixed();
426 return m_list.isEmpty() ?
427 (typename TLIST::TYPE)TypedVectorConstants<typename TLIST::OPAQUE_TYPE>::undefinedValue() :
428 m_list.removeFirst();
431 template<class TLIST>
432 uint32_t TypedVectorObject<TLIST>::AS3_unshift(Atom* argv, int argc)
434 checkFixed();
435 _splice(0, argc, 0, argv);
436 return m_list.length();
439 template<class TLIST>
440 typename TLIST::TYPE TypedVectorObject<TLIST>::_getNativeIntProperty(int32_t index_i) const
442 // Implicitly convert negative values to large uints, which will always be > length
443 uint32_t const index = checkReadIndex_u(uint32_t(index_i));
444 return m_list.get(index);
447 template<class TLIST>
448 void TypedVectorObject<TLIST>::_setNativeIntProperty(int32_t index_i, typename TLIST::TYPE value)
450 // Implicitly convert negative values to large uints, which will always be > length
451 uint32_t const index = checkWriteIndex_u(uint32_t(index_i));
452 m_list.set(index, value);
455 template<class TLIST>
456 typename TLIST::TYPE TypedVectorObject<TLIST>::_getNativeUintProperty(uint32_t index) const
458 index = checkReadIndex_u(index);
459 return m_list.get(index);
462 template<class TLIST>
463 void TypedVectorObject<TLIST>::_setNativeUintProperty(uint32_t index, typename TLIST::TYPE value)
465 index = checkWriteIndex_u(index);
466 m_list.set(index, value);
469 template<class TLIST>
470 bool TypedVectorObject<TLIST>::_hasUintProperty(uint32_t index) const
472 return (index < m_list.length());
475 template<class TLIST>
476 Atom TypedVectorObject<TLIST>::_getUintProperty(uint32_t index) const
478 index = checkReadIndex_u(index);
479 return valueToAtom((typename TLIST::OPAQUE_TYPE)m_list.get(index));
482 template<class TLIST>
483 void TypedVectorObject<TLIST>::_setUintProperty(uint32_t index, Atom value)
485 index = checkWriteIndex_u(index);
486 typename TLIST::OPAQUE_TYPE tmp;
487 atomToValue(value, tmp);
488 m_list.set(index, (typename TLIST::TYPE)tmp);
491 template<class TLIST>
492 Atom TypedVectorObject<TLIST>::_getIntProperty(int32_t index_i) const
494 // Implicitly convert negative values to large uints, which will always be > length
495 uint32_t const index = uint32_t(index_i);
496 return _getUintProperty(index);
499 template<class TLIST>
500 void TypedVectorObject<TLIST>::_setIntProperty(int32_t index_i, Atom value)
502 // Implicitly convert negative values to large uints, which will always be > length
503 uint32_t const index = uint32_t(index_i);
504 _setUintProperty(uint32_t(index), value);
507 template<class TLIST>
508 void FASTCALL TypedVectorObject<TLIST>::throwRangeError(uint32_t index) const
510 toplevel()->throwRangeError(kOutOfRangeError, core()->uintToString(index), core()->uintToString(m_list.length()));
513 // ----------------------------
514 // ----------------------------
515 // ----------------------------
519 #endif /* __avmplus_VectorClass_impl__ */