Leopold Toetsch <[EMAIL PROTECTED]> writes: > I have a (partial?) solution for this. What AFAIK is going on is > something like this: > > C-stack: Parrot_open() ... later ... do_dod_run() > ... ... > $1 = pmc_new sub $0x44, %esp > ... > IO-PMC -----------------------> > ... > trace_system_stack() > > So during a DOD run the trails of an IO PMC are found on the system > stack during trace_mem_block. The main problem seems to be, that gcc > uses 16-byte aligned stack frames by default. So there are "holes" in > the stack, where it is not unlikely, that we find trails of PMCs used > in earlier functions calls.
*Ouch* I spend the whole Friday searching this unbound PMCs, but failed to find them, they seemed to be nowhere in the stack-frames. Now you found out that they aren't in a stack-frame. > I did compile parrot with: > > -mpreferred-stack-boundary=2 > > and the t/pmc/io_2.pasm test succeeds with all run loops then. > > As we don't pass around mmx/sse memory locations above option should be > safe. [...] We should really rethink the statement "We will always walking the stack". The timely destruction needs to know for sure if an object is alive or not. The conservative stack-walking will not give you this information. The stackwalking was introduced to solve the infant mortality problem. One of its big advatage was its convinience for the C-programmer: Just use a PMC, and you are done. But with timely this convinience suddenly has vanished: The programmer has to make sure that every local variable is initialized, and that the program is compiled with the right options. This may not be a problem in the Parrot-core, but in an extension module this is a big problem. The wrong stack boundarys e.g. may cost performance. Ok, then we need another solution for the infant mortality problem. The requirments for this are: - PMC should be traced exact (timely destruction requieres this) - allows recursive calls of run_core - should not be fooled by longjmp Furthermore the system should be simple and fast. For bonus points it should be portable. Some ideas solving this problem: Not discussing the solutions of docs/dev/infant.dev here. * Use C++ for the PMCs This would give a very convienient way of handling this. The constructors and destructors are emitted by the compiler. Therefor a simple explicit neonate-flag can be handlet correctly. Even PMC assignments are no problem because of operator overloading. The disadvatage of this: its C++. * mark all PMC values on the stack All creations of PMCs are recorded and only these PMCs are traced. This could be handled by a macro like #define NEW_PMC(var) PMC *var = register_pmc(&var) A longjmp can use some wrapper-code which cleans up the stack above the current stacktop. But this will only work if there is reliable way to detect when an end of scope, otherwise the above problem can bite us again. If the programmer has to take care of the scope exit this is not more than a clever neonate-flag which takes care of longjmps. * use a liked list of frames Every call to a parrot function gets an extra parameter of the type struct gc_frame { struct gc_frame *prev; Pobj *pobj; } * A function not allocating anything just pass on the previous gc_frame foo(struct ParrotInterp *interpreter, struct gc_frame *frame, ...) { bar(interpreter, frame, ...); } whereas a function using a temporary is working this way foo(struct ParrotInterp *interpreter, struct gc_frame *frame, ...) { struct gc_frame temp = { frame, NULL }; temp.pobj = bar(interpreter, frame); baz(interpreter, &temp); } This scheme is exact, works thru longjumps and recursive run_cores and only the active objects are traced, but it has the problem that it changes the signatur of every parrot-function. Comments? boe -- Juergen Boemmels [EMAIL PROTECTED] Fachbereich Physik Tel: ++49-(0)631-205-2817 Universitaet Kaiserslautern Fax: ++49-(0)631-205-3906 PGP Key fingerprint = 9F 56 54 3D 45 C1 32 6F 23 F6 C7 2F 85 93 DD 47