Merge remote-tracking branch 'redux/master' into sh4-pool
[tamarin-stm.git] / core / VectorClass.cpp
blob9b43a31b45ecbcfa875821d14ab8fb9b3288f26b
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 ***** */
42 #include "avmplus.h"
44 #include "VectorClass-impl.h"
46 namespace avmplus
48 // Force explicit instantiations for various non-inlined methods;
49 // some compilers don't need this, but some do.
51 template class TypedVectorClass<IntVectorObject>;
52 template class TypedVectorClass<UIntVectorObject>;
53 template class TypedVectorClass<DoubleVectorObject>;
54 template class TypedVectorClass<ObjectVectorObject>;
56 template class TypedVectorObject< DataList<int32_t> >;
57 template class TypedVectorObject< DataList<uint32_t> >;
58 template class TypedVectorObject< DataList<double> >;
59 template class TypedVectorObject< AtomList >;
62 namespace avmplus
64 // ----------------------------
66 // helper method
67 // sets index to the uint32_t value of name, if it can be converted
68 // isNumber is set to true if name was a number (whether it was a uint32_t value or not)
69 VectorBaseObject::VectorIndexStatus VectorBaseObject::getVectorIndex(Atom name, uint32_t& index) const
71 if (AvmCore::getIndexFromAtom(name, &index))
73 return kValidNumber;
75 else if (AvmCore::isString(name))
77 Stringp s = core()->string(name);
78 wchar c = s->charAt(0);
79 // Does it look like a number?
80 if (s->length() > 0 && c >= '0' && c <= '9')
82 double const index_d = s->toNumber();
83 if (!MathUtils::isNaN(index_d))
85 // name is a string that looks like a number
86 // Note: convert using int, not uint, as it's much faster
87 int32_t const index_i = int32_t(index_d);
88 index = uint32_t(index_i);
89 return (double(index_i) == index_d) ? kValidNumber : kInvalidNumber;
93 return kNotNumber;
96 // ----------------------------
98 VectorClass::VectorClass(VTable *vtable)
99 : ClassClosure(vtable)
101 setPrototypePtr(toplevel()->objectClass->construct());
104 /*static*/ Stringp VectorClass::makeVectorClassName(AvmCore* core, Traits* t)
106 Stringp s = core->newConstantStringLatin1("Vector.<");
107 s = s->append(t->formatClassName());
108 s = s->append(core->newConstantStringLatin1(">"));
109 // all callers want it interned, so let's do it here
110 return core->internString(s);
113 ClassClosure* VectorClass::getTypedVectorClass(ClassClosure* typeClass)
115 ClassClosure* result = NULL;
116 Toplevel* toplevel = this->toplevel();
117 if (typeClass == NULL)
119 result = toplevel->objectVectorClass();
121 else if (typeClass == toplevel->intClass())
123 result = toplevel->intVectorClass();
125 else if (typeClass == toplevel->uintClass())
127 result = toplevel->uintVectorClass();
129 else if (typeClass == toplevel->numberClass())
131 result = toplevel->doubleVectorClass();
133 else
135 // if we have an object, we must have an itraits (otherwise the typearg is not a Class)
136 Traits* typeTraits = typeClass->vtable->traits->itraits;
137 if (!typeTraits)
138 toplevel->throwVerifyError(kCorruptABCError);
140 Domain* typeDomain = typeClass->traits()->pool->domain;
141 if ((result = typeDomain->getParameterizedType(typeClass)) == NULL)
143 Stringp fullname = VectorClass::makeVectorClassName(core(), typeTraits);
145 VTable* vt = this->vtable->newParameterizedVTable(typeTraits, fullname);
147 vt->ivtable->createInstanceProc = ClassClosure::impossibleCreateInstanceProc;
148 ObjectVectorClass* parameterizedVector = ObjectVectorClass::create(vt->gc(), vt);
149 parameterizedVector->m_typeTraits = typeClass ? typeClass->traits()->itraits : NULL;
150 parameterizedVector->setDelegate(toplevel->classClass()->prototypePtr());
152 // Is this right? Should each instantiation get its own prototype?
153 parameterizedVector->setPrototypePtr(toplevel->objectVectorClass()->prototypePtr());
154 typeDomain->addParameterizedType(typeClass, parameterizedVector);
156 result = parameterizedVector;
159 AvmAssert(result != NULL);
160 return result;
163 Atom VectorClass::applyTypeArgs(int argc, Atom* argv)
165 Toplevel* toplevel = this->toplevel();
167 // Vector only takes 1 type argument
168 AvmAssert(argc==1);
169 if (argc != 1)
171 toplevel->typeErrorClass()->throwError(kWrongTypeArgCountError, traits()->formatClassName(), core()->toErrorString(1), core()->toErrorString(argc));
174 Atom const typeAtom = argv[0];
176 ClassClosure* typeClass = NULL;
177 if (!ISNULL(typeAtom))
179 if (atomKind(typeAtom) != kObjectType)
180 toplevel->throwVerifyError(kCorruptABCError);
182 typeClass = (ClassClosure*)AvmCore::atomToScriptObject(typeAtom);
183 if (!typeClass->vtable->traits->itraits)
184 toplevel->throwVerifyError(kCorruptABCError);
186 return getTypedVectorClass(typeClass)->atom();
189 Atom VectorClass::construct(int /*argc*/, Atom* /*argv*/)
191 toplevel()->throwTypeError(kConstructOfNonFunctionError);
192 return undefinedAtom;
195 // FIXME: this could return a non-ObjectVectorObject, so we should really
196 // return VectorBaseObject instead.
197 ObjectVectorObject* VectorClass::newVector(ClassClosure* type, uint32_t length)
199 ClassClosure* vc = getTypedVectorClass(type);
200 Atom args[2] = { nullObjectAtom, core()->uintToAtom(length) };
201 return (ObjectVectorObject*)AvmCore::atomToScriptObject(vc->construct(1, args));
204 // ----------------------------
206 IntVectorClass::IntVectorClass(VTable* vtable)
207 : TypedVectorClass<IntVectorObject>(vtable)
209 // This is an ugly hack: Vector<> doesn't work properly with the ClassManifest setup,
210 // because the name it returns for itself isn't the name listed for finddef.
211 // To work around this (and maintain legacy internal behavior), we pre-emptively
212 // enter the Vector classes into the table upon first creation. (Arguably the name
213 // lookup issue should be fixed.)
214 toplevel()->builtinClasses()->fillInClass(avmplus::NativeID::abcclass___AS3___vec_Vector_int, this);
215 this->m_typeTraits = toplevel()->intClass()->traits()->itraits;
218 Atom IntVectorClass::construct(int argc, Atom* argv)
220 return constructImpl(argc, argv);
223 // ----------------------------
225 UIntVectorClass::UIntVectorClass(VTable* vtable)
226 : TypedVectorClass<UIntVectorObject>(vtable)
228 // This is an ugly hack: Vector<> doesn't work properly with the ClassManifest setup,
229 // because the name it returns for itself isn't the name listed for finddef.
230 // To work around this (and maintain legacy internal behavior), we pre-emptively
231 // enter the Vector classes into the table upon first creation. (Arguably the name
232 // lookup issue should be fixed.)
233 toplevel()->builtinClasses()->fillInClass(avmplus::NativeID::abcclass___AS3___vec_Vector_uint, this);
234 this->m_typeTraits = toplevel()->uintClass()->traits()->itraits;
237 Atom UIntVectorClass::construct(int argc, Atom* argv)
239 return constructImpl(argc, argv);
242 // ----------------------------
244 DoubleVectorClass::DoubleVectorClass(VTable* vtable)
245 : TypedVectorClass<DoubleVectorObject>(vtable)
247 // This is an ugly hack: Vector<> doesn't work properly with the ClassManifest setup,
248 // because the name it returns for itself isn't the name listed for finddef.
249 // To work around this (and maintain legacy internal behavior), we pre-emptively
250 // enter the Vector classes into the table upon first creation. (Arguably the name
251 // lookup issue should be fixed.)
252 toplevel()->builtinClasses()->fillInClass(avmplus::NativeID::abcclass___AS3___vec_Vector_double, this);
253 this->m_typeTraits = toplevel()->numberClass()->traits()->itraits;
256 Atom DoubleVectorClass::construct(int argc, Atom* argv)
258 return constructImpl(argc, argv);
261 // ----------------------------
263 ObjectVectorClass::ObjectVectorClass(VTable* vtable)
264 : TypedVectorClass<ObjectVectorObject>(vtable)
266 // This is an ugly hack: Vector<> doesn't work properly with the ClassManifest setup,
267 // because the name it returns for itself isn't the name listed for finddef.
268 // To work around this (and maintain legacy internal behavior), we pre-emptively
269 // enter the Vector classes into the table upon first creation. (Arguably the name
270 // lookup issue should be fixed.)
271 toplevel()->builtinClasses()->fillInClass(avmplus::NativeID::abcclass___AS3___vec_Vector_object, this);
272 this->m_typeTraits = toplevel()->objectClass->traits()->itraits;
275 Atom ObjectVectorClass::construct(int argc, Atom* argv)
277 return constructImpl(argc, argv);
280 // ----------------------------
282 IntVectorObject::IntVectorObject(VTable* ivtable, ScriptObject* delegate)
283 : TypedVectorObject< DataList<int32_t> >(ivtable, delegate)
287 IntVectorObject* IntVectorObject::newThisType()
289 return (IntVectorObject*)_newVector();
292 // ----------------------------
294 UIntVectorObject::UIntVectorObject(VTable* ivtable, ScriptObject* delegate)
295 : TypedVectorObject< DataList<uint32_t> >(ivtable, delegate)
299 UIntVectorObject* UIntVectorObject::newThisType()
301 return (UIntVectorObject*)_newVector();
304 // ----------------------------
306 DoubleVectorObject::DoubleVectorObject(VTable* ivtable, ScriptObject* delegate)
307 : TypedVectorObject< DataList<double> >(ivtable, delegate)
311 DoubleVectorObject* DoubleVectorObject::newThisType()
313 return (DoubleVectorObject*)_newVector();
316 // ----------------------------
318 ObjectVectorObject::ObjectVectorObject(VTable* ivtable, ScriptObject* delegate)
319 : TypedVectorObject< AtomList >(ivtable, delegate)
323 ObjectVectorObject* ObjectVectorObject::newThisType()
325 return (ObjectVectorObject*)_newVector();