aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2014-03-13 21:28:30 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-18 09:05:57 +0100
commit09f3cfee8d5e34b5f7058586c52c3fc36d295d93 (patch)
tree34e2f85fc7914780db09365dc0654d9201f829f4 /src/qml/jsruntime
parent6b425f3182e57cb7cda6b559f3ee9673137706d0 (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.cpp192
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h14
-rw-r--r--src/qml/jsruntime/qv4object.cpp9
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)