// Preserve Stack Definitions. // // File: preserve.h // Author: course // Version: 1 // Defines the preserve stack. #ifndef PRESERVE_H #define PRESERVE_H #include "object.h" // When a routine calls another that may allocate an // object, intermediate results needed by the calling // routine may be garbage collected. To prevent this, // these intermediate results are pushed onto the // preservation stack, and the garbage collector takes // care to mark all objects listed in the preservation // stack as in-use. // // To be sure everything that should be preserved is // preserved, it is desirable to follow some simple, // easily applied rule specifying which routine is // responsible for preserving what. The rule we use // is: // // PRESERVATION RULE: when a routine calls another, // the caller must preserve all intermediate // results he will need after the call returns, // and all arguments he is passing to the called // routine; except that the following commonly // used routines will preserve all their arguments // for the benefit of their caller: // // make_cons // apply // // Note that in order to preserve an object, you // need not store a pointer to it in the // preservation stack; it suffices to store a // pointer to it in a symbol, or in a dotted pair // that itself has been preserved. // // // Some consequences of this rule are that if u is an // unpreserved "object *" variable, and x, y, z are // preserved "object *" values, then // // u = make_cons // (x, make_cons (y, make_cons (z, u))); // // u = make_cons (make_cons (x, u), y); // // are OK, but // // u = make_cons (make_cons (x, y), u); // // u = make_cons // (make_cons (x, u), make_cons (y, u)); // // u = make_cons // (make_cons (x, y), make_symbol ("xxyz")); // // are not. // This class defines the preserve stack. It contains // no non-static members and has no instances. // class preserve_stack { public: // Preserve an object: push it into preservation // stack. // friend object * preserve (object * ob); // Release an object: pop it from preservation // stack. // friend object * release (); // Initialize preserve_stack. // static void initialize(); private: // Functions called on over/underflow error. // static void overflow(); static void underflow(); // Preserve stack. // Current points at next empty entry, and is // incremented when entry is pushed. End = location // just after stack. // static object * stack [PRESERVE_STACK_SIZE]; static object ** current; static object ** end; // Other functions that use internal preserve stack // data. // friend void gc(); // In gc.cc. friend class catch_area; // In catch.h. friend void toplevel // In toplevel.cc. (bool silent, bool stop_on_error); }; inline object * preserve (object * ob) { if (preserve_stack::current >= preserve_stack::end) preserve_stack::overflow(); return * preserve_stack::current ++ = ob; } inline object * release () { if ( preserve_stack::current <= preserve_stack::stack ) preserve_stack::underflow(); return * -- preserve_stack::current; } #endif // PRESERVE_H