Another (maybe silly) possibility suggested itself to me based on a
private mail re: infant mortality from Thomas Whateley: could we try
optimistic allocations?

Say we have a single memory backtracking jump buffer in the
interpreter. Then, before creating objects that cannot be easily
anchored to the root set, do a setjmp() and proceed ahead
optimistically under the assumption that no DOD runs will occur. You
must be careful here not to do anything with side effects that can't
be undone easily. Then, if DOD is triggered before you can anchor or
forget about the allocated objects, the interpreter does a longjmp()
back to your backtrack point:

  somefunc() {
    int dod_blocked = 0;
    if (setjmp(interp->dod_backtrack_jmpbuf)) {
      undo any partial state
      do_DOD_run()
      block DOD
      dod_blocked = 1;
    }

    ...code...

    interp->dod_backtrack_jmpbuf = NULL;
    if (dod_blocked) unblock DOD;
  }

It adds a single setjmp() to the common case, which may be
prohibitively slow for all I know. Although you can use the same
optimistic approach without longjmp(); you'd just have to write your
code so that it undoes the partial state if any object allocation call
fails:

  somefunc() {
    interp->on_alloc_fail = RETURN_NULL;
      .
      .
      .
      if (alloc_object() == NULL) {
        undo everything
        do_DOD_run
        interp->on_alloc_fail = CRASH_AND_BURN
        start over
      }
      .
      .
      .
    interp->on_alloc_fail = DO_DOD_RUN /* the default */
  }

This way, the common case isn't slowed at all.

Both feel too complex to be workable, though. I just thought I'd throw
it out there to round out the set of possibilities.

Reply via email to