-
-
Notifications
You must be signed in to change notification settings - Fork 405
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
Varying length instruction operands #3253
Conversation
Ran the full quickjs benchmarks and collected the size of all the bytecode generated. MainTotal bytecode generated size: 202.411KB PRTotal bytecode generated size: 110.361KB This is a |
This is awesome! Great optimization |
fcb4182
to
af5d660
Compare
Test262 conformance changes
|
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #3253 +/- ##
==========================================
- Coverage 49.72% 49.36% -0.37%
==========================================
Files 443 444 +1
Lines 43378 43843 +465
==========================================
+ Hits 21570 21642 +72
- Misses 21808 22201 +393
☔ View full report in Codecov by Sentry. |
af5d660
to
eca1b75
Compare
eca1b75
to
1820df1
Compare
a53595f
to
a1af47c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice work. I just have a few comments / questions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice optimization work! The only suggestion I have would be to make Opcode::Half/Wide
an operand itself. This would simplify the logic a lot, since Operand
would remain the same, and only instructions that want to opt-in into the varying operands logic would read the first operand as a VaryingOperandKind
, then read the rest of the operands based off of that.
What do you think?
This would be a more simple approach, but it would incurred memory and performance penalties. It would require an additional byte per varying instruction, additionally we would have to add logic for conditionally branching based on that varying kind ( I favored the current approach because by default, it's assumed that the operands are So we only pay a price (additional table jump) when we need more than a |
Ahhh, because we would have to store the varying kind for all varying instructions even if the instruction is |
29974b7
to
58e3a7d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some small nitpicks that don't block merging. Really well done!
dc90423
to
1fba8c2
Compare
Depends on #3201
Currently almost all operands are
u32
size, this is because it is enough for most cases, but we waste space since most of the time the size is smaller thanu8::MAX
.This is an optimization that reduces that size of the operands of bytecode instructions, by default if the instruction is executed then it is assumed that the operands are
u8
type. When we need a larger size we prefix the opcode with a modifier (Half
foru16
orWide
foru32
).This allows us to greatly reduce the memory footprint of the generated bytecode.
V8 does this optimization, but it is not exclusive to v8 bytecode, since most CISC architectures have this as well (x86 being of of them).