aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2014-01-17 12:19:34 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-20 21:14:35 +0100
commit393108500832dcefa4c4def442a08f20d3fbc4cd (patch)
tree64676214630008b9f5434c933590d9adf9baf094 /src
parentbf6191f090b326eb0776cd4e921ddb56c8daa8a9 (diff)
Use lookups for indexed accesses
This speeds up reading array data from objects significantly. Change-Id: I5d17a7b3e7583a16dc76d1ee6cbc1d7134e4c2fa Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qv4compileddata.cpp4
-rw-r--r--src/qml/compiler/qv4compileddata_p.h3
-rw-r--r--src/qml/compiler/qv4compiler.cpp10
-rw-r--r--src/qml/compiler/qv4compiler_p.h1
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp8
-rw-r--r--src/qml/compiler/qv4isel_p.h1
-rw-r--r--src/qml/jsruntime/qv4lookup.cpp72
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h6
8 files changed, 104 insertions, 1 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index 9eac0e678d..717e7f4ba2 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -101,12 +101,16 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine)
l->setter = QV4::Lookup::setterGeneric;
else if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_GlobalGetter)
l->globalGetter = QV4::Lookup::globalGetterGeneric;
+ else if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_IndexedGetter)
+ l->indexedGetter = QV4::Lookup::indexedGetterGeneric;
for (int j = 0; j < QV4::Lookup::Size; ++j)
l->classList[j] = 0;
l->level = -1;
l->index = UINT_MAX;
l->name = runtimeStrings[compiledLookups[i].nameIndex].asString();
+ if (compiledLookups[i].type_and_flags == CompiledData::Lookup::Type_IndexedGetter)
+ l->engine = engine;
}
}
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index 83e8058be1..4208ec9441 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -102,7 +102,8 @@ struct Lookup
enum Type {
Type_Getter = 0x0,
Type_Setter = 0x1,
- Type_GlobalGetter = 2
+ Type_GlobalGetter = 2,
+ Type_IndexedGetter = 3
};
quint32 type_and_flags;
diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp
index 9041b04837..d18c43a969 100644
--- a/src/qml/compiler/qv4compiler.cpp
+++ b/src/qml/compiler/qv4compiler.cpp
@@ -72,6 +72,15 @@ int QV4::Compiler::JSUnitGenerator::getStringId(const QString &string) const
return stringToId.value(string);
}
+uint QV4::Compiler::JSUnitGenerator::registerIndexedGetterLookup()
+{
+ CompiledData::Lookup l;
+ l.type_and_flags = CompiledData::Lookup::Type_IndexedGetter;
+ l.nameIndex = 0;
+ lookups << l;
+ return lookups.size() - 1;
+}
+
uint QV4::Compiler::JSUnitGenerator::registerGetterLookup(const QString &name)
{
CompiledData::Lookup l;
@@ -81,6 +90,7 @@ uint QV4::Compiler::JSUnitGenerator::registerGetterLookup(const QString &name)
return lookups.size() - 1;
}
+
uint QV4::Compiler::JSUnitGenerator::registerSetterLookup(const QString &name)
{
CompiledData::Lookup l;
diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h
index 1596fcb622..4779b5d3c4 100644
--- a/src/qml/compiler/qv4compiler_p.h
+++ b/src/qml/compiler/qv4compiler_p.h
@@ -70,6 +70,7 @@ struct Q_QML_EXPORT JSUnitGenerator {
uint registerGetterLookup(const QString &name);
uint registerSetterLookup(const QString &name);
uint registerGlobalGetterLookup(const QString &name);
+ uint registerIndexedGetterLookup();
int registerRegExp(QQmlJS::V4IR::RegExp *regexp);
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index 415fdad8e9..6df94e713d 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -1015,6 +1015,14 @@ void InstructionSelection::setQObjectProperty(V4IR::Expr *source, V4IR::Expr *ta
void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target)
{
+ if (useFastLookups) {
+ uint lookup = registerIndexedGetterLookup();
+ generateLookupCall(target, lookup, qOffsetOf(QV4::Lookup, indexedGetter),
+ Assembler::PointerToValue(base),
+ Assembler::PointerToValue(index));
+ return;
+ }
+
#if 0 // QT_POINTER_SIZE == 8
V4IR::Temp *tbase = base->asTemp();
V4IR::Temp *tindex = index->asTemp();
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 5ddafc07ab..6f33098172 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -72,6 +72,7 @@ public:
void setUseFastLookups(bool b) { useFastLookups = b; }
int registerString(const QString &str) { return jsGenerator->registerString(str); }
+ uint registerIndexedGetterLookup() { return jsGenerator->registerIndexedGetterLookup(); }
uint registerGetterLookup(const QString &name) { return jsGenerator->registerGetterLookup(name); }
uint registerSetterLookup(const QString &name) { return jsGenerator->registerSetterLookup(name); }
uint registerGlobalGetterLookup(const QString &name) { return jsGenerator->registerGlobalGetterLookup(name); }
diff --git a/src/qml/jsruntime/qv4lookup.cpp b/src/qml/jsruntime/qv4lookup.cpp
index 80b8b08a1a..c9d22523a9 100644
--- a/src/qml/jsruntime/qv4lookup.cpp
+++ b/src/qml/jsruntime/qv4lookup.cpp
@@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE
using namespace QV4;
+
ReturnedValue Lookup::lookup(ValueRef thisObject, Object *obj, PropertyAttributes *attrs)
{
int i = 0;
@@ -107,6 +108,77 @@ ReturnedValue Lookup::lookup(Object *obj, PropertyAttributes *attrs)
return Primitive::emptyValue().asReturnedValue();
}
+ReturnedValue Lookup::indexedGetterGeneric(Lookup *l, const ValueRef object, const ValueRef index)
+{
+ if (object->isObject() && index->asArrayIndex() < UINT_MAX) {
+ l->indexedGetter = indexedGetterObjectInt;
+ return indexedGetterObjectInt(l, object, index);
+ }
+ return indexedGetterFallback(l, object, index);
+}
+
+ReturnedValue Lookup::indexedGetterFallback(Lookup *l, const ValueRef object, const ValueRef index)
+{
+ Q_UNUSED(l);
+ ExecutionContext *ctx = l->engine->currentContext();
+ Scope scope(ctx);
+ uint idx = index->asArrayIndex();
+
+ Scoped<Object> o(scope, object);
+ if (!o) {
+ if (idx < UINT_MAX) {
+ if (String *str = object->asString()) {
+ if (idx >= (uint)str->toQString().length()) {
+ return Encode::undefined();
+ }
+ const QString s = str->toQString().mid(idx, 1);
+ return scope.engine->newString(s)->asReturnedValue();
+ }
+ }
+
+ if (object->isNullOrUndefined()) {
+ QString message = QStringLiteral("Cannot read property '%1' of %2").arg(index->toQStringNoThrow()).arg(object->toQStringNoThrow());
+ return ctx->throwTypeError(message);
+ }
+
+ o = __qmljs_convert_to_object(ctx, object);
+ if (!o) // type error
+ return Encode::undefined();
+ }
+
+ if (idx < UINT_MAX) {
+ if (!o->arrayData->hasAttributes()) {
+ ScopedValue v(scope, o->arrayData->get(idx));
+ if (!v->isEmpty())
+ return v->asReturnedValue();
+ }
+
+ return o->getIndexed(idx);
+ }
+
+ ScopedString name(scope, index->toString(ctx));
+ if (scope.hasException())
+ return Encode::undefined();
+ return o->get(name);
+
+}
+
+
+ReturnedValue Lookup::indexedGetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index)
+{
+ uint idx = index->asArrayIndex();
+ if (idx == UINT_MAX || !object->isObject())
+ return indexedGetterGeneric(l, object, index);
+
+ Object *o = object->objectValue();
+ if (o->arrayData && o->arrayData->type == ArrayData::Simple) {
+ if (idx < static_cast<SimpleArrayData *>(o->arrayData)->len)
+ if (!o->arrayData->data[idx].isEmpty())
+ return o->arrayData->data[idx].asReturnedValue();
+ }
+
+ return indexedGetterFallback(l, object, index);
+}
ReturnedValue Lookup::getterGeneric(QV4::Lookup *l, const ValueRef object)
{
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index f47b603c15..50874411de 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -55,11 +55,13 @@ namespace QV4 {
struct Lookup {
enum { Size = 4 };
union {
+ ReturnedValue (*indexedGetter)(Lookup *l, const ValueRef object, const ValueRef index);
ReturnedValue (*getter)(Lookup *l, const ValueRef object);
ReturnedValue (*globalGetter)(Lookup *l, ExecutionContext *ctx);
void (*setter)(Lookup *l, const ValueRef object, const ValueRef v);
};
union {
+ ExecutionEngine *engine;
InternalClass *classList[Size];
struct {
void *dummy0;
@@ -72,6 +74,10 @@ struct Lookup {
uint index;
String *name;
+ static ReturnedValue indexedGetterGeneric(Lookup *l, const ValueRef object, const ValueRef index);
+ static ReturnedValue indexedGetterFallback(Lookup *l, const ValueRef object, const ValueRef index);
+ static ReturnedValue indexedGetterObjectInt(Lookup *l, const ValueRef object, const ValueRef index);
+
static ReturnedValue getterGeneric(Lookup *l, const ValueRef object);
static ReturnedValue getter0(Lookup *l, const ValueRef object);
static ReturnedValue getter1(Lookup *l, const ValueRef object);