Files
ladybird/Tests/LibJS/Bytecode/expected/generator-yield.txt
Andreas Kling 51758f3022 LibJS: Make bytecode register allocator O(1)
Generator::allocate_register used to scan the free pool to find the
lowest-numbered register and then Vec::remove it, making every
allocation O(n) in the size of the pool. When loading https://x.com/
on my Linux machine, we spent ~800ms in this function alone!

This logic only existed to match the C++ register allocation ordering
while transitioning from C++ to Rust in the LibJS compiler, so now
we can simply get rid of it and make it instant. :^)

So drop the "always hand out the lowest-numbered free register" policy
and use the pool as a plain LIFO stack. Pushing and popping the back
of the Vec are both O(1), and peak register usage is unchanged since
the policy only affects which specific register gets reused, not how
aggressively.
2026-04-21 13:59:55 +02:00

68 lines
1.7 KiB
Plaintext

$9403c830 generator-yield.js:11:1
Registers: 9
Blocks: 1
Constants:
[0] = Undefined
block0:
[ 0] GetGlobal dst:reg6, `multi_yield`
[ 18] Call dst:reg5, callee:reg6, this_value:Undefined, multi_yield
[ 38] SetGlobal `g`, src:reg5
[ 50] GetGlobal dst:reg6, `g`
[ 68] GetById dst:reg7, base:reg6, `next` (g.next)
[ 88] Call dst:reg5, callee:reg7, this_value:reg6, g.next
[ a8] GetGlobal dst:reg6, `g`
[ c0] GetById dst:reg8, base:reg6, `next` (g.next)
[ e0] Call dst:reg7, callee:reg8, this_value:reg6, g.next
[ 100] End value:reg7
multi_yield$617e06b7 generator-yield.js:7:5
Registers: 10
Blocks: 12
Constants:
[0] = Undefined
[1] = Int32(1)
[2] = Int32(5)
[3] = Int32(2)
block0:
[ 0] Yield continuation_label:block1, value:Undefined
block1:
[ 10] Yield continuation_label:block2, value:Int32(1)
block2:
[ 20] Mov dst:reg5, src:reg0
[ 30] GetCompletionFields type_dst:reg6, value_dst:reg7, completion:reg5
[ 40] JumpStrictlyEquals lhs:reg6, rhs:Int32(1), true_target:block3, false_target:block4
block3:
[ 58] Yield continuation_label:block7, value:Int32(2)
block4:
[ 68] JumpStrictlyEquals lhs:reg6, rhs:Int32(5), true_target:block5, false_target:block6
block5:
[ 80] Throw src:reg7
block6:
[ 88] Yield value:reg7
block7:
[ 98] Mov dst:reg7, src:reg0
[ a8] GetCompletionFields type_dst:reg5, value_dst:reg6, completion:reg7
[ b8] JumpStrictlyEquals lhs:reg5, rhs:Int32(1), true_target:block8, false_target:block9
block8:
[ d0] Yield value:Undefined
block9:
[ e0] JumpStrictlyEquals lhs:reg5, rhs:Int32(5), true_target:block10, false_target:block11
block10:
[ f8] Throw src:reg6
block11:
[ 100] Yield value:reg6