  Self-adjusting computation offers a language-based approach to writing
programs that automatically respond to dynamically changing data. Recent work
made significant progress in developing sound semantics and associated
implementations of self-adjusting computation for high-level, functional
languages. These techniques, however, do not address issues that arise for
low-level languages, i.e., stack-based imperative languages that lack strong
type systems and automatic memory management.
  In this paper, we describe techniques for self-adjusting computation which
are suitable for low-level languages. Necessarily, we take a different approach
than previous work: instead of starting with a high-level language with
additional primitives to support self-adjusting computation, we start with a
low-level intermediate language, whose semantics is given by a stack-based
abstract machine. We prove that this semantics is sound: it always updates
computations in a way that is consistent with full reevaluation. We give a
compiler and runtime system for the intermediate language used by our abstract
machine. We present an empirical evaluation that shows that our approach is
efficient in practice, and performs favorably compared to prior proposals.
