Voldenet this itself is not critical, but maybe moar should eventually be able to throw errors properly – for example MVM_file_open_fh can tell you if something is a directory or maybe give you platform-specific error, but it gets flattened into a string 02:01
while you can parse strings and they don't change often, it still feels icky to do that 02:13
04:31 ShimmerFairy left 04:40 ShimmerFairy joined 13:08 librasteve_ joined
Geth MoarVM/moar-gdb-rrdb: 8 commits pushed by (Timo Paulssen)++ 13:20
timo (just a rebase)
13:34 guifa_ joined 15:53 guifa_ left 15:59 guifa_ joined
Geth MoarVM/2026.06: 12f1c345f1 | (Will Coleda)++ | 2 files
Update changelog and version
16:24
MoarVM: coke++ created pull request #2019:
Update changelog and version
16:25
MoarVM/main: 12f1c345f1 | (Will Coleda)++ | 2 files
Update changelog and version
16:28
MoarVM/main: cfc173f079 | (Will Coleda)++ (committed using GitHub Web editor) | 2 files
Merge pull request #2019 from MoarVM/2026.06

Update changelog and version
17:32 librasteve_ left
timo uhhhh do we resolve bytecode annotations purely by the cur_op offset into effective_bytecode and then looking at the static frame's annotation segment? that seems like we would get wrong filename / line number pairs for frames as soon as spesh is involved ... which may or may not include instrumentation such as the one the debugserver uses to add breakpoint instructions (though the breakpoint 17:54
instructions would go on correct locations, since they would still be correct when the spesh graph used for instrumentation was created)
18:16 ShimmerFairy left 18:18 ShimmerFairy joined
Geth MoarVM/moar-gdb-rrdb: 13 commits pushed by (Timo Paulssen)++
review: github.com/MoarVM/MoarVM/compare/1...037a8879a2
18:22
timo ^- rebase, but also new features and changes
18:35 guifa_ left 18:36 librasteve_ joined, guifa_ joined 18:41 guifa_ left 18:46 ShimmerFairy left 18:51 ShimmerFairy joined 19:07 MasterDuke joined
MasterDuke timo: i'm looking through the still-existing iter spesh code. when running my example, `if (in_facts->flags & MVM_SPESH_FACT_KNOWN_TYPE) {` in `iter_facts()` is not true, when called in `case MVM_OP_iter` in `add_bb_facts()` 19:10
the test code is: `nqp -e 'my $l := nqp::list(); my int $p := 0; while $p++ < 10_000 { nqp::push($l, $p) }; my int $j := 10000; while $j-- { my $iter := nqp::iterator($l); nqp::while($iter, my $a := nqp::shift($iter)) }'` 19:11
i know very little about facts. how do i tell why the type isn't known? 19:12
timo you'll definitely want to be looking at the spesh log for this
MasterDuke there are only two `iter`s in the spesh log 19:13
oh, from the before and after of `<mainline> 19:14
`iter            r11(12),   r1(6)`
`r1(6): usages=2, flags=0     (merged from 2 regs)` 19:15
`r11(12): usages=0, flags=0`
timo ok, so we can't prove what is being iterated over there
MasterDuke oh, which registers should i be looking at, they have different numbers before and after optimization 19:16
oh, but either set are pretty much the same 19:17
(in the facts they have) 19:18
it's essentially the same if i change to iterating over an nqp::list_i
timo the before-optimization facts are going to have many missing flags and known types and such 19:19
at least potentially
MasterDuke before and after are essentially the same 19:23
timo so, the register equivalent to r1(6), i.e. what we're creating the iter for, comes from a PHI that has two inputs, which is what "merged from 2" means 19:25
can you see what these versions of the register are, and where they come from? 19:26
i'm assuming the PHI lives where the loop is entered from before or from the jump-back address
MasterDuke hm, "can you see what these versions of the register are, and where they come from?" how do i get that from the spesh log? 19:27
timo go up to the instructions and find a PHI that has the target as its first argument, the other arguments are the sources 19:28
MasterDuke there are a bunch of PHIs a couple instructions before the iter
`PHI               r1(6),   r1(0),   r1(5)`?
timo PHI means "the register r1 has different versions in the different predecessors of this block"
so we can only rely on what we know to be true about all incoming versions, that's what "merged" refers to 19:29
MasterDuke `r1(0): usages=3, flags=0` and `r1(5): usages=1, flags=0     (merged from 2 regs)`
Geth MoarVM/moar-gdb-rrdb: ae24fde56a | (Timo Paulssen)++ | tools/libmoar.so-gdb.py
gdb plugin: RRDB: Fix sql statements, allow skipping gc tracking

Recording the before and after address of every object when they get
  moved around by the GC takes a significant chunk of the time when
creating the rrdb, and there isn't anything yet that uses any of the information anyway.
19:31
timo so we know literally nothing about these two. r1(5) is also merged from others though
MasterDuke `PHI               r1(5),   r1(3),   r1(7)` where `r1(3): usages=2, flags=0     (merged from 2 regs)` and `r1(7): usages=6, deopt=20,19, flags=0     (merged from 4 regs)` 19:33
timo well, you can already guess what i'd tell you next :D 19:34
MasterDuke maybe there's too much inlining happening to make this a good test case?
timo try making the loop that goes over the $l into a sub and passing the $l in, then (unless nqp inlines it itself for some reason) spesh should learn what the type of the incoming argument actually is, and guard on it 19:35
19:36 guifa_ joined
MasterDuke still doesn't know the type in `iter_facts()` 19:40
but i do see `Observed type specialization of 'iter-a-bunch' ... It was planned for the type tuple: Type 0: BOOTIntArray (Conc)` 19:41
timo ok, then the register it puts the $l into from the function arguments is expected to have the known type flag on it
MasterDuke r0(2)? 19:48
timo might be 19:51
MasterDuke well, i see `r0(2): usages=1, flags=9     KnTyp Concr (type: BOOTIntArray)`
Geth MoarVM/moar-gdb-rrdb: 1890e0618a | (Timo Paulssen)++ | tools/libmoar.so-gdb.py
gdb plugin: Output bytecode file and cuuid in single-frame view too
timo that's good. so it'll go through some instructions, likely including a PHI or two, before reaching the `iter` opcode 19:52
MasterDuke yeah `iter              r7(4),   r0(4)`, where `r7(4): usages=1, flags=0` and `r0(4): usages=2, flags=0     (merged from 2 regs)` 19:53
`PHI               r0(4),   r0(0),   r0(3)` where `r0(0): usages=2, flags=0` and `r0(3): usages=1, flags=0     (merged from 2 regs)` 19:54
`PHI               r0(3),   r0(2),   r0(5)` where `r0(2): usages=1, flags=9     KnTyp Concr (type: BOOTIntArray)` and `r0(5): usages=6, deopt=10,9, flags=0     (merged from 4 regs)` 19:55
timo so all of versions 0, 3, and 4 don't have the info any more
and r0(0) probably comes from the BB number 0? i.e. has no value set to it at all?
MasterDuke i believe so, i don't see it as the first arg in any of the PHIs 19:56
Geth MoarVM/moar-gdb-rrdb: e504417c10 | (Timo Paulssen)++ | tools/libmoar.so-gdb.py
gdb plugin: Fix TC sorting, reject cases like "double tc" out-right
20:02
timo the BB that has the PHI with r0(0) in the middle would have a Predecessor where that's the version of the register that "lives there" 20:03
does this frame have any frame handlers? like a handler goto annotation somewhere? I think we currently create a "fake" successor of BB 0 to every BB that has a handler jump point, or maybe every BB that's covered by a handler 20:04
MasterDuke don't see anything like that
BB 4 and 8 have PHIs with r0(0) 20:05
timo anything interesting in 4 and 8's Preds? 20:06
MasterDuke `0, 3` and `0, 5, 6, 7`. don't know if that's interesting 20:07
Geth MoarVM/moar-gdb-rrdb: 6e7788d834 | (Timo Paulssen)++ | tools/libmoar.so-gdb.py
gdb plugin: Fix TC sorting, reject cases like "double tc" out-right
20:13
timo there's the BB 0
we're doing that for some kind of extra safety so we don't mess things up, but it does frustrate optimization like in this case 20:14
MasterDuke should i do some more random work before/after the iteration to "isolate" it? 20:16
timo gist.github.com/timo/20b8e7f029b21...1be3bdce7f 20:17
can you try "upgrading" to rakudo?
MasterDuke oh, nice
still calling nqp::iter though? 20:18
timo yeah. may need a nqp::decont or two here and there 20:19
or maybe using IterationBuffer
actually, native arrays are repr'd VMArray IIRC?
MasterDuke i think so. hm, doesn't optimize iter-a-bunch now 20:22
`raku -e 'use nqp; my $l := nqp::list_i(); my int $p = 0; while $p++ < 10_000 { nqp::push_i($l, $p) }; sub iter-a-bunch(Mu $list is raw) { my int $j = 10000; while $j-- { my $iter := nqp::iterator($list); nqp::while($iter, my $a := nqp::shift($iter)) }; }; iter-a-bunch($l)'` is what i ran 20:24
or `raku -e 'use nqp; my int @l; my int $p = 0; while $p++ < 10_000 { @l.push($p) }; sub iter-a-bunch(int @list) { my int $j = 10000; while $j-- { my $iter := nqp::iterator(@list); nqp::while($iter, my $a := nqp::shift($iter)) }; }; iter-a-bunch(@l)'` 20:26
timo it doesn't show up in the spesh log at all? 20:27
MasterDuke not as a before/after 20:28
changed to call it a bunch of times, now it does 20:29
`Type 0: array[int] (Conc)`
`iter             r10(4),   r1(4)` where `r10(4): usages=1, flags=0` and `r1(4): usages=2, flags=0     (merged from 4 regs)` 20:33
`PHI               r1(4),   r1(0),   r1(3),   r1(5),   r1(5)` where `r1(0): usages=2, flags=0` and `r1(3): usages=1, flags=0     (merged from 4 regs)` and `r1(5): usages=10, deopt=13,12, flags=0     (merged from 4 regs)` 20:34
`PHI               r1(3),   r1(2),   r1(5),   r1(5),   r1(5)` where `r1(2): usages=1, flags=9     KnTyp Concr (type: array[int])` 20:35
timo ugh. still got version 0 in there, which is probably from BB 0 again 20:36
MasterDuke added some fluff beginning and end of the sub. `iter             r17(7),   r1(7)` where `r17(7): usages=1, flags=0` and `r1(7): usages=2, flags=0     (merged from 4 regs)` 20:40
`PHI               r1(7),   r1(0),   r1(6),   r1(8),   r1(8)` still the `(0)` 20:41
timo i mean, facts could always take the type for iterators and say we know that's the type right? but we wouldn't have knowledge about whether it's an array or hash iterator 20:42
MasterDuke right now the code does distinguish those 20:43
Geth MoarVM/moar-gdb-rrdb: 13b30534e2 | (Timo Paulssen)++ | tools/libmoar.so-gdb.py
gdb plugin: throw out some debug noise
20:45
MoarVM/moar-gdb-rrdb: 4b00388fca | (Timo Paulssen)++ | tools/libmoar.so-gdb.py
gdb plugin: RRDB: don't store "elapsed time" redundantly

it only changes from one event to the next, so storing an extra table with event to elapsed time values makes a lot more sense.
timo what exactly were you looking to optimize? the boolification of the iterator, right?
MasterDuke yeah 20:48
timo what does that look like by that point? 20:50
MasterDuke the original thought was optimizing looping via iter+shift, which triggered my reach-into-the-array-body attempt. but then you pointed out the problem with that and said the boolification of the iterator was taking time 20:51
you mean in spesh? 20:52
timo yeah 20:53
i assume it's a dispatch to boot-boolify before, and after just a runcfunc
MasterDuke i see a lot of boot-boolify dispatches, trying to figure out the right one... 20:54
but yeah, i see two boot-boolifys in the before of iter-a-bunch and two sp_runcfunc_i after 20:56
timo right 20:57
i hope it doesn't sp_runcfunc_i into box into unbox right away
do you know about the trace spesh optimizer gdb script?
MasterDuke hm, don't think i've used that
and i don't see any box/unbox at all in iter-a-bunch 20:58
timo that's good at least
the trace spesh script works by putting a bunch of breakpoints in different spots in spesh's optimize, then at each of these it spits out MVM_spesh_dump (i.e. the same stuff that lands in the spesh log) into a file and tracks the files in a scratch git repository, then at the end you can see a git log with diffs of how the spesh dump changes step by step 21:00
MasterDuke oooo
timo you load it into gdb with the "source" command I think
it's in moarvm's tools folder
you do have to be in the right spot at the start in order for it to work right, i.e. at the start of the right frame's spesh happening 21:01
and uhhh with changes in spesh's code, maybe a few of the break points are no longer valid?
MasterDuke seems to be doing something 21:03
well, it was. now it looks like it's just sitting 21:05
timo it should throw you into a pager, but you can go to /tmp and look for the folder where the git repo was created to go in and "git log -u" yourself 21:06
21:06 guifa_ left
MasterDuke `fatal: your current branch 'master' does not have any commits yet` 21:07
timo so it wasn't very successful, huh?
MasterDuke added 13 breakpoints, but doesn't seem to be doing much after that 21:08
timo you got a gdb prompt again? otherwise you can ctrl-c and see what's up
MasterDuke no prompt 21:09
and ctrl-c didn't do anything
21:12 guifa_ joined
timo :| 21:14
pstree showing anything suspicious? could be a different process has the tty or something
MasterDuke         │                   ├─bash─┬─gdb─┬─raku───{raku} 21:15
        │                   │      │     └─8*[{gdb}]
but afk for a while. dinner and then putting kids to bed. should be back later this evening if anybody is still around 21:21
timo all right! 21:22
21:25 MasterDuke left 21:52 guifa_ left 21:57 guifa_ joined 22:13 librasteve_ left 23:47 guifa_ left 23:51 guifa_ joined