From 800bc0ed8d22bae49e7e3c5efce59aa33e5d6998 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Sun, 14 Apr 2013 23:38:46 +0200 Subject: Specialized lookups for accessor properties Change-Id: Ic4afb5b2b73b3311077d3d64ddc03fa6da842e82 Reviewed-by: Simon Hausmann --- src/v4/qv4lookup.cpp | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/v4/qv4lookup.h | 8 ++- 2 files changed, 140 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/v4/qv4lookup.cpp b/src/v4/qv4lookup.cpp index 76e1c415ca..38a11a99de 100644 --- a/src/v4/qv4lookup.cpp +++ b/src/v4/qv4lookup.cpp @@ -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); +} + } } diff --git a/src/v4/qv4lookup.h b/src/v4/qv4lookup.h index c287c97124..38546cd65b 100644 --- a/src/v4/qv4lookup.h +++ b/src/v4/qv4lookup.h @@ -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; -- cgit v1.2.3