diff options
author | Lars Knoll <lars.knoll@qt.io> | 2016-12-09 10:47:57 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2016-12-11 17:00:29 +0000 |
commit | 4dd13bb4c3b8da79c7ae7f68d930cabff381ead0 (patch) | |
tree | 0fd13507bba269420dfb89e9d134065d2d8a4c7c | |
parent | 8c322d89ee13f15141f3115dcb5ee9567270ba32 (diff) |
Get rid of SimpleScriptFunction
Now that the code paths are very similar, we can simply to the
check whether to do a fast or slow function call in
ScriptFunction::call/contruct. To make this fast, cache the
result of the required check in QV4::Function
Change-Id: I03085ca2beb83b1721b60b0d7b2ab4c9266d1e48
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 8 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine_p.h | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4function.cpp | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4function_p.h | 10 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 80 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject_p.h | 22 |
6 files changed, 31 insertions, 94 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index 0520bfe216..2b90b43eab 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -281,10 +281,10 @@ ExecutionEngine::ExecutionEngine(EvalISelFactory *factory) jsObjects[FunctionProto] = memoryManager->allocObject<FunctionPrototype>(functionProtoClass, objectPrototype()); functionClass = emptyClass->addMember(id_prototype(), Attr_NotEnumerable|Attr_NotConfigurable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_Prototype); - simpleScriptFunctionClass = functionClass->addMember(id_name(), Attr_ReadOnly, &index); - Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Name); - simpleScriptFunctionClass = simpleScriptFunctionClass->addMember(id_length(), Attr_ReadOnly, &index); - Q_ASSERT(index == Heap::SimpleScriptFunction::Index_Length); + scriptFunctionClass = functionClass->addMember(id_name(), Attr_ReadOnly, &index); + Q_ASSERT(index == Heap::ScriptFunction::Index_Name); + scriptFunctionClass = scriptFunctionClass->addMember(id_length(), Attr_ReadOnly, &index); + Q_ASSERT(index == Heap::ScriptFunction::Index_Length); protoClass = emptyClass->addMember(id_constructor(), Attr_NotEnumerable, &index); Q_ASSERT(index == Heap::FunctionObject::Index_ProtoConstructor); diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index bf6898001f..1c20ad30aa 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -255,7 +255,7 @@ public: InternalClass *stringClass; InternalClass *functionClass; - InternalClass *simpleScriptFunctionClass; + InternalClass *scriptFunctionClass; InternalClass *protoClass; InternalClass *regExpExecArrayClass; diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index e3f839afd2..358c2d079c 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -84,6 +84,9 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, internalClass = internalClass->addMember(compilationUnit->runtimeStrings[localsIndices[i]]->identifier, Attr_NotConfigurable); activationRequired = compiledFunction->nInnerFunctions > 0 || (compiledFunction->flags & (CompiledData::Function::HasDirectEval | CompiledData::Function::UsesArgumentsObject)); + + canUseSimpleCall = !needsActivation() && !(compiledFunction->flags & CompiledData::Function::HasCatchOrWith) && + !(compiledFunction->nFormals > QV4::Global::ReservedArgumentCount) && !isNamedExpression(); } Function::~Function() diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h index 802af43cdc..54d0528c42 100644 --- a/src/qml/jsruntime/qv4function_p.h +++ b/src/qml/jsruntime/qv4function_p.h @@ -71,6 +71,7 @@ struct Q_QML_EXPORT Function { uint nFormals; bool activationRequired; bool hasQmlDependencies; + bool canUseSimpleCall; Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function, ReturnedValue (*codePtr)(ExecutionEngine *, const uchar *)); @@ -91,14 +92,7 @@ struct Q_QML_EXPORT Function { inline bool needsActivation() const { return activationRequired; } - inline bool canUseSimpleFunction() const { - if (needsActivation() || - compiledFunction->flags & CompiledData::Function::HasCatchOrWith || - compiledFunction->nFormals > QV4::Global::ReservedArgumentCount || - isNamedExpression()) - return false; - return true; - } + inline bool canUseSimpleFunction() const { return canUseSimpleCall; } QQmlSourceLocation sourceLocation() const { diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index 93f707392c..0c1dc21347 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -194,10 +194,8 @@ void FunctionObject::markObjects(Heap::Base *that, ExecutionEngine *e) Object::markObjects(that, e); } -Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function, bool createProto) +Heap::FunctionObject *FunctionObject::createScriptFunction(ExecutionContext *scope, Function *function) { - if (function->canUseSimpleFunction()) - return scope->d()->engine->memoryManager->allocObject<SimpleScriptFunction>(scope, function, createProto); return scope->d()->engine->memoryManager->allocObject<ScriptFunction>(scope, function); } @@ -421,7 +419,10 @@ void ScriptFunction::construct(const Managed *that, Scope &scope, CallData *call Q_ASSERT(v4Function); ScopedContext c(scope, f->scope()); - c->call(scope, callData, v4Function, f); + if (v4Function->canUseSimpleCall) + c->simpleCall(scope, callData, v4Function); + else + c->call(scope, callData, v4Function, f); if (Q_UNLIKELY(v4->hasException)) { scope.result = Encode::undefined(); @@ -445,12 +446,13 @@ void ScriptFunction::call(const Managed *that, Scope &scope, CallData *callData) Q_ASSERT(v4Function); ScopedContext c(scope, f->scope()); - c->call(scope, callData, v4Function, f); + if (v4Function->canUseSimpleCall) + c->simpleCall(scope, callData, v4Function); + else + c->call(scope, callData, v4Function, f); } -DEFINE_OBJECT_VTABLE(SimpleScriptFunction); - -void Heap::SimpleScriptFunction::init(QV4::ExecutionContext *scope, Function *function, bool createProto) +void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function) { FunctionObject::init(); this->scope = scope->d(); @@ -463,16 +465,10 @@ void Heap::SimpleScriptFunction::init(QV4::ExecutionContext *scope, Function *fu Scope s(scope); ScopedFunctionObject f(s, this); - if (createProto) { - ScopedString name(s, function->name()); - f->init(name, createProto); - f->defineReadonlyProperty(scope->d()->engine->id_length(), Primitive::fromInt32(f->formalParameterCount())); - } else { - Q_ASSERT(internalClass && internalClass->find(s.engine->id_length()) == Index_Length); - Q_ASSERT(internalClass && internalClass->find(s.engine->id_name()) == Index_Name); - *propertyData(Index_Name) = function->name(); - *propertyData(Index_Length) = Primitive::fromInt32(f->formalParameterCount()); - } + ScopedString name(s, function->name()); + f->init(name, true); + Q_ASSERT(internalClass && internalClass->find(s.engine->id_length()) == Index_Length); + *propertyData(Index_Length) = Primitive::fromInt32(f->formalParameterCount()); if (scope->d()->strictMode) { ScopedProperty pd(s); @@ -483,53 +479,7 @@ void Heap::SimpleScriptFunction::init(QV4::ExecutionContext *scope, Function *fu } } -void SimpleScriptFunction::construct(const Managed *that, Scope &scope, CallData *callData) -{ - ExecutionEngine *v4 = scope.engine; - if (Q_UNLIKELY(v4->hasException)) { - scope.result = Encode::undefined(); - return; - } - CHECK_STACK_LIMITS(v4, scope); - - Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that)); - - InternalClass *ic = scope.engine->emptyClass; - ScopedObject proto(scope, f->protoForConstructor()); - callData->thisObject = v4->newObject(ic, proto); - - QV4::Function *v4Function = f->function(); - Q_ASSERT(v4Function); - - ScopedContext c(scope, f->scope()); - c->simpleCall(scope, callData, v4Function); - - if (Q_UNLIKELY(v4->hasException)) { - scope.result = Encode::undefined(); - } else if (!scope.result.isObject()) { - scope.result = callData->thisObject; - } -} - -void SimpleScriptFunction::call(const Managed *that, Scope &scope, CallData *callData) -{ - ExecutionEngine *v4 = scope.engine; - if (v4->hasException) { - scope.result = Encode::undefined(); - return; - } - CHECK_STACK_LIMITS(v4, scope); - - Scoped<SimpleScriptFunction> f(scope, static_cast<const SimpleScriptFunction *>(that)); - - QV4::Function *v4Function = f->function(); - Q_ASSERT(v4Function); - - ScopedContext c(scope, f->scope()); - c->simpleCall(scope, callData, v4Function); -} - -Heap::Object *SimpleScriptFunction::protoForConstructor() const +Heap::Object *ScriptFunction::protoForConstructor() const { Scope scope(engine()); ScopedObject p(scope, protoProperty()); diff --git a/src/qml/jsruntime/qv4functionobject_p.h b/src/qml/jsruntime/qv4functionobject_p.h index 56e3cb92f7..ee11d3c07e 100644 --- a/src/qml/jsruntime/qv4functionobject_p.h +++ b/src/qml/jsruntime/qv4functionobject_p.h @@ -105,15 +105,12 @@ struct IndexedBuiltinFunction : FunctionObject { uint index; }; -struct SimpleScriptFunction : FunctionObject { +struct ScriptFunction : FunctionObject { enum { Index_Name = FunctionObject::Index_Prototype + 1, Index_Length }; - void init(QV4::ExecutionContext *scope, Function *function, bool createProto = true); -}; - -struct ScriptFunction : SimpleScriptFunction { + void init(QV4::ExecutionContext *scope, Function *function); }; struct BoundFunction : FunctionObject { @@ -149,7 +146,7 @@ struct Q_QML_EXPORT FunctionObject: Object { static void construct(const Managed *that, Scope &scope, CallData *); static void call(const Managed *that, Scope &scope, CallData *d); - static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function, bool createProto = true); + static Heap::FunctionObject *createScriptFunction(ExecutionContext *scope, Function *function); ReturnedValue protoProperty() const { return propertyData(Heap::FunctionObject::Index_Prototype)->asReturnedValue(); } @@ -222,9 +219,9 @@ void Heap::IndexedBuiltinFunction::init(QV4::ExecutionContext *scope, uint index } -struct SimpleScriptFunction: FunctionObject { - V4_OBJECT2(SimpleScriptFunction, FunctionObject) - V4_INTERNALCLASS(simpleScriptFunctionClass) +struct ScriptFunction : FunctionObject { + V4_OBJECT2(ScriptFunction, FunctionObject) + V4_INTERNALCLASS(scriptFunctionClass) static void construct(const Managed *, Scope &scope, CallData *callData); static void call(const Managed *that, Scope &scope, CallData *callData); @@ -232,13 +229,6 @@ struct SimpleScriptFunction: FunctionObject { Heap::Object *protoForConstructor() const; }; -struct ScriptFunction: SimpleScriptFunction { - V4_OBJECT2(ScriptFunction, FunctionObject) - - static void construct(const Managed *, Scope &scope, CallData *callData); - static void call(const Managed *that, Scope &scope, CallData *callData); -}; - struct BoundFunction: FunctionObject { V4_OBJECT2(BoundFunction, FunctionObject) |