Update TCO to handle tail recursion with non-identical argument counts

Signed-off-by: HyukWoo Park <hyukwoo.park@samsung.com>
This commit is contained in:
HyukWoo Park 2023-11-09 19:49:14 +09:00 committed by Patrick Kim
commit 11d9427bb8
2 changed files with 15 additions and 5 deletions

View file

@ -1540,7 +1540,7 @@ Value Interpreter::interpret(ExecutionState* state, ByteCodeBlock* byteCodeBlock
TailRecursion* code = (TailRecursion*)programCounter;
const Value& callee = registerFile[code->m_calleeIndex];
if (UNLIKELY((callee != Value(state->resolveCallee())) || (state->m_argc != code->m_argumentCount))) {
if (UNLIKELY((callee != Value(state->resolveCallee())) || (state->initTCO() && (state->m_argc != code->m_argumentCount)))) {
// goto slow path
return InterpreterSlowPath::tailRecursionSlowCase(*state, code, callee, registerFile);
}
@ -1548,12 +1548,13 @@ Value Interpreter::interpret(ExecutionState* state, ByteCodeBlock* byteCodeBlock
// fast tail recursion
ASSERT(callee.isPointerValue() && callee.asPointerValue()->isScriptFunctionObject());
ASSERT(callee.asPointerValue()->asScriptFunctionObject()->codeBlock() == byteCodeBlock->codeBlock());
ASSERT(state->m_argc == code->m_argumentCount);
ASSERT(!state->initTCO() || (state->m_argc == code->m_argumentCount));
if (code->m_argumentCount) {
// At the start of tail call, we need to allocate a buffer for arguments
// because recursive tail call reuses this buffer
if (UNLIKELY(!state->initTCO())) {
state->m_argc = code->m_argumentCount;
Value* newArgs = ALLOCA(sizeof(Value) * code->m_argumentCount, Value);
state->setTCOArguments(newArgs);
}
@ -1564,6 +1565,8 @@ Value Interpreter::interpret(ExecutionState* state, ByteCodeBlock* byteCodeBlock
}
}
state->setInitTCO();
// set this value
registerFile[byteCodeBlock->m_requiredOperandRegisterNumber] = state->inStrictMode() ? Value() : state->context()->globalObjectProxy();
@ -1582,7 +1585,7 @@ Value Interpreter::interpret(ExecutionState* state, ByteCodeBlock* byteCodeBlock
const Value& callee = registerFile[code->m_calleeIndex];
const Value& receiver = registerFile[code->m_receiverIndex];
if (UNLIKELY((callee != Value(state->resolveCallee())) || (state->m_argc != code->m_argumentCount))) {
if (UNLIKELY((callee != Value(state->resolveCallee())) || (state->initTCO() && (state->m_argc != code->m_argumentCount)))) {
// goto slow path
return InterpreterSlowPath::tailRecursionWithReceiverSlowCase(*state, code, callee, receiver, registerFile);
}
@ -1590,12 +1593,13 @@ Value Interpreter::interpret(ExecutionState* state, ByteCodeBlock* byteCodeBlock
// fast tail recursion with receiver
ASSERT(callee.isPointerValue() && callee.asPointerValue()->isScriptFunctionObject());
ASSERT(callee.asPointerValue()->asScriptFunctionObject()->codeBlock() == byteCodeBlock->codeBlock());
ASSERT(state->m_argc == code->m_argumentCount);
ASSERT(!state->initTCO() || (state->m_argc == code->m_argumentCount));
if (code->m_argumentCount) {
// At the start of tail call, we need to allocate a buffer for arguments
// because recursive tail call reuses this buffer
if (UNLIKELY(!state->initTCO())) {
state->m_argc = code->m_argumentCount;
Value* newArgs = ALLOCA(sizeof(Value) * code->m_argumentCount, Value);
state->setTCOArguments(newArgs);
}
@ -1606,6 +1610,8 @@ Value Interpreter::interpret(ExecutionState* state, ByteCodeBlock* byteCodeBlock
}
}
state->setInitTCO();
// set this value (receiver) // FIXME
if (state->inStrictMode()) {
registerFile[byteCodeBlock->m_requiredOperandRegisterNumber] = receiver;