Skip to content

Commit

Permalink
Expand TCO on nullish and conditional expression
Browse files Browse the repository at this point in the history
Signed-off-by: HyukWoo Park <[email protected]>
  • Loading branch information
clover2123 authored and ksh8281 committed May 11, 2023
1 parent f621248 commit 0285779
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 21 deletions.
29 changes: 24 additions & 5 deletions src/parser/ast/BinaryExpressionNullishCoalescingNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,38 @@ class BinaryExpressionNullishCoalescingNode : public ExpressionNode {
context->m_canSkipCopyToRegister = false;
}

size_t resultRegisterExpected = dstRegister;
m_left->generateExpressionByteCode(codeBlock, context, dstRegister);

m_left->generateExpressionByteCode(codeBlock, context, resultRegisterExpected);

codeBlock->pushCode<JumpIfUndefinedOrNull>(JumpIfUndefinedOrNull(ByteCodeLOC(m_loc.index), true, resultRegisterExpected), context, this->m_loc.index);
codeBlock->pushCode<JumpIfUndefinedOrNull>(JumpIfUndefinedOrNull(ByteCodeLOC(m_loc.index), true, dstRegister), context, this->m_loc.index);
size_t pos = codeBlock->lastCodePosition<JumpIfUndefinedOrNull>();

m_right->generateExpressionByteCode(codeBlock, context, resultRegisterExpected);
m_right->generateExpressionByteCode(codeBlock, context, dstRegister);
codeBlock->peekCode<JumpIfUndefinedOrNull>(pos)->m_jumpPosition = codeBlock->currentCodeSize();

context->m_canSkipCopyToRegister = directBefore;
}

#if defined(ENABLE_TCO)
virtual void generateTCOExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context, ByteCodeRegisterIndex dstRegister, bool& isTailCall) override
{
bool isSlow = !canUseDirectRegister(context, m_left, m_right);
bool directBefore = context->m_canSkipCopyToRegister;
if (isSlow) {
context->m_canSkipCopyToRegister = false;
}

m_left->generateExpressionByteCode(codeBlock, context, dstRegister);

codeBlock->pushCode<JumpIfUndefinedOrNull>(JumpIfUndefinedOrNull(ByteCodeLOC(m_loc.index), true, dstRegister), context, this->m_loc.index);
size_t pos = codeBlock->lastCodePosition<JumpIfUndefinedOrNull>();

// try TCO only for right hand-side because we need to check the result of left hand-side expression
m_right->generateTCOExpressionByteCode(codeBlock, context, dstRegister, isTailCall);
codeBlock->peekCode<JumpIfUndefinedOrNull>(pos)->m_jumpPosition = codeBlock->currentCodeSize();

context->m_canSkipCopyToRegister = directBefore;
}
#endif

virtual void iterateChildrenIdentifier(const std::function<void(AtomicString name, bool isAssignment)>& fn) override
{
Expand Down
8 changes: 3 additions & 5 deletions src/parser/ast/CallExpressionNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ class CallExpressionNode : public ExpressionNode {
}

#if defined(ENABLE_TCO)
virtual void generateTCOExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context, ByteCodeRegisterIndex dstRegister, bool& skipEnd) override
virtual void generateTCOExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context, ByteCodeRegisterIndex dstRegister, bool& isTailCall) override
{
if (m_callee->isIdentifier() && m_callee->asIdentifier()->name().string()->equals("eval")) {
ByteCodeRegisterIndex evalIndex = context->getRegister();
Expand Down Expand Up @@ -416,8 +416,7 @@ class CallExpressionNode : public ExpressionNode {
} else if (isCalleeHasReceiver) {
if (dstRegister == context->m_returnRegister) {
// Try tail recursion optimization (TCO)
ASSERT(!skipEnd);
skipEnd = true;
isTailCall = true;
if (context->m_codeBlock->isTailRecursionTarget()) {
codeBlock->pushCode(TailRecursionWithReceiver(ByteCodeLOC(m_loc.index), receiverIndex, calleeIndex, argumentsStartIndex, m_arguments.size()), context, this->m_loc.index);
} else {
Expand All @@ -429,8 +428,7 @@ class CallExpressionNode : public ExpressionNode {
} else {
if (dstRegister == context->m_returnRegister) {
// Try tail recursion optimization (TCO)
ASSERT(!skipEnd);
skipEnd = true;
isTailCall = true;
if (context->m_codeBlock->isTailRecursionTarget()) {
codeBlock->pushCode(TailRecursion(ByteCodeLOC(m_loc.index), calleeIndex, argumentsStartIndex, m_arguments.size()), context, this->m_loc.index);
} else {
Expand Down
26 changes: 24 additions & 2 deletions src/parser/ast/ConditionalExpressionNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ class ConditionalExpressionNode : public ExpressionNode {
virtual ASTNodeType type() override { return ASTNodeType::ConditionalExpression; }
virtual void generateExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context, ByteCodeRegisterIndex dstRegister) override
{
size_t resultRegisterExpected = dstRegister;

size_t testReg = m_test->getRegister(codeBlock, context);
m_test->generateExpressionByteCode(codeBlock, context, testReg);
codeBlock->pushCode(JumpIfFalse(ByteCodeLOC(m_loc.index), testReg), context, this->m_loc.index);
Expand All @@ -59,6 +57,30 @@ class ConditionalExpressionNode : public ExpressionNode {
jumpForEndOfConsequence->m_jumpPosition = codeBlock->currentCodeSize();
}

#if defined(ENABLE_TCO)
virtual void generateTCOExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context, ByteCodeRegisterIndex dstRegister, bool& isTailCall) override
{
size_t testReg = m_test->getRegister(codeBlock, context);
m_test->generateExpressionByteCode(codeBlock, context, testReg);
codeBlock->pushCode(JumpIfFalse(ByteCodeLOC(m_loc.index), testReg), context, this->m_loc.index);

// give testReg
context->giveUpRegister();

size_t jumpPosForTestIsFalse = codeBlock->lastCodePosition<JumpIfFalse>();
m_consequente->generateTCOExpressionByteCode(codeBlock, context, dstRegister, isTailCall);
codeBlock->pushCode(Jump(ByteCodeLOC(m_loc.index), SIZE_MAX), context, this->m_loc.index);
JumpIfFalse* jumpForTestIsFalse = codeBlock->peekCode<JumpIfFalse>(jumpPosForTestIsFalse);
size_t jumpPosForEndOfConsequence = codeBlock->lastCodePosition<Jump>();

jumpForTestIsFalse->m_jumpPosition = codeBlock->currentCodeSize();
m_alternate->generateTCOExpressionByteCode(codeBlock, context, dstRegister, isTailCall);

Jump* jumpForEndOfConsequence = codeBlock->peekCode<Jump>(jumpPosForEndOfConsequence);
jumpForEndOfConsequence->m_jumpPosition = codeBlock->currentCodeSize();
}
#endif

virtual void iterateChildrenIdentifier(const std::function<void(AtomicString name, bool isAssignment)>& fn) override
{
m_test->iterateChildrenIdentifier(fn);
Expand Down
4 changes: 2 additions & 2 deletions src/parser/ast/Node.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,9 @@ class Node {
}

#if defined(ENABLE_TCO)
virtual void generateTCOExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context, ByteCodeRegisterIndex dstRegister, bool& skipEnd)
virtual void generateTCOExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context, ByteCodeRegisterIndex dstRegister, bool& isTailCall)
{
UNUSED_PARAMETER(skipEnd);
UNUSED_PARAMETER(isTailCall);
generateExpressionByteCode(codeBlock, context, dstRegister);
}
#endif
Expand Down
7 changes: 4 additions & 3 deletions src/parser/ast/ReturnStatementNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ class ReturnStatementNode : public StatementNode {
}
context->giveUpRegister();
} else {
bool skipEnd = false;
bool isTailCall = false;
size_t r;
if (m_argument) {
r = m_argument->getRegister(codeBlock, context);
if (context->tryCatchWithBlockStatementCount() == 0) {
// consider tail recursion (TCO)
context->setReturnRegister(r);
#if defined(ENABLE_TCO)
m_argument->generateTCOExpressionByteCode(codeBlock, context, r, skipEnd);
m_argument->generateTCOExpressionByteCode(codeBlock, context, r, isTailCall);
#else
m_argument->generateExpressionByteCode(codeBlock, context, r);
#endif
Expand All @@ -81,7 +81,8 @@ class ReturnStatementNode : public StatementNode {
codeBlock->pushCode(LoadLiteral(ByteCodeLOC(m_loc.index), r, Value()), context, this->m_loc.index);
}

if (!skipEnd) {
if (!isTailCall || (m_argument->type() != CallExpression)) {
// skip End bytecode only if it directly returns the result of tail call
codeBlock->pushCode(End(ByteCodeLOC(m_loc.index), r), context, this->m_loc.index);
}
context->giveUpRegister();
Expand Down
4 changes: 0 additions & 4 deletions tools/test/test262/excludelist.orig.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5070,8 +5070,6 @@
<test id="language/expressions/class/scope-name-lex-open-heritage"><reason>TODO</reason></test>
<test id="language/expressions/coalesce/chainable-if-parenthesis-covered-logical-and"><reason>TODO</reason></test>
<test id="language/expressions/coalesce/chainable-if-parenthesis-covered-logical-or"><reason>TODO</reason></test>
<test id="language/expressions/coalesce/tco-pos-null"><reason>TODO</reason></test>
<test id="language/expressions/coalesce/tco-pos-undefined"><reason>TODO</reason></test>
<test id="language/expressions/comma/tco-final"><reason>TODO</reason></test>
<test id="language/expressions/compound-assignment/S11.13.2_A6.10_T1"><reason>TODO</reason></test>
<test id="language/expressions/compound-assignment/S11.13.2_A6.11_T1"><reason>TODO</reason></test>
Expand Down Expand Up @@ -5117,8 +5115,6 @@
<test id="language/expressions/compound-assignment/right-shift-non-simple"><reason>TODO</reason></test>
<test id="language/expressions/compound-assignment/subtract-non-simple"><reason>TODO</reason></test>
<test id="language/expressions/compound-assignment/u-right-shift-non-simple"><reason>TODO</reason></test>
<test id="language/expressions/conditional/tco-cond"><reason>TODO</reason></test>
<test id="language/expressions/conditional/tco-pos"><reason>TODO</reason></test>
<test id="language/expressions/delete/super-property-null-base"><reason>TODO</reason></test>
<test id="language/expressions/dynamic-import/2nd-param-assert-enumeration"><reason>TODO</reason></test>
<test id="language/expressions/function/eval-var-scope-syntax-err"><reason>TODO</reason></test>
Expand Down

0 comments on commit 0285779

Please sign in to comment.