Factor out protoHasArray and hasAccessorProperty
authorPeter Varga <pvarga@inf.u-szeged.hu>
Thu, 15 Aug 2013 13:54:15 +0000 (15:54 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Sat, 17 Aug 2013 10:51:56 +0000 (12:51 +0200)
The Object::protoHasArray() function returns true if any object in the
prototype chain contains an array element. The new member
hasAccessorProperty of the Managed class is set true if the object
has any accessor property.

Change-Id: Ic29d303eb058d4faed2a47ed8fab18e376ccba68
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
src/qml/jsruntime/qv4arrayobject.cpp
src/qml/jsruntime/qv4managed_p.h
src/qml/jsruntime/qv4object.cpp
src/qml/jsruntime/qv4object_p.h

index ee69be4..d7f4bab 100644 (file)
@@ -269,13 +269,7 @@ Value ArrayPrototype::method_push(SimpleCallContext *ctx)
         return Value::fromDouble(newLen);
     }
 
-    bool protoHasArray = false;
-    Object *p = instance;
-    while ((p = p->prototype))
-        if (p->arrayDataLen)
-            protoHasArray = true;
-
-    if (!protoHasArray && instance->arrayDataLen <= len) {
+    if (!instance->protoHasArray() && instance->arrayDataLen <= len) {
         for (uint i = 0; i < ctx->argumentCount; ++i) {
             Value v = ctx->argument(i);
 
@@ -349,13 +343,7 @@ Value ArrayPrototype::method_shift(SimpleCallContext *ctx)
 
     Value result = front ? instance->getValue(front, instance->arrayAttributes ? instance->arrayAttributes[pidx] : Attr_Data) : Value::undefinedValue();
 
-    bool protoHasArray = false;
-    Object *p = instance;
-    while ((p = p->prototype))
-        if (p->arrayDataLen)
-            protoHasArray = true;
-
-    if (!protoHasArray && instance->arrayDataLen <= len) {
+    if (!instance->protoHasArray() && instance->arrayDataLen <= len) {
         if (!instance->sparseArray) {
             if (instance->arrayDataLen) {
                 ++instance->arrayOffset;
@@ -502,13 +490,7 @@ Value ArrayPrototype::method_unshift(SimpleCallContext *ctx)
     Object *instance = ctx->thisObject.toObject(ctx);
     uint len = getLength(ctx, instance);
 
-    bool protoHasArray = false;
-    Object *p = instance;
-    while ((p = p->prototype))
-        if (p->arrayDataLen)
-            protoHasArray = true;
-
-    if (!protoHasArray && instance->arrayDataLen <= len) {
+    if (!instance->protoHasArray() && instance->arrayDataLen <= len) {
         for (int i = ctx->argumentCount - 1; i >= 0; --i) {
             Value v = ctx->argument(i);
 
index 5e3c142..227cd4b 100644 (file)
@@ -155,7 +155,7 @@ private:
 protected:
     Managed(InternalClass *internal)
         : _data(0), vtbl(&static_vtbl), internalClass(internal)
-    { inUse = 1; extensible = 1; }
+    { inUse = 1; extensible = 1; hasAccessorProperty = 0; }
 
 public:
     void *operator new(size_t size, MemoryManager *mm);
@@ -290,7 +290,8 @@ public:
             uint type : 8;
             mutable uint subtype : 3;
             uint bindingKeyFlag : 1;
-            uint unused : 12;
+            uint hasAccessorProperty : 1;
+            uint unused : 11;
         };
     };
 
index 747140b..45a0a19 100644 (file)
@@ -298,6 +298,9 @@ Property *Object::insertMember(String *s, PropertyAttributes attributes)
     uint idx;
     internalClass = internalClass->addMember(s, attributes, &idx);
 
+    if (attributes.isAccessor())
+        hasAccessorProperty = 1;
+
     if (idx >= memberDataAlloc) {
         memberDataAlloc = qMax((uint)8, 2*memberDataAlloc);
         Property *newMemberData = new Property[memberDataAlloc];
@@ -912,6 +915,8 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, String *name, const Pr
             cattrs->setWritable(false);
         if (!succeeded)
             goto reject;
+        if (attrs.isAccessor())
+            hasAccessorProperty = 1;
         return true;
     }
 
@@ -1049,6 +1054,8 @@ bool Object::__defineOwnProperty__(ExecutionContext *ctx, Property *current, Str
         if (arrayAttributes)
             arrayAttributes[current - arrayData] = cattrs;
     }
+    if (attrs.isAccessor())
+        hasAccessorProperty = 1;
     return true;
   reject:
     if (ctx->strictMode)
@@ -1067,27 +1074,7 @@ void Object::copyArrayData(Object *other)
 {
     Q_ASSERT(isArrayObject());
 
-    bool protoHasArray = false;
-    Object *p = other;
-    while ((p = p->prototype))
-        if (p->arrayDataLen)
-            protoHasArray = true;
-
-    bool arrayHasGetter = false;
-    if (!protoHasArray && other->arrayAttributes) {
-        for (uint i = 0; i < other->arrayDataLen; ++i) {
-            if (other->arrayAttributes[i].isAccessor()) {
-                const Property &pd = other->arrayData[i];
-                FunctionObject *getter = pd.getter();
-                if (getter) {
-                    arrayHasGetter = true;
-                    break;
-                }
-            }
-        }
-    }
-
-    if (protoHasArray || arrayHasGetter) {
+    if (other->protoHasArray() || other->hasAccessorProperty) {
         uint len = other->arrayLength();
         Q_ASSERT(len);
 
@@ -1113,13 +1100,7 @@ void Object::copyArrayData(Object *other)
 
 Value Object::arrayIndexOf(Value v, uint fromIndex, uint endIndex, ExecutionContext *ctx, Object *o)
 {
-    bool protoHasArray = false;
-    Object *p = o;
-    while ((p = p->prototype))
-        if (p->arrayDataLen)
-            protoHasArray = true;
-
-    if (protoHasArray || o->arrayAttributes) {
+    if (o->protoHasArray() || o->arrayAttributes) {
         // lets be safe and slow
         for (uint i = fromIndex; i < endIndex; ++i) {
             bool exists;
index ffcca13..e6b1e04 100644 (file)
@@ -223,6 +223,8 @@ public:
     void setArrayLengthUnchecked(uint l);
 
     Property *arrayInsert(uint index, PropertyAttributes attributes = Attr_Data) {
+        if (attributes.isAccessor())
+            hasAccessorProperty = 1;
 
         Property *pd;
         if (!sparseArray && (index < 0x1000 || index < arrayDataLen + (arrayDataLen >> 2))) {
@@ -317,6 +319,16 @@ public:
     void arrayReserve(uint n);
     void ensureArrayAttributes();
 
+    inline bool protoHasArray() {
+        Object *p = this;
+
+        while ((p = p->prototype))
+            if (p->arrayDataLen)
+                return true;
+
+        return false;
+    }
+
     inline Value get(String *name, bool *hasProperty = 0)
     { return vtbl->get(this, name, hasProperty); }
     inline Value getIndexed(uint idx, bool *hasProperty = 0)