Dan Sugalski <[EMAIL PROTECTED]> writes:

[...]

> > > The chill and warm runtime methods take a PMC or a frozen representation
> > > of a PMC (respectively) and provide a human readable version of that PMC.
> >
> > 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. It's a function that
> belongs in the freeze/thaw API as it's just an alternate encoding or
> decoding. (Arguably it ought not be a separate API entry at all and just
> another encoding scheme, but that requires transcoding serialization
> forms, and I'd rather not get into that)

This is really just a naming problem. Dan wants to call the
vtable-function freeze and have different encodings for all kinds of
dumping/pretty_printing/marking. Leo calls the function traverse and
controlls it by callbacks.

My personal opinion on this naming problem is: traverse describes more
generaly what the function does. Marking live objects by freezing them
in an encoding that does return nothing just sounds plain wrong.

Freeze should be just a user of the general traverse function. (And
this does mean it is also no vtable function)

STRING *freeze(PMC *pmc, whatever *encoding)
{
   return (STRING *)pmc->vtable->traverse(pmc, freeze_callbacks, encoding);
}

or even the freeze_encodings are callback_sets: freeze_xml,
freeze_yaml, freeze_binary, whatever.

>>>   1) Freezing at the destruction level may *not* use any additional memory
>>>      for object traversal
>>
>> What is "Freezing at the destruction level"? Is this anyhow related to
>> destruction ordering?
> 
> No. There are some valid cases where an object, after having been declared
> dead by the DOD, wants to serialize itself. Persistent object stores
> apparently do this, and it makes a certain amount of sense--when the
> object goes out of scope the current state is flushed to disk.

This is a question of what is allowed at destruction time. You don't
want to allow memory allocation, but allow freezing. That gets hard,
because you need at least allocate the STRING where you want to put
your frozen stream.

> It puts a number of unpleasant constraints on the core freeze routines.
> User code can violate them and take the consequences, but we can't.

We can call (hopefully) arbitary user code in destruction routines. So
this argument does not count

>>> Note that I do *not* want to have multiple object traversal systems in
>>> parrot! We have one for DOD, and proposals have ranged upwards from there.
>>> No. That is *not* happening--the chance for error is significant, the
>>> side-effects of the error annoying and tough to track down for complex
>>> cases (akin to the trouble with tracking down GC issues), and just not
>>> necessary. (Perhaps desirable for speed/space reasons, but desirable
>>> isn't necessary)

Freeze is just another traversal method. Just calling it freeze
instead of traverse does not change this fact. You can limit the power
of encodings, but this does not change the fact that you need to walk
all children

>> DOD's mark() routine has different requirements then a general
>> traverse() for freeze(), chill(), clone(), and destruction ordering.
>> Using just mark() will have these side effects that you want to avoid.
> 
> 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.

mark() may be implemented in form of a general traverse. Let the
profiler decide if a special purpose mark() or a general traverse is
better.

>> A general traverse() can be depth first of breadth first, mark() isn't
>> required do have any specific ordering as long as it sets live bits
>> everywhere.
> 
> I'm pretty sure that with a singly linked list we can get a generally
> properly-ordered flattened tree without having to do an insane number of
> passes across the dead object store. I may be incorrect in this, but I
> don't think so, and for our purposes the live bit can be safely ignored if
> we end up setting it, though potentially with another pass over the dead
> store, which may end up prohibitively expensive. We'll see.

I'm pretty sure that a singly linked list is not enough. I had done
some experiments with this. One pass my be enough, but you need to
keep track of the tree-traversal and of the partial ordered
list. These to things don't play well together. Maybe this can be cut
down to two lists, or one list and one bit per pmc.
 
>> 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.

Destruction ordering just enforces that small PMCs can't have
destructors. If they have destructors they must be big, big enough to
construct the ordered list of objects without allocating any memory.

If you think about it: The call to the destructors is done after
free_unused_pobjects completed. The memory of the objects without
destructors is already freed. If you are still in an out of memory
situation when the destructors are run, then its also very likely that
you are in a not much better situation afterwards. 

>> While freeze() and friends have to pull in each PMC into the cache, just
>> setting the live bit on a PMC hasn't. Further: Lukes proposal for
>> speeding up timely destruction puts objects either in front or at the
>> end of the next_for_GC chain. This IMHO implies that mark() is unusable
>> as your general and solely iterator.
> 
> We may end up playing macro games with the code. I can live with multiple
> instantiations of the code, but I want only a single chunk of source to be
> maintained.

You know we already have two versions of pobject_lives lying around.

[...]

boe

Reply via email to