From fa0344bfe68365ae9f15c2c4a451ec037f16d55c Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 4 Apr 2013 15:05:24 +0200 Subject: Clean up the property lookup code Also look a bit deeper into the proto chain. This speeds up the deltablue benchmark by 10% Change-Id: Id3f5de58f336d7ca74c7c32e6c30564410baf1e4 Reviewed-by: Simon Hausmann --- src/v4/qv4functionobject.h | 52 ++++++++++++++++++++++++- src/v4/qv4isel_masm.cpp | 7 ++-- src/v4/qv4runtime.cpp | 97 +++++++--------------------------------------- 3 files changed, 69 insertions(+), 87 deletions(-) diff --git a/src/v4/qv4functionobject.h b/src/v4/qv4functionobject.h index 2c1809c59b..8531afda20 100644 --- a/src/v4/qv4functionobject.h +++ b/src/v4/qv4functionobject.h @@ -103,10 +103,58 @@ struct URIErrorPrototype; struct InternalClass; struct Lookup { - InternalClass *mainClass; - InternalClass *protoClass; + enum { Size = 4 }; + InternalClass *classList[Size]; + int level; uint index; String *name; + + PropertyDescriptor *lookup(Object *obj) { + int i = 0; + while (i < level && obj && obj->internalClass == classList[i]) { + obj = obj->prototype; + ++i; + } + + if (index != UINT_MAX && obj->internalClass == classList[i]) + return obj->memberData + index; + + while (i < Size && obj) { + classList[i] = obj->internalClass; + + index = obj->internalClass->find(name); + if (index != UINT_MAX) { + level = i; + return obj->memberData + index; + } + + obj = obj->prototype; + ++i; + } + level = i; + + while (obj) { + index = obj->internalClass->find(name); + if (index != UINT_MAX) + return obj->memberData + index; + + obj = obj->prototype; + } + return 0; + } + + PropertyDescriptor *setterLookup(Object *o) { + if (o->internalClass == classList[0]) + return o->memberData + index; + + uint idx = o->internalClass->find(name); + if (idx != UINT_MAX) { + classList[0] = o->internalClass; + index = idx; + return o->memberData + index; + } + return 0; + } }; struct Function { diff --git a/src/v4/qv4isel_masm.cpp b/src/v4/qv4isel_masm.cpp index ee6132464a..30f5b3f6be 100644 --- a/src/v4/qv4isel_masm.cpp +++ b/src/v4/qv4isel_masm.cpp @@ -1186,9 +1186,10 @@ uint InstructionSelection::addLookup(VM::String *name) { uint index = (uint)_lookups.size(); VM::Lookup l; - l.mainClass = 0; - l.protoClass = 0; - l.index = 0; + for (int i = 0; i < Lookup::Size; ++i) + l.classList[i] = 0; + l.level = -1; + l.index = UINT_MAX; l.name = name; _lookups.append(l); return index; diff --git a/src/v4/qv4runtime.cpp b/src/v4/qv4runtime.cpp index 5240efd0ec..c889753392 100644 --- a/src/v4/qv4runtime.cpp +++ b/src/v4/qv4runtime.cpp @@ -700,37 +700,11 @@ void __qmljs_get_property_lookup(ExecutionContext *ctx, Value *result, const Val Value res; Lookup *l = ctx->lookups + lookupIndex; if (Object *o = object.asObject()) { - PropertyDescriptor *p = 0; - if (o->internalClass == l->mainClass) { - if (!l->protoClass) { - p = o->memberData + l->index; - } else if (o->prototype && o->prototype->internalClass == l->protoClass) { - p = o->prototype->memberData + l->index; - } - } - - if (!p) { - uint idx = o->internalClass->find(l->name); - if (idx < UINT_MAX) { - l->mainClass = o->internalClass; - l->protoClass = 0; - l->index = idx; - p = o->memberData + idx; - } else if (o->prototype) { - idx = o->prototype->internalClass->find(l->name); - if (idx < UINT_MAX) { - l->mainClass = o->internalClass; - l->protoClass = o->prototype->internalClass; - l->index = idx; - p = o->prototype->memberData + idx; - } - } - } - + PropertyDescriptor *p = l->lookup(o); if (p) res = p->type == PropertyDescriptor::Data ? p->value : o->getValue(ctx, p); else - res = o->get(ctx, l->name); + res = Value::undefinedValue(); } else { if (Managed *m = object.asManaged()) { res = m->get(ctx, l->name); @@ -748,18 +722,10 @@ void __qmljs_set_property_lookup(ExecutionContext *ctx, const Value &object, int Object *o = object.toObject(ctx); Lookup *l = ctx->lookups + lookupIndex; - if (l->index != ArrayObject::LengthPropertyIndex || !o->isArrayObject()) { - if (o->internalClass == l->mainClass) { - o->putValue(ctx, o->memberData + l->index, value); - return; - } - - uint idx = o->internalClass->find(l->name); - if (idx < UINT_MAX) { - l->mainClass = o->internalClass; - l->index = idx; - return o->putValue(ctx, o->memberData + idx, value); - } + PropertyDescriptor *p = l->setterLookup(o); + if (p && (l->index != ArrayObject::LengthPropertyIndex || !o->isArrayObject())) { + o->putValue(ctx, p, value); + return; } o->put(ctx, l->name, value); @@ -883,55 +849,22 @@ void __qmljs_call_property(ExecutionContext *context, Value *result, const Value *result = res; } -void __qmljs_call_property_lookup(ExecutionContext *context, Value *result, const Value &thatObject, uint index, Value *args, int argc) +void __qmljs_call_property_lookup(ExecutionContext *context, Value *result, const Value &thisObject, uint index, Value *args, int argc) { - Value thisObject = thatObject; Lookup *l = context->lookups + index; Object *baseObject; - if (thisObject.isString()) { - baseObject = context->engine->stringPrototype; - } else { - if (!thisObject.isObject()) - thisObject = Value::fromObject(__qmljs_convert_to_object(context, thisObject)); - - assert(thisObject.isObject()); + if (thisObject.isObject()) baseObject = thisObject.objectValue(); - } - - PropertyDescriptor *p = 0; - if (baseObject->internalClass == l->mainClass) { - if (!l->protoClass) { - p = baseObject->memberData + l->index; - } else if (baseObject->prototype && baseObject->prototype->internalClass == l->protoClass) { - p = baseObject->prototype->memberData + l->index; - } - } - - if (!p) { - uint idx = baseObject->internalClass->find(l->name); - if (idx < UINT_MAX) { - l->mainClass = baseObject->internalClass; - l->protoClass = 0; - l->index = idx; - p = baseObject->memberData + idx; - } else if (baseObject->prototype) { - idx = baseObject->prototype->internalClass->find(l->name); - if (idx < UINT_MAX) { - l->mainClass = baseObject->internalClass; - l->protoClass = baseObject->prototype->internalClass; - l->index = idx; - p = baseObject->prototype->memberData + idx; - } - } - } - - Value func; - if (p) - func = p->type == PropertyDescriptor::Data ? p->value : baseObject->getValue(context, p); + else if (thisObject.isString()) + baseObject = context->engine->stringPrototype; else - func = baseObject->get(context, l->name); + baseObject = __qmljs_convert_to_object(context, thisObject); + PropertyDescriptor *p = l->lookup(baseObject); + if (!p) + context->throwTypeError(); + Value func = p->type == PropertyDescriptor::Data ? p->value : baseObject->getValue(context, p); FunctionObject *o = func.asFunctionObject(); if (!o) context->throwTypeError(); -- cgit v1.2.3