From beda28a8561258188ae8c4473db2a8b5c01d96ed Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Tue, 12 Feb 2013 22:25:39 +0100 Subject: [PATCH] Also lookup properties in the prototype by index We can only do this when getting properties, as setting values will always happen on the main object. Change-Id: I0336dd393bf78144d54ed8b6008011a7046e325d Reviewed-by: Simon Hausmann --- src/v4/qmljs_runtime.cpp | 80 ++++++++++++++++++++++++++++++++++------------ src/v4/qv4functionobject.h | 3 +- src/v4/qv4isel_masm.cpp | 3 +- 3 files changed, 64 insertions(+), 22 deletions(-) diff --git a/src/v4/qmljs_runtime.cpp b/src/v4/qmljs_runtime.cpp index 4c32b85..f3555e3 100644 --- a/src/v4/qmljs_runtime.cpp +++ b/src/v4/qmljs_runtime.cpp @@ -680,18 +680,40 @@ Value __qmljs_get_property_lookup(ExecutionContext *ctx, Value object, int looku { Lookup *l = ctx->lookups + lookupIndex; if (Object *o = object.asObject()) { - if (o->internalClass == l->internalClass) - return o->getValue(ctx, o->memberData + l->index); + 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; + } + } - uint idx = o->internalClass->find(l->name); - if (idx < UINT_MAX) { - l->internalClass = o->internalClass; - l->index = idx; - return o->getValue(ctx, o->memberData + idx); + 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; + } + } } - return object.objectValue()->__get__(ctx, l->name); - } else if (object.isString() && l->name->isEqualTo(ctx->engine->id_length)) { + if (p) + return o->getValue(ctx, p); + else + return object.objectValue()->__get__(ctx, l->name); + } + + if (object.isString() && l->name->isEqualTo(ctx->engine->id_length)) { return Value::fromInt32(object.stringValue()->toQString().length()); } else { object = __qmljs_to_object(object, ctx); @@ -714,14 +736,14 @@ void __qmljs_set_property_lookup(ExecutionContext *ctx, Value object, int lookup Lookup *l = ctx->lookups + lookupIndex; if (l->index != ArrayObject::LengthPropertyIndex || !o->isArrayObject()) { - if (o->internalClass == l->internalClass) { + 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->internalClass = o->internalClass; + l->mainClass = o->internalClass; l->index = idx; return o->putValue(ctx, o->memberData + idx, value); } @@ -840,21 +862,39 @@ Value __qmljs_call_property_lookup(ExecutionContext *context, Value thisObject, 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; + } + } - Value func; - - if (baseObject->internalClass == l->internalClass) { - func = baseObject->getValue(context, baseObject->memberData + l->index); - } else { + if (!p) { uint idx = baseObject->internalClass->find(l->name); if (idx < UINT_MAX) { - l->internalClass = baseObject->internalClass; + l->mainClass = baseObject->internalClass; + l->protoClass = 0; l->index = idx; - func = baseObject->getValue(context, baseObject->memberData + idx); - } else { - func = baseObject->__get__(context, l->name); + 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 = baseObject->getValue(context, p); + else + func = baseObject->__get__(context, l->name); + FunctionObject *o = func.asFunctionObject(); if (!o) context->throwTypeError(); diff --git a/src/v4/qv4functionobject.h b/src/v4/qv4functionobject.h index 9a49674..d6930b9 100644 --- a/src/v4/qv4functionobject.h +++ b/src/v4/qv4functionobject.h @@ -103,7 +103,8 @@ struct URIErrorPrototype; struct InternalClass; struct Lookup { - InternalClass *internalClass; + InternalClass *mainClass; + InternalClass *protoClass; uint index; String *name; }; diff --git a/src/v4/qv4isel_masm.cpp b/src/v4/qv4isel_masm.cpp index 7e74e07..0960adf 100644 --- a/src/v4/qv4isel_masm.cpp +++ b/src/v4/qv4isel_masm.cpp @@ -969,7 +969,8 @@ uint InstructionSelection::addLookup(VM::String *name) { uint index = (uint)_lookups.size(); VM::Lookup l; - l.internalClass = 0; + l.mainClass = 0; + l.protoClass = 0; l.index = 0; l.name = name; _lookups.append(l); -- 2.7.4