Specialized lookups for accessor properties
authorLars Knoll <lars.knoll@digia.com>
Sun, 14 Apr 2013 21:38:46 +0000 (23:38 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Mon, 15 Apr 2013 08:51:13 +0000 (10:51 +0200)
Change-Id: Ic4afb5b2b73b3311077d3d64ddc03fa6da842e82
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/v4/qv4lookup.cpp
src/v4/qv4lookup.h

index 76e1c41..38a11a9 100644 (file)
@@ -39,6 +39,7 @@
 **
 ****************************************************************************/
 #include "qv4lookup.h"
+#include "qv4functionobject.h"
 
 QT_BEGIN_NAMESPACE
 
@@ -62,6 +63,14 @@ void Lookup::lookupPropertyGeneric(QQmlJS::VM::Lookup *l, ExecutionContext *ctx,
                     *result = p->value;
                 return;
             } else {
+                if (l->level == 0)
+                    l->lookupProperty = lookupPropertyAccessor0;
+                else if (l->level == 1)
+                    l->lookupProperty = lookupPropertyAccessor1;
+                else if (l->level == 2)
+                    l->lookupProperty = lookupPropertyAccessor2;
+                if (result)
+                    *result = p->value;
                 Value res = o->getValue(ctx, p, attrs);
                 if (result)
                     *result = res;
@@ -119,7 +128,7 @@ void Lookup::lookupProperty2(Lookup *l, ExecutionContext *ctx, Value *result, co
                 o = o->prototype;
                 if (l->classList[2] == o->internalClass) {
                     if (result)
-                        *result = o->prototype->memberData[l->index].value;
+                        *result = o->memberData[l->index].value;
                     return;
                 }
             }
@@ -129,6 +138,71 @@ void Lookup::lookupProperty2(Lookup *l, ExecutionContext *ctx, Value *result, co
     lookupPropertyGeneric(l, ctx, result, object);
 }
 
+void Lookup::lookupPropertyAccessor0(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object)
+{
+    if (Object *o = object.asObject()) {
+        if (l->classList[0] == o->internalClass) {
+            Value res;
+            FunctionObject *getter = o->memberData[l->index].getter();
+            if (!getter)
+                res = Value::undefinedValue();
+            else
+                res = getter->call(ctx, object, 0, 0);
+            if (result)
+                *result = res;
+            return;
+        }
+    }
+    l->lookupProperty = lookupPropertyGeneric;
+    lookupPropertyGeneric(l, ctx, result, object);
+}
+
+void Lookup::lookupPropertyAccessor1(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object)
+{
+    if (Object *o = object.asObject()) {
+        if (l->classList[0] == o->internalClass &&
+            l->classList[1] == o->prototype->internalClass) {
+            Value res;
+            FunctionObject *getter = o->prototype->memberData[l->index].getter();
+            if (!getter)
+                res = Value::undefinedValue();
+            else
+                res = getter->call(ctx, object, 0, 0);
+            if (result)
+                *result = res;
+            return;
+        }
+    }
+    l->lookupProperty = lookupPropertyGeneric;
+    lookupPropertyGeneric(l, ctx, result, object);
+}
+
+void Lookup::lookupPropertyAccessor2(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object)
+{
+    if (Object *o = object.asObject()) {
+        if (l->classList[0] == o->internalClass) {
+            o = o->prototype;
+            if (l->classList[1] == o->internalClass) {
+                o = o->prototype;
+                if (l->classList[2] == o->internalClass) {
+                    Value res;
+                    FunctionObject *getter = o->memberData[l->index].getter();
+                    if (!getter)
+                        res = Value::undefinedValue();
+                    else
+                        res = getter->call(ctx, object, 0, 0);
+                    if (result)
+                        *result = res;
+                    return;
+                }
+            }
+        }
+    }
+    l->lookupProperty = lookupPropertyGeneric;
+    lookupPropertyGeneric(l, ctx, result, object);
+}
+
+
 void Lookup::lookupGlobalGeneric(Lookup *l, ExecutionContext *ctx, Value *result)
 {
     Object *o = ctx->engine->globalObject;
@@ -145,6 +219,12 @@ void Lookup::lookupGlobalGeneric(Lookup *l, ExecutionContext *ctx, Value *result
             *result = p->value;
             return;
         } else {
+            if (l->level == 0)
+                l->lookupGlobal = lookupGlobalAccessor0;
+            else if (l->level == 1)
+                l->lookupGlobal = lookupGlobalAccessor1;
+            else if (l->level == 2)
+                l->lookupGlobal = lookupGlobalAccessor2;
             Value res = o->getValue(ctx, p, attrs);
             if (result)
                 *result = res;
@@ -194,6 +274,58 @@ void Lookup::lookupGlobal2(Lookup *l, ExecutionContext *ctx, Value *result)
     lookupGlobalGeneric(l, ctx, result);
 }
 
+void Lookup::lookupGlobalAccessor0(Lookup *l, ExecutionContext *ctx, Value *result)
+{
+    Object *o = ctx->engine->globalObject;
+    if (l->classList[0] == o->internalClass) {
+        FunctionObject *getter = o->memberData[l->index].getter();
+        if (!getter)
+            *result = Value::undefinedValue();
+        else
+            *result = getter->call(ctx, Value::undefinedValue(), 0, 0);
+        return;
+    }
+    l->lookupGlobal = lookupGlobalGeneric;
+    lookupGlobalGeneric(l, ctx, result);
+}
+
+void Lookup::lookupGlobalAccessor1(Lookup *l, ExecutionContext *ctx, Value *result)
+{
+    Object *o = ctx->engine->globalObject;
+    if (l->classList[0] == o->internalClass &&
+        l->classList[1] == o->prototype->internalClass) {
+        FunctionObject *getter = o->prototype->memberData[l->index].getter();
+        if (!getter)
+            *result = Value::undefinedValue();
+        else
+            *result = getter->call(ctx, Value::undefinedValue(), 0, 0);
+        return;
+    }
+    l->lookupGlobal = lookupGlobalGeneric;
+    lookupGlobalGeneric(l, ctx, result);
+}
+
+void Lookup::lookupGlobalAccessor2(Lookup *l, ExecutionContext *ctx, Value *result)
+{
+    Object *o = ctx->engine->globalObject;
+    if (l->classList[0] == o->internalClass) {
+        o = o->prototype;
+        if (l->classList[1] == o->internalClass) {
+            o = o->prototype;
+            if (l->classList[2] == o->internalClass) {
+                FunctionObject *getter = o->memberData[l->index].getter();
+                if (!getter)
+                    *result = Value::undefinedValue();
+                else
+                    *result = getter->call(ctx, Value::undefinedValue(), 0, 0);
+                return;
+            }
+        }
+    }
+    l->lookupGlobal = lookupGlobalGeneric;
+    lookupGlobalGeneric(l, ctx, result);
+}
+
 }
 }
 
index c287c97..38546cd 100644 (file)
@@ -54,7 +54,7 @@ namespace QQmlJS {
 namespace VM {
 
 struct Lookup {
-    enum { Size = 4 };
+    enum { Size = 3 };
     union {
         void (*lookupProperty)(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object);
         void (*lookupGlobal)(Lookup *l, ExecutionContext *ctx, Value *result);
@@ -68,11 +68,17 @@ struct Lookup {
     static void lookupProperty0(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object);
     static void lookupProperty1(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object);
     static void lookupProperty2(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object);
+    static void lookupPropertyAccessor0(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object);
+    static void lookupPropertyAccessor1(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object);
+    static void lookupPropertyAccessor2(Lookup *l, ExecutionContext *ctx, Value *result, const Value &object);
 
     static void lookupGlobalGeneric(Lookup *l, ExecutionContext *ctx, Value *result);
     static void lookupGlobal0(Lookup *l, ExecutionContext *ctx, Value *result);
     static void lookupGlobal1(Lookup *l, ExecutionContext *ctx, Value *result);
     static void lookupGlobal2(Lookup *l, ExecutionContext *ctx, Value *result);
+    static void lookupGlobalAccessor0(Lookup *l, ExecutionContext *ctx, Value *result);
+    static void lookupGlobalAccessor1(Lookup *l, ExecutionContext *ctx, Value *result);
+    static void lookupGlobalAccessor2(Lookup *l, ExecutionContext *ctx, Value *result);
 
     Property *lookup(Object *obj, PropertyAttributes *attrs) {
         int i = 0;