(* Low level stack tricks. *) (constants space-header-tag stack-frame-tag stack-cont-tag stack-closure-tag words-per-space-header words-per-stack-frame words-per-stack-cont words-per-stack-closure words-per-ptr) (* Note that the SUCCESSOR field in not part of the following records; its just there to allow the following object to be created. *) (blockrecord space-header ((typetag byte) (gone flag) (spare1 bits 7) (spare2 byte) (age byte) (free fullxpointer) (size fullxpointer) (wordsleft fullxpointer) (hiptr fullxpointer) (successor fullxpointer))) (blockrecord stack-frame ((typetag byte) (gone flag) (objectified flag) (embedded flag) (spare1 bits 5) (nargs byte) (age byte) (proc fullxpointer) (arg1 fullxpointer) (arg2 fullxpointer) (arg3 fullxpointer))) (blockrecord stack-cont ((typetag byte) (gone flag) (spare1 bits 7) (spare2 byte) (age byte) (pc fullxpointer) (env fullxpointer) (frame fullxpointer) (next fullxpointer) (cont fullxpointer) (successor fullxpointer))) (blockrecord stack-closure ((typetag byte) (gone flag) (spare1 bits 7) (spare2 byte) (age byte) (skeleton fullxpointer) (env fullxpointer) (successor fullxpointer))) (blockrecord cell ((contents fullxpointer) (successor fullxpointer))) (blockrecord typed-object ((typetag byte) (gone flag) (spare1 bits 7) (spare2 byte) (age byte))) (blockrecord gc-object ((typetag byte) (gone flag) (spare1 bits 7) (spare2 byte) (age byte) (snake fullxpointer))) (globalvars new-space old-space future-survivor-space past-survivor-space wrap-anchor user-spaces) (defun initialise-tags-etc () (prog () (setq stack-frame-tag 1) (setq stack-cont-tag 2) (setq stack-closure-tag 3) (setq space-header-tag 4) (setq words-per-space-header 10) (setq words-per-stack-cont 12) (setq words-per-stack-closure 6) (setq words-per-stack-frame 4) (setq words-per-ptr 2))) (initialise-tags-etc) (* They are all constants. *) (* Strictly speaking, not every pointer to into arrayspace is one of ours. This may have to be changed later. *) (defmacro stack-object? (x) (type? arrayblock x)) (defun create-space (npointers) (prog (space space-size) (setq space-size (itimes npointers words-per-ptr)) (setq space (\allocblock space-size)) (for i from 0 to (sub1 space-size) do (\putbase space i 0)) (replace (space-header typetag) of space with space-header-tag) (replace (space-header size) of space with space-size) (replace (space-header hiptr) of space with (\addbase space (idifference space-size words-per-ptr))) (replace (space-header free) of space with (locf (fetch (space-header successor) of space))) (replace (space-header wordsleft) of space with (idifference space-size words-per-space-header)) (return space))) (defun create-spaces (nold nnew nsurvivors) (prog () (setq wrap-anchor nil) (setq old-space (create-space nold)) (setq new-space (create-space nnew)) (setq future-survivor-space (create-space nsurvivors)) (setq past-survivor-space (create-space nsurvivors)) (apply 'addtovar (list 'user-spaces old-space new-space future-survivor-space past-survivor-space)) (return nil))) (defun reset-space (space dont-zero) (prog (space-size) (setq space-size (fetch (space-header size) of space)) (if dont-zero then (\putbase space 0 0) (\putbase space 1 0) else (for i from 0 to (sub1 space-size) do (\putbase space i 0))) (replace (space-header typetag) of space with space-header-tag) (replace (space-header size) of space with space-size) (replace (space-header hiptr) of space with (\addbase space (idifference space-size words-per-ptr))) (replace (space-header free) of space with (locf (fetch (space-header successor) of space))) (replace (space-header wordsleft) of space with (idifference space-size words-per-space-header)) (return space))) (defun reset-spaces () (prog () (setq wrap-anchor nil) (for s in user-spaces do (reset-space s nil)) (return user-spaces))) (defun parse-space (space fn) (prog (scan-ptr free-ptr tag age nw) (* Run through the entire space, calling fn on each object. *) (setq free-ptr (fetch (space-header free) of space)) (setq scan-ptr space) (while (ptrgtp free-ptr scan-ptr) do (setq tag (fetch (typed-object typetag) of scan-ptr)) (setq age (fetch (typed-object age) of scan-ptr)) (select tag (space-header-tag (apply* fn tag scan-ptr words-per-space-header age) (setq scan-ptr (locf (fetch (space-header successor) of scan-ptr)))) (stack-closure-tag (apply* fn tag scan-ptr words-per-stack-closure age) (setq scan-ptr (locf (fetch (stack-closure successor) of scan-ptr)))) (stack-cont-tag (apply* fn tag scan-ptr words-per-stack-cont age) (setq scan-ptr (locf (fetch (stack-cont successor) of scan-ptr)))) (stack-frame-tag (setq nw (iplus words-per-stack-frame (itimes words-per-ptr (fetch (stack-frame nargs) of scan-ptr)))) (apply* fn tag scan-ptr nw age) (setq scan-ptr (\addbase scan-ptr nw))) (shouldnt "can't parse stack"))) (return nil))) (defun in-space? (space ptr) (and (ptrgtp ptr space) (not (ptrgtp ptr (fetch (space-header hiptr) of space))))) (defmacro in-new-space? (x) (in-space? new-space x)) (defmacro in-past-survivor-space? (x) (in-space? past-survivor-space x)) (defmacro in-future-survivor-space? (x) (in-space? future-survivor-space x)) (defmacro in-old-space? (x) (in-space? old-space x)) (defmacro allocate-from (space xnwords) (prog (xfree xleft) (setq xfree (fetch (space-header free) of space)) (setq xleft (fetch (space-header wordsleft) of space)) (if (ilessp xleft xnwords) then (shouldnt "out of space")) (replace (space-header free) of space with (\addbase xfree xnwords)) (replace (space-header wordsleft) of space with (idifference xleft xnwords)) (return xfree))) (defmacro ncreate-cont (xpc xenv xframe xnext xcont) (uninterruptably (prog (xnew-cont) (setq xnew-cont (allocate-from new-space words-per-stack-cont)) (putbase xnew-cont 0 0) (putbase xnew-cont 1 0) (replace (stack-cont typetag) of xnew-cont with stack-cont-tag) (replace (stack-cont pc) of xnew-cont with xpc) (replace (stack-cont env) of xnew-cont with xenv) (replace (stack-cont frame) of xnew-cont with xframe) (replace (stack-cont next) of xnew-cont with xnext) (replace (stack-cont cont) of xnew-cont with xcont) (return xnew-cont)))) (defmacro ncreate-closure (xskeleton xenv) (uninterruptably (prog (xnew-closure) (setq xnew-closure (allocate-from new-space words-per-stack-closure)) (putbase xnew-closure 0 0) (putbase xnew-closure 1 0) (replace (stack-closure typetag) of xnew-closure with stack-closure-tag) (replace (stack-closure skeleton) of xnew-closure with xskeleton) (replace (stack-closure env) of xnew-closure with xenv) (return xnew-closure)))) (defmacro stack-closure? (x) (and (stack-object? x) (eq stack-closure-tag (fetch (typed-object typetag) of x)))) (defmacro ncreate-frame (xnargs xembedded xobjectified) (uninterruptably (prog (xnew-frame xarg-ptr) (setq xnew-frame (allocate-from new-space (iplus words-per-stack-frame (itimes xnargs words-per-ptr)))) (putbase xnew-frame 0 0) (putbase xnew-frame 1 0) (replace (stack-frame typetag) of xnew-frame with stack-frame-tag) (replace (stack-frame nargs) of xnew-frame with xnargs) (replace (stack-frame embedded) of xnew-frame with xembedded) (replace (stack-frame objectified) of xnew-frame with xobjectified) (replace (stack-frame proc) of xnew-frame with 0) (setq xarg-ptr (locf (fetch (stack-frame arg1) of xnew-frame))) (for i from 1 to xnargs do (replace (cell contents) of xarg-ptr with i) (setq xarg-ptr (locf (fetch (cell successor) of xarg-ptr)))) (return xnew-frame)))) (datatype nlisp-object (uglyaddr nextobj)) (defmacro wrap (x) (setq wrap-anchor (create nlisp-object uglyaddr ← x nextobj ← wrap-anchor))) (defmacro unwrap (x) (fetch (nlisp-object uglyaddr) of x)) (defmacro closure? (x) (and (type? nlisp-object x) (stack-closure? (unwrap x)))) (defun show-spaces () (prog () (printout nil "< < < N E W S P A C E > > >" t) (parse-space new-space (function print-object)) (printout nil "< < < P A S T S U R V I V O R S > > >" t) (parse-space past-survivor-space (function print-object)) (printout nil "< < < F U T U R E S U R V I V O R S > > >" t) (parse-space future-survivor-space (function print-object)) (printout nil "< < < O L D S P A C E > > >" t) (parse-space old-space (function print-object)) (return nil))) (defun show-space (space) (parse-space space (function print-object))) (defun print-object (tag obj nwords age) (prog (nargs arg-ptr) (printout nil "Object " .I6.8.t (\hiloc obj) "," .I6.8.t (\loloc obj) " (age " age ")") (if (fetch (typed-object gone) of obj) then (printout nil " [Gone]")) (select tag (space-header-tag (printout nil " is a header block." t) (printout nil " size: " (fetch (space-header size) of obj) t) (printout nil " free: " (fetch (space-header free) of obj) t) (printout nil " wordsleft: " (fetch (space-header wordsleft) of obj) t) (printout nil " hiptr: " (fetch (space-header hiptr) of obj) t)) (stack-closure-tag (printout nil " is a closure." t) (printout nil " skeleton: " (fetch (stack-closure skeleton) of obj) t) (printout nil " env: " (fetch (stack-closure env) of obj) t)) (stack-cont-tag (printout nil " is a continuation." t) (printout nil " pc: " (fetch (stack-cont pc) of obj) t) (printout nil " env: " (fetch (stack-cont env) of obj) t) (printout nil " frame: " (fetch (stack-cont frame) of obj) t) (printout nil " next: " (fetch (stack-cont next) of obj) t) (printout nil " cont: " (fetch (stack-cont cont) of obj) t)) (stack-frame-tag (setq nargs (fetch (stack-frame nargs) of obj)) (printout nil " is a frame, nargs: " nargs) (printout nil " emb: " (fetch (stack-frame embedded) of obj)) (printout nil " obj: " (fetch (stack-frame objectified) of obj) t) (printout nil " proc: " (fetch (stack-frame proc) of obj) t) (setq arg-ptr (locf (fetch (stack-frame arg1) of obj))) (for i from 1 to nargs do (printout nil " arg" i ": " (fetch (cell contents) of arg-ptr) t) (setq arg-ptr (locf (fetch (cell successor) of arg-ptr)))) ) (shouldnt "Unknown tag")))) STOP