aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4functionobject.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2024-05-06 17:18:09 +0200
committerUlf Hermann <ulf.hermann@qt.io>2024-05-14 14:17:02 +0200
commit1f13344e500e837e296212eaf3525e57e14cd055 (patch)
treecda35827cc5227793078f4620aad8e0593ed627d /src/qml/jsruntime/qv4functionobject.cpp
parent8b6a9403bf2e04d34b9b07d2780186029fab99d0 (diff)
V4: Move FunctionObject flags into VTable
These are really rather generic type traits that shouldn't be stored in individual objects. Moving them away slims down FunctionObject even more. FunctionObject doesn't add any extra overhead on top of Object anymore. You also cannot easily cast an object that doesn't implement any call methods to FunctionObject anymore. Therefore, we can derive from FunctionObject even if we only need to implement call methods in a further derived class. The fact that ProxyObject is not a FunctionObject but its derivatives are is already tested as part of the ecmascript test suite. Task-number: QTBUG-124662 Change-Id: I5632de8c54ac1d6a4b15c4926c655b87b475db49 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4functionobject.cpp')
-rw-r--r--src/qml/jsruntime/qv4functionobject.cpp35
1 files changed, 15 insertions, 20 deletions
diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp
index 153e8964e8..7240500012 100644
--- a/src/qml/jsruntime/qv4functionobject.cpp
+++ b/src/qml/jsruntime/qv4functionobject.cpp
@@ -37,8 +37,6 @@ void Heap::FunctionObject::init(QV4::ExecutionEngine *engine, QV4::String *name)
ScopedFunctionObject f(s, this);
if (name)
f->setName(name);
-
- isConstructor = (vtable()->callAsConstructor != QV4::FunctionObject::virtualCallAsConstructor);
}
void Heap::FunctionObject::init(QV4::ExecutionEngine *engine, const QString &name)
@@ -100,22 +98,14 @@ ReturnedValue FunctionObject::name() const
return get(engine()->id_name());
}
-ReturnedValue FunctionObject::virtualCall(
- const FunctionObject *f, const Value *, const Value *, int)
-{
- return f->engine()->throwTypeError(QStringLiteral("Function can only be called with |new|."));
-}
-
-void FunctionObject::virtualCallWithMetaTypes(
- const FunctionObject *f, QObject *, void **, const QMetaType *, int)
+ReturnedValue FunctionObject::failCall() const
{
- f->engine()->throwTypeError(QStringLiteral("Function can only be called with |new|."));
+ return engine()->throwTypeError(QStringLiteral("Function can only be called with |new|."));
}
-ReturnedValue FunctionObject::virtualCallAsConstructor(
- const FunctionObject *f, const Value *, int, const Value *)
+ReturnedValue FunctionObject::failCallAsConstructor() const
{
- return f->engine()->throwTypeError(QStringLiteral("Function is not a constructor."));
+ return engine()->throwTypeError(QStringLiteral("Function is not a constructor."));
}
void FunctionObject::virtualConvertAndCall(
@@ -431,7 +421,13 @@ ReturnedValue FunctionPrototype::method_bind(const FunctionObject *b, const Valu
boundArgs->set(scope.engine, i, argv[i + 1]);
}
- return BoundFunction::create(target, boundThis, boundArgs)->asReturnedValue();
+ if (target->isConstructor()) {
+ return scope.engine->memoryManager->allocate<BoundConstructor>(target, boundThis, boundArgs)
+ ->asReturnedValue();
+ }
+
+ return scope.engine->memoryManager->allocate<BoundFunction>(target, boundThis, boundArgs)
+ ->asReturnedValue();
}
ReturnedValue FunctionPrototype::method_hasInstance(const FunctionObject *, const Value *thisObject, const Value *argv, int argc)
@@ -569,7 +565,6 @@ void Heap::ArrowFunction::init(QV4::ExecutionContext *scope, Function *function,
Scope s(scope);
Q_ASSERT(internalClass && internalClass->verifyIndex(s.engine->id_length()->propertyKey(), Index_Length));
setProperty(s.engine, Index_Length, Value::fromInt32(int(function->compiledFunction->length)));
- canBeTailCalled = true;
}
void Heap::ScriptFunction::init(QV4::ExecutionContext *scope, Function *function)
@@ -725,9 +720,6 @@ void Heap::BoundFunction::init(
this->boundArgs.set(s.engine, boundArgs ? boundArgs->d() : nullptr);
this->boundThis.set(s.engine, boundThis);
- if (!target->isConstructor())
- isConstructor = false;
-
ScopedObject f(s, this);
ScopedValue l(s, target->get(engine->id_length()));
@@ -766,7 +758,10 @@ ReturnedValue BoundFunction::virtualCall(const FunctionObject *fo, const Value *
return checkedResult(v4, target->call(jsCallData));
}
-ReturnedValue BoundFunction::virtualCallAsConstructor(const FunctionObject *fo, const Value *argv, int argc, const Value *)
+DEFINE_OBJECT_VTABLE(BoundConstructor);
+
+ReturnedValue BoundConstructor::virtualCallAsConstructor(
+ const FunctionObject *fo, const Value *argv, int argc, const Value *)
{
const BoundFunction *f = static_cast<const BoundFunction *>(fo);
Scope scope(f->engine());