Skip to content

Commit

Permalink
Apply TCO for sequence and logical operations located at the end of t…
Browse files Browse the repository at this point in the history
…he return statement

Signed-off-by: HyukWoo Park <[email protected]>
  • Loading branch information
clover2123 committed Oct 19, 2023
1 parent f0ddc35 commit 60d8127
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 19 deletions.
48 changes: 41 additions & 7 deletions src/parser/ast/BinaryExpressionLogicalAndNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,53 @@ class BinaryExpressionLogicalAndNode : public ExpressionNode {
context->m_canSkipCopyToRegister = false;
}

size_t resultRegisterExpected = dstRegister;

m_left->generateExpressionByteCode(codeBlock, context, resultRegisterExpected);
if (UNLIKELY(m_left->isLiteral())) {
bool boolVal = m_left->asLiteral()->value().toBoolean();
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>(JumpIfFalse(ByteCodeLOC(m_loc.index), dstRegister), context, this->m_loc.index);
size_t pos = codeBlock->lastCodePosition<JumpIfFalse>();

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

codeBlock->pushCode<JumpIfFalse>(JumpIfFalse(ByteCodeLOC(m_loc.index), resultRegisterExpected), context, this->m_loc.index);
size_t pos = codeBlock->lastCodePosition<JumpIfFalse>();
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<JumpIfFalse>(pos)->m_jumpPosition = codeBlock->currentCodeSize();
if (UNLIKELY(m_left->isLiteral())) {
bool boolVal = m_left->asLiteral()->value().toBoolean();
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>(JumpIfFalse(ByteCodeLOC(m_loc.index), dstRegister), context, this->m_loc.index);
size_t pos = codeBlock->lastCodePosition<JumpIfFalse>();

m_right->generateExpressionByteCode(codeBlock, context, dstRegister);
codeBlock->peekCode<JumpIfFalse>(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
46 changes: 41 additions & 5 deletions src/parser/ast/BinaryExpressionLogicalOrNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,53 @@ class BinaryExpressionLogicalOrNode : public ExpressionNode {
context->m_canSkipCopyToRegister = false;
}

m_left->generateExpressionByteCode(codeBlock, context, dstRegister);
if (UNLIKELY(m_left->isLiteral())) {
bool boolVal = m_left->asLiteral()->value().toBoolean();
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>(JumpIfTrue(ByteCodeLOC(m_loc.index), dstRegister), context, this->m_loc.index);
size_t pos = codeBlock->lastCodePosition<JumpIfTrue>();

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

codeBlock->pushCode<JumpIfTrue>(JumpIfTrue(ByteCodeLOC(m_loc.index), dstRegister), context, this->m_loc.index);
size_t pos = codeBlock->lastCodePosition<JumpIfTrue>();
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<JumpIfTrue>(pos)->m_jumpPosition = codeBlock->currentCodeSize();
if (UNLIKELY(m_left->isLiteral())) {
bool boolVal = m_left->asLiteral()->value().toBoolean();
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>(JumpIfTrue(ByteCodeLOC(m_loc.index), dstRegister), context, this->m_loc.index);
size_t pos = codeBlock->lastCodePosition<JumpIfTrue>();

m_right->generateExpressionByteCode(codeBlock, context, dstRegister);
codeBlock->peekCode<JumpIfTrue>(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
23 changes: 20 additions & 3 deletions src/parser/ast/SequenceExpressionNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<void(AtomicString name, bool isAssignment)>& fn) override
{
Expand Down
2 changes: 1 addition & 1 deletion src/parser/ast/WhileStatementNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class WhileStatementNode : public StatementNode {

size_t whileStart = codeBlock->currentCodeSize();
size_t testPos = SIZE_MAX;
if (m_test->isLiteral() && m_test->asLiteral()->value().isPrimitive() && m_test->asLiteral()->value().toBoolean()) {
if (m_test->isLiteral() && m_test->asLiteral()->value().toBoolean()) {
// skip generate code
} else {
if (m_test->isRelationOperation()) {
Expand Down
3 changes: 0 additions & 3 deletions tools/test/test262/excludelist.orig.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5070,7 +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/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>
<test id="language/expressions/compound-assignment/S11.13.2_A6.1_T1"><reason>TODO</reason></test>
Expand Down Expand Up @@ -5121,7 +5120,6 @@
<test id="language/expressions/generators/eval-var-scope-syntax-err"><reason>TODO</reason></test>
<test id="language/expressions/generators/generator-created-after-decl-inst"><reason>TODO</reason></test>
<test id="language/expressions/generators/yield-as-generator-expression-binding-identifier"><reason>TODO</reason></test>
<test id="language/expressions/logical-and/tco-right"><reason>TODO</reason></test>
<test id="language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-arrow-function"><reason>TODO</reason></test>
<test id="language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-class-expression"><reason>TODO</reason></test>
<test id="language/expressions/logical-assignment/lgcl-and-assignment-operator-namedevaluation-function"><reason>TODO</reason></test>
Expand All @@ -5131,7 +5129,6 @@
<test id="language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-arrow-function"><reason>TODO</reason></test>
<test id="language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-class-expression"><reason>TODO</reason></test>
<test id="language/expressions/logical-assignment/lgcl-or-assignment-operator-namedevaluation-function"><reason>TODO</reason></test>
<test id="language/expressions/logical-or/tco-right"><reason>TODO</reason></test>
<test id="language/expressions/object/__proto__-permitted-dup-shorthand"><reason>TODO</reason></test>
<test id="language/expressions/object/dstr/object-rest-proxy-get-not-called-on-dontenum-keys"><reason>TODO</reason></test>
<test id="language/expressions/object/dstr/object-rest-proxy-gopd-not-called-on-excluded-keys"><reason>TODO</reason></test>
Expand Down

0 comments on commit 60d8127

Please sign in to comment.