> Remember that the higher level (eg perl6) will expect to be able to find the > PMC afterwards. For example: > > $foo = "abc"; > $bar = \$foo; > print $$bar; > $foo = 3; > print $$bar;
This depends upon how variables and the registers interact. If, like a real CPU, registers must be stored back into traditional memory as variables, then there is no problem. Code looks something like: #$foo = "abc"; new P0, PerlString set P0, "abc" stash_store P0, "foo"; #^ or however we store into the current stash, or global stash #$bar = \$foo; new P1, PerlRef set P1, "foo" #^ or whatever namespace we are in. it could also be a pointer #to some particular point in the stash, or whatnot. #print $$bar deref P2, P1 #put the PMC pointed to by P1, into P2 print P2 #$foo = 3; new P0, PerlInt #^ not strictly necessary, but it makes a new PMC, #which is necessary for this example set P0, 3 stash_store P0, "foo"; #print $$bar deref P2, P1 print P2 If instead, registers are aliased onto traditional memory variables, such that a PMC pointed to by a register is *also* pointed to by a stash somewhere, then it's a bit harder. One approach that's an extension of my previous idea (where we obliterate the destination PMC), is to change the PMC* of registers to PMC**. This allows us to support the example you mentioned, and also allows us to blindly obliterate whatever value is in the destination with our newly constructed PMC, assued the old one will be properly GC'ed. This is currently the approach I am leaning towards, if registers are aliased onto variables. (Otherwise I prefer the approach mentioned above, which is more inline with traditional register architectures.). I thought about leaving PMC*'s and doing a memcpy over it, but that's a 'bad thing' in terms of support PMC-header custom DOD routines. Another example of the ugliness in terms of supporting the GC for the PMC's is: STRING* s = string_copy(INTERP, (STRING*)SELF->cache.struct_val); dest->cache.struct_val = string_concat(INTERP, s, value->vtable->get_string(INTERP, value), 0 ); /* don't destroy s, as it is dest->cache.struct_val */ What's the point of making a copy of that string? I don't really know, and I don't see the point. The comment at the end doesn't help any, either .. I'm hoping it's just code written under false assumptions. Right now, it's not GC safe since 's' is not traceable, and if a dod run occurs, s will be GC'ed. Same thing for the 'get_string' result, which is also not traceable from the root set. To make this GC-safe, we need to: a) store them all in temp variables b) mark them as immortal/immune c) operate on everything, get the result, and store it d) unmark them If we had C++, we could do all sorts of nice tricks with objects and deterministic destruction at code block end. But we don't. This leads to verbose code that's not easy or intuitive to write, with every PMC method needing to do the above abcd logic to operate on variables. Thoughts or comments? Mike Lambert PS: If you want, I can submit a patch that fixes the GC bugs in the current system, leaving the semantics the same. It's just going to be extremely ugly, verbose, and not nice to look at. (And not fun for me to write, either.)