diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2018-09-04 12:19:10 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2018-10-05 11:18:16 +0000 |
commit | 052d22e116957a170e290a49d077d3e9f290a237 (patch) | |
tree | 8d63f1b622a7c93d8b845c3d77f796f5ad18493b /src/qml/jsruntime/qv4runtime.cpp | |
parent | 08342d761369c3755778f6d69fa6f5907ae1aead (diff) |
ES7: Implement Tail Position Calls in the runtime
Change-Id: If1629109722496b3fd10b36b2376548440f2fee9
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4runtime.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4runtime.cpp | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 470629bd1f..66cd06ee1f 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -1536,13 +1536,32 @@ ReturnedValue Runtime::method_constructWithSpread(ExecutionEngine *engine, const return static_cast<const FunctionObject &>(function).callAsConstructor(arguments.argv, arguments.argc, &newTarget); } -ReturnedValue Runtime::method_tailCall(ExecutionEngine *engine, const Value &function, const Value &thisObject, Value *argv, int argc) +ReturnedValue Runtime::method_tailCall(CppStackFrame *frame, ExecutionEngine *engine) { - //### unwinding the stack, etc, is done in a subsequent patch + // IMPORTANT! The JIT assumes that this method has the same amount (or less) arguments than + // the jitted function, so it can safely do a tail call. + + Value *tos = engine->jsStackTop; + const Value &function = tos[StackOffsets::tailCall_function]; + const Value &thisObject = tos[StackOffsets::tailCall_thisObject]; + Value *argv = reinterpret_cast<Value *>(frame->jsFrame) + tos[StackOffsets::tailCall_argv].int_32(); + int argc = tos[StackOffsets::tailCall_argc].int_32(); + if (!function.isFunctionObject()) return engine->throwTypeError(); - return static_cast<const FunctionObject &>(function).call(&thisObject, argv, argc); + const FunctionObject &fo = static_cast<const FunctionObject &>(function); + if (!frame->callerCanHandleTailCall || !fo.canBeTailCalled() || engine->debugger()) { + // Cannot tailcall, do a normal call: + return fo.call(&thisObject, argv, argc); + } + + memcpy(frame->jsFrame->args, argv, argc * sizeof(Value)); + frame->init(engine, fo.function(), frame->jsFrame->args, argc, frame->callerCanHandleTailCall); + frame->setupJSFrame(frame->savedStackTop, fo, fo.scope(), thisObject, Primitive::undefinedValue()); + engine->jsStackTop = frame->savedStackTop + frame->requiredJSStackFrameSize(); + frame->pendingTailCall = true; + return Encode::undefined(); } void Runtime::method_throwException(ExecutionEngine *engine, const Value &value) |