in reply to How is redefining a sub internally done?

It says "gv[IV \&main::g] s"

"gv" means a glob. "\&" means a code ref. Odd. Let's look at pp_gv.

According to a comment and an assert in pp_gv, the attached SV "might be a real GV or might be an RV to a CV". So it could be *main::g or \&main::g. Does B::Concise distinguish between these, or does it always print \&main::g?

That's as far as I got.

Replies are listed 'Best First'.
Re^2: How is redefining a sub internally done?
by dave_the_m (Monsignor) on Sep 30, 2024 at 21:57 UTC
    Normally, sub calls are compiled into a typeglob retrieval followed by a retrieval of the CV slot within that typeglob. The GV OP has a pointer to the GV associated with the name hard-baked in at compile time. The OP_GV pushes the GV on the stack, then the OP_ENTERSUB pops thes the GV off the stack, accesses its CV slot, calls the associated CV.

    However as an optimisation, GVs which only have their CV slot used, are instead created as an RV to a CV. So for example, for

    package FOO; sub f { ... } f()
    at compile time, the value of the hash entry $FOO::{f} is created as an RV to the CV associated with f, rather than as a full typeglob. When the GV op is compiled, it points to that RV. When the GV op is called, it pushes that RV onto the stack. When the ENTERSUB is is called, it pops that value, notices that it's an RV rather than a GV, and extracts the CV as the thing referenced.

    When things get more complex, the 'RV to a CV' SV is upgraded to a full GV with the CV in its code slot.

    An 'RV to CV' is smaller and quicker than a full GV (a GV points to a GP which has a CV slot - so two allocations, two dereferences).

    Dave.

Re^2: How is redefining a sub internally done?
by LanX (Saint) on Sep 27, 2024 at 15:22 UTC
    > Does B::Concise distinguish between these

    Yes, for instance if a sub is not predefined in the STASH you'll see the *main::g or rather *g form.

    Also in (for me) random cases where it's predefined.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    see Wikisyntax for the Monastery

    Update
    ~/perl $ perl -MO=Concise,-exec -e'g();' 1 <0> enter v 2 <;> nextstate(main 1 -e:1) v:{ 3 <0> pushmark s 4 <#> gv[*g] s/EARLYCV 5 <1> entersub[t2] vKS/TARG 6 <@> leave[1 ref] vKP/REFC -e syntax OK ~/perl $

    s/EARLYCV means the sub was unknown at compile time.

      Inherited subs are cached into the namespace that inherits them.

      # Causes something akin to # `*Foo::method = \&Base::method;` $foo->method();

      But it uses a counter system to invalidate the cache. The package's counter is incremented when the package is changed, making it so the counter in the cached entry no longer matches the package's, invalidating the cached entry.

      Perhaps that same mechanism is used here.

        Well maybe

        I tried to look into the code of pp_entersub but didn't understand much... 🤷🏻‍♂️

        Personally when trying to implement this, I would try to use the original sub to link to the current one. Hence just a hop away.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        see Wikisyntax for the Monastery