Ok, this thread has now +45 entries, I'll try to summarize the
proposed PMC traversal schemes.

0) As the subject still applies ;-) we want to be able to dump() or
pretty_print() a PMC (and possibly aggregate members of that). This
turns out to be a special case of a deep traversal over nested PMCs
of any kind, which might contain self-references and the like.

1) There are more such traverse-like operations namely DOD, clone(),
freeze(). thaw() is different, as we run over the frozen byte-stream
and regenerate the PMC structures from that.

2) Proposals for DOD, freeze(), clone(), dump()

2a) Implement clone() & dump() on top of freeze(): clone=freeze+thaw,
dump() is generated in the debugger sub-system

2b) A general traverse() vtable that calls freeze/clone/dump-vtables.
DOD is a separate traversal (mark).[1]

2c) A more general traverse(), which is our current DOD mark()
functionality using next_for_GC.[2]

Comparison                                     2a     2b     2c
--------------------------------------------------------------------
clone needs intermediate frozen string[3]      yes     -      -
clone involves 2 steps                         yes     -      -
dump has to know PMCs internals[4]             yes     -      -
duplicates recognition overhead                Hash   Hash    -
Traversals per aggregate for clone/freeze[5]    1      1      3
Thread-safe[6]                                 yes    yes     -
Increases PMC size[7]                           -      -     yes
Adds complexity to DOD[8]                       -      -     yes
Cache friendly[9]                               -     yes     -
Code duplication[10]                            -      -     yes

[1] I consider Benjamin's proposal as some generalization of this for
now and a mixture of 2a) and 2b) (clone=freeze/thaw).

[2] mark() as of Parrot 0.0.6, each PMC gets on the next_for_GC list

[3] e.g. for clone(Array[10000]) the intermediate frozen image is
first generated in memory, then scanned again during thaw().

[4] what about dynamically loaded PMCs?

[5] 2c): 1. mark() per PMC, 2. clone() or freeze(), 3. clear
next_for_GC. mark is called inside clone/freeze again, which additonally
kills data cache coherency.

[6] While all schemes aren't thread-safe from user level (e.g.
manually sorting an array containing shared PMCs, while it gets
frozen), 2c) isn't thread-safe at low-level, as the next_for_GC
pointer inside the PMC is used as a duplicate marker. But if a user
changes shared resources its a user problem. We only guarantee atomic
updates per PMC (s. P6E p 86f by Dan).

[7] next_for_GC (and others like poperties) are in the PMC_EXT
structure now. Plain PMC scalars don't contain other PMCs, so the can
be marked life directly by setting just their live_flag.

[8] Additionally DOD has some shortcuts for marking e.g. a PMC
pointing to another or to an array of PMCs.

[9] 2a): The intermediate frozen image for clone()
    2c): 3 passes over aggregates; each PMC gets pulled in during DOD

[10] 2a): mark + freeze
     2b): mark + traverse
     2c): all traverse functions duplicated

This is of course my personal POV. If anything is wrong above please
correct me as well as WRT missing issues.

My major concerns are regarding footnotes [3], [5], [7], [8], and [9].
These haven't been commented/answered yet at all.

Thanks for reading til here ;-)
leo

leo

Reply via email to