From: Michael R. Blair Date: Mon, 28 Mar 1994 11:08:57 +0000 (+0000) Subject: pretty pretty texinfo kludge X-Git-Tag: 20090517-FFI~7200 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=0dc87813864a7005c12cfe19d619ba63d6ac61e3;p=mit-scheme.git pretty pretty texinfo kludge --- diff --git a/v7/src/wabbit/README b/v7/src/wabbit/README index f3a5b844d..92b6822a3 100644 --- a/v7/src/wabbit/README +++ b/v7/src/wabbit/README @@ -1 +1,549 @@ -Wabbit -- documentation to be supplied. +@c -*- TeX-Info -*- + +This is file: /scheme/documentation/README.wabbit + +@node Top + +What's up, Doc? +--------------- + + The MIT C-Scheme garbage collector has been extended w/ an alternative gc-loop +which supports ``wabbit hunting'' and ``headhunting'' garbage collection. + + +To enable wabbit hunting, evaluate: (load-option 'wabbit) + +``Wabbit hunting'' is when you have a reference to an object and you want to +collect all other references to that same object. For instance, several data +structures may share (alias) the same sub-datum. Wabbit hunting allows you to +collect all such sharers, presumably to update them all in an interesting way +or just to collect sharing statitistics or a sharing histogram. + + +To enable headhunting, evaluate: (load-option 'headhunt) + +``Headhunting'' is when you wish to reify all ``headed'' objects in storage +(heap *and* constant space) into one moby vector. Note that base objects such +qas fixnums, Booleans, and characters, etc are not ``headed'': they are not +referenced by an object pointer. Presumably, it is interesting to go +headhunting to gather usage statistics and histograms and to do delicate memory +surgery. For this reason, great care must be taken in groveling over a +``headhunt collection'' (the result of a headhunting GC). + + + +@menu + +* Wabbit Descwiptor:: Data abstraction: descriptor of target wabbits + +* Wabbit Buffer:: The buffer for recording wabbit sightings + +* Wabbit Hole:: The format of wabbit sighting records + +* Fudd Thunk:: A thunk to invoke after targets are gathered + +* Headhunt Collection:: The format of headhunt results + +* Swabbing Wabbit Descwiptors:: Automagic swabbing upon return from the hunt + +* Procedures Summary:: Utilities for wabbit hunting and headhunting + +* Examples:: A few sample wabbit hunts and headhunts. + +@end menu + + +@node Wabbit Descwiptor + +A ``Wabbit Descwiptor'' is a 4-element vector: + + ------------------------------------------------------------------------ + 0. Boolean hunt disable flag -- (a.k.a. ``duck season'' flag) + avoid wabbit hunting and/or headhunting + upon the next GC flip. + + 1. Wabbit vector -- vector of object references to target objects + (a.k.a. ``wabbits'') + + 2. Wabbit buffer -- vector into which wabbit sightings are recorded. + This must be of length (2 + twice wabbit vect len). + + 3. Boolean headhunt enable flag -- if FALSE, no headhunt is performed. + else this slot will be replaced by a + headhunt collection upon completion + of the headhunting wabbit hunt. + ------------------------------------------------------------------------ + + **** + NB a) Both the WABBIT-VECTOR and the WABBIT-BUFFER must reside in the heap + **** i.e., they may *not* reside in constant space or on the stack. + + b) Both the wabbit buffer and the headhunt collection slots are zeroed + upon return, since they may contain unsafe pointers. Moreover, it + is unsafe for the FUDD-THUNK to return them or otherwise close over + them. Consider them only to be very fluid parameter sources for the + FUDD-THUNK. + + +@menu + +* Default Fudd Thunks:: + +@end menu + + +@node Fudd Thunk + +What's a Fudd Thunk? +-------------------- + + After the hunt has concluded, all the target wabbits (if any) will reside in +the wabbit buffer of the wabbit descwiptor and all heads collected (if any) +will reside in the headhunt-collection slot of the wabbit descwiptor. It is at +this point that the FUDD-THUNK is invoked. + + A ``FUDD-THUNK'' is a procedure of no arguments. Whatever result it returns +is the result of the call to WABBIT-HUNT or HEADHUNT, whichever was called. It +is therefore imperative that the FUDD-THUNK not return unsafe values (wabbit +holes that might reference the stack). + + Normally, you will write Fudd thunks which use (GET-WABBIT-DESCWIPTOR) and the +wabbit buffer and headhunt collection accessors on wabbit descwiptors. See the +example section below for a few samples of how the Fudd thunks are used. Most +important, note the upon exit from a call to WABBIT-HUNT or HEADHUNT, the +wabbit buffer and headhunt collection in the wabbit descwiptor are ``swabbed'' +soas to release wascally wabit holes and the moby headhunt collection. See the +``swabbing'' section below. + + +Default Fudd Thunks +------------------- + + The default Fudd-thunk for wabbit hunting is fluid-bound to the global +variable *DEFAULT-FUDD-THUNK*. The default Fudd thunk merely returns the +wabbit buffer, which will have been swabbed in the return process. That is, its +wabbit holes will have been nullified. + + The default Fudd-thunk for headhunting is fluid-bound to the global variable +*DEFAULT-HEADHUNT-FUDD-THUNK* The default headhunt Fudd thunk returns the +headhunt collection. This will *not* have been swabbed out (but the headhunt +collection slot in the wabbit descwiptor will have been swabbed), so you must +be careful what you do with the result of HEADHUNT called with the default +headhunt Fudd thunk. It is best to simply drop it, being careful not to let the +printer hash it as the result of an interactive REPL call. + + + +@node Wabbit Buffer + + The ``Wabbit Buffer'' should be a vector of FALSEs before the wabbit hunting +is initiated. At the end of the wabbit hunt, the wabbit buffer contents will +be laid out as follows: + + -------------------------------------------------------------------------- + slot 0 = Boolean flag: TRUE if all wabbit sightings were recorded in the + wabbit buffer + FALSE if the wabbit buffer was too small to accomo- + date a record for each wabbit sighting. + (In this case, the FUDD-THUNK should do a + bit of cleanup work so the same wabbit + hunt can be re-initiated later.) + + slot 1 = Fixnum: number of wabbit sightings recorded in the wabbit buffer + + slot 2 = Object reference: cite of first wabbit sighting (``wabbit hole'') + + slot 3 = Number: offset into first sighting object where wabbit is hiding + -------------------------------------------------------------------------- + +...and so on, with even-index slots containing wabbit holes and odd-index +slots, indices. Note that slot 1 should hold the index of the first even +slot that holds FALSE and all slots thereafter should likewise hold FALSE. + +It is not really essential that the wabbit buffer be cleared before a hunt +since the slot 1 indicates the index of the first garbage slot. Nonetheless, it +is poor form to supply a populated vector. + +Note also that the wabbit buffer will be ``swabbed'' upon return from the hunt. + + +@node Wabbit Hole + + A ``Wabbit Hole'' is normally a headed object reference (a pointer) but it +may in very rare circumstances be a ``wascally wabbit hole''. There are only +three kinds of wascally wabbit holes: + + --------------------------------------------------------------------------- + 1. Characters: these indicate references to wabbit holes in constant space. + To reify the character into a cell whose contents holds the + wabbit, apply CELLIFY to the slot ref that holds the char. + (NB: the char as printed holds only part of the addr; you + must vector-ref into the wabbit buffer to get all the + addr bits. This is incredible magic.) + + 2. Null Refs: these indicate headless objects. They should never appear. + + 3. Stack Refs: these indicate objects on the control stack. Since we reify + the stack into the heap as part of the call to WABBIT-HUNT and + HEADHUNT, these too should never appear unless you are doing + something painfully obscure (and dangerous!). + --------------------------------------------------------------------------- + +If you ever encounter Null or Stack wabbit holes, you may want to send a +friendly bug report (?) to bug-cscheme@zurich.ai.mit.edu with a reproducable +test script. (If we cannot reproduce it, we cannot fix it.) + +@node Headhunt Collection + +The ``Headhunt Collection'' is a vector of arbitrary (fixnum) length. It is +intended to contain a pointer to the head of every object in the heap which has +an object header (spec., numbers, Booleans, etc not included). If all headed +heap objects fit in the space available after the GC flip, then slot 0 of this +headhunt collection is TRUE. If not, slot 0 is FALSE and the vector contains as +many object head references as actually did fit. + + +************ Be verwy verwy careful when headhunting... if you are not careful +** CAVEAT ** to release the headhunt collection (e.g., don't let it escape) or +************ if you gobble up too much intermediate state in traversing it, you + will exhaust the available heap space and go down in flames. This + is a very fragile system memory feature intended for only the + most ginger-fingered discriminating systems wizards. For instance + it may someday lead to a post-GC garbage scavenger. Nonetheless, + it readily lends itself to self abuse if not treated reverently. + + +@node Swabbing Wabbit Descwiptors + +Swabbing Wabbit Descwiptors +--------------------------- + + Upon exit from WABBIT-HUNT or HEADHUNT, the wabbit descwiptor with repsect to +which the hunt was performed will be ``swabbed'' so as to release the wabbit +holes and the headhunt collection. Specifically, the first two slots of the +WABBIT-BUFFER (indicating all-found? and index-of-first-null) are left +unmolested. The remainder of the WABBIT-BUFFER is cleared back to all be #F. +This way no dangerous wabbit holes (e.g., stack refs) will be left dangling in +the wabbit descwiptor after the hunt. In addition, the HEADHUNT-COLLECTION slot +of the wabbit descwiptor is set to the number of heads collected, which is then +negated if not all heads were accomodated by the heap. That is, if say +314159264 were found but more heads existed but could not fit in the +headhhunt-collection, then the headhunt-collection slot of the wabbit +descwiptor will be set to -314159264. + + Note that the HEADHUNT-COLLECTION vector itself is not cleared: this could +waste a lot of time and would not really free up significant space since the +vector would still exist in the heap. It is therefore important that you not +carelessly return the HEADHUNT-COLLECTION from the thunk since this could allow +its subsequent capture, from instance by the hashing printer in the interactive +REPL. Moreover, this HEADHUNT-COLLECTION may contain entries that were moved +into the heap from the stack by the nature of the WABBIT-HUNT/HEADHUNT calls +(they do a cwcc to reify the control stack onto the heap). Thus, the +HEADHUNT-COLLECTION may contain dangerous pointers after the return from the +hunt call. You can crash your Scheme in a very nasty way if you do not take +heed of this danger. + +[Implementors' note: this swabbing is accomplished via an unwind protect which + calls gc-wabbit::%swab-wad upon exit from the hunt.] + +@node Procedures Summary + +@menu + +* Wabbit Hunt:: +* Wabbit Season and Duck Season:: +* Wabbit Descwiptors:: +* Default Fudd Thunks:: +* Cellify:: +* Headhunt:: + +@end menu + +@node Wabbit Hunt + +(WABBIT-HUNT WABBIT-DESCWIPTOR #!optional FUDD-THUNK) + + Open wabbit season on wabbits matching WABBIT-DESCWIPTOR and go wabbit + hunting. Once all the wabbits have been wounded up, invoke FUDD-THUNK, + weturning the wesult of FUDD-THUNK as the wesult of the wabbit hunt. + + The optional FUDD-THUNK pawameter defaults to the value of the fluid + vawiable: *DEFAULT-FUDD-THUNK*, which defaults to just weturning the + wabbit buffer (which will have been swabbed upon return!). + + +@node Wabbit Season and Duck Season + +(WABBIT-SEASON! WABBIT-DESCWIPTOR) + + Declare open season on wabbits matching our target descwiptor. + Returns the old wabbit descwiptor (possibly FALSE). + +(DUCK-SEASON!) + + Disable wabbit hunting... returns descwiptor from latest wabbit hunt. + +**** + NB WABBIT/DUCK-SEASON! mutate the system wabbit descwiptor accessed via +**** calls to (GET-WABBIT-DESCWIPTOR). + + +(WABBIT-SEASON?) +( DUCK-SEASON?) + + It is wabbit-season if the value returned by (GET-WABBIT-DESCWIPTOR) is a +valid wabbit descwiptor with the hunt-disable flag disabled (i.e., hunt is +enabled). Otherwise, it is duck season. + + +@node Wabbit Descwiptors + +(GET-WABBIT-DESCWIPTOR) + + Returns the current wabbit descwiptor as installed by WABBIT/DUCK-SEASON! +(which are implicitly called from WABBIt-HUNT and HEADHUNT). This may *not* +always be a valid instance of a WABBIT-DESCWIPTOR so it is best to check the +result using (WABBIT-DESCWIPTOR object). + + +(WABBIT-DESCWIPTOR? object) + + Returns TRUE if OBJECT is a 4-element vector; FALSE otherwise. That is, the +WABBIT-DESCWIPTOR is a transparent type (non-opaque). + + +The painfully obvious creator, selectors and mutators are as follows: + +(MAKE-WABBIT-DESCWIPTOR hunt-disable-flag + wabbit-vector + wabbit-buffer + headhunt-enable-flag) + + + (WABBIT-DESCWIPTOR/HUNT-DISABLE-FLAG wabbit-descwiptor) + (WABBIT-DESCWIPTOR/WABBIT-VECTOR wabbit-descwiptor) + (WABBIT-DESCWIPTOR/WABBIT-BUFFER wabbit-descwiptor) + (WABBIT-DESCWIPTOR/HEADHUNT-ENABLE-FLAG wabbit-descwiptor) + +(SET-WABBIT-DESCWIPTOR/HUNT-DISABLE-FLAG! wabbit-descwiptor new-value) +(SET-WABBIT-DESCWIPTOR/WABBIT-VECTOR! wabbit-descwiptor new-value) +(SET-WABBIT-DESCWIPTOR/WABBIT-BUFFER! wabbit-descwiptor new-value) +(SET-WABBIT-DESCWIPTOR/HEADHUNT-ENABLE-FLAG! wabbit-descwiptor new-value) + + +In addition, the following aliases were thought to be handy: + + WABBIT-DESCWIPTOR/HEADHUNT-COLLECTION = + WABBIT-DESCWIPTOR/HEADHUNT-ENABLE-FLAG + + SET-WABBIT-DESCWIPTOR/HEADHUNT-COLLECTION! = + SET-WABBIT-DESCWIPTOR/HEADHUNT-ENABLE-FLAG! + + +See the section on Wabbit Descwiptor for details of the components types and +formats. + +@menu + +* Wabbit Descwiptor:: + +@end menu + + +@node Default Fudd Thunks + +Wabbit Hunting +-------------- + +*DEFAULT-FUDD-THUNK* + +Global fluid variable bound to a procedure of no arguments that is called upon +collection of all the wabbit holes into the wabbit buffer (and heads into the +HEADHUNT-COLLECTION if headhunting is enabled) + + + +Headhunting +----------- + +*DEFAULT-HEADHUNT-FUDD-THUNK* + +Global fluid variable bound to a procedure of no arguments that is called upon +collection of all heads during HEADHUNTing (and upon collection of all wabbit +holes into the wabbit buffer if the wabbit vector is non-empty). + + +*DEFAULT-HEADHUNT-WABBIT-DESCWIPTOR* + +The default wabbit descwiptor used by calls to HEADHUNT. It contains a null +wabbit-vector and a wabbit buffer of only two slots (for the flag and index). +This is a global variable that can be fluid bound to any valid wabbit +descwiptor instance. + + +@node Cellify + +(CELLIFY CONSTANTSPACE-WABBIT-HOLE) ;; c-space wabbit holes print as characters + + This is a *very* precarious hack. It returns a cell whose contents point to +the wabbit hole in constant space. This cell should not be permitted to escape +from the Fudd-thunk where (presumably) it was created, else a spurious pointer +into constant space would result and who knows how it might piss off the +garbage collector. Specifically, don't go pretty-printing these cells 'cause +the printer hashes output so the display hashtable will capture the cell. + + In general, you should go have a nice quiet discussion with a system wizard +before frobbing with CELLIFY. It can save you a *lot* of trouble, believe me. + + +@node Headhunt + +(HEADHUNT #!optional HEADHUNT-FUDD-THUNK HEADHUNT-WABBIT-DESCWIPTOR) + +The HEADHUNT-WABBIT-DESCWIPTOR is installed, which declares open season on no +wabbits but does call for headhunting to commence. Afterward, the +HEADHUNT-FUDD-THUNK is invoked (on no arguments) and its result it the result +of the call to HEADHUNT. + +The optional HEADHUNT-FUDD-THUNK parameter default to the value of +*DEFAULT-HEADHUNT-FUDD-THUNK*. Similarly for HEADHUNT-WABBIT-DESCWIPTOR. + +As with WABBIT-HUNTing Fudd thunks, the HEADHUNT-FUDD-THUNK is free to access +the wabbit descwiptors wabbit-buffer and headhunt-collection slots, but should +be careful in doing so. Letting dangerous bits escape can be treacherous. + +Also, as with WABBIT-HUNTing, the wabbit descwiptor is swabbed upon completion +of the hunt. (In fact, this is just an alternative caller interface to the +WABBIT-HUNT procedure for those more interested in headhunting than in wabbit +hunting. To each his own.) + +@menu + +* Default Fudd Thunks:: + +@end menu + + +@node Examples + +;;; +;;; Sample usage (and mis-usage) +;;; + +@menu + +* Wreckless:: Wabbit Hunt - mis-use / abuse +* Non-Wreckless:: Wabbit Hunt - good use +* Dangerous:: Wabbit Hunt - poor use +* Semi-Wreckless:: Headhunt - fair use + +@end menu + + +@node Wreckless + +#| Sample wreckless wabbit hunt... (does not swab the wabbit buffer) + -------------------------------- +(define foobarbaz (cons 'a 'b)) + +(begin + (wabbit-season! + (make-wabbit-descwiptor false ; hunt disable flag disabled + (vector foobarbaz) ; wabbit vector + (make-vector 10 #f) ; wabbit buffer + false ; headhunt enable flag disabled + )) + 'be-careful!) + +(gc-flip) + +(define done (duck-season!)) + +(pp done) ; lookin' for trouble + +;returns: #(#t #((a . b)) #(#t 4 (foobarbaz a . b) 1 () () () () () ()) ()) +|# + + +@node Non-Wreckless + +#| Sample non-wreckless wabbit hunt... (safe wabbit hole count) + ------------------------------------ +(wabbit-hunt + (make-wabbit-descwiptor false ; hunt disable flag disabled + (vector foobarbaz) ; wabbit vector + (make-vector 10 #f) ; wabbit buffer + false ; headhunt enable flag disabled + )) + +; evaluated repeatedly... (stable wabbit hole count... holes swabbed upon exit) +; +;Value 31: #(#t 6 () () () () () () () ()) ; - 6 = wabbit hole count + 2 +;Value 32: #(#t 6 () () () () () () () ()) +;Value 33: #(#t 6 () () () () () () () ()) +|# + + +@node Dangerous + +#| Sample dangerous wabbit hunt... (fudd thunk exposes the wabbit holes...hash) + ----------------------------- +(wabbit-hunt + (make-wabbit-descwiptor false ; hunt disable flag disabled + (vector foobarbaz) ; wabbit vector + (make-vector 10 #f) ; wabbit buffer + false ; headhunt enable flag disabled + ) + (named-lambda (exposing-fudd-thunk) + (let* ((wabbuf (wabbit-descwiptor/wabbit-buffer (get-wabbit-descwiptor))) + (got-em-all? (vector-ref wabbuf 0)) + (last-hole-index (vector-ref wabbuf 1))) + (display "\n; #(") + (do ((index 2 (1+ index))) + ((>= index last-hole-index) + (if got-em-all? + (display ")\n; Th-th-th-that's all folks!") + (display ")\n; And many more.... maybe?!?")) + (newline)) + (write (vector-ref wabbuf index)) ; DANGER! WRITE hashes output. + (write-char #\Space))))) + +; evaluated repeatedly... (stable display) + +; #((foobarbaz a . b) 1 #((a . b)) 1 ) +; Th-th-th-that's all folks! +;No value + +; #((foobarbaz a . b) 1 #((a . b)) 1 ) +; Th-th-th-that's all folks! +;No value + +; #((foobarbaz a . b) 1 #((a . b)) 1 ) +; Th-th-th-that's all folks! +;No value + +; #((foobarbaz a . b) 1 #((a . b)) 1 ) +; Th-th-th-that's all folks! +;No value +|# + + +@node Semi-Wreckless + +#| Sample semi-wreckless headhunt... (default headhunt-fudd-thunk exposes coll) + ------------------------------- + +(begin (headhunt) + (wabbit-descwiptor/headhunt-enable-flag (get-wabbit-descwiptor))) + +; evaluated repeatedly... (stable head count... if negative, partial count) +; +;Value: 23648 +;Value: 23648 +;Value: 23648 +|# + + +@c Local Variables: +@c compile-command: "simple-make-info /scheme/documentation/README.wabbit wabbit" +@c End: