Perl

NAVIGATION
CATEGORIES
REFERRENCE
LINKS
  • Subs may not contain dynamic call info, ever (was r10151)

    6 answers - 944 bytes - related search similar search Add To My Delicious Add To My Stumble Upon Add To My Google Mark Add To My Facebook Add To My Digg Add To My Reddit

    Wed, Nov 23, 2005 at 03:14:40PM -0000, leo (AT) cvs (DOT) perl.org wrote:
    implement Sub.get_caller() method; test
    You keep confusing static and dynamic call information.
    Like I've said (repeatedly :-)), rule #1 of call info is:
    Subs don't have callers.
    Call frames have callers.
    Therefore, this code is not K, because the Parrot_sub structure has
    information it can't have:
    + METHD PMC* get_caller() {
    + struct Parrot_sub * sub = PMC_sub(SELF);
    + PMC* cont, *sub_pmc;
    + cont = sub->ctx->current_cont;
    + sub_pmc = PMC_cont(cont)->to_ctx->current_sub;
    + return sub_pmc ? sub_pmc : PMCNULL;
    + }
    Parrot_sub must not have a ctx member. Parrot_sub must have no
    members which reflect dynamic calls, because with recursion you can
    guarantee that there's no one correct answer for any dynamic query on
    a Sub. (Continuations just make it worse.)
  • No.1 | | 1692 bytes | |

    Nov 23, 2005, at 19:08, Chip Salzenberg wrote:

    Wed, Nov 23, 2005 at 03:14:40PM -0000, leo (AT) cvs (DOT) perl.org wrote:
    >implement Sub.get_caller() method; test
    >

    You keep confusing static and dynamic call information.

    Not confusing actually, maybe abusing the static sub structure by
    adding a dynamic field 'ctx' - yes.

    Like I've said (repeatedly :-)), rule #1 of call info is:

    Subs don't have callers.
    Call frames have callers.

    And callframes aren't PMCs (because we don't have weak pointers)
    therefore an introspection of :outer can only return the 'Sub' of outer
    but not actually the real call frame aka the context

    The introspection $frame.get_lexpad (pdd20) can't be implemented w/o
    that currently.

    outer_sub - (the static sub PMC info) can't refer to :outer because the
    :outer can be a closure too. There are many incarnations of the :outer
    then. Therefore the implementation needs sub->ctx (currently and IMH).

    Therefore, this code is not K, because the Parrot_sub structure has
    information it can't have:
    >
    >+ METHD PMC* get_caller() {


    It returns the sub PMC of the caller, which is rather useless for the
    one case of recursive subs - yes.
    There is still the interpreter based interface, so I can just remove
    this code - np.

    Parrot_sub must not have a ctx member.

    Ack all, but how do I implement this then:

    me = interpinfo .INTERPINFCURRENT_SUB
    outer = me."get_outer"()
    pad = outer."get_lexpad"()

    leo
  • No.2 | | 952 bytes | |

    Nov 23, 2005, at 19:08, Chip Salzenberg wrote:

    You keep confusing static and dynamic call information.

    While at static objects like subroutine PMCs - there is some code
    around that is setting properties on .Sub objects.

    $ find . -name '*.imc' -o -name '*.pir' | xargs grep -w setprop

    At least one in is bogus if
    not illegal:

    .const .Sub stub = "_reader_stub"
    setprop stub, "CALL", source

    What should we do WRT e.g. setprop:
    - disallow it at all for .Sub PMCs (it would be ok for .Closures,
    because these are distinct)
    - only allow it for 'clone'ed subroutine PMCs

    See also src/packfile.c:3200 and :377. The latter ('mark_1_seg') is run
    from GC to keep PMC 'constants' alive and I really don't like this. If
    PMC constants are created in the constant PMC pool, DD-marking isn't
    needed anymore.

    leo
  • No.3 | | 1124 bytes | |

    Wed, Nov 23, 2005 at 10:49:18PM +0100, Leopold Toetsch wrote:
    Nov 23, 2005, at 19:08, Chip Salzenberg wrote:
    >You keep confusing static and dynamic call information.


    Not confusing actually, maybe abusing the static sub structure by
    adding a dynamic field 'ctx' - yes.

    Point taken - the code may be confused, but that doesn't mean you are.
    :-) But that kind of abuse is just going to end in tears.

    Chip:
    Subs don't have callers.
    Call frames have callers.

    And callframes aren't PMCs (because we don't have weak pointers)
    therefore an introspection of :outer can only return the 'Sub' of outer
    but not actually the real call frame aka the context

    The introspection $frame.get_lexpad (pdd20) can't be implemented w/o
    that currently.

    Thanks for the reminder, I'd forgotten to put that IRC discussion into
    the doc. I just committed r10202, which includes:

    +For example, to get the immediate caller's LexPad, use:
    +
    + $P0 = getinterp
    + $P1 = $P0["lexpad"; 1]
  • No.4 | | 2432 bytes | |

    Wed, Nov 23, 2005 at 10:49:18PM +0100, Leopold Toetsch wrote:
    outer_sub - (the static sub PMC info) can't refer to :outer because the
    :outer can be a closure too. There are many incarnations of the :outer
    then. Therefore the implementation needs sub->ctx (currently and IMH).

    The docs conflate non-closure Subs and closure Subs in confusing way.
    Sorry. So I'm going to write my way through this. I think the design
    as is can work, with each Sub having a static outer_sub attribute, but
    only if closures also have an attribute that points to the Sub that
    they were created from.

    (Perl 5 calls this closure-creation process "cloning". I might adopt
    it, even though the reasons for the name are obsolete. I kept the
    term "pad" even though it's also technically obsolete)

    K, here goes. Correct me where I go wrong:

    * The initial static result of compilation is N Parrot_subroutines
    (Subs).

    * Each of these Subs may have a non-NULL outer_sub attribute, which
    describes the textual relationship of the Subs in the original
    source code. For example, given:

    sub foo {
    my sub bar {
    my sub baz {
    }
    }
    }

    baz.outer_sub is bar, and bar.outer_sub is foo.

    * This is a static description of a static situation (the source code
    doesn't evolve at runtime). So it need never change.

    * The result of newclosure is a new Sub, but I'm going to call it a
    Closure for clarity in this message.

    Now speculation:

    * We are free to give the Closure a new outer_sub attribute at the
    time it's created, if we choose, and that won't violate the rule
    that the original (source) Sub's attributes should be const, as
    long as the old outer_sub value can be captured.

    * For a nested closure like &baz above, how about if at newclosure
    time, we set the outer_sub to the specific Closure of bar that is
    currently executing?

    In order to do this:

    * Closures would need an attribute that points to the Sub they were
    created from. That would allow us to connect the running &bar
    _Closure_ to the &bar _Sub_ it was created from. (The reason we
    would need that connection is that the Sub &baz's outer_sub
    attribute points only to the static Sub &bar.)

    K so far?

    If so I'll follow up with design docs.
  • No.5 | | 2085 bytes | |

    Well, I had the right idea, but at a key moment I zigged when
    I should have zagged. So let's try this again.

    Wed, Nov 23, 2005 at 10:49:18PM +0100, Leopold Toetsch wrote:
    outer_sub - (the static sub PMC info) can't refer to :outer because the
    :outer can be a closure too. There are many incarnations of the :outer
    then. Therefore the implementation needs sub->ctx (currently and IMH).

    The docs accidentally conflate non-closure Subs and closure Subs. So
    I'm going to write my way through this. I think the design as is can
    work, with each Sub having a static outer_sub attribute, but only if
    closures also have an attribute that points to the Sub that they were
    created from.

    (Perl 5 calls this closure-creation process "cloning". I'll adopt
    that term for this doc, and maybe permanently.)

    K, here goes. Correct me where I go wrong:

    * The initial static result of compilation is N Parrot_subroutines
    (Subs).

    * Each of these Subs may have a non-NULL outer_sub attribute, which
    describes the textual relationship of the Subs in the original
    source code. For example, given:

    sub foo {
    my sub bar {
    my sub baz {
    }
    }
    }

    baz.outer_sub is bar, and bar.outer_sub is foo.

    * This is a static description of a static situation (the source code
    doesn't evolve at runtime). So it need never change.

    * The result of newclosure is a new Sub, but I'm going to call it a
    Closure for clarity in this message.

    * Each Closure has an "outer_ctx" attribute, which points to the
    call frame in which it was cloned. That call frame contains a
    pointer to the Sub (or Closure) that cloned the leaf Closure.

    * Therefore, we have outer_sub for the relationship of non-Closure
    Subs, and caller_ctx for Closure (cloning) relationships.

    * And thus there should be no need to modify a Sub after compilation,
    nor a Closure after cloning.

    Does this describe the current situation and its features?
  • No.6 | | 2849 bytes | |

    Thu, Nov 24, 2005 at 08:54:54AM +0100, Leopold Toetsch wrote:
    Nov 23, 2005, at 19:08, Chip Salzenberg wrote:
    >You keep confusing static and dynamic call information.


    While at static objects like subroutine PMCs - there is some code
    around that is setting properties on .Sub objects.

    Just to be clear, I don't think setting properties on a Sub is
    necessarily a bad thing. Let's say a user wants to create a bunch of
    Subs and then set properties on them for some design reason, say for
    the purpose of categorization or debugging or some such. That's fine
    with me. I'm only concerned (at the moment :-)) about Parrot itself
    storing dynamic (call-stack-dependent) state inside Sub objects.

    BTW, this principle still applies to Closures, but in a non-obvious
    way. Closures are cloned they can be called recursively, so call
    stack info about _them_ being called still can't be stored in them.
    Granted, they have attributes like "outer_ctx" (now) or "lex_env"
    (someday). But those are actually metadata relating to the single
    moment of the creation of the Closure: once the Closure is created,
    they never change. So they're still really const attributes.

    $ find . -name '*.imc' -o -name '*.pir' | xargs grep -w setprop

    Whole bunch of 'em, yup.

    At least one in is bogus if
    not illegal:

    .const .Sub stub = "_reader_stub"
    setprop stub, "CALL", source

    That is surely a bug. It's non-reentrant at the very least.

    I'd have to learn more about the Stream library to suggest a good fix.
    A lame fix might be a static Hash that uses something stream-specific
    as a key and the "CALL" attribute that would otherwise have been set on
    those Subs as a value. maybe a property on the stream? (I'm just
    guessing that there is such a thing as a stream PMC.)

    See also src/packfile.c:3200 and :377. The latter ('mark_1_seg') is run
    from GC to keep PMC 'constants' alive and I really don't like this. If
    PMC constants are created in the constant PMC pool, DD-marking isn't
    needed anymore.

    (Those line numbers don't match any more btw - if you want to write more
    about it please update them)

    The comment on mark_1_seg says that manually marking const PMCs is a
    consequence of non-const-created properties. I think that's valid.
    Granted, I don't like the idea of

    3.14159 but hexagonal #[*]

    and I hope nobody writes that. But the case of adding new properties to
    compiled Subs seems valid.
    [*] joke about Illinois (?) legislator who attempted to declare
    that, officially, pi == 3. Consequences to all circles in the
    state should be obvious. :-,

Re: Subs may not contain dynamic call info, ever (was r10151)


max 4000 letters.
Your nickname that display:
In order to stop the spam: 1 + 1 =
QUESTION ON "Perl"

EMSDN.COM