Fix 682280 - Vector.length is slow (r=edwsmith)
authorLars T Hansen <lhansen@adobe.com>
Tue, 18 Oct 2011 19:58:45 +0200
changeset 6663 18834e3c7831b0d5afd3d05560a7197c568dbeba
parent 6662 fa0426abcac87fa67177a2294348a5e931c8c029
child 6664 d9a0641933d5f18092ebf1b49bffccdda7bb21e1
child 6665 2fbf4ecd80c592b86869146a1cfd19a963c9ff97
push id3964
push userlhansen@adobe.com
push dateTue, 18 Oct 2011 17:58:51 +0000
reviewersedwsmith
bugs682280
Fix 682280 - Vector.length is slow (r=edwsmith)
core/CodegenLIR.cpp
--- a/core/CodegenLIR.cpp
+++ b/core/CodegenLIR.cpp
@@ -3326,17 +3326,61 @@ namespace avmplus
             // NOTE opd2 is the stack offset to the reciever
             const Multiname* name = pool->precomputedMultiname(opd1);
             const FrameValue& obj = state->peek(opd2); // object
             Binding b = toplevel->getBinding(obj.traits, name);
 
             // early bind accessor
             if (AvmCore::hasGetterBinding(b))
             {
-                // Invoke the getter
+                // Inline certain blessed and possibly-hot accessors.
+                //
+                // -  Optimize access to vector's "length", which is final.
+                //
+                //    The verifier has computed that the return type of the "length" 
+                //    getter is uint, so we can just load "len" here: it is a uint32_t.
+
+                int32_t arrayDataOffset = -1;
+                int32_t lenOffset = -1;
+
+                MethodInfo* getter_info = obj.traits->getTraitsBindings()->getMethod(AvmCore::bindingToGetterId(b));
+                switch (getter_info->method_id())
+                {
+                    case avmplus::NativeID::__AS3___vec_Vector_object_length_get:
+                        arrayDataOffset = int32_t(offsetof(ObjectVectorObject, m_list.m_data));
+                        lenOffset = int32_t(offsetof(AtomListHelper::LISTDATA, len));
+                        goto vector_length;
+                    case avmplus::NativeID::__AS3___vec_Vector_double_length_get:
+                        arrayDataOffset = int32_t(offsetof(DoubleVectorObject, m_list.m_data));
+                        lenOffset = int32_t(offsetof(DataListHelper<double>::LISTDATA, len));
+                        goto vector_length;
+                    case avmplus::NativeID::__AS3___vec_Vector_int_length_get:
+                        arrayDataOffset = int32_t(offsetof(IntVectorObject, m_list.m_data));
+                        lenOffset = int32_t(offsetof(DataListHelper<int32_t>::LISTDATA, len));
+                        goto vector_length;
+                    case avmplus::NativeID::__AS3___vec_Vector_uint_length_get:
+                        arrayDataOffset = int32_t(offsetof(UIntVectorObject, m_list.m_data));
+                        lenOffset = int32_t(offsetof(DataListHelper<uint32_t>::LISTDATA, len));
+                        goto vector_length;
+
+                    // Add more specializations here
+
+                    default:
+                        goto invoke_getter;
+                }
+                
+            vector_length: {
+                LIns *arrayData = loadIns(LIR_ldp, arrayDataOffset, localGetp(sp), ACCSET_OTHER, LOAD_NORMAL);
+                LIns *arrayLen  = loadIns(LIR_ldi, lenOffset, arrayData, ACCSET_OTHER, LOAD_NORMAL);
+                localSet(sp, arrayLen, type);
+                break;
+            }
+
+            invoke_getter:
+                // Default case: Invoke the getter
                 int disp_id = AvmCore::bindingToGetterId(b);
                 const TraitsBindingsp objtd = obj.traits->getTraitsBindings();
                 MethodInfo *f = objtd->getMethod(disp_id);
                 AvmAssert(f != NULL);
 
                 if (!obj.traits->isInterface()) {
                     emitTypedCall(OP_callmethod, disp_id, 0, type, f);
                 }