diff options
author | Lars Knoll <lars.knoll@digia.com> | 2014-03-13 21:28:30 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-03-18 09:05:57 +0100 |
commit | 09f3cfee8d5e34b5f7058586c52c3fc36d295d93 (patch) | |
tree | 34e2f85fc7914780db09365dc0654d9201f829f4 /src/qml/jsruntime | |
parent | 6b425f3182e57cb7cda6b559f3ee9673137706d0 (diff) |
Add some specialized lookups for two internal classes
Some methods are being called with two different types of objects,
alternating between them. This adds a specialized lookup for that
case. Speeds up the splay test by ~20%.
Also create a clean path to a fallback lookup instead of going back
to the generic lookup and then alternating.
Change-Id: I3082d70d27155ef5f2cf2b680d227c6dd389956d
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4lookup.cpp | 192 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4lookup_p.h | 14 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 9 |
3 files changed, 187 insertions, 28 deletions
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp index 081b5b3514..875a02732f 100644 --- a/src/qml/jsruntime/qv4lookup.cpp +++ b/src/qml/jsruntime/qv4lookup.cpp @@ -288,6 +288,52 @@ ReturnedValue Lookup::getterGeneric(QV4::Lookup *l, const ValueRef object) return Encode::undefined(); } +ReturnedValue Lookup::getterTwoClasses(Lookup *l, const ValueRef object) +{ + Lookup l1 = *l; + + if (l1.getter == Lookup::getter0 || l1.getter == Lookup::getter1) { + if (Object *o = object->asObject()) { + ReturnedValue v = o->getLookup(l); + Lookup l2 = *l; + + if (l2.getter == Lookup::getter0 || l2.getter == Lookup::getter1) { + // if we have a getter0, make sure it comes first + if (l2.getter == Lookup::getter0) + qSwap(l1, l2); + + l->classList[0] = l1.classList[0]; + l->classList[1] = l1.classList[1]; + l->classList[2] = l2.classList[0]; + l->classList[3] = l2.classList[1]; + l->index = l1.index; + l->index2 = l2.index; + + if (l1.getter == Lookup::getter0) { + l->getter = (l2.getter == Lookup::getter0) ? Lookup::getter0getter0 : Lookup::getter0getter1; + } else { + Q_ASSERT(l1.getter == Lookup::getter1 && l2.getter == Lookup::getter1); + l->getter = Lookup::getter1getter1; + } + return v; + } + } + } + + l->getter = getterFallback; + return getterFallback(l, object); +} + +ReturnedValue Lookup::getterFallback(Lookup *l, const ValueRef object) +{ + QV4::Scope scope(l->name->engine()); + QV4::ScopedObject o(scope, object->toObject(scope.engine->currentContext())); + if (!o) + return Encode::undefined(); + QV4::ScopedString s(scope, l->name); + return o->get(s); +} + ReturnedValue Lookup::getter0(Lookup *l, const ValueRef object) { if (object->isManaged()) { @@ -295,10 +341,9 @@ ReturnedValue Lookup::getter0(Lookup *l, const ValueRef object) // the internal class won't match Object *o = object->objectValue(); if (l->classList[0] == o->internalClass) - return static_cast<Object *>(o)->memberData[l->index].asReturnedValue(); + return o->memberData[l->index].asReturnedValue(); } - l->getter = getterGeneric; - return getterGeneric(l, object); + return getterTwoClasses(l, object); } ReturnedValue Lookup::getter1(Lookup *l, const ValueRef object) @@ -311,8 +356,7 @@ ReturnedValue Lookup::getter1(Lookup *l, const ValueRef object) l->classList[1] == o->prototype()->internalClass) return o->prototype()->memberData[l->index].asReturnedValue(); } - l->getter = getterGeneric; - return getterGeneric(l, object); + return getterTwoClasses(l, object); } ReturnedValue Lookup::getter2(Lookup *l, const ValueRef object) @@ -330,10 +374,60 @@ ReturnedValue Lookup::getter2(Lookup *l, const ValueRef object) } } } - l->getter = getterGeneric; - return getterGeneric(l, object); + l->getter = getterFallback; + return getterFallback(l, object); +} + +ReturnedValue Lookup::getter0getter0(Lookup *l, const ValueRef object) +{ + if (object->isManaged()) { + // we can safely cast to a QV4::Object here. If object is actually a string, + // the internal class won't match + Object *o = object->objectValue(); + if (l->classList[0] == o->internalClass) + return o->memberData[l->index].asReturnedValue(); + if (l->classList[2] == o->internalClass) + return o->memberData[l->index2].asReturnedValue(); + } + l->getter = getterFallback; + return getterFallback(l, object); +} + +ReturnedValue Lookup::getter0getter1(Lookup *l, const ValueRef object) +{ + if (object->isManaged()) { + // we can safely cast to a QV4::Object here. If object is actually a string, + // the internal class won't match + Object *o = object->objectValue(); + if (l->classList[0] == o->internalClass) + return o->memberData[l->index].asReturnedValue(); + if (l->classList[2] == o->internalClass && + l->classList[3] == o->prototype()->internalClass) + return o->prototype()->memberData[l->index2].asReturnedValue(); + } + l->getter = getterFallback; + return getterFallback(l, object); +} + +ReturnedValue Lookup::getter1getter1(Lookup *l, const ValueRef object) +{ + if (object->isManaged()) { + // we can safely cast to a QV4::Object here. If object is actually a string, + // the internal class won't match + Object *o = object->objectValue(); + if (l->classList[0] == o->internalClass && + l->classList[1] == o->prototype()->internalClass) + return o->prototype()->memberData[l->index].asReturnedValue(); + if (l->classList[2] == o->internalClass && + l->classList[3] == o->prototype()->internalClass) + return o->prototype()->memberData[l->index2].asReturnedValue(); + return getterFallback(l, object); + } + l->getter = getterFallback; + return getterFallback(l, object); } + ReturnedValue Lookup::getterAccessor0(Lookup *l, const ValueRef object) { if (object->isManaged()) { @@ -351,8 +445,8 @@ ReturnedValue Lookup::getterAccessor0(Lookup *l, const ValueRef object) return getter->call(callData); } } - l->getter = getterGeneric; - return getterGeneric(l, object); + l->getter = getterFallback; + return getterFallback(l, object); } ReturnedValue Lookup::getterAccessor1(Lookup *l, const ValueRef object) @@ -373,8 +467,8 @@ ReturnedValue Lookup::getterAccessor1(Lookup *l, const ValueRef object) return getter->call(callData); } } - l->getter = getterGeneric; - return getterGeneric(l, object); + l->getter = getterFallback; + return getterFallback(l, object); } ReturnedValue Lookup::getterAccessor2(Lookup *l, const ValueRef object) @@ -400,11 +494,10 @@ ReturnedValue Lookup::getterAccessor2(Lookup *l, const ValueRef object) } } } - l->getter = getterGeneric; - return getterGeneric(l, object); + l->getter = getterFallback; + return getterFallback(l, object); } - ReturnedValue Lookup::primitiveGetter0(Lookup *l, const ValueRef object) { if (object->type() == l->type) { @@ -625,21 +718,49 @@ void Lookup::setterGeneric(Lookup *l, const ValueRef object, const ValueRef valu o->setLookup(l, value); } +void Lookup::setterTwoClasses(Lookup *l, const ValueRef object, const ValueRef value) +{ + Lookup l1 = *l; + + if (Object *o = object->asObject()) { + o->setLookup(l, value); + + if (l->setter == Lookup::setter0) { + l->setter = setter0setter0; + l->classList[1] = l1.classList[0]; + l->index2 = l1.index; + return; + } + } + + l->setter = setterFallback; + setterFallback(l, object, value); +} + +void Lookup::setterFallback(Lookup *l, const ValueRef object, const ValueRef value) +{ + QV4::Scope scope(l->name->engine()); + QV4::ScopedObject o(scope, object->toObject(scope.engine->currentContext())); + if (o) { + QV4::ScopedString s(scope, l->name); + o->put(s, value); + } +} + void Lookup::setter0(Lookup *l, const ValueRef object, const ValueRef value) { - Object *o = object->asObject(); + Object *o = static_cast<Object *>(object->asManaged()); if (o && o->internalClass == l->classList[0]) { o->memberData[l->index] = *value; return; } - l->setter = setterGeneric; - setterGeneric(l, object, value); + setterTwoClasses(l, object, value); } void Lookup::setterInsert0(Lookup *l, const ValueRef object, const ValueRef value) { - Object *o = object->asObject(); + Object *o = static_cast<Object *>(object->asManaged()); if (o && o->internalClass == l->classList[0]) { if (!o->prototype()) { if (l->index >= o->memberDataAlloc) @@ -650,13 +771,13 @@ void Lookup::setterInsert0(Lookup *l, const ValueRef object, const ValueRef valu } } - l->setter = setterGeneric; - setterGeneric(l, object, value); + l->setter = setterFallback; + setterFallback(l, object, value); } void Lookup::setterInsert1(Lookup *l, const ValueRef object, const ValueRef value) { - Object *o = object->asObject(); + Object *o = static_cast<Object *>(object->asManaged()); if (o && o->internalClass == l->classList[0]) { Object *p = o->prototype(); if (p && p->internalClass == l->classList[1]) { @@ -668,13 +789,13 @@ void Lookup::setterInsert1(Lookup *l, const ValueRef object, const ValueRef valu } } - l->setter = setterGeneric; - setterGeneric(l, object, value); + l->setter = setterFallback; + setterFallback(l, object, value); } void Lookup::setterInsert2(Lookup *l, const ValueRef object, const ValueRef value) { - Object *o = object->asObject(); + Object *o = static_cast<Object *>(object->asManaged()); if (o && o->internalClass == l->classList[0]) { Object *p = o->prototype(); if (p && p->internalClass == l->classList[1]) { @@ -689,8 +810,27 @@ void Lookup::setterInsert2(Lookup *l, const ValueRef object, const ValueRef valu } } - l->setter = setterGeneric; - setterGeneric(l, object, value); + l->setter = setterFallback; + setterFallback(l, object, value); +} + +void Lookup::setter0setter0(Lookup *l, const ValueRef object, const ValueRef value) +{ + Object *o = static_cast<Object *>(object->asManaged()); + if (o) { + if (o->internalClass == l->classList[0]) { + o->memberData[l->index] = *value; + return; + } + if (o->internalClass == l->classList[1]) { + o->memberData[l->index2] = *value; + return; + } + } + + l->setter = setterFallback; + setterFallback(l, object, value); + } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h index 7f107bf8eb..3dd2c7f6ce 100644 --- a/src/qml/jsruntime/qv4lookup_p.h +++ b/src/qml/jsruntime/qv4lookup_p.h @@ -71,7 +71,10 @@ struct Lookup { unsigned type; }; }; - int level; + union { + int level; + uint index2; + }; uint index; String *name; @@ -84,9 +87,15 @@ struct Lookup { static void indexedSetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index, const ValueRef v); static ReturnedValue getterGeneric(Lookup *l, const ValueRef object); + static ReturnedValue getterTwoClasses(Lookup *l, const ValueRef object); + static ReturnedValue getterFallback(Lookup *l, const ValueRef object); + static ReturnedValue getter0(Lookup *l, const ValueRef object); static ReturnedValue getter1(Lookup *l, const ValueRef object); static ReturnedValue getter2(Lookup *l, const ValueRef object); + static ReturnedValue getter0getter0(Lookup *l, const ValueRef object); + static ReturnedValue getter0getter1(Lookup *l, const ValueRef object); + static ReturnedValue getter1getter1(Lookup *l, const ValueRef object); static ReturnedValue getterAccessor0(Lookup *l, const ValueRef object); static ReturnedValue getterAccessor1(Lookup *l, const ValueRef object); static ReturnedValue getterAccessor2(Lookup *l, const ValueRef object); @@ -107,10 +116,13 @@ struct Lookup { static ReturnedValue globalGetterAccessor2(Lookup *l, ExecutionContext *ctx); static void setterGeneric(Lookup *l, const ValueRef object, const ValueRef value); + static void setterTwoClasses(Lookup *l, const ValueRef object, const ValueRef value); + static void setterFallback(Lookup *l, const ValueRef object, const ValueRef value); static void setter0(Lookup *l, const ValueRef object, const ValueRef value); static void setterInsert0(Lookup *l, const ValueRef object, const ValueRef value); static void setterInsert1(Lookup *l, const ValueRef object, const ValueRef value); static void setterInsert2(Lookup *l, const ValueRef object, const ValueRef value); + static void setter0setter0(Lookup *l, const ValueRef object, const ValueRef value); ReturnedValue lookup(ValueRef thisObject, Object *obj, PropertyAttributes *attrs); ReturnedValue lookup(Object *obj, PropertyAttributes *attrs); diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index f5c1be767f..37dc0a8bfb 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -485,6 +485,8 @@ ReturnedValue Object::getLookup(Managed *m, Lookup *l) l->getter = Lookup::getter1; else if (l->level == 2) l->getter = Lookup::getter2; + else + l->getter = Lookup::getterFallback; return v; } else { if (l->level == 0) @@ -493,6 +495,8 @@ ReturnedValue Object::getLookup(Managed *m, Lookup *l) l->getter = Lookup::getterAccessor1; else if (l->level == 2) l->getter = Lookup::getterAccessor2; + else + l->getter = Lookup::getterFallback; return v; } } @@ -544,8 +548,11 @@ void Object::setLookup(Managed *m, Lookup *l, const ValueRef value) } o = o->prototype(); l->classList[2] = o->internalClass; - if (!o->prototype()) + if (!o->prototype()) { l->setter = Lookup::setterInsert2; + return; + } + l->setter = Lookup::setterGeneric; } void Object::advanceIterator(Managed *m, ObjectIterator *it, StringRef name, uint *index, Property *pd, PropertyAttributes *attrs) |