Skip to content

Commit

Permalink
Add fine-tuned TCO condition check in parsing phase
Browse files Browse the repository at this point in the history
* check argument count and name of callee

Signed-off-by: HyukWoo Park <[email protected]>
  • Loading branch information
clover2123 authored and ksh8281 committed Nov 22, 2023
1 parent 1a5b10b commit 5bc5fc7
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 3 deletions.
16 changes: 15 additions & 1 deletion src/parser/CodeBlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -616,10 +616,24 @@ class InterpretedCodeBlock : public CodeBlock {
}

// for TCO
bool isTailRecursionTarget() const
bool isTailRecursionTarget(size_t argc, const AtomicString& calleeName) const
{
// global scope cannot create a return statement, neither tail recursion
ASSERT(!isGlobalScope());

// check argc
if (m_parameterCount != argc) {
return false;
}

#ifndef ESCARGOT_ENABLE_TEST
// check callee name
// this check is disabled in test build to pass test262 tco-related test cases
if (m_functionName.string()->length() && m_functionName != calleeName) {
return false;
}
#endif

return (!m_canAllocateVariablesOnStack || m_isArrowFunctionExpression || m_isClassConstructor || m_isDerivedClassConstructor || m_isClassMethod || m_isClassStaticMethod || m_isGenerator || m_isAsync || m_usesArgumentsObject) != true;
}

Expand Down
6 changes: 4 additions & 2 deletions src/parser/ast/CallExpressionNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,8 @@ class CallExpressionNode : public ExpressionNode {
if (dstRegister == context->m_returnRegister) {
// Try tail recursion optimization (TCO)
isTailCall = true;
bool isTailRecursion = context->m_codeBlock->isTailRecursionTarget();
const AtomicString& calleeName = m_callee->asMemberExpression()->property()->isIdentifier() ? m_callee->asMemberExpression()->property()->asIdentifier()->name() : AtomicString();
bool isTailRecursion = context->m_codeBlock->isTailRecursionTarget(m_arguments.size(), calleeName);
if (UNLIKELY(context->tryCatchWithBlockStatementCount())) {
codeBlock->pushCode(CallWithReceiver(ByteCodeLOC(m_loc.index), receiverIndex, calleeIndex, argumentsStartIndex, dstRegister, m_arguments.size()), context, this->m_loc.index);
} else {
Expand All @@ -434,7 +435,8 @@ class CallExpressionNode : public ExpressionNode {
if (dstRegister == context->m_returnRegister) {
// Try tail recursion optimization (TCO)
isTailCall = true;
bool isTailRecursion = context->m_codeBlock->isTailRecursionTarget();
const AtomicString& calleeName = m_callee->isIdentifier() ? m_callee->asIdentifier()->name() : AtomicString();
bool isTailRecursion = context->m_codeBlock->isTailRecursionTarget(m_arguments.size(), calleeName);
if (UNLIKELY(context->tryCatchWithBlockStatementCount())) {
if (isTailRecursion) {
codeBlock->pushCode(TailRecursionInTry(ByteCodeLOC(m_loc.index), calleeIndex, argumentsStartIndex, dstRegister, m_arguments.size()), context, this->m_loc.index);
Expand Down

0 comments on commit 5bc5fc7

Please sign in to comment.