aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-11-14 22:08:00 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-12-04 09:45:25 +0100
commit8e25658011699596996e80d3d08f17ef2efa0634 (patch)
tree1b8322bd409e274c837e20dc64187fff3431fef2 /src/qml/jsruntime
parent0e864f2814959b0861ea5b07108893c2c4a047c6 (diff)
Speedup JS instanceof operator
Cache the prototype of the functionobject, and inline hasInstance. This removes a vtbl method and speeds things up quite a bit. Change-Id: Ic68f301f7e09763d445a98bffa2cd201303f902e Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4context.cpp1
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp51
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h9
-rw-r--r--src/qml/jsruntime/qv4managed.cpp11
-rw-r--r--src/qml/jsruntime/qv4managed_p.h5
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp30
-rw-r--r--src/qml/jsruntime/qv4string.cpp1
7 files changed, 50 insertions, 58 deletions
diff --git a/src/qml/jsruntime/qv4context.cpp b/src/qml/jsruntime/qv4context.cpp
index 372c9ce54b..b0fb535361 100644
--- a/src/qml/jsruntime/qv4context.cpp
+++ b/src/qml/jsruntime/qv4context.cpp
@@ -58,7 +58,6 @@ const ManagedVTable ExecutionContext::static_vtbl =
markObjects,
destroy,
0 /*collectDeletables*/,
- hasInstance,
0,
0,
0,
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 037f06cd35..32ef98327b 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -81,6 +81,8 @@ FunctionObject::FunctionObject(ExecutionContext *scope, const StringRef name, bo
, formalParameterCount(0)
, varCount(0)
, function(0)
+ , protoCacheClass(0)
+ , protoCacheIndex(UINT_MAX)
{
init(name, createProto);
}
@@ -93,6 +95,8 @@ FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, boo
, formalParameterCount(0)
, varCount(0)
, function(0)
+ , protoCacheClass(0)
+ , protoCacheIndex(UINT_MAX)
{
// set the name to something here, so that a gc run a few lines below doesn't crash on it
this->name = scope->engine->id_undefined;
@@ -158,33 +162,6 @@ ReturnedValue FunctionObject::newInstance()
return construct(callData);
}
-bool FunctionObject::hasInstance(Managed *that, const ValueRef value)
-{
- Scope scope(that->internalClass->engine);
- ScopedFunctionObject f(scope, static_cast<FunctionObject *>(that));
-
- ScopedObject v(scope, value);
- if (!v)
- return false;
-
- Scoped<Object> o(scope, f->get(scope.engine->id_prototype));
- if (!o) {
- scope.engine->current->throwTypeError();
- return false;
- }
-
- while (v) {
- v = v->prototype();
-
- if (! v)
- break;
- else if (o.getPointer() == v)
- return true;
- }
-
- return false;
-}
-
ReturnedValue FunctionObject::construct(Managed *that, CallData *)
{
ExecutionEngine *v4 = that->internalClass->engine;
@@ -231,6 +208,19 @@ FunctionObject *FunctionObject::creatScriptFunction(ExecutionContext *scope, Fun
return new (scope->engine->memoryManager) SimpleScriptFunction(scope, function);
}
+ReturnedValue FunctionObject::protoProperty()
+{
+ if (protoCacheClass != internalClass) {
+ protoCacheClass = internalClass;
+ protoCacheIndex = internalClass->find(internalClass->engine->id_prototype);
+ }
+ if (protoCacheIndex < UINT_MAX) {
+ if (internalClass->propertyData.at(protoCacheIndex).isData())
+ return memberData[protoCacheIndex].value.asReturnedValue();
+ }
+ return get(internalClass->engine->id_prototype);
+}
+
DEFINE_MANAGED_VTABLE(FunctionCtor);
@@ -667,6 +657,7 @@ BoundFunction::BoundFunction(ExecutionContext *scope, FunctionObjectRef target,
, boundArgs(boundArgs)
{
vtbl = &static_vtbl;
+ subtype = FunctionObject::BoundFunction;
this->boundThis = boundThis;
Scope s(scope);
@@ -718,12 +709,6 @@ ReturnedValue BoundFunction::construct(Managed *that, CallData *dd)
return f->target->construct(callData);
}
-bool BoundFunction::hasInstance(Managed *that, const ValueRef value)
-{
- BoundFunction *f = static_cast<BoundFunction *>(that);
- return FunctionObject::hasInstance(f->target, value);
-}
-
void BoundFunction::markObjects(Managed *that, ExecutionEngine *e)
{
BoundFunction *o = static_cast<BoundFunction *>(that);
diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h
index 2fc36d862f..c4fd49bec5 100644
--- a/src/qml/jsruntime/qv4functionobject_p.h
+++ b/src/qml/jsruntime/qv4functionobject_p.h
@@ -97,7 +97,8 @@ struct Q_QML_EXPORT FunctionObject: Object {
// Used with Managed::subType
enum FunctionType {
RegularFunction = 0,
- WrappedQtMethod = 1
+ WrappedQtMethod = 1,
+ BoundFunction
};
enum {
@@ -112,6 +113,8 @@ struct Q_QML_EXPORT FunctionObject: Object {
unsigned int formalParameterCount;
unsigned int varCount;
Function *function;
+ InternalClass *protoCacheClass;
+ uint protoCacheIndex;
FunctionObject(ExecutionContext *scope, const StringRef name, bool createProto = false);
FunctionObject(ExecutionContext *scope, const QString &name = QString(), bool createProto = false);
@@ -136,11 +139,12 @@ struct Q_QML_EXPORT FunctionObject: Object {
static FunctionObject *creatScriptFunction(ExecutionContext *scope, Function *function);
+ ReturnedValue protoProperty();
+
protected:
FunctionObject(InternalClass *ic);
static void markObjects(Managed *that, ExecutionEngine *e);
- static bool hasInstance(Managed *that, const ValueRef value);
static void destroy(Managed *that)
{ static_cast<FunctionObject*>(that)->~FunctionObject(); }
};
@@ -235,7 +239,6 @@ struct BoundFunction: FunctionObject {
static void destroy(Managed *);
static void markObjects(Managed *that, ExecutionEngine *e);
- static bool hasInstance(Managed *that, const ValueRef value);
};
}
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index 6455a08037..895ae8d91b 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -52,7 +52,6 @@ const ManagedVTable Managed::static_vtbl =
0 /*markObjects*/,
destroy,
0 /*collectDeletables*/,
- hasInstance,
0,
0,
0,
@@ -178,11 +177,6 @@ QString Managed::className() const
return QString::fromLatin1(s);
}
-bool Managed::hasInstance(Managed *m, const ValueRef)
-{
- return m->engine()->current->throwTypeError();
-}
-
ReturnedValue Managed::construct(Managed *m, CallData *)
{
return m->engine()->current->throwTypeError();
@@ -208,11 +202,6 @@ bool Managed::isEqualTo(Managed *, Managed *)
return false;
}
-bool Managed::hasInstance(const ValueRef v)
-{
- return vtbl->hasInstance(this, v);
-}
-
ReturnedValue Managed::get(const StringRef name, bool *hasProperty)
{
return vtbl->get(this, name, hasProperty);
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 47ac5e05e4..220363efff 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -84,7 +84,6 @@ struct ManagedVTable
void (*markObjects)(Managed *, ExecutionEngine *e);
void (*destroy)(Managed *);
void (*collectDeletables)(Managed *, GCDeletable **deletable);
- bool (*hasInstance)(Managed *, const ValueRef value);
ReturnedValue (*get)(Managed *, const StringRef name, bool *hasProperty);
ReturnedValue (*getIndexed)(Managed *, uint index, bool *hasProperty);
void (*put)(Managed *, const StringRef name, const ValueRef value);
@@ -108,7 +107,6 @@ const QV4::ManagedVTable classname::static_vtbl = \
markObjects, \
destroy, \
0, \
- hasInstance, \
get, \
getIndexed, \
put, \
@@ -132,7 +130,6 @@ const QV4::ManagedVTable classname::static_vtbl = \
markObjects, \
destroy, \
collectDeletables, \
- hasInstance, \
get, \
getIndexed, \
put, \
@@ -240,7 +237,6 @@ public:
*reinterpret_cast<Managed **>(this) = m;
}
- bool hasInstance(const ValueRef v);
ReturnedValue construct(CallData *d);
ReturnedValue call(CallData *d);
ReturnedValue get(const StringRef name, bool *hasProperty = 0);
@@ -263,7 +259,6 @@ public:
Property *advanceIterator(ObjectIterator *it, StringRef name, uint *index, PropertyAttributes *attributes);
static void destroy(Managed *that) { that->_data = 0; }
- static bool hasInstance(Managed *that, const ValueRef value);
static ReturnedValue construct(Managed *m, CallData *d);
static ReturnedValue call(Managed *m, CallData *);
static ReturnedValue getLookup(Managed *m, Lookup *);
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index 50fea04b2f..62923b90f9 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -300,12 +300,34 @@ ReturnedValue __qmljs_delete_name(ExecutionContext *ctx, const StringRef name)
QV4::ReturnedValue __qmljs_instanceof(ExecutionContext *ctx, const ValueRef left, const ValueRef right)
{
- Object *o = right->asObject();
- if (!o)
+ FunctionObject *f = right->asFunctionObject();
+ if (!f)
return ctx->throwTypeError();
- bool r = o->hasInstance(left);
- return Encode(r);
+ if (f->subtype == FunctionObject::BoundFunction)
+ f = static_cast<BoundFunction *>(f)->target;
+
+ Scope scope(ctx->engine);
+ ScopedObject v(scope, left);
+ if (!v)
+ return Encode(false);
+
+ Scoped<Object> o(scope, f->protoProperty());
+ if (!o) {
+ scope.engine->current->throwTypeError();
+ return Encode(false);
+ }
+
+ while (v) {
+ v = v->prototype();
+
+ if (! v)
+ break;
+ else if (o.getPointer() == v)
+ return Encode(true);
+ }
+
+ return Encode(false);
}
QV4::ReturnedValue __qmljs_in(ExecutionContext *ctx, const ValueRef left, const ValueRef right)
diff --git a/src/qml/jsruntime/qv4string.cpp b/src/qml/jsruntime/qv4string.cpp
index 0e43d03987..7ac83ced02 100644
--- a/src/qml/jsruntime/qv4string.cpp
+++ b/src/qml/jsruntime/qv4string.cpp
@@ -108,7 +108,6 @@ const ManagedVTable String::static_vtbl =
markObjects,
destroy,
0 /*collectDeletables*/,
- hasInstance,
get,
getIndexed,
put,