Files
ladybird/Tests/LibJS/Bytecode/expected/for-of-cond-rhs-block-order.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

110 lines
3.1 KiB
Plaintext

$9cd3e64e for-of-cond-rhs-block-order.js:6:1
Registers: 7
Blocks: 1
Constants:
[0] = Undefined
[1] = Null
block0:
[ 0] GetGlobal dst:reg6, `f`
[ 18] Call dst:reg5, callee:reg6, this_value:Undefined, f, arguments:[Null, Null]
[ 40] End value:reg5
f$0adf9089 for-of-cond-rhs-block-order.js:2:21
Registers: 17
Blocks: 20
Locals: n~0, r~1
Constants:
[0] = Bool(false)
[1] = Undefined
[2] = Int32(1)
[3] = Int32(2)
block0:
[ 0] GetLexicalEnvironment dst:reg4
[ 8] JumpIf condition:arg0, true_target:block3, false_target:block4
block1:
[ 18] End value:Undefined
block2:
[ 20] IteratorNextUnpack dst_value:reg10, dst_done:reg11, iterator_object:reg5, iterator_next:reg8, iterator_done:reg6
[ 38] JumpIf condition:reg11, true_target:block1, false_target:block8
block3:
[ 48] Mov dst:reg6, src:arg0
[ 58] GetById dst:reg7, base:reg6, `x` (o.x)
[ 78] Mov dst:reg5, src:reg7
[ 88] Jump target:block5
block4:
[ 90] Mov dst:reg5, src:arg1
block5:
[ a0] GetGlobal dst:reg6, `Object`
[ b8] GetById dst:reg8, base:reg6, `entries` (Object.entries)
[ d8] NewObject dst:reg9
[ e8] Call dst:reg7, callee:reg8, this_value:reg6, Object.entries, arguments:[reg9]
[ 110] GetIterator dst_iterator_object:reg5, dst_iterator_next:reg8, dst_iterator_done:reg6, iterable:reg7
[ 128] Jump target:block2
block6:
[ 130] Catch dst:reg9
[ 138] SetLexicalEnvironment environment:reg4
[ 140] Mov dst:reg7, src:Int32(1)
block7:
[ 150] JumpStrictlyEquals lhs:reg7, rhs:Int32(1), true_target:block16, false_target:block17
block8:
[ 168] Mov dst:reg12, src:Bool(false)
[ 178] GetIterator dst_iterator_object:reg13, dst_iterator_next:reg14, dst_iterator_done:reg15, iterable:reg10
[ 190] IteratorNextUnpack dst_value:reg16, dst_done:reg12, iterator_object:reg13, iterator_next:reg14, iterator_done:reg15
[ 1a8] JumpFalse condition:reg12, target:block10
block9:
[ 1b8] Mov dst:reg16, src:Undefined
[ 1c8] Jump target:block10
block10:
[ 1d0] Mov dst:r~1, src:reg16
[ 1e0] JumpFalse condition:reg12, target:block12
block11:
[ 1f0] Mov dst:reg16, src:Undefined
[ 200] Jump target:block13
block12:
[ 208] IteratorNextUnpack dst_value:reg16, dst_done:reg12, iterator_object:reg13, iterator_next:reg14, iterator_done:reg15
[ 220] JumpTrue condition:reg12, target:block11
block13:
[ 230] Mov dst:n~0, src:reg16
[ 240] JumpFalse condition:reg12, target:block15
block14:
[ 250] ThrowIfTDZ src:r~1
[ 258] Jump target:block2
block15:
[ 260] IteratorClose iterator_object:reg13, iterator_next:reg14, iterator_done:reg15, completion_value:Undefined
[ 278] Jump target:block14
block16:
[ 280] IteratorClose iterator_object:reg5, iterator_next:reg8, iterator_done:reg6, completion_value:reg9
[ 298] Throw src:reg9
block17:
[ 2a0] IteratorClose iterator_object:reg5, iterator_next:reg8, iterator_done:reg6, completion_value:Undefined
[ 2b8] JumpStrictlyEquals lhs:reg7, rhs:Int32(2), true_target:block18, false_target:block19
block18:
[ 2d0] Return value:reg9
block19:
[ 2d8] Throw src:reg9
Exception handlers:
[ 168 .. 280] => handler block6