Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JSC] Stop eagerly emitting wide32 opcodes #10641

Conversation

tadeuzagallo
Copy link
Member

@tadeuzagallo tadeuzagallo commented Feb 24, 2023

53e0cdd

[JSC] Stop eagerly emitting wide32 opcodes
https://bugs.webkit.org/show_bug.cgi?id=252891
rdar://105876002

Reviewed by Yusuke Suzuki.

There were 3 cases where we emitted 32-bit wide opcodes:
- OpEnumeratorGetByVal and OpEnumeratorInByVal: we might need to de-optimize these
into OpGetByVal and OpInByVal respectively, and although the take the same arguments,
the metadata ID might overflow whatever size we picked when emitting the original
opcode. To address this, we allocate the metadataID upfront and ensure we emit a
size that will fit the metadataID. These operators are not super common, and worst
case scenario we'll get one extra wide OpGetByVal due to the eagerly allocated metadata.
- OpJneqPtr: similar optimization, we can optimize `o.hasOwnProperty(p)` to a no-op
if we can guarantee that the iterator hasn't been modified. Here we can guarantee that
will always be able to emit a narrow jump, since the jump is only over a OpEnumeratorHasOwnProperty +
the value we're iterating over, which is guaranteed to be a variable.

Additionally, make the deoptimization a little more precise by not deoptimizing
everything in the loop body if we assign to the iterator, but instead only the
operations after the assignment. We are still conservative with regards to loops,
and if there's any reassignment we'll deoptimize everything after the first
loop_hint we encountered.

* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitWideJumpIfNotFunctionHasOwnProperty):
(JSC::BytecodeGenerator::emitInByVal):
(JSC::BytecodeGenerator::emitGetByVal):
(JSC::rewriteOp):
(JSC::ForInContext::finalize):
* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h:
(JSC::ForInContext::addGetInst):
(JSC::ForInContext::addInInst):

Canonical link: https://commits.webkit.org/261125@main

74dd1f0

Misc iOS, tvOS & watchOS macOS Linux Windows
βœ… πŸ§ͺ style βœ… πŸ›  ios βœ… πŸ›  mac βœ… πŸ›  wpe βœ… πŸ›  wincairo
βœ… πŸ›  ios-sim βœ… πŸ›  mac-AS-debug βœ… πŸ›  gtk
βœ… πŸ§ͺ webkitperl βœ… πŸ§ͺ ios-wk2 βœ… πŸ§ͺ api-mac βœ… πŸ§ͺ gtk-wk2
βœ… πŸ§ͺ api-ios βœ… πŸ§ͺ mac-wk1 βœ… πŸ§ͺ api-gtk
βœ… πŸ›  πŸ§ͺ jsc βœ… πŸ›  tv βœ… πŸ§ͺ mac-wk2 βœ… πŸ›  jsc-armv7
βœ… πŸ›  πŸ§ͺ jsc-arm64 βœ… πŸ›  tv-sim βœ… πŸ§ͺ mac-AS-debug-wk2 βœ… πŸ§ͺ jsc-armv7-tests
βœ… πŸ›  watch βœ… πŸ§ͺ mac-wk2-stress βœ… πŸ›  jsc-mips
βœ… πŸ›  πŸ§ͺ merge βœ… πŸ›  watch-sim βœ… πŸ§ͺ jsc-mips-tests

@tadeuzagallo tadeuzagallo requested a review from a team as a code owner February 24, 2023 10:36
@tadeuzagallo tadeuzagallo self-assigned this Feb 24, 2023
@tadeuzagallo tadeuzagallo added the JavaScriptCore For bugs in JavaScriptCore, the JS engine used by WebKit, other than kxmlcore issues. label Feb 24, 2023
Copy link
Member

@Constellation Constellation left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r=me

Comment on lines 1531 to 1532
OpJneqPtr::emit<OpcodeSize::Wide32>(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::hasOwnPropertyFunction), target.bind(this));
// We know that if we replace this with a jump, it'll be a near jump just over
// an OpEnumeratorHasOwnProperty + variable resolution at most, so there's no
// need to emit a wide opcode here
OpJneqPtr::emit(this, cond, moveLinkTimeConstant(nullptr, LinkTimeConstant::hasOwnPropertyFunction), target.bind(this));
return m_lastInstruction.offset();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove this function and write it directly in HasOwnPropertyFunctionCallDotNode::emitBytecode?
Making it a helper function in BytecodeGenerator would accidentally allow the future other users to use it without keeping the above invariant.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We never emit bytecodes directly from NodesCodegen though, and we wouldn't have access to the last instruction's offset. I can expose all that, but given that this function only works for hasOwnProperty, and that if someone uses it incorrectly we'll catch it in the assertion in finalize, do you think it's a problem? Alternatively, I can move everything into emitEnumeratorHasOwnProperty, maybe that's better?

OpJmp::emit(&generator, BoundLabel(static_cast<int>(newBranchTarget) - static_cast<int>(branchInstIndex)));
BoundLabel targetLabel(static_cast<int>(newBranchTarget) - static_cast<int>(branchInstIndex));

#ifndef NDEBUG
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use #if ASSERT_ENABLED

@tadeuzagallo tadeuzagallo force-pushed the eng/JSC-Stop-eagerly-emitting-wide32-opcodes branch from ddda5b1 to 74dd1f0 Compare March 2, 2023 15:59
@tadeuzagallo tadeuzagallo added the merge-queue Applied to send a pull request to merge-queue label Mar 3, 2023
https://bugs.webkit.org/show_bug.cgi?id=252891
rdar://105876002

Reviewed by Yusuke Suzuki.

There were 3 cases where we emitted 32-bit wide opcodes:
- OpEnumeratorGetByVal and OpEnumeratorInByVal: we might need to de-optimize these
into OpGetByVal and OpInByVal respectively, and although the take the same arguments,
the metadata ID might overflow whatever size we picked when emitting the original
opcode. To address this, we allocate the metadataID upfront and ensure we emit a
size that will fit the metadataID. These operators are not super common, and worst
case scenario we'll get one extra wide OpGetByVal due to the eagerly allocated metadata.
- OpJneqPtr: similar optimization, we can optimize `o.hasOwnProperty(p)` to a no-op
if we can guarantee that the iterator hasn't been modified. Here we can guarantee that
will always be able to emit a narrow jump, since the jump is only over a OpEnumeratorHasOwnProperty +
the value we're iterating over, which is guaranteed to be a variable.

Additionally, make the deoptimization a little more precise by not deoptimizing
everything in the loop body if we assign to the iterator, but instead only the
operations after the assignment. We are still conservative with regards to loops,
and if there's any reassignment we'll deoptimize everything after the first
loop_hint we encountered.

* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitWideJumpIfNotFunctionHasOwnProperty):
(JSC::BytecodeGenerator::emitInByVal):
(JSC::BytecodeGenerator::emitGetByVal):
(JSC::rewriteOp):
(JSC::ForInContext::finalize):
* Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h:
(JSC::ForInContext::addGetInst):
(JSC::ForInContext::addInInst):

Canonical link: https://commits.webkit.org/261125@main
@webkit-commit-queue webkit-commit-queue force-pushed the eng/JSC-Stop-eagerly-emitting-wide32-opcodes branch from 74dd1f0 to 53e0cdd Compare March 3, 2023 09:26
@webkit-commit-queue
Copy link
Collaborator

Committed 261125@main (53e0cdd): https://commits.webkit.org/261125@main

Reviewed commits have been landed. Closing PR #10641 and removing active labels.

@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label Mar 3, 2023
@webkit-commit-queue webkit-commit-queue merged commit 53e0cdd into WebKit:main Mar 3, 2023
@tadeuzagallo tadeuzagallo deleted the eng/JSC-Stop-eagerly-emitting-wide32-opcodes branch May 17, 2023 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JavaScriptCore For bugs in JavaScriptCore, the JS engine used by WebKit, other than kxmlcore issues.
Projects
None yet
4 participants