From 94563551e3990d82a5f89c590c9ad5b5040339af Mon Sep 17 00:00:00 2001 From: HyukWoo Park Date: Thu, 19 Oct 2023 12:04:05 +0900 Subject: [PATCH] Apply TCO for sequence and logical operations located at the end of the return statement Signed-off-by: HyukWoo Park --- .../ast/BinaryExpressionLogicalAndNode.h | 50 ++++++++++++++++--- .../ast/BinaryExpressionLogicalOrNode.h | 48 ++++++++++++++++-- src/parser/ast/SequenceExpressionNode.h | 23 +++++++-- src/parser/ast/WhileStatementNode.h | 2 +- tools/test/test262/excludelist.orig.xml | 3 -- 5 files changed, 107 insertions(+), 19 deletions(-) diff --git a/src/parser/ast/BinaryExpressionLogicalAndNode.h b/src/parser/ast/BinaryExpressionLogicalAndNode.h index 1a8ad8be2..ae043e68d 100644 --- a/src/parser/ast/BinaryExpressionLogicalAndNode.h +++ b/src/parser/ast/BinaryExpressionLogicalAndNode.h @@ -42,19 +42,55 @@ class BinaryExpressionLogicalAndNode : public ExpressionNode { context->m_canSkipCopyToRegister = false; } - size_t resultRegisterExpected = dstRegister; - - m_left->generateExpressionByteCode(codeBlock, context, resultRegisterExpected); + if (UNLIKELY(m_left->isLiteral())) { + ExecutionState stateForTest(codeBlock->m_codeBlock->context()); + bool boolVal = m_left->asLiteral()->value().toBoolean(stateForTest); + if (boolVal) { + m_right->generateExpressionByteCode(codeBlock, context, dstRegister); + } else { + m_left->generateExpressionByteCode(codeBlock, context, dstRegister); + } + } else { + m_left->generateExpressionByteCode(codeBlock, context, dstRegister); + codeBlock->pushCode(JumpIfFalse(ByteCodeLOC(m_loc.index), dstRegister), context, this->m_loc.index); + size_t pos = codeBlock->lastCodePosition(); + + m_right->generateExpressionByteCode(codeBlock, context, dstRegister); + codeBlock->peekCode(pos)->m_jumpPosition = codeBlock->currentCodeSize(); + } - codeBlock->pushCode(JumpIfFalse(ByteCodeLOC(m_loc.index), resultRegisterExpected), context, this->m_loc.index); - size_t pos = codeBlock->lastCodePosition(); + context->m_canSkipCopyToRegister = directBefore; + } - m_right->generateExpressionByteCode(codeBlock, context, resultRegisterExpected); +#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; + } - codeBlock->peekCode(pos)->m_jumpPosition = codeBlock->currentCodeSize(); + if (UNLIKELY(m_left->isLiteral())) { + ExecutionState stateForTest(codeBlock->m_codeBlock->context()); + bool boolVal = m_left->asLiteral()->value().toBoolean(stateForTest); + if (boolVal) { + m_right->generateTCOExpressionByteCode(codeBlock, context, dstRegister, isTailCall); + } else { + m_left->generateTCOExpressionByteCode(codeBlock, context, dstRegister, isTailCall); + } + } else { + m_left->generateExpressionByteCode(codeBlock, context, dstRegister); + codeBlock->pushCode(JumpIfFalse(ByteCodeLOC(m_loc.index), dstRegister), context, this->m_loc.index); + size_t pos = codeBlock->lastCodePosition(); + + m_right->generateExpressionByteCode(codeBlock, context, dstRegister); + codeBlock->peekCode(pos)->m_jumpPosition = codeBlock->currentCodeSize(); + } context->m_canSkipCopyToRegister = directBefore; } +#endif virtual void iterateChildrenIdentifier(const std::function& fn) override { diff --git a/src/parser/ast/BinaryExpressionLogicalOrNode.h b/src/parser/ast/BinaryExpressionLogicalOrNode.h index dc4ff1497..5485d5527 100644 --- a/src/parser/ast/BinaryExpressionLogicalOrNode.h +++ b/src/parser/ast/BinaryExpressionLogicalOrNode.h @@ -42,17 +42,55 @@ class BinaryExpressionLogicalOrNode : public ExpressionNode { context->m_canSkipCopyToRegister = false; } - m_left->generateExpressionByteCode(codeBlock, context, dstRegister); + if (UNLIKELY(m_left->isLiteral())) { + ExecutionState stateForTest(codeBlock->m_codeBlock->context()); + bool boolVal = m_left->asLiteral()->value().toBoolean(stateForTest); + if (boolVal) { + m_left->generateExpressionByteCode(codeBlock, context, dstRegister); + } else { + m_right->generateExpressionByteCode(codeBlock, context, dstRegister); + } + } else { + m_left->generateExpressionByteCode(codeBlock, context, dstRegister); + codeBlock->pushCode(JumpIfTrue(ByteCodeLOC(m_loc.index), dstRegister), context, this->m_loc.index); + size_t pos = codeBlock->lastCodePosition(); + + m_right->generateExpressionByteCode(codeBlock, context, dstRegister); + codeBlock->peekCode(pos)->m_jumpPosition = codeBlock->currentCodeSize(); + } - codeBlock->pushCode(JumpIfTrue(ByteCodeLOC(m_loc.index), dstRegister), context, this->m_loc.index); - size_t pos = codeBlock->lastCodePosition(); + context->m_canSkipCopyToRegister = directBefore; + } - m_right->generateExpressionByteCode(codeBlock, context, dstRegister); +#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; + } - codeBlock->peekCode(pos)->m_jumpPosition = codeBlock->currentCodeSize(); + if (UNLIKELY(m_left->isLiteral())) { + ExecutionState stateForTest(codeBlock->m_codeBlock->context()); + bool boolVal = m_left->asLiteral()->value().toBoolean(stateForTest); + if (boolVal) { + m_left->generateTCOExpressionByteCode(codeBlock, context, dstRegister, isTailCall); + } else { + m_right->generateTCOExpressionByteCode(codeBlock, context, dstRegister, isTailCall); + } + } else { + m_left->generateExpressionByteCode(codeBlock, context, dstRegister); + codeBlock->pushCode(JumpIfTrue(ByteCodeLOC(m_loc.index), dstRegister), context, this->m_loc.index); + size_t pos = codeBlock->lastCodePosition(); + + m_right->generateExpressionByteCode(codeBlock, context, dstRegister); + codeBlock->peekCode(pos)->m_jumpPosition = codeBlock->currentCodeSize(); + } context->m_canSkipCopyToRegister = directBefore; } +#endif virtual void iterateChildrenIdentifier(const std::function& fn) override { diff --git a/src/parser/ast/SequenceExpressionNode.h b/src/parser/ast/SequenceExpressionNode.h index 306f180cd..4366b001a 100644 --- a/src/parser/ast/SequenceExpressionNode.h +++ b/src/parser/ast/SequenceExpressionNode.h @@ -35,16 +35,33 @@ class SequenceExpressionNode : public ExpressionNode { virtual void generateExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context, ByteCodeRegisterIndex dstRegister) override { + ASSERT(m_expressions.size()); ByteCodeRegisterIndex r = 0; - for (SentinelNode* expression = m_expressions.begin(); expression != m_expressions.end(); expression = expression->next()) { + for (SentinelNode* expression = m_expressions.begin(); expression != m_expressions.back(); expression = expression->next()) { r = expression->astNode()->getRegister(codeBlock, context); expression->astNode()->generateExpressionByteCode(codeBlock, context, r); context->giveUpRegister(); } - if (r != dstRegister) { - codeBlock->pushCode(Move(ByteCodeLOC(m_loc.index), r, dstRegister), context, this->m_loc.index); + + // directly store the result of the last expression on to dstRegister + m_expressions.back()->astNode()->generateExpressionByteCode(codeBlock, context, dstRegister); + } + +#if defined(ENABLE_TCO) + virtual void generateTCOExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context, ByteCodeRegisterIndex dstRegister, bool& isTailCall) override + { + ASSERT(m_expressions.size()); + ByteCodeRegisterIndex r = 0; + for (SentinelNode* expression = m_expressions.begin(); expression != m_expressions.back(); expression = expression->next()) { + r = expression->astNode()->getRegister(codeBlock, context); + expression->astNode()->generateExpressionByteCode(codeBlock, context, r); + context->giveUpRegister(); } + + // directly store the result of the last expression on to dstRegister + m_expressions.back()->astNode()->generateTCOExpressionByteCode(codeBlock, context, dstRegister, isTailCall); } +#endif virtual void iterateChildrenIdentifier(const std::function& fn) override { diff --git a/src/parser/ast/WhileStatementNode.h b/src/parser/ast/WhileStatementNode.h index a9c109a4c..995234c25 100644 --- a/src/parser/ast/WhileStatementNode.h +++ b/src/parser/ast/WhileStatementNode.h @@ -54,7 +54,7 @@ class WhileStatementNode : public StatementNode { size_t whileStart = codeBlock->currentCodeSize(); size_t testPos = SIZE_MAX; ExecutionState stateForTest(codeBlock->m_codeBlock->context()); - if (m_test->isLiteral() && m_test->asLiteral()->value().isPrimitive() && m_test->asLiteral()->value().toBoolean(stateForTest)) { + if (m_test->isLiteral() && m_test->asLiteral()->value().toBoolean(stateForTest)) { // skip generate code } else { if (m_test->isRelationOperation()) { diff --git a/tools/test/test262/excludelist.orig.xml b/tools/test/test262/excludelist.orig.xml index 3fc13932d..272273c7e 100644 --- a/tools/test/test262/excludelist.orig.xml +++ b/tools/test/test262/excludelist.orig.xml @@ -5070,7 +5070,6 @@ TODO TODO TODO - TODO TODO TODO TODO @@ -5121,7 +5120,6 @@ TODO TODO TODO - TODO TODO TODO TODO @@ -5131,7 +5129,6 @@ TODO TODO TODO - TODO TODO TODO TODO