aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-04-04 15:05:24 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2013-04-05 11:04:21 +0200
commitfa0344bfe68365ae9f15c2c4a451ec037f16d55c (patch)
tree15f16736656b9ab5bc98fb6cb004867e4a6cabdf /src
parent90dbc177757e16ad6cfcf5a195cbf610fe68a92d (diff)
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 <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/v4/qv4functionobject.h52
-rw-r--r--src/v4/qv4isel_masm.cpp7
-rw-r--r--src/v4/qv4runtime.cpp97
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();