Skip to content

Commit

Permalink
[JSC] Emit more efficient bytecodes for some patterns in the wild
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=276858
rdar://132180708

Reviewed by Yijia Huang.

Through careful review of Angular generated code, we found several patterns. This patch optimizes them.

1. When try-catch-finally is used, we were not using emitNodeInIgnoreResultPosition. We should use that
   so that we can potentially convert some of call bytecodes to call_ignore_result.
2. !(function () { ... })() pattern is used well in the wild. This patch attempts to remove `!` when we detect
   that the resulted value is not used since ! is not user-observable.

* Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp:
(JSC::UnaryOpNode::emitBytecode):
(JSC::TryNode::emitBytecode):

Canonical link: https://commits.webkit.org/281177@main
  • Loading branch information
Constellation committed Jul 21, 2024
1 parent fff9f7a commit b6dc732
Showing 1 changed file with 23 additions and 4 deletions.
27 changes: 23 additions & 4 deletions Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3074,6 +3074,19 @@ RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d

RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
{
if (dst == generator.ignoredResult()) {
// op_not is not user-observable. We can skip it completely if the result is not used.
// This is used in the wild, for example,
// ```
// !(function (a) {
// ...
// })(a);
// ```
if (opcodeID() == op_not) {
generator.emitNodeInIgnoreResultPosition(m_expr);
return nullptr;
}
}
RefPtr<RegisterID> src = generator.emitNode(m_expr);
generator.emitExpressionInfo(position(), position(), position());
return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src.get(), m_expr->resultDescriptor());
Expand Down Expand Up @@ -4940,7 +4953,10 @@ void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
if (!m_catchBlock && m_finallyBlock)
finallyTryData = tryData;

generator.emitNode(tryCatchDst.get(), m_tryBlock);
if (tryCatchDst == generator.ignoredResult())
generator.emitNodeInIgnoreResultPosition(m_tryBlock);
else
generator.emitNode(tryCatchDst.get(), m_tryBlock);

if (m_finallyBlock)
generator.emitJump(*finallyLabel);
Expand Down Expand Up @@ -4974,9 +4990,12 @@ void TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
if (generator.shouldBeConcernedWithCompletionValue())
generator.emitLoad(tryCatchDst.get(), jsUndefined());

if (m_finallyBlock)
generator.emitNode(tryCatchDst.get(), m_catchBlock);
else
if (m_finallyBlock) {
if (tryCatchDst == generator.ignoredResult())
generator.emitNodeInIgnoreResultPosition(m_catchBlock);
else
generator.emitNode(tryCatchDst.get(), m_catchBlock);
} else
generator.emitNodeInTailPosition(tryCatchDst.get(), m_catchBlock);
generator.emitLoad(thrownValueRegister.get(), jsUndefined());

Expand Down

0 comments on commit b6dc732

Please sign in to comment.