Fri Aug 28 21:01:50 CEST 2009

GC restarts: clear separation between PURE and LINEAR functions.

To catch GC restarts in the definition of linera primitives, a simple
trick can be used for testing: simply kill the reference to the GC
right before a mutation is made.

So, primitives are either purely functional and can have allocation,
or are linear and cannot perform allocation but are allowed to perform
in-place operations.

Let's say that a primitive starts in pure mode, but whenver it mutates
something, it switches to impure mode.

In order to test all primitives, a freelist = NIL + GC step can be
performed before the execution of each primitive to cover the case
where a primitive needs extra storage.


- The VM: replace all PUSH/DROP operations with a FROM_TO. Start with
  making this type-tagged.  There is a real problem in the exception
  handler: it might fail as there is no guarantee there's enough

- Find a more highlevel way of doing this.  Preferably static.  Can't
  this be solved as a type issue?  In C?

- Am I solving a real problem, or is this just a consequence of the
  way the GC is implemented?  The real problem is to make a
  distinction between PURE and LINEAR, where the latter cannot perform
  any allocations, and the former cannot perform any mutations.

- Try it first in Scheme.

Ok.  In Scheme it doesn't seem to be such a problem.

Now, in PF, can't we make LINEAR the default?  The problem is then:
how to specify nonlinear words?

Let's say it's allowed to switch to PURE mode at the entry point of a

There's something fishy going on with exceptions in Scheme too:
exceptions should NOT perform allocations.  The _sc_step() might have
switched to linear mode, so the sc_make_error might trigger GC.

    switch(exception = setjmp(sc->m.r.step)) {
        case EXCEPT_TRY:
            rv = _sc_step(sc, state);
        case EXCEPT_ABORT: 
            rv = sc_make_error(sc, sc->m.error_tag, sc->m.error_arg, 
                               state, const_to_object(sc->m.r.prim));
            sc->m.error_arg = NIL;
            sc->m.error_tag = NIL;

(fixed: sc_make_error is now called before _sc_step, to preallocate
such that the error allocation itself can't trigger GC restart).

Maybe primitive exceptions should be linear?  There are a lot of
nuances here..  It needs to be simplified.

EDIT: I'm still using the earlier paradigm of ``pure before linear''.
In the C code this requires respecting some invariants in an
error-prone dentralized way, but the principle itself holds and seems
to have some higher significance: 

   You can use pure funcitional operations as long as you don't change
   the world state.  I.e. it's either PURE or LINEAR.  And you're
   allowed to switch from pure to linear, but not the other way

Practically, this makes memory management easier in the presence of
brutally low-level C-code.  Also, it's quite simple to enforce
linearity: simply do not pass a reference to the allocator!  It's more
difficult to enforce purity however.  In C this can't be enforced (or
maybe it can.. using some `const' declarations..)