diff options
author | Ulf Hermann <[email protected]> | 2024-04-30 11:55:01 +0200 |
---|---|---|
committer | Ulf Hermann <[email protected]> | 2024-05-14 14:16:57 +0200 |
commit | 8b6a9403bf2e04d34b9b07d2780186029fab99d0 (patch) | |
tree | 3849365bf54aea733e6ee3af0165bcb95215c9d2 /src/qml/jsruntime/qv4runtime.cpp | |
parent | 2f7a97806e950967ba67b6f07614ca0def8bda48 (diff) |
V4: Slim down FunctionObject
Most FunctionObjects do not actually need their custom jsCall members.
They will only call the functions from the vtable anyway. FunctionObject
can therefore be split into a static and a dynamic variant. Only the
dyanmic variant needs to carry (and invoke) the extra pointer. The
jsCallWithMetaTypes pointer is completely pointless because none of the
dynamic functions actually implement it.
Furthermore, the QV4::Function and QV4::ExecutionContext pointers in
FunctionObject are only needed by actual JavaScript functions. The
builtins that like to be dynamic functions never need them. Therefore,
split out another class for this.
In the generic FunctionObject, we need the capability to decide at run
time whether the function shall be a constructor or not. Add a flag to
replace the check for jsCallAsConstructor.
Also, where we can, avoid the pessimization of checking whether a
function is a constructor before trying to call it as constructor.
Rather have the default implementation throw the exception.
As a side effect, for most functions we don't need an ExecutionContext
anymore. The engine is enough.
Task-number: QTBUG-124662
Change-Id: Iac657fa71288dd6ec230a33de2986ba3bcf4628c
Reviewed-by: Fabian Kosmale <[email protected]>
Diffstat (limited to 'src/qml/jsruntime/qv4runtime.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index c51c94ffe4..2b1fb8f3b6 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1029,7 +1029,7 @@ ReturnedValue Runtime::LoadName::call(ExecutionEngine *engine, int nameIndex) static Object *getSuperBase(Scope &scope) { - ScopedFunctionObject f(scope); + Scoped<JavaScriptFunctionObject> f(scope); ScopedObject homeObject(scope); if (scope.engine->currentStackFrame->isJSTypesFrame()) { JSTypesStackFrame *frame = static_cast<JSTypesStackFrame *>( @@ -1188,7 +1188,7 @@ ReturnedValue Runtime::LoadSuperConstructor::call(ExecutionEngine *engine, const if (!f) return engine->throwTypeError(); Heap::Object *c = static_cast<const Object &>(t).getPrototypeOf(); - if (!c->vtable()->isFunctionObject || !static_cast<Heap::FunctionObject *>(c)->isConstructor()) + if (!c->vtable()->isFunctionObject || !static_cast<Heap::FunctionObject *>(c)->isConstructor) return engine->throwTypeError(); return c->asReturnedValue(); } @@ -1627,20 +1627,23 @@ ReturnedValue Runtime::TailCall::call(JSTypesStackFrame *frame, ExecutionEngine int argc = tos[StackOffsets::tailCall_argc].int_32(); Q_ASSERT(argc >= 0); - if (!function.isFunctionObject()) + const JavaScriptFunctionObject *jsfo = function.as<JavaScriptFunctionObject>(); + if (!jsfo) { + if (const FunctionObject *fo = function.as<FunctionObject>()) + return checkedResult(engine, fo->call(&thisObject, argv, argc)); return engine->throwTypeError(); + } - const FunctionObject &fo = static_cast<const FunctionObject &>(function); - if (!frame->callerCanHandleTailCall() || !fo.canBeTailCalled() || engine->debugger() - || unsigned(argc) > fo.formalParameterCount()) { + if (!frame->callerCanHandleTailCall() || !jsfo->canBeTailCalled() || engine->debugger() + || unsigned(argc) > jsfo->formalParameterCount()) { // Cannot tailcall, do a normal call: - return checkedResult(engine, fo.call(&thisObject, argv, argc)); + return checkedResult(engine, jsfo->call(&thisObject, argv, argc)); } memmove(frame->jsFrame->args, argv, argc * sizeof(Value)); - frame->init(fo.function(), frame->jsFrame->argValues<Value>(), argc, + frame->init(jsfo->function(), frame->jsFrame->argValues<Value>(), argc, frame->callerCanHandleTailCall()); - frame->setupJSFrame(frame->framePointer(), fo, fo.scope(), thisObject, + frame->setupJSFrame(frame->framePointer(), *jsfo, jsfo->scope(), thisObject, Primitive::undefinedValue()); engine->jsStackTop = frame->framePointer() + frame->requiredJSStackFrameSize(); frame->setPendingTailCall(true); |