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.