On Tue, 21 Oct 2003, Leopold Toetsch wrote: > Dan Sugalski <[EMAIL PROTECTED]> wrote: > > On Tue, 21 Oct 2003, Leopold Toetsch wrote: > > [ thaw ] > > >> This should IMHO be able to create constant PMCs out of metadata, e.g. > >> for subroutine objects. So there should be some means to tell thaw() to > >> create PMC(s) in the constant_pmc_pool. > > > There should be a way to put PMCs in the constant pool in general. I was > > thinking a constant op would work--something like > > > constant Ix, [SP]y > > > to make the string or PMC Y a constant at slot X in the constant pool. > > You can append items to the constant table. You can't declare existing > items as constant, because you can't change the underlying object pool, > where the object was allocated. This would change the objects address.
The object's address should be irrelevant for the constant table. PMCs are referenced in the opstream by table offset. This offset can be into a PMC pool, or into a pointer table. While the pointer table has an extra level of indirection to it it adds flexibility and takes some pressure off of the ordering of PMCs for instantiated constants. > > Passing in the PMC header to be filled in also works, though both fail if > > you want full PMC trees marked as constants since thawing out a PMC stream > > may involve creating multiple PMCs. (In which case we might be better > > temporarily switching allocation pools at constant creation time, rather > > than passing in PMCs) > > These are either serious shortcomings or unneeded workarounds. An extra > parameter to relevant vtables can take care of such special cases. Not necessarily, no. The number of PMCs that are reconstituted for a set of constant frozen PMCs is indeterminate. If we're instantiating bytecode with constant PMCs in it it's possible the class that backs those PMCs has changed and things instantiate differently than they might otherwise do. If we've frozen 20 PMCs, all we can guarantee is that when we unthaw them that we've got at least 20 PMCs, though we may have more, and the extras arguably should be allocated from the constant PMC arena (though not given slots in the constant table) so we can skip scanning the constant arenas for dead objects needing cleanup. > >> I dunno, why chill() is superior to dump() or pretty_print(), but the > >> name doesn't really matter. > > > The important thing is that it's not a vtable method. > > Ah, that's the difference. How shall the system pretty-print dynamically > loaded PMCs then, when only a bytecode-stream is available? IMHO only a > vtable in the class can perform that job. If the dynamically loaded PMC class doesn't have a backing Parrot class, you can't, and get the default, relatively primitive dump. > >> > 1) Freezing at the destruction level may *not* use any additional memory > >> > for object traversal > > > It puts a number of unpleasant constraints on the core freeze routines. > > Constructing the frozen stream definitely needs memory. I don't see the > difference, to memory consumed by a seen hash. Can you please elaborate > a bit more on this. Constructing the frozen stream will need some memory, yes. At the moment all it needs is a chunk of random memory and that's it, so we may well fail because we're out of memory. We may, however, have general pool memory handy. We can't guarantee that we have *any* headers, however, since we can legitimately be called from within the destruct phase of a DOD run, which may have been triggered by an out-of-headers condition. Depending on how we flesh things out freezing may also not require any additional memory--if we relax the requirement for freezing to allow the output to be a PMC, we may be backed directly to a file or other storage that doesn't involve RAM allocation. > > The only thing that mark does that the general traversal doesn't, in the > > abstract, is flip the object's live flag. Everything else is an > > optimization of code which we can, if we need, discard. > > Yes, mark() can be written in terms of a general traverse, which gets a > vtable function (and a data pointer). mark is basically traverse(mark, > 0). But this isn't true the other way round. You can't do freeze based > on the mark iterator. How do you pass the desired output format? What does the desired output format have to do with any of this? All marking does is put things on the list of PMCs to be visited if it hasn't already been visited, so we get to that PMC at some point as we walk the visited list. In the context of the DOD sweep it also sets the live flag, but we could, if we chose, skip that and use the presence of a non-NULL value in the mark chain address for a PMC as an indicator of liveness. (Though yes, I realize that this means potentially skipping some of the optimizations, so I'm not proposing it as a requirement for the DOD sweep implementation) > >> mark() is called permanently in a running interpreter, that does non > >> trivial things. There are shortcuts for scalars, DOD is highly optimized > >> not to destroy cache coherency. Using mark() also implies to back out > >> my small PMC patches. All the advantages of smaller scalars are gone > >> then. > > > All of this stuff for freezing is going to end up killing the small PMC > > patch anyway, unfortunately, since we're going to have to be able to > > traverse PMCs in the destruction phase, which means we have to have the > > means of traversal at hand as we can't guarantee that we can allocate more > > PMCs or resize the PMCs ext data. > > A scalar can't contain or reference other PMCs, so it can't be a > potential source of freeze loops. If I now spit out (PMC: Int, ID=xy, > value=5) twice or (PMC: ID=other) doesn't really matter. thaw() can take > care of duplicates, if needed. Other PMCs have the next_for_GC pointer. Thaw can only properly take care of duplicates if the duplicates are correctly indicated in the serialization stream. Identical end-values are *not* sufficient to note multiple references to the same PMC. > Albeit I'm not convinced, that we can't have a seen hash. It takes an insane amount of memory and requires header allocation. We can't allocate headers, and the memory requirements are extreme. Been there, done that, it was a bad idea. Consider this arbitrarily and unconditionally ruled out if you're unwilling to believe the stats that were previously posted about this. Dan