aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2016-12-09 10:47:57 +0100
committerLars Knoll <lars.knoll@qt.io>2016-12-11 17:00:29 +0000
commit4dd13bb4c3b8da79c7ae7f68d930cabff381ead0 (patch)
tree0fd13507bba269420dfb89e9d134065d2d8a4c7c
parent8c322d89ee13f15141f3115dcb5ee9567270ba32 (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.cpp8
-rw-r--r--src/qml/jsruntime/qv4engine_p.h2
-rw-r--r--src/qml/jsruntime/qv4function.cpp3
-rw-r--r--src/qml/jsruntime/qv4function_p.h10
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp80
-rw-r--r--src/qml/jsruntime/qv4functionobject_p.h22
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)