Vec[vec.length++] = e instead of vec.push(e)


#1

Code readabilitiy is art, but I doubt either the AVM2 or the ABC generator in MXMLC would optimise that readability… because AS3 is, at all, property-based. But it’s interesting to avoid the standard Vector#push(...) method and instead do vector[vector.length++] = e for adding an single element in some cases. If more are needed, then grow length more than one. vector.length += x.

But why avoid the pushing method? It receives argument elements as an Array (using the rest parameter). The AS3 API reference also says…

Note, however, that when using the push() method or unshift() method to add values to a Vector, the arguments’ data types are not checked at compile time. Instead, they are checked at run time.

So it’s unlikely there’ll be a ahead-of-time optimisation by AVM2 for the conventional usage of the Vector#push() method. Increasing the length manually and setting the element directly isn’t so hard, anyways.


#2

well … hold on

this is a very nice feature to have a VM being able to tell you at runtime that the type is wrong

do some tests here because you’re assuming one way is faster than the other

I would argue that if vectors does not check the type at compile time it is for speed reasons
vectors are the fastest thing at reading and writing

check Int Keys: Object vs. Dictionary vs. Array vs. Vector
and look at the results

Vectors are a bit of a bastard classes in AS3, added late to the language they are a bit weird
but still are quite performant on specific cases

see more articles here
https://jacksondunstan.com/?s=vector

on one side they have to be able to work in ES mode
eg. Vector.as

        prototype.push = function (...args) // rest args are efficient
        {
            // Type check - Vector methods are not generic.
            castToThisType(this);

            // making it type specialized, otherwise compiler treats 'this' as untyped
            var v:Vector$object = this;
            
            // FP 10.1 throws this error specifically, the setting of the element in the
            // loop below will generate error 1125 instead.
            if (v.fixed)
                Error.throwError(RangeError, 1126);

            // The loop is correct because Tamarin (as of June 2010) has a 4GB object limit.
            // Thus at most 1G elements can be accommodated in a Vector, and the index never
            // wraps around.
            var n:uint = v.length;
            var i:uint=0;
            var argc:uint=args.length;
            while (i < argc) 
            {
                v[n] = args[i];
                i++;
                n++;
            }
            v.length = n;
            return n;
        }

but on the other side, in AS3 mode, they are a native implementation
eg. VectorImpl.as

AS3 native function push(...items:Array): uint;

eg. VectorClass-impl.h

    template<class TLIST>
    uint32_t TypedVectorObject<TLIST>::AS3_push(Atom* argv, int argc)
    {
        checkFixed();
        _splice(m_list.length(), argc, 0, argv);
        return m_list.length();
    }

the details of why it is like that are explained here VectorClass.h

/* Documentation on the structure of the Vector code in Tamarin (2011-10-20).
 *
 *
 * Five components: AS3, ABC, ASC, verifier, runtime.  These interact in various ways and a
 * linear narrative is not possible.
 *
 *
 * On the AS3 side we have this (core/Vector.as, core/VectorImpl.as):
 *
 *   package __AS3__.vec 
 *   {
 *     class Vector ...
 *     class Vector$int ...
 *     class Vector$uint ...
 *     class Vector$double ...
 *     class Vector$object ...
 *   }
 *
 * The namespace "__AS3__.vec" is an artifact of a time when we did not have good API
 * versioning and could not introduce new top-level names without the risk of breaking
 * existing code.  Today we would probably have made "Vector" public & versioned.
 *
 * "Vector" is public in its package but cannot be instantiated (a run-time error is thrown)
 * and has no members.  It is possible to capture its value and use it as part of a type 
 * application, eg, "var v=Vector; new v.<int>" will create a Vector.<int>.  It's also 
 * referenced in code using the APPLYTYPE instruction and CONSTANT_TypeName multiname kind (below).
 *
 * Vector$int, Vector$uint, Vector$double, and Vector$object are not public in their package.
 * They represent Vector.<int>, Vector.<uint>, Vector.<Number>, and Vector.<*> respectively;
 * the first three special cases are provided in order to specialize the representation
 * and the last is a catch-all.

...
 */

closed #3

archived #4