diff options
author | Lars Knoll <lars.knoll@digia.com> | 2013-11-14 22:08:00 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-12-04 09:45:25 +0100 |
commit | 8e25658011699596996e80d3d08f17ef2efa0634 (patch) | |
tree | 1b8322bd409e274c837e20dc64187fff3431fef2 /src/qml/jsruntime | |
parent | 0e864f2814959b0861ea5b07108893c2c4a047c6 (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.cpp | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 51 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject_p.h | 9 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4managed.cpp | 11 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4managed_p.h | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 30 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4string.cpp | 1 |
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, |