- Timestamp:
- Apr 20, 2008, 12:41:46 AM (17 years ago)
- Location:
- release/1.2/source
- Files:
-
- 2 deleted
- 29 edited
- 3 copied
-
cocoa-ide/cocoa-backtrace.lisp (modified) (1 diff)
-
cocoa-ide/cocoa-typeout.lisp (modified) (1 diff)
-
cocoa-ide/hemlock/src/key-event.lisp (modified) (1 diff)
-
cocoa-ide/processes-window.lisp (modified) (1 diff)
-
compiler/PPC/ppc2.lisp (modified) (2 diffs)
-
compiler/X86/x862.lisp (modified) (2 diffs)
-
compiler/nx-basic.lisp (modified) (3 diffs)
-
compiler/nx0.lisp (modified) (9 diffs)
-
doc/ccl-documentation.html (copied) (copied from trunk/source/doc/ccl-documentation.html )
-
doc/release-notes.txt (modified) (1 diff)
-
doc/src/build.xml (modified) (19 diffs)
-
doc/src/ide.xml (modified) (2 diffs)
-
doc/src/implementation.xml (modified) (10 diffs)
-
doc/src/install.xml (modified) (11 diffs)
-
doc/src/modifying.xml (modified) (7 diffs)
-
doc/src/using.xml (modified) (7 diffs)
-
examples/cocoa/tiny.lisp (copied) (copied from trunk/source/examples/cocoa/tiny.lisp )
-
examples/hons-example.lisp (deleted)
-
examples/opengl-ffi.lisp (modified) (1 diff)
-
examples/rubix/rubix.lisp (modified) (1 diff)
-
examples/tiny.lisp (deleted)
-
level-1/l1-clos-boot.lisp (modified) (1 diff)
-
level-1/l1-clos.lisp (modified) (7 diffs)
-
level-1/l1-dcode.lisp (modified) (3 diffs)
-
level-1/l1-streams.lisp (modified) (1 diff)
-
lib/compile-ccl.lisp (modified) (2 diffs)
-
lib/macros.lisp (modified) (20 diffs)
-
lib/nfcomp.lisp (modified) (1 diff)
-
lib/pprint.lisp (modified) (1 diff)
-
library/chud-metering.lisp (modified) (4 diffs)
-
library/chud-metering.txt (modified) (2 diffs)
-
library/oprofile.txt (copied) (copied from trunk/source/library/oprofile.txt )
-
objc-bridge/objc-clos.lisp (modified) (1 diff)
-
objc-bridge/objc-support.lisp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
release/1.2/source/cocoa-ide/cocoa-backtrace.lisp
r7804 r9200 154 154 (setq val-p t value (cddr rawval)))))) 155 155 (if val-p 156 ( cinspect value))))))156 (inspect value)))))) 157 157 158 158 -
release/1.2/source/cocoa-ide/cocoa-typeout.lisp
r7804 r9200 38 38 39 39 (objc:defmethod #/initWithFrame: ((self typeout-view) (frame :<NSR>ect)) 40 (declare (special *default-font-name* *default-font-size*)) 40 41 (call-next-method frame) 41 42 (let* ((scrollview (make-instance 'ns:ns-scroll-view -
release/1.2/source/cocoa-ide/hemlock/src/key-event.lisp
r8428 r9200 120 120 ;;; signals an error. 121 121 ;;; 122 #+unused 122 123 (defun mouse-translation-info (button event-key info) 123 124 (let ((event-dispatch (svref *mouse-translation-info* button))) -
release/1.2/source/cocoa-ide/processes-window.lisp
r7804 r9200 98 98 (unless (minusp row) 99 99 (setq p (svref processes row)) 100 ( cinspect p)100 (inspect p) 101 101 (#/refresh: self self))))) 102 102 -
release/1.2/source/compiler/PPC/ppc2.lisp
r9105 r9200 2019 2019 (eql (hard-regspec-value unscaled-idx) ppc::arg_y) 2020 2020 (eql (hard-regspec-value val-reg) ppc::arg_z)) 2021 ( nx-error"Bug: invalid register targeting for gvset: ~s" (list src unscaled-idx val-reg)))2021 (compiler-bug "Bug: invalid register targeting for gvset: ~s" (list src unscaled-idx val-reg))) 2022 2022 (! call-subprim-3 val-reg (subprim-name->offset '.SPgvset) src unscaled-idx val-reg)) 2023 2023 (is-node … … 5003 5003 (! unbind-interrupt-level-inline) 5004 5004 (! unbind-interrupt-level))) 5005 ( nx-error"unknown payback token ~s" r)))))))5005 (compiler-bug "unknown payback token ~s" r))))))) 5006 5006 5007 5007 (defun ppc2-spread-lambda-list (seg listform whole req opt rest keys -
release/1.2/source/compiler/X86/x862.lisp
r9105 r9200 2167 2167 (eql (hard-regspec-value unscaled-idx) x8664::arg_y) 2168 2168 (eql (hard-regspec-value val-reg) x8664::arg_z)) 2169 ( nx-error"Bug: invalid register targeting for gvset: ~s" (list src unscaled-idx val-reg)))2169 (compiler-bug "Bug: invalid register targeting for gvset: ~s" (list src unscaled-idx val-reg))) 2170 2170 (! call-subprim-3 val-reg (subprim-name->offset '.SPgvset) src unscaled-idx val-reg)) 2171 2171 (is-node … … 5028 5028 (! unbind-interrupt-level-inline)) 5029 5029 (! unbind-interrupt-level))) 5030 ( nx-error"unknown payback token ~s" r)))))))5030 (compiler-bug "unknown payback token ~s" r))))))) 5031 5031 5032 5032 (defun x862-spread-lambda-list (seg listform whole req opt rest keys -
release/1.2/source/compiler/nx-basic.lisp
r8861 r9200 488 488 (ecase (compiler-warning-warning-type condition) 489 489 (:global-mismatch "the current global definition of ~s") 490 (:environment-mismatch "the definition of ~s visible in the current compilation unit ")490 (:environment-mismatch "the definition of ~s visible in the current compilation unit.") 491 491 (:lexical-mismatch "the lexically visible definition of ~s")) 492 492 callee))) 493 494 493 495 494 (defparameter *compiler-warning-formats* 496 495 '((:special . "Undeclared free variable ~S") 497 496 (:unused . "Unused lexical variable ~S") 498 (:ignore . "Variable ~S not ignored ")497 (:ignore . "Variable ~S not ignored.") 499 498 (:undefined-function . "Undefined function ~S") 500 499 (:unknown-declaration . "Unknown declaration ~S") 501 500 (:unknown-type-declaration . "Unknown type ~S") 502 (:macro-used-before-definition . "Macro function ~S was used before it was defined ")501 (:macro-used-before-definition . "Macro function ~S was used before it was defined.") 503 502 (:unsettable . "Shouldn't assign to variable ~S") 504 503 (:global-mismatch . report-compile-time-argument-mismatch) … … 507 506 (:type . "Type declarations violated in ~S") 508 507 (:type-conflict . "Conflicting type declarations for ~S") 509 (:special-fbinding . "Attempt to bind compiler special name: ~s. Result undefined ")508 (:special-fbinding . "Attempt to bind compiler special name: ~s. Result undefined.") 510 509 (:lambda . "Suspicious lambda-list: ~s") 511 (:result-ignored . "Function result ignored in call to ~s"))) 510 (:result-ignored . "Function result ignored in call to ~s") 511 (:program-error . "~a"))) 512 512 513 513 514 (defun report-compiler-warning (condition stream) … … 520 521 (apply #'format stream format-string (compiler-warning-args condition)) 521 522 (funcall format-string condition stream)) 522 (format stream ".")523 ;(format stream ".") 523 524 (let ((nrefs (compiler-warning-nrefs condition))) 524 525 (when (and nrefs (neq nrefs 1)) -
release/1.2/source/compiler/nx0.lisp
r9059 r9200 1255 1255 (%i+ (%i- boundtocount 1) varcount))))))))) 1256 1256 1257 ;; Home-baked handler-case replacement. About 10 times as fast as full handler-case. 1258 ;;(LET ((S 0)) (DOTIMES (I 1000000) (INCF S))) took 45,678 microseconds 1259 ;;(LET ((S 0)) (DOTIMES (I 1000000) (BLOCK X (ERROR (CATCH 'X (RETURN-FROM X (INCF S))))))) took 57,485 1260 ;;(LET ((S 0)) (DOTIMES (I 1000000) (HANDLER-CASE (INCF S) (ERROR (C) C)))) took 168,947 1261 (defmacro with-program-error-handler (handler &body body) 1262 (let ((tag (gensym))) 1263 `(block ,tag 1264 (,handler (catch 'program-error-handler (return-from ,tag (progn ,@body))))))) 1265 1257 1266 (defun nx1-compile-lambda (name lambda-form &optional 1258 1267 (p (make-afunc)) … … 1307 1316 (if (%non-empty-environment-p *nx-lexical-environment*) 1308 1317 (setf (afunc-bits p) (logior (ash 1 $fbitnonnullenv) (the fixnum (afunc-bits p))))) 1309 (multiple-value-bind (body decls) 1310 (parse-body (%cddr lambda-form) *nx-lexical-environment* t) 1311 (setf (afunc-lambdaform p) lambda-form) 1312 (setf (afunc-acode p) (nx1-lambda (%cadr lambda-form) body decls)) 1313 (nx1-transitively-punt-bindings *nx-punted-vars*) 1314 (setf (afunc-blocks p) *nx-blocks*) 1315 (setf (afunc-tags p) *nx-tags*) 1316 (setf (afunc-inner-functions p) *nx-inner-functions*) 1317 (setf (afunc-all-vars p) *nx-all-vars*) 1318 (setf (afunc-vcells p) *nx1-vcells*) 1319 (setf (afunc-fcells p) *nx1-fcells*) 1320 (let* ((warnings (merge-compiler-warnings *nx-warnings*)) 1321 (name *nx-cur-func-name*)) 1322 (dolist (inner *nx-inner-functions*) 1323 (dolist (w (afunc-warnings inner)) 1324 (push name (compiler-warning-function-name w)) 1325 (push w warnings))) 1326 (setf (afunc-warnings p) warnings)) 1327 p))) 1318 1319 (setf (afunc-lambdaform p) lambda-form) 1320 (with-program-error-handler 1321 (lambda (c) 1322 (setf (afunc-acode p) (nx1-lambda () `((error ',c)) nil))) 1323 (handler-bind ((warning (lambda (c) 1324 (nx1-whine :program-error c) 1325 (muffle-warning c))) 1326 (program-error (lambda (c) 1327 (when (typep c 'compile-time-program-error) 1328 (setq c (make-condition 'simple-program-error 1329 :format-control (simple-condition-format-control c) 1330 :format-arguments (simple-condition-format-arguments c)))) 1331 (nx1-whine :program-error c) 1332 (throw 'program-error-handler c)))) 1333 (multiple-value-bind (body decls) 1334 (with-program-error-handler (lambda (c) `(error ',c)) 1335 (parse-body (%cddr lambda-form) *nx-lexical-environment* t)) 1336 (setf (afunc-acode p) (nx1-lambda (%cadr lambda-form) body decls))))) 1337 1338 (nx1-transitively-punt-bindings *nx-punted-vars*) 1339 (setf (afunc-blocks p) *nx-blocks*) 1340 (setf (afunc-tags p) *nx-tags*) 1341 (setf (afunc-inner-functions p) *nx-inner-functions*) 1342 (setf (afunc-all-vars p) *nx-all-vars*) 1343 (setf (afunc-vcells p) *nx1-vcells*) 1344 (setf (afunc-fcells p) *nx1-fcells*) 1345 (let* ((warnings (merge-compiler-warnings *nx-warnings*)) 1346 (name *nx-cur-func-name*)) 1347 (dolist (inner *nx-inner-functions*) 1348 (dolist (w (afunc-warnings inner)) 1349 (push name (compiler-warning-function-name w)) 1350 (push w warnings))) 1351 (setf (afunc-warnings p) warnings)) 1352 p)) 1328 1353 1329 1354 (defun method-lambda-p (form) … … 1591 1616 1592 1617 (defun nx1-typed-form (original env) 1593 (nx1-transformed-form (nx-transform original env) env)) 1618 (let ((form (with-program-error-handler 1619 (lambda (c) 1620 (nx-transform `(error ',c) env)) 1621 (nx-transform original env)))) 1622 (nx1-transformed-form form env))) 1594 1623 1595 1624 (defun nx1-transformed-form (form &optional (env *nx-lexical-environment*)) … … 1801 1830 1802 1831 (defun nx1-typed-call (sym args) 1803 ( let ((type (nx1-call-result-type sym args))1804 (form (nx1-call sym args)))1805 (if (eq type t)1806 form1807 (list (%nx1-operator typed-form) type form))))1832 (multiple-value-bind (type errors-p) (nx1-call-result-type sym args) 1833 (let ((form (nx1-call sym args nil nil errors-p))) 1834 (if (eq type t) 1835 form 1836 (list (%nx1-operator typed-form) type form))))) 1808 1837 1809 1838 ;;; Wimpy. … … 1813 1842 (lexenv-def nil) 1814 1843 (defenv-def nil) 1815 (somedef nil)) 1844 (somedef nil) 1845 (whined nil)) 1816 1846 (when (and sym 1817 1847 (symbolp sym) … … 1823 1853 (if args-p 1824 1854 (nx1-whine :undefined-function sym args spread-p) 1825 (nx1-whine :undefined-function sym))) 1855 (nx1-whine :undefined-function sym)) 1856 (setq whined t)) 1826 1857 (when (and args-p (setq somedef (or lexenv-def defenv-def global-def))) 1827 1858 (multiple-value-bind (deftype reason) 1828 1859 (nx1-check-call-args somedef args spread-p) 1829 1860 (when deftype 1830 (nx1-whine deftype sym reason args spread-p)))) 1831 (nx-target-type *nx-form-type*))) 1861 (nx1-whine deftype sym reason args spread-p) 1862 (setq whined t)))) 1863 (values (nx-target-type *nx-form-type*) whined))) 1832 1864 1833 1865 (defun find-ftype-decl (sym env) … … 1943 1975 ;;; If "sym" is an expression (not a symbol which names a function), 1944 1976 ;;; the caller has already alphatized it. 1945 (defun nx1-call (sym args &optional spread-p global-only )1977 (defun nx1-call (sym args &optional spread-p global-only inhibit-inline) 1946 1978 (nx1-verify-length args 0 nil) 1947 1979 (let ((args-in-regs (if spread-p 1 (backend-num-arg-regs *target-backend*)))) … … 1954 1986 (make-acode (%nx1-operator self-call) (nx1-arglist args args-in-regs) spread-p)) 1955 1987 (multiple-value-bind (lambda-form containing-env token) (nx-inline-expansion sym *nx-lexical-environment* global-only) 1956 (or (nx1-expand-inline-call lambda-form containing-env token args spread-p *nx-lexical-environment*) 1988 (or (and (not inhibit-inline) 1989 (nx1-expand-inline-call lambda-form containing-env token args spread-p *nx-lexical-environment*)) 1957 1990 (multiple-value-bind (info afunc) (if (and (symbolp sym) (not global-only)) (nx-lexical-finfo sym)) 1958 1991 (when (eq 'macro (car info)) … … 1978 2011 (if (and (or (null spread-p) (eq (length args) 1))) 1979 2012 (if (and token (not (memq token *nx-inline-expansions*))) 1980 (let* ((*nx-inline-expansions* (cons token *nx-inline-expansions*)) 1981 (lambda-list (cadr lambda-form)) 1982 (body (cddr lambda-form)) 1983 (new-env (new-lexical-environment env))) 1984 (setf (lexenv.mdecls new-env) 2013 (with-program-error-handler (lambda (c) (declare (ignore c)) nil) 2014 (let* ((*nx-inline-expansions* (cons token *nx-inline-expansions*)) 2015 (lambda-list (cadr lambda-form)) 2016 (body (cddr lambda-form)) 2017 (new-env (new-lexical-environment env))) 2018 (setf (lexenv.mdecls new-env) 1985 2019 `((speed . ,(speed-optimize-quantity old-env)) 1986 (space . ,(space-optimize-quantity old-env))1987 (safety . ,(space-optimize-quantity old-env))1988 (compilation-speed . ,(compilation-speed-optimize-quantity old-env))1989 (debug . ,(debug-optimize-quantity old-env))))1990 (if spread-p1991 (nx1-destructure lambda-list (car args) nil nil body new-env)1992 (nx1-lambda-bind lambda-list args body new-env))))))2020 (space . ,(space-optimize-quantity old-env)) 2021 (safety . ,(space-optimize-quantity old-env)) 2022 (compilation-speed . ,(compilation-speed-optimize-quantity old-env)) 2023 (debug . ,(debug-optimize-quantity old-env)))) 2024 (if spread-p 2025 (nx1-destructure lambda-list (car args) nil nil body new-env) 2026 (nx1-lambda-bind lambda-list args body new-env))))))) 1993 2027 1994 2028 ; note that regforms are reversed: arg_z is always in the car -
release/1.2/source/doc/release-notes.txt
r8427 r9200 1 ClozureCL 1.2 2 ============= 3 4 Welcome to the first ClozureCL (aka OpenMCL) release in about 2.5 years! 5 (There have been a lot of 1.1-prerelease snapshots in that time frame, 6 and there's been a lot of development activity; hopefully, it'll be 7 a little easier for people who wish to use a relatively stable version 8 to do so and still make it easy for those who want to track the bleeding 9 edge of development to do so.) 10 11 [In the fall of 2007, Alice Hartley of Digitool announced that MCL (the 12 commercial product from which OpenMCL was derived) would be opensourced. 13 In order to reduce potential confusion between the new "open MCL" and 14 "OpenMCL" - and to coincidentally make the primary implementation package 15 and default installation directory name ("ccl") meaningful again - we 16 decided to rename OpenMCL to "Clozure CL" (or "CCL"). There are still 17 references to the old name in URLs, bits and pieces of the lisp itself, 18 mailing lists, and elsewhere.] 19 20 Obtaining Clozure CL 21 -------------------- 22 Gzip'ed tar archives of Clozure CL 1.2 are available via anonymous FTP 23 from: 24 25 <ftp://clozure.com/pub/release/1.2> 26 27 in files whose names are of the form 28 clozurecl-1.2-[RELEASE-LEVEL-]PLATFORM.tar.gz 29 30 where 31 RELEASE-LEVEL may be "rcN" to indicate "release candidate N", or absent, and 32 PLATFORM is one of "linuxppc", "darwinppc", "linuxx8664", "darwinx8664", or 33 "freebsdx8664". The "ppc" archives contain 32- and 64-bit binaries and 34 interfaces; the x8664 archives are (still) 64-bit only. All archives 35 contain full sources and documentation, and also svn 1.4x metainformation 36 (see below.) 37 38 It's also possible to check out content equivalent to any of these 39 archives by using an "svn" client (again, see below.). The URL is of the 40 form: 41 42 http://svn.clozure.com/publicsvn/openmcl/release/1.2/PLATFORM/ccl 43 44 where PLATFORM is defined as above. 45 46 To check out a fresh copy of the current CCL 1.2 distribution for DarwinPPC, 47 one would do something like: 48 49 shell> cd some-directory-that-doesn't-have-a-ccl-subdirectory 50 shell> svn co http://svn.clozure.com/publicsvn/openmcl/release/1.2/darwinppc/ccl 51 52 We plan on making disk images (.dmg files) containing the Cocaa IDE and 53 the full CCL distribution available in the near future. 54 55 Documentation 56 ------------- 57 58 Documentation is available online at: 59 60 <http://ccl.clozure.com/ccl-documentation.html> 61 62 A recent version of the HTML documentation is also included in the 63 distribution, along with the DocBook source from which it's derived. 64 These release notes describe some important recent (for some value 65 of "recent") changes. 66 67 Bug Reporting 68 ------------- 69 70 Please use the trac instance at 71 72 <http://trac.clozure.com/openmcl> 73 74 to review existing bug reports and submit new ones. 75 76 CVS out, SVN in: 77 --------------- 78 79 Until the spring of 2007, ClozureCL used CVS for revision control; 80 tar archives for the 1.0 release and 1.1 snapshots contained CVS 81 metainformation, and it was generally possible to use "cvs update" 82 and related commands to update an installation to the latest version. 83 84 At that time, we switched to using the Subversion ("SVN") revision 85 control system, but continued to mirror the main line of development 86 in CVS (to the extent that this was possible, given some limitations 87 of CVS.) 88 89 This release is entirely SVN-based and makes use of Subversion features 90 that can't be supported in CVS. Subversion clients are widely available 91 for all platforms that ClozureCL runs on: 92 93 - FreeBSD and Linux users will likely find that subversion packages 94 are readily available through their distribution's package management 95 systems. 96 97 - 'svn' is preinstalled on OSX Leopard 98 99 - OSX Tiger users can install Subversion via Fink or MacPorts, or 100 look at <http://downloads.open.collab.net/binaries.html> for other 101 options. 102 103 It should be possible to use GUI svn clients if you prefer. 104 105 Note that the tar archives that contain ClozureCL distributions 106 contain svn metainformation that assumes the use of a version 1.4 or 107 later svn client; the format of some of that metainformation isn't 108 understood by older clients. If you have an older client (and can't 109 install something more up-to-date), you ignore the tarballs and just 110 check out the full CCL distribution (sources, binaries, interfaces 111 ...) via svn. 112 113 Quick guide to svn: 114 ------------------ 115 shell> cd ccl # wherever that is ... 116 shell> svn update # try to synch working copy with svn repository 117 118 shell> svn revert <files> # discard local changes to <files>, recover 119 # versions from last update. 120 121 svn notes/issues 122 ---------------- 123 124 svn does a fairly good job of handling binary files, and in fact the 125 CCL lisp kernel, heap image, and interface database files are maintained 126 in svn. (One benefit of this scheme is that it may be a little easier 127 to distribute modified heap images that reflect changes that may be hard 128 to bootstrap from source.) Occasionally, an "svn update" operation may 129 fail to replace a locally-modified copy of a binary file; when this 130 happens, one way to recover is to use "svn revert" to discard local 131 changes. 132 133 The "Welcome ..." banner (and the string returned by 134 LISP-IMPLEMENTATION-VERSION) contain the repository's revision number 135 (an integer that increases whenever any file in the CCL repository 136 changes) as of the time that the lisp image is built. If there are 137 locally-modified files (including re-compiled kernels or heap images) 138 in the working copy, the revision number may contain a trailing "M" 139 character; this isn't very significant, but might be a little mysterious. 140 141 1.1 release notes 142 ----------------- 143 All of the information contained in the file ccl/doc/release-notes-1.1.txt 144 should be incorporated into the documentation; people who didn't use 145 the 1.1 "snapshot" releases might find that file to be worth skimming. 146 Some highlights include: 147 148 - use of Unicode internally, and support for reading and writing streams 149 encoded in many commonly-used character encoding schemes. 150 - support for 64-bit x86 (amd64/x86-64) hardware (32-bit Intel support 151 is under active development, but is not yet ready for public consumption.) 152 - many changes to the Cocoa Bridge, lots of enhancements to the Cocoa-based 153 IDE (which runs on 32-bit DarwinPPC under Tiger and Leopard and on 64-bit 154 DarwinX8664 on Leopard. 155 - lots of other changes (didn't I already write down descriptions of 156 them somewhere ? 157 158 More recent changes 159 ------------------- 160 161 - The keywords :MCL and :OPENMCL-HASH-CONSING have been removed from 162 *FEATURES*, and the keywords :CLOZURE-COMMON-LISP, :CCL and :CCL-1.2 163 have been added. :OPENMCL-HASH-CONSING denoted an experimental 164 feature that was never used, and the presence of :MCL created some 165 confusion (OpenMCL/CCL and commercial MCL have been diverging for 166 about 10 years now, and many of the things that typically need read-time 167 conditionalization - pathname syntax, threading, networking ... - need 168 to be conditionalized differently for the two implementations.) Code 169 that has used the presence/absence of the :MCL feature to conditionalize 170 for OpenMCL may need to be reviewed. 171 172 The presence of :CCL-1.2 should be viewed as "features described in the 173 Clozure CL 1.2 documentation are present", i.e., "this is at least version 174 1.2 of CCL". 175 176 There should also be a "simple" keyword denoting the OS name - :LINUX, 177 :DARWIN, or :FREEBSD. 178 179 - sockets support :CONNECT-TIMEOUT arguments and streams (including sockets) 180 support :READ-TIMEOUT and :WRITE-TIMEOUT arguments in their creation functions 181 (OPEN, MAKE-SOCKET, etc.) An active socket connect operation that takes 182 longer than the number of seconds specified in the socket's :CONNECT-TIMEOUT 183 argument - or an I/O operation that takes longer than the applicable 184 :READ-TIMEOUT or :WRITE-TIMEOUT's argument - will cause an error to be 185 signaled. 186 187 - profiling via Apple's CHUD tools (finally) works on 64-bit versions of 188 CCL. See ccl/library/chud-metering.txt for details. 189 190 - profiling on x86-64 Linux - using the 'oprofile' profiler - is now 191 supported (or, more accurately, it's possible to generate symbolic 192 information that allows 'oprofile' and related tools to give meaningful 193 names to lisp functions.) See ccl/library/oprofile.txt for details. 194 195 - on OSX/Darwin, pathnames are now recognized as being encoded in 196 "decomposed UTF-8", which isn't quite as bad as it sounds. (This 197 should mean that pathnames that contain non-ASCII characters should 198 be handled correctly.) 199 200 - in the Cocoa IDE, Hemlock editor commands now run in the main event 201 thread (they used to run in a dedicated, per-window thread), and many 202 other aspects of Hemlock/Cocoa integration have been simplified and 203 improved. Aside from offering greater stability, these changes make 204 the Hemlock programming interface a lot more tractable. People 205 interested in writing Hemlock editor commands for use in the IDE may 206 find a revised version of the Hemlock Command Implementor's Manual 207 <http://trac.clozure.com/openmcl/wiki/HemlockProgrammer> useful. 208 209 When run as a standalone application, the IDE provides a "console" 210 window which displays diagnostic output that otherwise only appears 211 in the system logs. 212 213 - lots of bug fixes, smaller changes, and performance improvements. 214 215 -
release/1.2/source/doc/src/build.xml
r9071 r9200 1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"[ 3 <!ENTITY rest "<varname>&rest</varname>">4 <!ENTITY key "<varname>&key</varname>">5 <!ENTITY optional "<varname>&optional</varname>">6 <!ENTITY body "<varname>&body</varname>">7 <!ENTITY aux "<varname>&aux</varname>">8 <!ENTITY allow-other-keys "<varname>&allow-other-keys</varname>">9 <!ENTITY CCL "Clozure CL">10 ]>11 <chapter><title>Building &CCL; from its Source Code</title>12 <anchor id="Building-CCL"/>13 <para>&CCL;, like many other Lisp implementations, consists of a3 <!ENTITY rest "<varname>&rest</varname>"> 4 <!ENTITY key "<varname>&key</varname>"> 5 <!ENTITY optional "<varname>&optional</varname>"> 6 <!ENTITY body "<varname>&body</varname>"> 7 <!ENTITY aux "<varname>&aux</varname>"> 8 <!ENTITY allow-other-keys "<varname>&allow-other-keys</varname>"> 9 <!ENTITY CCL "Clozure CL"> 10 ]> 11 <chapter><title>Building &CCL; from its Source Code</title> 12 <anchor id="Building-CCL"/> 13 <para>&CCL;, like many other Lisp implementations, consists of a 14 14 kernel and a heap image. The kernel is an ordinary C program, and 15 15 is built with a C compiler. It provides very basic and … … 20 20 nor the heap image can stand alone.</para> 21 21 22 <para>You may already know that, when you have a C compiler which22 <para>You may already know that, when you have a C compiler which 23 23 is written in C, you need a working C compiler to build the 24 24 compiler. Similarly, the &CCL; heap image includes a Lisp 25 25 compiler, which is written in Lisp. You therefore need a working 26 26 Lisp compiler in order to build the Lisp heap image.</para> 27 28 <para>Where will you get a working Lisp compiler? No worries; you27 28 <para>Where will you get a working Lisp compiler? No worries; you 29 29 can use a precompiled copy of a (slightly older and compatible) 30 30 version of &CCL;. This section explains how to do all this.</para> 31 31 32 <para>In principle it should be possible to use another32 <para>In principle it should be possible to use another 33 33 implementation of Common Lisp as the host compiler, rather than an 34 34 older &CCL;; this would be a challenging and experimental way to 35 35 build, and is not described here.</para> 36 36 37 <sect1 id="building-definitions"><title>Building Definitions</title>38 <para>The following terms are used in subsequent sections; it37 <sect1 id="building-definitions"><title>Building Definitions</title> 38 <para>The following terms are used in subsequent sections; it 39 39 may be helpful to refer to these definitions.</para> 40 40 41 <para><indexterm><primary>fasl42 files</primary></indexterm><glossterm linkend="fasl-file">fasl43 files</glossterm> are the object files produced41 <para><indexterm><primary>fasl 42 files</primary></indexterm><glossterm linkend="fasl-file">fasl 43 files</glossterm> are the object files produced 44 44 by <literal>compile-file</literal>. fasl files store the 45 45 machine code associated with function definitions and the … … 52 52 <xref linkend="Platform-specific-filename-conventions"/> </para> 53 53 54 <para>The <indexterm><primary>lisp55 kernel</primary></indexterm> <glossterm linkend="lisp_kernel">Lisp56 kernel</glossterm> is a C program with a fair amount of54 <para>The <indexterm><primary>lisp 55 kernel</primary></indexterm> <glossterm linkend="lisp_kernel">Lisp 56 kernel</glossterm> is a C program with a fair amount of 57 57 platform-specific assembly language code. Its basic job is to 58 58 map a lisp heap image into memory, transfer control to some … … 64 64 <xref linkend="Platform-specific-filename-conventions"/>.</para> 65 65 66 <para>A <indexterm><primary>heap67 image</primary></indexterm> <glossterm linkend="lisp_image">heap68 image</glossterm> is a file that can be quickly mapped into a66 <para>A <indexterm><primary>heap 67 image</primary></indexterm> <glossterm linkend="lisp_image">heap 68 image</glossterm> is a file that can be quickly mapped into a 69 69 process' address space. Conceptually, it's not too different 70 70 from an executable file or shared library in the OS's native … … 77 77 <xref linkend="Platform-specific-filename-conventions"/>.</para> 78 78 79 <para>A <indexterm><primary>bootstrapping80 image</primary></indexterm> bootstrapping image is a minimal79 <para>A <indexterm><primary>bootstrapping 80 image</primary></indexterm> bootstrapping image is a minimal 81 81 heap image used in the process of building &CCL; itself. The 82 82 bootstrapping image contains just enough code to load the rest … … 88 88 .</para> 89 89 90 <para>Each supported platform (and possibly a few90 <para>Each supported platform (and possibly a few 91 91 as-yet-unsupported ones) has a uniquely named subdirectory of 92 92 <literal>ccl/lisp-kernel/</literal>; each such … … 98 98 <xref linkend="Platform-specific-filename-conventions"/>.</para> 99 99 100 <sect2 id="filename_conventions">101 <title>Platform-specific filename conventions</title>102 <table id ="Platform-specific-filename-conventions">103 <title>Platform-specific filename conventions</title>104 <tgroup cols="6">105 <thead>100 <sect2 id="filename_conventions"> 101 <title>Platform-specific filename conventions</title> 102 <table id ="Platform-specific-filename-conventions"> 103 <title>Platform-specific filename conventions</title> 104 <tgroup cols="6"> 105 <thead> 106 106 <row> 107 <entry>Platform</entry>108 <entry>kernel</entry>109 <entry>full-image</entry>110 <entry>boot-image</entry>111 <entry>fasl extension</entry>112 <entry>kernel-build directory</entry>113 </row>114 </thead>115 <tbody>116 <row>117 <entry>DarwinPPC32</entry>118 <entry>dppccl</entry>119 <entry>dppccl.image</entry>120 <entry>ppc-boot.image</entry>121 <entry>.dfsl</entry>122 <entry>darwinppc</entry>123 </row>124 <row>125 <entry>LinuxPPC32</entry>126 <entry>ppccl</entry>127 <entry>PPCCL</entry>128 <entry>ppc-boot</entry>129 <entry>.pfsl</entry>130 <entry>linuxppc</entry>131 </row>132 <row>133 <entry>DarwinPPC64</entry>134 <entry>dppccl64</entry>135 <entry>dppccl64.image</entry>136 <entry>ppc-boot64.image</entry>137 <entry>.d64fsl</entry>138 <entry>darwinppc64</entry>139 </row>140 <row>141 <entry>LinuxPPC64</entry>142 <entry>ppccl64</entry>143 <entry>PPCCL64</entry>144 <entry>ppc-boot64</entry>145 <entry>.p64fsl</entry>146 <entry>linuxppc64</entry>147 </row>148 <row>149 <entry>LinuxX8664</entry>150 <entry>lx86cl64</entry>151 <entry>LX86CL64</entry>152 <entry>x86-boot64</entry>153 <entry>.lx64fsl</entry>154 <entry>linuxx8664</entry>155 </row>156 <row>157 <entry>DarwinX8664</entry>158 <entry>dx86cl64</entry>159 <entry>dx86cl64.image</entry>160 <entry>x86-boot64.image</entry>161 <entry>.dx64fsl</entry>162 <entry>darwinx8664</entry>163 </row>164 <row>165 <entry>FreeBSDX8664</entry>166 <entry>fx86cl64</entry>167 <entry>FX86CL64</entry>168 <entry>fx86-boot64</entry>169 <entry>.fx64fsl</entry>170 <entry>freebsdx8664</entry>171 </row>172 </tbody>173 </tgroup>174 </table>175 </sect2>176 </sect1>177 178 <sect1 id="Setting-Up-to-Build">179 <title>Setting Up to Build</title>180 <para>There are currently three versions of &CCL; that you107 <entry>Platform</entry> 108 <entry>kernel</entry> 109 <entry>full-image</entry> 110 <entry>boot-image</entry> 111 <entry>fasl extension</entry> 112 <entry>kernel-build directory</entry> 113 </row> 114 </thead> 115 <tbody> 116 <row> 117 <entry>DarwinPPC32</entry> 118 <entry>dppccl</entry> 119 <entry>dppccl.image</entry> 120 <entry>ppc-boot.image</entry> 121 <entry>.dfsl</entry> 122 <entry>darwinppc</entry> 123 </row> 124 <row> 125 <entry>LinuxPPC32</entry> 126 <entry>ppccl</entry> 127 <entry>PPCCL</entry> 128 <entry>ppc-boot</entry> 129 <entry>.pfsl</entry> 130 <entry>linuxppc</entry> 131 </row> 132 <row> 133 <entry>DarwinPPC64</entry> 134 <entry>dppccl64</entry> 135 <entry>dppccl64.image</entry> 136 <entry>ppc-boot64.image</entry> 137 <entry>.d64fsl</entry> 138 <entry>darwinppc64</entry> 139 </row> 140 <row> 141 <entry>LinuxPPC64</entry> 142 <entry>ppccl64</entry> 143 <entry>PPCCL64</entry> 144 <entry>ppc-boot64</entry> 145 <entry>.p64fsl</entry> 146 <entry>linuxppc64</entry> 147 </row> 148 <row> 149 <entry>LinuxX8664</entry> 150 <entry>lx86cl64</entry> 151 <entry>LX86CL64</entry> 152 <entry>x86-boot64</entry> 153 <entry>.lx64fsl</entry> 154 <entry>linuxx8664</entry> 155 </row> 156 <row> 157 <entry>DarwinX8664</entry> 158 <entry>dx86cl64</entry> 159 <entry>dx86cl64.image</entry> 160 <entry>x86-boot64.image</entry> 161 <entry>.dx64fsl</entry> 162 <entry>darwinx8664</entry> 163 </row> 164 <row> 165 <entry>FreeBSDX8664</entry> 166 <entry>fx86cl64</entry> 167 <entry>FX86CL64</entry> 168 <entry>fx86-boot64</entry> 169 <entry>.fx64fsl</entry> 170 <entry>freebsdx8664</entry> 171 </row> 172 </tbody> 173 </tgroup> 174 </table> 175 </sect2> 176 </sect1> 177 178 <sect1 id="Setting-Up-to-Build"> 179 <title>Setting Up to Build</title> 180 <para>There are currently three versions of &CCL; that you 181 181 might want to use (and therefore might want to build from 182 182 source):</para> 183 <itemizedlist>184 <listitem><para>Version 1.0 - the more stable version</para></listitem>185 <listitem><para>Version 1.1 - the more recent version, which186 runs on more platforms (including x86-64 platforms) and187 supports Unicode</para></listitem>188 <listitem><para>Version 1.2 - supports (at least) all of the189 features and platforms as 1.1, but is distributed and updated190 differently</para></listitem>191 </itemizedlist>192 <para>All versions are available for download from the &CCL;183 <itemizedlist> 184 <listitem><para>Version 1.0 - the more stable version</para></listitem> 185 <listitem><para>Version 1.1 - the more recent version, which 186 runs on more platforms (including x86-64 platforms) and 187 supports Unicode</para></listitem> 188 <listitem><para>Version 1.2 - supports (at least) all of the 189 features and platforms as 1.1, but is distributed and updated 190 differently</para></listitem> 191 </itemizedlist> 192 <para>All versions are available for download from the &CCL; 193 193 website in the form of archives that contain everything you need 194 194 to work with &CCL;, including the complete sources, a full 195 195 heap image, and the foreign-function interface database.</para> 196 <para>Version 1.0 archives are named196 <para>Version 1.0 archives are named 197 197 <literal>openmcl-</literal><replaceable>platform</replaceable><literal>-all-1.0.tar.gz</literal>, 198 198 where <replaceable>platform</replaceable> is either … … 201 201 undergoing active development, you won't ever need to update 202 202 these sources.</para> 203 <para>Version 1.1 archives are named203 <para>Version 1.1 archives are named 204 204 <literal>openmcl-</literal><replaceable>platform</replaceable><literal>-snapshot-</literal><replaceable>yymmdd</replaceable><literal>.tar.gz</literal>, 205 205 where <replaceable>platform</replaceable> is either … … 209 209 <replaceable>yymmdd</replaceable> is the year, month, and day 210 210 the snapshot was released.</para> 211 <para>Because version 1.1 is undergoing active development,211 <para>Because version 1.1 is undergoing active development, 212 212 there may be times when you want to get sources that are more 213 213 recent than the most recent snapshot and use them to build … … 218 218 working-copy information in it, so all you need to do to update 219 219 is</para> 220 <programlisting>220 <programlisting> 221 221 $ cd ccl 222 222 $ cvs login # password is "cvs" 223 # this step only needs to be done once,224 # that'll store the trivially encrypted225 # password in ~/.cvspas223 # this step only needs to be done once, 224 # that'll store the trivially encrypted 225 # password in ~/.cvspas 226 226 $ cvs update 227 </programlisting>228 <para>Unless you tell it to, cvs won't delete ("prune") empty227 </programlisting> 228 <para>Unless you tell it to, cvs won't delete ("prune") empty 229 229 directories or create new ones when the repository changes. 230 230 It's generally a good habit to use</para> 231 <programlisting>231 <programlisting> 232 232 $ cvs update -d -P # create dirs as needed, prune empty ones 233 </programlisting>234 <para>Version 1.2 archives follow naming conventions that are233 </programlisting> 234 <para>Version 1.2 archives follow naming conventions that are 235 235 similar to those used by 1.0 (though more platforms are supported.) 236 236 However, rather than containing CVS working-copy information, the 237 237 1.2 (and, presumably, later) archives contain metainformation used 238 238 by the Subversion (svn) source-code control system.</para> 239 <para>Subversion client programs are pre-installed on OSX 10.5 and239 <para>Subversion client programs are pre-installed on OSX 10.5 and 240 240 later and are typically either pre-installed or readily available 241 241 on Linux and FreeBSD platforms. The <ulink url="http://subversion.tigris.org">Subversion web page</ulink> contains links to subversion client programs 242 242 for many platforms; users of OSX versions 10.4 and earlier can also 243 243 install Subversion clients via Fink or MacPorts.</para> 244 245 </sect1>246 247 <sect1 id="Building-Everything">248 <title>Building Everything</title>249 <para>Given that you now have everything you need, do the244 245 </sect1> 246 247 <sect1 id="Building-Everything"> 248 <title>Building Everything</title> 249 <para>Given that you now have everything you need, do the 250 250 following in a running &CCL; to bring your Lisp system 251 251 completely up to date.</para> 252 <programlisting>252 <programlisting> 253 253 ? (ccl:rebuild-ccl :full t) 254 </programlisting>255 <para>That call to the function <literal>rebuild-ccl</literal>256 will performthe following steps:</para>257 <itemizedlist>258 <listitem>259 <para>Deletes all fasl files and other object files in the260 <literal>ccl</literal>directory tree</para>261 </listitem>262 <listitem>263 <para>Runs an external process whichdoes a264 <literal>make</literal> in the currentplatform's kernel265 build directory to create a new kernel</para>266 </listitem>267 <listitem>268 <para>Does <literal>(compile-ccl t)</literal> in the running269 lisp, to produce aset of fasl files from the “higher270 level” lisp sources.</para>271 </listitem>272 <listitem>273 <para>Does <literal>(xload-level-0 :force)</literal> in the274 running lisp, to compile thelisp sources in the275 “ccl:level-0;” directory into fasl files and276 then createa bootstrapping image from those fasl277 files.</para>278 </listitem>279 <listitem>280 <para>Runs another external process, which causes the newly281 compiled lispkernel to load the new bootstrapping image.282 The bootsrtrapping image then loadsthe “higher283 level” fasl files and a new copy of the platform's284 full heap imageis then saved.</para>285 </listitem>286 </itemizedlist>287 <para>If all goes well, it'll all happen without user254 </programlisting> 255 <para>That call to the function <literal>rebuild-ccl</literal> 256 performs the following steps:</para> 257 <itemizedlist> 258 <listitem> 259 <para>Deletes all fasl files and other object files in the 260 <literal>ccl</literal> directory tree</para> 261 </listitem> 262 <listitem> 263 <para>Runs an external process that does a 264 <literal>make</literal> in the current platform's kernel 265 build directory to create a new kernel</para> 266 </listitem> 267 <listitem> 268 <para>Does <literal>(compile-ccl t)</literal> in the running 269 lisp, to produce a set of fasl files from the “higher 270 level” lisp sources.</para> 271 </listitem> 272 <listitem> 273 <para>Does <literal>(xload-level-0 :force)</literal> in the 274 running lisp, to compile the lisp sources in the 275 “ccl:level-0;” directory into fasl files and 276 then create a bootstrapping image from those fasl 277 files.</para> 278 </listitem> 279 <listitem> 280 <para>Runs another external process, which causes the newly 281 compiled lisp kernel to load the new bootstrapping image. 282 The bootsrtrapping image then loads the “higher 283 level” fasl files and a new copy of the platform's 284 full heap image is then saved.</para> 285 </listitem> 286 </itemizedlist> 287 <para>If all goes well, it'll all happen without user 288 288 intervention and with some simple progress messages. If 289 289 anything goes wrong during execution of either of the external 290 290 processes, the process output is displayed as part of a lisp 291 291 error message.</para> 292 <para><literal>rebuild-ccl</literal> is essentially just a short292 <para><literal>rebuild-ccl</literal> is essentially just a short 293 293 cut for running all the individual steps involved in rebuilding 294 294 the system. You can also execute these steps individually, as 295 295 described below.</para> 296 </sect1>297 298 <sect1 id="Building-the-kernel">299 <title>Building the kernel</title>300 <para>The Lisp kernel is the executable whichyou run to use296 </sect1> 297 298 <sect1 id="Building-the-kernel"> 299 <title>Building the kernel</title> 300 <para>The Lisp kernel is the executable that you run to use 301 301 Lisp. It doesn't actually contain the entire Lisp 302 302 implementation; rather, it loads a heap image which contains the 303 specifics -the "library", as it might be called if this was a C303 specifics—the "library", as it might be called if this was a C 304 304 program. The kernel also provides runtime support to the heap 305 305 image, such as garbage collection, memory allocation, exception 306 306 handling, and the OS interface.</para> 307 307 308 <para>The Lisp kernel file has different names on different 309 platforms. See FIXTHIS . On all platforms the lisp kernel sources reside 308 <para>The Lisp kernel file has different names on different 309 platforms. See 310 <xref linkend="Platform-specific-filename-conventions"/>. On all 311 platforms the lisp kernel sources reside 310 312 in <literal>ccl/lisp-kernel</literal>.</para> 311 313 312 <para>This section gives directions on how to rebuild the Lisp314 <para>This section gives directions on how to rebuild the Lisp 313 315 kernel from its source code. Most &CCL; users will rarely 314 316 have to do this. You probably will only need to do it if you are … … 319 321 ? (rebuild-ccl :full t) 320 322 </programlisting> 321 </para>322 323 324 <sect2 id="Kernel-build-prerequisites">325 <title>Kernel build prerequisites</title>326 <para>The &CCL; kernel can be bult with the following widely327 available tools:</para>328 <itemizedlist>329 <listitem><para>cc or gcc- the GNU C compiler</para></listitem>330 <listitem><para>ld - the GNU linker</para></listitem>331 <listitem><para>m4 or gm4- the GNU m4 macro processor</para></listitem>332 <listitem><para>as - the GNU assembler (version 2.10.1 or later)</para></listitem>333 <listitem><para>make - either GNU make or, on FreeBSD, the default BSD make program</para></listitem>334 </itemizedlist>335 <para> In general, the more recent the versions of those336 tools, the better; some versions of gcc 3.x on Linux have337 difficulty compiling some of the kernel source code correctly338 (so gcc 4.0 should be used, if possible.) On OSX, the339 versions of the tools distributed with XCode should work fine;340 on Linux, the versions of the tools installed with the OS (or341 available through its package management system) should work342 fine if they're "recent enough". On FreeBSD, the installed343 version of the <literal>m4</literal> program doesn't support344 some features that the kernel build process depends on; the345 GNU version of the m4 macroprocessor (called346 <literal>gm4</literal> on FreeBSD) should be installed347 348 </para>349 </sect2>350 <sect2 id="kernel-build-command">351 <title>Using "make" to build the lisp kernel</title>352 <para>With those tools in place, do:323 </para> 324 325 326 <sect2 id="Kernel-build-prerequisites"> 327 <title>Kernel build prerequisites</title> 328 <para>The &CCL; kernel can be bult with the following widely 329 available tools:</para> 330 <itemizedlist> 331 <listitem><para>cc or gcc- the GNU C compiler</para></listitem> 332 <listitem><para>ld - the GNU linker</para></listitem> 333 <listitem><para>m4 or gm4- the GNU m4 macro processor</para></listitem> 334 <listitem><para>as - the GNU assembler (version 2.10.1 or later)</para></listitem> 335 <listitem><para>make - either GNU make or, on FreeBSD, the default BSD make program</para></listitem> 336 </itemizedlist> 337 <para> In general, the more recent the versions of those 338 tools, the better; some versions of gcc 3.x on Linux have 339 difficulty compiling some of the kernel source code correctly 340 (so gcc 4.0 should be used, if possible.) On OSX, the 341 versions of the tools distributed with XCode should work fine; 342 on Linux, the versions of the tools installed with the OS (or 343 available through its package management system) should work 344 fine if they're "recent enough". On FreeBSD, the installed 345 version of the <literal>m4</literal> program doesn't support 346 some features that the kernel build process depends on; the 347 GNU version of the m4 macroprocessor (called 348 <literal>gm4</literal> on FreeBSD) should be installed. 349 350 </para> 351 </sect2> 352 <sect2 id="kernel-build-command"> 353 <title>Using "make" to build the lisp kernel</title> 354 <para>With those tools in place, do: 353 355 <programlisting> 354 356 shell> cd ccl/lisp-kernel/<replaceable>PLATFORM</replaceable> 355 357 shell> make 356 </programlisting>357 </para>358 <para>That'll assemble several assembly language source files,358 </programlisting> 359 </para> 360 <para>That'll assemble several assembly language source files, 359 361 compile several C source files, and link 360 362 ../../<replaceable>the kernel</replaceable>. 361 </para>362 </sect2>363 </sect1>364 <sect1 id="Building-the-heap-image">365 <title>Building the heap image</title>366 <para>The initial heap image is loaded by the Lisp kernel, and367 provides most allof the language implementation The heap image363 </para> 364 </sect2> 365 </sect1> 366 <sect1 id="Building-the-heap-image"> 367 <title>Building the heap image</title> 368 <para>The initial heap image is loaded by the Lisp kernel, and 369 provides most of the language implementation The heap image 368 370 captures the entire state of a running Lisp (except for external 369 371 resources, such as open files and TCP sockets). After it is … … 371 373 exactly the same as those of the old Lisp process when the image 372 374 was created.</para> 373 <para>The heap image is how we get around the fact that we can't375 <para>The heap image is how we get around the fact that we can't 374 376 run Lisp code until we have a working Lisp implementation, and 375 377 we can't make our Lisp implementation work until we can run Lisp … … 377 379 implementation, all we need to do is load it into memory and 378 380 start using it.</para> 379 <para>If you're building a new version of &CCL;, you need to381 <para>If you're building a new version of &CCL;, you need to 380 382 build a new heap image.</para> 381 <para>(You might also wish to build a heap image if you have a382 large program which it is very complicated or time-consuming to383 <para>(You might also wish to build a heap image if you have a 384 large program that is very complicated or time-consuming to 383 385 load, so that you will be able to load it once, save an image, 384 386 and thenceforth never have to load it again. At any time, a heap … … 387 389 <literal>ccl:save-application</literal>.)</para> 388 390 389 <sect2 id="Development-cycle">390 <title>Development cycle</title>391 <para>Creating a new &CCL; full heap image consists of the391 <sect2 id="Development-cycle"> 392 <title>Development cycle</title> 393 <para>Creating a new &CCL; full heap image consists of the 392 394 following steps:</para> 393 <orderedlist>394 <listitem><para>Using your existing &CCL;, create a395 bootstrapping image</para></listitem>396 <listitem><para>Using your existing &CCL;, recompile your397 updated &CCL; sources</para></listitem>398 <listitem><para>Invoke &CCL; with the bootstrapping image399 you just created (rather than with the existing full heap400 image).</para></listitem>401 </orderedlist>402 <para>When you invoke &CCL; with the bootstrapping image, it403 will start up, load al of the &CCL; fasl files, and save out404 anew full heap image. Voila. You've created a new heap405 image.</para>406 <para>A few points worth noting:</para>407 <itemizedlist>408 <listitem>409 <para>There's a circular dependency between the full heap410 image and thebootstrapping image, in that each is used to411 build the other.</para>412 </listitem>413 <listitem>414 <para>There are some minor implementation415 differences, but the environment in effect after the416 bootstrapping image has loaded its fasl files is essentially417 equivalent to the environment provided by the full heap418 image; the latter loads a lot faster and is easier to419 distribute, of course.</para>420 </listitem>421 <listitem>422 <para>If the full heap image doesn't work (because423 of an OScompatibilty problem or other bug), it's very likely424 that thebootstrapping image will suffer the same425 problems.</para>426 </listitem>427 </itemizedlist>428 <para>Given a bootstrapping image and a set of up-to-date fasl395 <orderedlist> 396 <listitem><para>Using your existing &CCL;, create a 397 bootstrapping image</para></listitem> 398 <listitem><para>Using your existing &CCL;, recompile your 399 updated &CCL; sources</para></listitem> 400 <listitem><para>Invoke &CCL; with the bootstrapping image 401 you just created (rather than with the existing full heap 402 image).</para></listitem> 403 </orderedlist> 404 <para>When you invoke &CCL; with the bootstrapping image, it 405 starts up, loads all of the &CCL; fasl files, and saves out a 406 new full heap image. Voila. You've created a new heap 407 image.</para> 408 <para>A few points worth noting:</para> 409 <itemizedlist> 410 <listitem> 411 <para>There's a circular dependency between the full heap 412 image and the bootstrapping image, in that each is used to 413 build the other.</para> 414 </listitem> 415 <listitem> 416 <para>There are some minor implementation 417 differences, but the environment in effect after the 418 bootstrapping image has loaded its fasl files is essentially 419 equivalent to the environment provided by the full heap 420 image; the latter loads a lot faster and is easier to 421 distribute, of course.</para> 422 </listitem> 423 <listitem> 424 <para>If the full heap image doesn't work (because 425 of an OS compatibilty problem or other bug), it's very likely 426 that the bootstrapping image will suffer the same 427 problems.</para> 428 </listitem> 429 </itemizedlist> 430 <para>Given a bootstrapping image and a set of up-to-date fasl 429 431 files, the development cycle usually involves editing lisp 430 432 sources (or updating those sources via cvs update), 431 433 recompiling modified files, and using the bootstrapping image 432 434 to produce a new heap image.</para> 433 </sect2>434 435 <sect2 id="Generating-a-bootstrapping-image">436 <title>Generating a bootstrapping image</title>437 <para>The bootstrapping image isn't provided in &CCL;435 </sect2> 436 437 <sect2 id="Generating-a-bootstrapping-image"> 438 <title>Generating a bootstrapping image</title> 439 <para>The bootstrapping image isn't provided in &CCL; 438 440 distributions. It can be built from the source code provided 439 441 in distributions (using a lisp image and kernel provided in … … 441 443 below.</para> 442 444 443 <para>The bootstrapping image is built by invoking a special445 <para>The bootstrapping image is built by invoking a special 444 446 utility inside a running &CCL; heap image to load files 445 447 contained in the <literal>ccl/level-0</literal> directory. The … … 449 451 "cross-dumping".</para> 450 452 451 <para>Given a source distribution, a lisp kernel, and aheap452 image, one can produce a bootst apping image by first invoking453 <para>Given a source distribution, a lisp kernel, and a heap 454 image, one can produce a bootstrapping image by first invoking 453 455 &CCL; from the shell:</para> 454 <programlisting>456 <programlisting> 455 457 shell> openmcl 456 458 Welcome to &CCL; .... ! 457 459 ? 458 </programlisting>459 <para>then calling <literal>ccl:xload-level-0</literal> at the460 lisp prompt</para>461 <programlisting>460 </programlisting> 461 <para>then calling <literal>ccl:xload-level-0</literal> at the 462 lisp prompt</para> 463 <programlisting> 462 464 ? (ccl:xload-level-0) 463 </programlisting>464 <para>This will compilethe lisp sources in the ccl/level-0465 </programlisting> 466 <para>This function compiles the lisp sources in the ccl/level-0 465 467 directory if they're newer than the corresponding fasl files 466 and will then load the resulting fasl files into a simulated467 lisp heap contained insidedata structures inside the running468 and then loads the resulting fasl files into a simulated lisp 469 heap contained in data structures inside the running 468 470 lisp. That simulated heap image is then written to 469 471 disk.</para> 470 <para><literal>xload-level-0</literal> should be called472 <para><literal>xload-level-0</literal> should be called 471 473 whenever your existing boot image is out-of-date with respect 472 474 to the source files in <literal>ccl:level-0;</literal> 473 475 :</para> 474 <programlisting>476 <programlisting> 475 477 ? (ccl:xload-level-0 :force) 476 </programlisting>477 <para>will forcerecompilation of the level-0 sources.</para>478 </sect2>479 480 <sect2 id="Generating-fasl-files">481 <title>Generating fasl files</title>482 <para> Calling:</para>483 <programlisting>478 </programlisting> 479 <para>forces recompilation of the level-0 sources.</para> 480 </sect2> 481 482 <sect2 id="Generating-fasl-files"> 483 <title>Generating fasl files</title> 484 <para> Calling:</para> 485 <programlisting> 484 486 ? (ccl:compile-ccl) 485 </programlisting>486 <para>at the lisp prompt will compileany fasl files that are487 out-of-date with respect to the corresponding lisp sources;488 <literal>(ccl:compile-ccl t)</literal> will force489 recompilation. <literal>ccl:compile-ccl</literal> will reload490 newly-compiled versions of some files;491 <literal>ccl:xcompile-ccl</literal> is analogous, but skips492 this reloading step.</para>493 <para>Unless there are bootstrapping considerations involved,494 it usually doesn't matter whether these filesreloaded after487 </programlisting> 488 <para>at the lisp prompt compiles any fasl files that are 489 out-of-date with respect to the corresponding lisp sources; 490 <literal>(ccl:compile-ccl t)</literal> forces 491 recompilation. <literal>ccl:compile-ccl</literal> reloads 492 newly-compiled versions of some files; 493 <literal>ccl:xcompile-ccl</literal> is analogous, but skips 494 this reloading step.</para> 495 <para>Unless there are bootstrapping considerations involved, it 496 usually doesn't matter whether these files are reloaded after 495 497 they're recompiled.</para> 496 <para>Calling <literal>compile-ccl</literal> or498 <para>Calling <literal>compile-ccl</literal> or 497 499 <literal>xcompile-ccl</literal> in an environment where fasl 498 500 files don't yet exist may produce warnings to that effect … … 504 506 warnings about undefined functions, etc. They should be 505 507 cleaned up at some point.</para> 506 </sect2>507 508 <sect2 id="Building-a-full-image-from-a-bootstrapping-image">509 <title>Building a full image from a bootstrapping image</title>510 <para>To build a full image from a bootstrapping image, just511 invoke the kernel with the bootstrapping image is an512 argument</para>513 <programlisting>508 </sect2> 509 510 <sect2 id="Building-a-full-image-from-a-bootstrapping-image"> 511 <title>Building a full image from a bootstrapping image</title> 512 <para>To build a full image from a bootstrapping image, just 513 invoke the kernel with the bootstrapping image as an 514 argument</para> 515 <programlisting> 514 516 $ cd ccl # wherever your ccl directory is 515 517 $ ./KERNEL BOOT_IMAGE 516 </programlisting>517 <para>Where <replaceable>KERNEL</replaceable> and518 </programlisting> 519 <para>Where <replaceable>KERNEL</replaceable> and 518 520 <replaceable>BOOT_IMAGE</replaceable> are the names of 519 521 the kernel and boot image appropriate to the platform you are 520 running on. See FIXTHIS</para>521 <para>That should load a few dozen fasl files (printing a522 running on. See <xref linkend="Platform-specific-filename-conventions"/></para> 523 <para>That should load a few dozen fasl files (printing a 522 524 message as each file is loaded.) If all of these files 523 525 successfully load, the lisp will print a prompt. You should be … … 526 528 you're confident that things loaded OK, you can save that 527 529 image.</para> 528 <programlisting>530 <programlisting> 529 531 ? (ccl:save-application "<replaceable>image_name</replaceable>") ; Overwiting the existing heap image 530 </programlisting> 531 <para>Where <replaceable>image_name</replaceable> is the name 532 of the full heap image for your platform. See FIXTHIS.</para> 533 <para>If things go wrong in the early stages of the loading 532 </programlisting> 533 <para>Where <replaceable>image_name</replaceable> is the name of 534 the full heap image for your platform. See 535 <xref linkend="Platform-specific-filename-conventions"/>.</para> 536 <para>If things go wrong in the early stages of the loading 534 537 sequence, errors are often difficult to debug; until a fair 535 538 amount of code (CLOS, the CL condition system, streams, the … … 539 542 cause the lisp kernel debugger (see ) to be invoked; it's 540 543 primitive, but can sometimes help one to get oriented.</para> 541 </sect2>542 </sect1>543 </chapter>544 </sect2> 545 </sect1> 546 </chapter> -
release/1.2/source/doc/src/ide.xml
r8981 r9200 43 43 <listitem> 44 44 <para>Run ccl from the shell. The easiest way to do this is 45 generally to execute the openmcl or openmcl64 command.</para>45 generally to execute the ccl or ccl64 command.</para> 46 46 </listitem> 47 47 <listitem> … … 55 55 56 56 <programlisting> 57 oshirion:ccl mikel$ openmcl6458 Welcome to Clozure Common Lisp Version 1.2-r8516MS(DarwinX8664)!59 ? (require :cocoa-application)60 ;Loading #P"ccl:cocoa-ide;fasls;cocoa-utils.dx64fsl.newest"...61 ;Loading #P"ccl:cocoa-ide;fasls;cocoa-defaults.dx64fsl.newest"...62 63 [...many lines of "Compiling" and "Loading" omitted...]64 65 Saving application to /usr/local/ccl/Clozure CL.app/66 67 oshirion:ccl mikel$57 oshirion:ccl mikel$ ccl64 58 Welcome to Clozure Common Lisp Version 1.2-r9198M-trunk (DarwinX8664)! 59 ? (require :cocoa-application) 60 ;Loading #P"ccl:cocoa-ide;fasls;cocoa-utils.dx64fsl.newest"... 61 ;Loading #P"ccl:cocoa-ide;fasls;cocoa-defaults.dx64fsl.newest"... 62 63 [...many lines of "Compiling" and "Loading" omitted...] 64 65 Saving application to /usr/local/ccl/Clozure CL.app/ 66 67 oshirion:ccl mikel$ 68 68 69 69 </programlisting> -
release/1.2/source/doc/src/implementation.xml
r8981 r9200 24 24 <sect1 id="Threads-and-exceptions"> 25 25 <title>Threads and exceptions</title> 26 26 27 <para>&CCL;'s threads are "native" (meaning that they're 27 scheduled and controlled by the operating system.) Most of the28 implications of this are discussed elsewhere; this section tries29 to describe how threads look from the lisp kernel's perspective30 (and especially from the GC's point of view.)</para>28 scheduled and controlled by the operating system.) Most of the 29 implications of this are discussed elsewhere; this section tries 30 to describe how threads look from the lisp kernel's perspective 31 (and especially from the GC's point of view.)</para> 31 32 <para>&CCL;'s runtime system tries to use machine-level 32 exception mechanisms (conditional traps when available, illegal33 instructions, memory access protection in some cases) to detect34 and handle ...exceptional situations. These situations35 include some TYPE-ERRORs and PROGRAM-ERRORS (notably36 wrong-number-of-args errors), and also include cases like "not37 being able to allocate memory without GCing or obtaining more38 memory from the OS." The general idea is that it's usually39 faster to pay (very occasional) exception-processing overhead40 and figure out what's going on in an exception handler than it41 is to maintain enough state and context to handle an exceptional42 case via a lighter-weight mechanism when that exceptional case43 (by definition) rarely occurs.</para>33 exception mechanisms (conditional traps when available, 34 illegal instructions, memory access protection in some cases) 35 to detect and handle exceptional situations. These situations 36 include some TYPE-ERRORs and PROGRAM-ERRORS (notably 37 wrong-number-of-args errors), and also include cases like "not 38 being able to allocate memory without GCing or obtaining more 39 memory from the OS." The general idea is that it's usually 40 faster to pay (very occasional) exception-processing overhead 41 and figure out what's going on in an exception handler than it 42 is to maintain enough state and context to handle an 43 exceptional case via a lighter-weight mechanism when that 44 exceptional case (by definition) rarely occurs.</para> 44 45 <para>Some emulated execution environments (the Rosetta PPC 45 emulator on x86 versions of Mac OS X) don't provide accurate46 exception information to exception handling functions. &CCL;47 can't run in such environments.</para>46 emulator on x86 versions of Mac OS X) don't provide accurate 47 exception information to exception handling functions. &CCL; 48 can't run in such environments.</para> 48 49 49 50 <sect2 id="The-Thread-Context-Record"> 50 <title>The Thread Context Record</title> 51 52 <para>When a lisp thread is first created (or when a thread 53 created by foreign code first calls back to lisp), a data 54 structure called a Thread Context Record (or TCR) is allocated 55 and initialized. On modern versions of Linux and FreeBSD, the 56 allocation actually happens via a set of thread-local-storage 57 ABI extensions, so a thread's TCR is created when the thread 58 is created and dies when the thread dies. (The World's Most 59 Advanced Operating System - as Apple's marketing literature 60 refers to Darwin - is not very advanced in this regard, and I 61 know of no reason to assume that advances will be made in this 62 area anytime soon.)</para> 51 <title>The Thread Context Record</title> 52 53 <para>When a lisp thread is first created (or when a thread 54 created by foreign code first calls back to lisp), a data 55 structure called a Thread Context Record (or TCR) is 56 allocated and initialized. On modern versions of Linux and 57 FreeBSD, the allocation actually happens via a set of 58 thread-local-storage ABI extensions, so a thread's TCR is 59 created when the thread is created and dies when the thread 60 dies. (The World's Most Advanced Operating System—as 61 Apple's marketing literature refers to Darwin—is not 62 very advanced in this regard, and I know of no reason to 63 assume that advances will be made in this area anytime 64 soon.)</para> 63 65 <para>A TCR contains a few dozen fields (and is therefore a 64 few hundred bytes in size.) The fields are mostly65 thread-specific information about the thread's stacks'66 locations and sizes, information about the underlying (POSIX)67 thread, and information about the thread's dynamic binding68 history and pending CATCH/UNWIND-PROTECTs. Some of this69 information could be kept in individual machine registers70 while the thread is running (and the PPC - which has more71 registers available - keeps a few things in registers that the72 X86-64 has to access via the TCR), but it's important to73 remember that the information is thread-specific and can't74 (for instance) be kept in a fixed global memory75 location.</para>66 few hundred bytes in size.) The fields are mostly 67 thread-specific information about the thread's stacks' 68 locations and sizes, information about the underlying (POSIX) 69 thread, and information about the thread's dynamic binding 70 history and pending CATCH/UNWIND-PROTECTs. Some of this 71 information could be kept in individual machine registers 72 while the thread is running (and the PPC - which has more 73 registers available - keeps a few things in registers that the 74 X86-64 has to access via the TCR), but it's important to 75 remember that the information is thread-specific and can't 76 (for instance) be kept in a fixed global memory 77 location.</para> 76 78 <para>When lisp code is running, the current thread's TCR is 77 kept in a register. On PPC platforms, a general purpose78 register is used; on x86-64, an (otherwise nearly useless)79 segment register works well (prevents the expenditure of a80 more generally useful general- purpose register for this81 purpose.)</para>79 kept in a register. On PPC platforms, a general purpose 80 register is used; on x86-64, an (otherwise nearly useless) 81 segment register works well (prevents the expenditure of a 82 more generally useful general- purpose register for this 83 purpose.)</para> 82 84 <para>The address of a TCR is aligned in memory in such a way 83 that a FIXNUM can be used to represent it. The lisp function84 CCL::%CURRENT-TCR returns the calling thread's TCR as a85 fixnum; actual value of the TCR's address is 4 or 8 times the86 value of this fixnum.</para>85 that a FIXNUM can be used to represent it. The lisp function 86 CCL::%CURRENT-TCR returns the calling thread's TCR as a 87 fixnum; actual value of the TCR's address is 4 or 8 times the 88 value of this fixnum.</para> 87 89 <para>When the lisp kernel initializes a new TCR, it's added 88 to a global list maintained by the kernel; when a thread89 exits, its TCR is removed from this list.</para>90 to a global list maintained by the kernel; when a thread 91 exits, its TCR is removed from this list.</para> 90 92 <para>When a thread calls foreign code, lisp stack pointers 91 are saved in its TCR, lisp registers (at least those whose92 value should be preserved across the call) are saved on the93 thread's value stack, and (on x86-64) RSP is switched to the94 control stack. A field in the TCR (tcr.valence) is then set95 to indicate that the thread is running foreign code, foreign96 argument registers are loaded from a frame on the foreign97 stack, and the foreign function is called. (That's a little98 oversimplified and possibly inaccurate, but the important99 things to note are that the thread "stops following lisp stack100 and register usage conventions" and that it advertises the101 fact that it's done so. Similar transitions in a thread's102 state ("valence") occur when it enters of exits an exception103 handler (which is sort of an OS/hardware-mandated foreign104 function call where the OS thoughtfully saves the thread's105 register state for it beforehand.)</para>93 are saved in its TCR, lisp registers (at least those whose 94 value should be preserved across the call) are saved on the 95 thread's value stack, and (on x86-64) RSP is switched to the 96 control stack. A field in the TCR (tcr.valence) is then set 97 to indicate that the thread is running foreign code, foreign 98 argument registers are loaded from a frame on the foreign 99 stack, and the foreign function is called. (That's a little 100 oversimplified and possibly inaccurate, but the important 101 things to note are that the thread "stops following lisp 102 stack and register usage conventions" and that it advertises 103 the fact that it's done so. Similar transitions in a 104 thread's state ("valence") occur when it enters or exits an 105 exception handler (which is sort of an OS/hardware-mandated 106 foreign function call where the OS thoughtfully saves the 107 thread's register state for it beforehand.)</para> 106 108 </sect2> 107 109 108 110 <sect2 id="Exception-contexts-comma---and-exception-handling-in-general"> 109 <title>Exception contexts, and exception-handling in general</title>111 <title>Exception contexts, and exception-handling in general</title> 110 112 <para>Unix-like OSes tend to refer to exceptions as "signals"; 111 the same general mechanism ("signal handling") is used to112 process both asynchronous OS-level events (such as the result113 of the keyboard driver noticing that ^C or ^Z has been114 pressed) and synchronous hardware-level events (like trying to115 execute an illegal instruction or access protected memory.)116 It makes some sense to defer ("block") handling of117 asynchronous signals so that some critical code sequences118 complete without interruption; since it's generally not119 possible for a thread to proceed after a synchronous exception120 unless and until its state is modified by an exception121 handler, it makes no sense to talk about blocking synchronous122 signals (though some OSes will let you do so and doing so can123 have mysterious effects.)</para>113 the same general mechanism ("signal handling") is used to 114 process both asynchronous OS-level events (such as the result 115 of the keyboard driver noticing that ^C or ^Z has been 116 pressed) and synchronous hardware-level events (like trying to 117 execute an illegal instruction or access protected memory.) 118 It makes some sense to defer ("block") handling of 119 asynchronous signals so that some critical code sequences 120 complete without interruption; since it's generally not 121 possible for a thread to proceed after a synchronous exception 122 unless and until its state is modified by an exception 123 handler, it makes no sense to talk about blocking synchronous 124 signals (though some OSes will let you do so and doing so can 125 have mysterious effects.)</para> 124 126 <para>On OSX/Darwin, the POSIX signal handling facilities 125 coexist with lower-level Mach-based exception handling126 facilities. Unfortunately, the way that this is implemented127 interacts poorly with debugging tools: GDB will generally stop128 whenever the target program encounters a Mach-level exception129 and offers no way to proceed from that point (and let the130 program's POSIX signal handler try to handle the exception);131 Apple's CrashReporter program has had a similar issue and,132 depending on how it's configured, may bombard the user with133 alert dialogs which falsely claim that an application has134 crashed (when in fact the application in question has135 routinely handled a routine exception.) On Darwin/OSX,136 &CCL; uses Mach thread-level exception handling facilities137 which run before GDB or CrashReporter get a chance to confuse138 themselves; &CCL;'s Mach exception handling tries to force139 the thread which received a synchronous exception to invoke a140 signal handling function ("as if" signal handling worked more141 usefully under Darwin.) Mach exception handlers run in a142 dedicated thread (which basically does nothing but wait for143 exception messages from the lisp kernel, obtain and modify144 information about the state of threads in which exceptions145 have occurred, and reply to the exception messages with an146 indication that the exception has been handled. The reply147 from a thread-level exception handler keeps the exception from148 being reported to GDB or CrashReporter and avoids the problems149 related to those programs. Since &CCL;'s Mach exception150 handler doesn't claim to handle debugging-related exceptions151 (from breakpoints or single-step operations), it's possible to152 use GDB to debug &CCL;.</para>127 coexist with lower-level Mach-based exception handling 128 facilities. Unfortunately, the way that this is implemented 129 interacts poorly with debugging tools: GDB will generally stop 130 whenever the target program encounters a Mach-level exception 131 and offers no way to proceed from that point (and let the 132 program's POSIX signal handler try to handle the exception); 133 Apple's CrashReporter program has had a similar issue and, 134 depending on how it's configured, may bombard the user with 135 alert dialogs which falsely claim that an application has 136 crashed (when in fact the application in question has 137 routinely handled a routine exception.) On Darwin/OSX, 138 &CCL; uses Mach thread-level exception handling facilities 139 which run before GDB or CrashReporter get a chance to confuse 140 themselves; &CCL;'s Mach exception handling tries to force 141 the thread which received a synchronous exception to invoke a 142 signal handling function ("as if" signal handling worked more 143 usefully under Darwin.) Mach exception handlers run in a 144 dedicated thread (which basically does nothing but wait for 145 exception messages from the lisp kernel, obtain and modify 146 information about the state of threads in which exceptions 147 have occurred, and reply to the exception messages with an 148 indication that the exception has been handled. The reply 149 from a thread-level exception handler keeps the exception from 150 being reported to GDB or CrashReporter and avoids the problems 151 related to those programs. Since &CCL;'s Mach exception 152 handler doesn't claim to handle debugging-related exceptions 153 (from breakpoints or single-step operations), it's possible to 154 use GDB to debug &CCL;.</para> 153 155 <para>On platforms where signal handling and debugging don't 154 get in each other's way, a signal handler is entered with all155 signals blocked. (This behavior is specified in the call to156 the sigaction() function which established the signal157 handler.) The signal handler receives three arguments from158 the OS kernel; the first is an integer which identifies the159 signal, the second is a pointer to an object of type160 "siginfo_t", which may or may not contain a few fields that161 would help to identify the cause of the exception, andthe162 third argument is a pointer to a data structure (calleda163 "ucontext" or something similar) which contains164 machine-dependent information about the state of the tread at165 the time that the exception/signal occurred. While166 asynchronous signals are blocked, the signal handler stores167 the pointer to its third argument (the "signal context") in a168 field in the current thread's TCR, sets some bits in another169 TCR field to indicate that the thread is now waiting to handle170 an exception, unblocks asynchronous signals, and waits for a171 global exception lock which serializes exception172 processing.</para>156 get in each other's way, a signal handler is entered with 157 all signals blocked. (This behavior is specified in the 158 call to the sigaction() function which established the 159 signal handler.) The signal handler receives three 160 arguments from the OS kernel; the first is an integer that 161 identifies the signal, the second is a pointer to an object 162 of type "siginfo_t", which may or may not contain a few 163 fields that would help to identify the cause of the 164 exception, and the third argument is a pointer to a data 165 structure (called a "ucontext" or something similar), which 166 contains machine-dependent information about the state of 167 the thread at the time that the exception/signal occurred. 168 While asynchronous signals are blocked, the signal handler 169 stores the pointer to its third argument (the "signal 170 context") in a field in the current thread's TCR, sets some 171 bits in another TCR field to indicate that the thread is now 172 waiting to handle an exception, unblocks asynchronous 173 signals, and waits for a global exception lock that 174 serializes exception processing.</para> 173 175 <para>On Darwin, the Mach exception thread creates a signal 174 context (and maybe a siginfo_t structure), stores the signal175 context in the thread's TCR, sets the TCR field which describes176 the thread's state, and arranges that the thread resume177 execution at its signal handling function (with a signal178 handler, possibly NULL siginfo_t, and signal context as179 arguments. When the thread resumes, it waits for the global180 exception lock.</para>176 context (and maybe a siginfo_t structure), stores the signal 177 context in the thread's TCR, sets the TCR field which describes 178 the thread's state, and arranges that the thread resume 179 execution at its signal handling function (with a signal 180 handler, possibly NULL siginfo_t, and signal context as 181 arguments. When the thread resumes, it waits for the global 182 exception lock.</para> 181 183 <para>On x86-64 platforms where signal handing can be used to 182 handle synchronous exceptions, there's an additional 183 complication: the OS kernel ordinarily allocates the signal 184 context and siginfo structures on the stack of the thread 185 which received the signal; in practice, that means "wherever 186 RSP is pointing." &CCL;'s <xref 187 linkend="Register-and-stack-usage-conventions"/> require that 188 the thread's value stack - where RSP is usually pointing while 189 lisp code is running - contain only "nodes" (properly tagged 190 lisp objects), and scribbling a signal context all over the 191 value stack would violate this requirement. To maintain 192 consistency, the sigaltstack() mechanism is used to cause the 193 signal to be delivered on (and the signal context and siginfo 194 to be allocated on) a special stack area (the last few pages 195 of the thread's control stack, in practice. When the signal 196 handler runs, it (carefully) copies the signal context and 197 siginfo to the thread's control stack and makes RSP point into 198 that stack before invoking the "real" signal handler. (The 199 effect of this hack is that the "real" signal handler always 200 runs on the thread's control stack.)</para> 184 handle synchronous exceptions, there's an additional 185 complication: the OS kernel ordinarily allocates the signal 186 context and siginfo structures on the stack of the thread 187 that received the signal; in practice, that means "wherever 188 RSP is pointing." &CCL;'s 189 <xref linkend="Register-and-stack-usage-conventions"/> 190 require that the thread's value stack—where RSP is 191 usually pointing while lisp code is running—contain 192 only "nodes" (properly tagged lisp objects), and scribbling 193 a signal context all over the value stack would violate this 194 requirement. To maintain consistency, the sigaltstack() 195 mechanism is used to cause the signal to be delivered on 196 (and the signal context and siginfo to be allocated on) a 197 special stack area (the last few pages of the thread's 198 control stack, in practice). When the signal handler runs, 199 it (carefully) copies the signal context and siginfo to the 200 thread's control stack and makes RSP point into that stack 201 before invoking the "real" signal handler. The effect of 202 this hack is that the "real" signal handler always runs on 203 the thread's control stack.</para> 201 204 <para>Once the exception handler has obtained the global 202 exception lock, it uses the values of the signal number,203 siginfo_t, and signal context arguments to determine the204 (logical) cause of the exception. Some exceptions may be205 caused by factors that should generate lisp errors or other206 serious conditions (stack overflow); if this is the case, the207 kernel code may release the global exception lock and call out208 to lisp code. (The lisp code in question may need to repeat209 some of the exception decoding process; in particular, it210 needs to be able to interpret register values in the signal211 context that it receives as an argument.)</para>205 exception lock, it uses the values of the signal number, 206 siginfo_t, and signal context arguments to determine the 207 (logical) cause of the exception. Some exceptions may be 208 caused by factors that should generate lisp errors or other 209 serious conditions (stack overflow); if this is the case, the 210 kernel code may release the global exception lock and call out 211 to lisp code. (The lisp code in question may need to repeat 212 some of the exception decoding process; in particular, it 213 needs to be able to interpret register values in the signal 214 context that it receives as an argument.)</para> 212 215 <para>In some cases, the lisp kernel exception handler may not 213 be able to recover from the exception (this is currently true214 of some types of memory-access fault and is also true of traps215 or illegal instructions that occur during foreign code216 execution. In such cases, the kernel exception handler217 reports the exception as "unhandled", and the kernel debugger218 is invoked.</para>216 be able to recover from the exception (this is currently true 217 of some types of memory-access fault and is also true of traps 218 or illegal instructions that occur during foreign code 219 execution. In such cases, the kernel exception handler 220 reports the exception as "unhandled", and the kernel debugger 221 is invoked.</para> 219 222 <para>If the kernel exception handler identifies the 220 exception's cause as being a transient out-of-memory condition221 (indicating that the current thread needs more memory to cons222 in), it tries to make that memory available. In some cases,223 doing so involves invoking the GC.</para>223 exception's cause as being a transient out-of-memory condition 224 (indicating that the current thread needs more memory to cons 225 in), it tries to make that memory available. In some cases, 226 doing so involves invoking the GC.</para> 224 227 </sect2> 225 228 226 229 <sect2 id="Threads-comma---exceptions-comma---and-the-GC"> 227 <title>Threads, exceptions, and the GC</title>230 <title>Threads, exceptions, and the GC</title> 228 231 <para>&CCL;'s GC is not concurrent: when the GC is invoked in 229 response to an exception in a particular thread, all other230 lisp threads must stop until the GC's work is done. The231 thread that triggered the GC iterates over the global TCR232 list, sending each other thread a distinguished "suspend"233 signal, then iterates over the list again, waiting for a234 per-thread semaphore that indicates that the thread has235 received the "suspend" signal and responded appropriately.236 Once all other threads have acknowledged the request to237 suspend themselves, the GC thread can run the GC proper (after238 doing any necessary <xref linkend="PC-lusering"/>.) Once the239 GC's completed its work, the thread that invoked the GC240 iterates over the global TCR list, raising a per-thread241 "resume" semaphore for each other thread.</para>232 response to an exception in a particular thread, all other 233 lisp threads must stop until the GC's work is done. The 234 thread that triggered the GC iterates over the global TCR 235 list, sending each other thread a distinguished "suspend" 236 signal, then iterates over the list again, waiting for a 237 per-thread semaphore that indicates that the thread has 238 received the "suspend" signal and responded appropriately. 239 Once all other threads have acknowledged the request to 240 suspend themselves, the GC thread can run the GC proper (after 241 doing any necessary <xref linkend="PC-lusering"/>.) Once the 242 GC's completed its work, the thread that invoked the GC 243 iterates over the global TCR list, raising a per-thread 244 "resume" semaphore for each other thread.</para> 242 245 <para>The signal handler for the asynchronous "suspend" signal 243 is entered with all asynchronous signals blocked. It saves244 its signal-context argument in a TCR slot, raises the tcr's245 "suspend" semaphore, then waits on the TCR's "resume"246 semaphore.</para>246 is entered with all asynchronous signals blocked. It saves 247 its signal-context argument in a TCR slot, raises the tcr's 248 "suspend" semaphore, then waits on the TCR's "resume" 249 semaphore.</para> 247 250 <para>The GC thread has access to the signal contexts of all 248 TCRs (including its own) at the time when the thread received249 an exception or acknowledged a request to suspend itself.250 This information (and information about stack areas in the TCR251 itself) allows the GC to identify the "stack locations and252 register contents" that are elements of the GC's root253 set.</para>251 TCRs (including its own) at the time when the thread received 252 an exception or acknowledged a request to suspend itself. 253 This information (and information about stack areas in the TCR 254 itself) allows the GC to identify the "stack locations and 255 register contents" that are elements of the GC's root 256 set.</para> 254 257 </sect2> 255 258 256 259 <sect2 id="PC-lusering"> 257 <title>PC-lusering</title>260 <title>PC-lusering</title> 258 261 <para>It's not quite accurate to say that &CCL;'s compiler 259 and runtime follow precise stack and register usage260 conventions at all times; there are a few exceptions:</para>261 262 <itemizedlist>262 and runtime follow precise stack and register usage 263 conventions at all times; there are a few exceptions:</para> 264 265 <itemizedlist> 263 266 <listitem> 264 <para>On both PPC and x86-64 platforms, consing isn't265 fully atomic.It takes at least a few instructions to266 allocate an object in memory(and slap a header on it if267 necessary); if a thread is interrupted in the middle of268 that instruction sequence, the new object may or may269 not have been created or fully initialized at the point in270 time that the interrupt occurred. (There are actually a271 few different states of partial initialization)</para>272 </listitem>273 <listitem>274 <para>On the PPC, the common act of building a lisp275 control stack frame involves allocating a four-word frame276 and storing three register values into that frame. (The277 fourth word - the back pointer to the previous frame - is278 automatically set when the frame is allocated.) The279 previous contents of those three words are unknown (there280 might have been a foreign stack frame at the same address a281 few instructions earlier),so interrupting a thread that's282 in the process of initializing a PPC control stack frame283 isn't GC-safe.</para>284 </listitem>267 <para>On both PPC and x86-64 platforms, consing isn't 268 fully atomic.It takes at least a few instructions to 269 allocate an object in memory(and slap a header on it if 270 necessary); if a thread is interrupted in the middle of 271 that instruction sequence, the new object may or may 272 not have been created or fully initialized at the point in 273 time that the interrupt occurred. (There are actually a 274 few different states of partial initialization)</para> 275 </listitem> 276 <listitem> 277 <para>On the PPC, the common act of building a lisp 278 control stack frame involves allocating a four-word frame 279 and storing three register values into that frame. (The 280 fourth word - the back pointer to the previous frame - is 281 automatically set when the frame is allocated.) The 282 previous contents of those three words are unknown (there 283 might have been a foreign stack frame at the same address a 284 few instructions earlier),so interrupting a thread that's 285 in the process of initializing a PPC control stack frame 286 isn't GC-safe.</para> 287 </listitem> 285 288 <listitem> 286 <para>There are similar problems with the initialization287 of temp stackframes on the PPC. (Allocation and288 initialization doesn't happen atomically, and the newly289 allocated stack memory may have undefined contents.)</para>290 </listitem>289 <para>There are similar problems with the initialization 290 of temp stackframes on the PPC. (Allocation and 291 initialization doesn't happen atomically, and the newly 292 allocated stack memory may have undefined contents.)</para> 293 </listitem> 291 294 <listitem> 292 <para><xref linkend="The-ephemeral-GC"/>'s write barrier293 has to be implemented atomically (i.e.,both an294 intergenerational store and the update of a295 corresponding reference bit has to happen without296 interruption, or neither of these events can297 happen.)</para>298 </listitem>295 <para><xref linkend="The-ephemeral-GC"/>'s write barrier 296 has to be implemented atomically (i.e.,both an 297 intergenerational store and the update of a 298 corresponding reference bit has to happen without 299 interruption, or neither of these events can 300 happen.)</para> 301 </listitem> 299 302 <listitem> 300 <para>There are a few more similar cases.</para>301 </listitem>303 <para>There are a few more similar cases.</para> 304 </listitem> 302 305 </itemizedlist> 303 306 304 307 <para>Fortunately, the number of these non-atomic instruction 305 sequences is small, and fortunately it's fairly easy for the306 interrupting thread to recognize when the interrupted thread307 is in the middle of such a sequence. When this is detected,308 the interrupting thread modifies the state of the interrupted309 thread (modifying its PC and other registers) so that it is no310 longer in the middle of such a sequence (it's either backed311 out of it or the remaining instructions are emulated.)</para>308 sequences is small, and fortunately it's fairly easy for the 309 interrupting thread to recognize when the interrupted thread 310 is in the middle of such a sequence. When this is detected, 311 the interrupting thread modifies the state of the interrupted 312 thread (modifying its PC and other registers) so that it is no 313 longer in the middle of such a sequence (it's either backed 314 out of it or the remaining instructions are emulated.)</para> 312 315 <para>This works because (a) many of the troublesome 313 instruction sequences are PPC-specific and it's relatively314 easy to partially disassemble the instructions surrounding the315 interrupted thread's PC on the PPC and (b) those instruction316 sequences are heavily stylized and intended to be easily317 recognized.</para>316 instruction sequences are PPC-specific and it's relatively 317 easy to partially disassemble the instructions surrounding the 318 interrupted thread's PC on the PPC and (b) those instruction 319 sequences are heavily stylized and intended to be easily 320 recognized.</para> 318 321 </sect2> 319 322 </sect1> … … 321 324 <sect1 id="Register-usage-and-tagging"> 322 325 <title>Register usage and tagging</title> 323 326 324 327 <sect2 id="Register-usage-and-tagging-overview"> 325 <title>Overview</title>326 <para>Regardless of other details of its implementation, a327 garbage collector's job is to partition the set of all328 heap-allocated lisp objects (CONSes, STRINGs, INSTANCEs, etc.)329 into two subsets. The first subset contains all objects that330 are transitively referenced from a small set of "root" objects331 (the contents of the stacks and registers of all active332 threads at the time the GC occurs and the values of some333 global variables.) The second subset contains everything334 else: those lisp objects that are not transitively reachable335 from the roots are garbage, and the memory occupied by garbage336 objects can be reclaimed (since the GC has just proven that337 it's impossible to reference them.)</para>328 <title>Overview</title> 329 <para>Regardless of other details of its implementation, a 330 garbage collector's job is to partition the set of all 331 heap-allocated lisp objects (CONSes, STRINGs, INSTANCEs, etc.) 332 into two subsets. The first subset contains all objects that 333 are transitively referenced from a small set of "root" objects 334 (the contents of the stacks and registers of all active 335 threads at the time the GC occurs and the values of some 336 global variables.) The second subset contains everything 337 else: those lisp objects that are not transitively reachable 338 from the roots are garbage, and the memory occupied by garbage 339 objects can be reclaimed (since the GC has just proven that 340 it's impossible to reference them.)</para> 338 341 <para>The set of live, reachable lisp objects basically form 339 the nodes of a (usually large) graph, with edges from each340 node A to any other objects (nodes) that object A341 references.</para>342 the nodes of a (usually large) graph, with edges from each 343 node A to any other objects (nodes) that object A 344 references.</para> 342 345 <para>Some nodes in this graph can never have outgoing edges: 343 an array with a specialized numeric or character type usually344 represents its elements in some (possibly more compact)345 specialized way. Some nodes may refer to lisp objects that346 are never allocated in memory (FIXNUMs, CHARACTERs,347 SINGLE-FLOATs on 64-bit platforms ..) This latter class of348 objects are sometimes called "immediates", but that's a little349 confusing because the term "immediate" is sometimes used to350 refer to things that can never be part of the big connectivity351 graph (e.g., the "raw" bits that make up a floating-point352 value, foreign address, or numeric value that needs to be used353 - at least fleetingly - in compiled code.)</para>346 an array with a specialized numeric or character type usually 347 represents its elements in some (possibly more compact) 348 specialized way. Some nodes may refer to lisp objects that 349 are never allocated in memory (FIXNUMs, CHARACTERs, 350 SINGLE-FLOATs on 64-bit platforms ..) This latter class of 351 objects are sometimes called "immediates", but that's a little 352 confusing because the term "immediate" is sometimes used to 353 refer to things that can never be part of the big connectivity 354 graph (e.g., the "raw" bits that make up a floating-point 355 value, foreign address, or numeric value that needs to be used 356 - at least fleetingly - in compiled code.)</para> 354 357 <para>For the GC to be able to build the connectivity graph 355 reliably, it's necessary for it to be able to reliably tell356 (a) whether or not a "potential root" - the contents of a357 machine register or stack location - is in fact a node and (b)358 for any node, whether it may have components that refer to359 other nodes.</para>358 reliably, it's necessary for it to be able to reliably tell 359 (a) whether or not a "potential root" - the contents of a 360 machine register or stack location - is in fact a node and (b) 361 for any node, whether it may have components that refer to 362 other nodes.</para> 360 363 <para>There's no reliable way to answer the first question on 361 stock hardware. (If everything was a node, as might be the362 case on specially microcoded "lisp machine" hardware, it363 wouldn't even need to be asked.) Since there's no way to just364 look at a machine word (the contents of a machine register or365 stack location) and tell whether or not it's a node or just366 some random non-node value, we have to either adopt and367 enforce strict conventions on register and stack usage or368 tolerate ambiguity.</para>364 stock hardware. (If everything was a node, as might be the 365 case on specially microcoded "lisp machine" hardware, it 366 wouldn't even need to be asked.) Since there's no way to just 367 look at a machine word (the contents of a machine register or 368 stack location) and tell whether or not it's a node or just 369 some random non-node value, we have to either adopt and 370 enforce strict conventions on register and stack usage or 371 tolerate ambiguity.</para> 369 372 <para>"Tolerating ambiguity" is an approach taken by some 370 ("conservative") GC schemes; by contrast, &CCL;'s GC is371 "precise", which in this case means that it believes that the372 contents of certain machine registers and stack locations are373 always nodes and that other registers and stack locations are374 never nodes and that these conventions are never violated by375 the compiler or runtime system. The fact that threads are376 preemptively scheduled means that a GC could occur (because of377 activity in some other thread) on any instruction boundary,378 which in turn means that the compiler and runtime system must379 follow precise <xref380 linkend="Register-and-stack-usage-conventions"/> at all381 times.</para>373 ("conservative") GC schemes; by contrast, &CCL;'s GC is 374 "precise", which in this case means that it believes that the 375 contents of certain machine registers and stack locations are 376 always nodes and that other registers and stack locations are 377 never nodes and that these conventions are never violated by 378 the compiler or runtime system. The fact that threads are 379 preemptively scheduled means that a GC could occur (because of 380 activity in some other thread) on any instruction boundary, 381 which in turn means that the compiler and runtime system must 382 follow precise <xref 383 linkend="Register-and-stack-usage-conventions"/> at all 384 times.</para> 382 385 <para>Once we've decided that a given machine word is a node, 383 a <xref linkend="Tagging-scheme"/> describes how the node's384 value and type are encoded in that machine word.</para>385 <para>Most of this - so far - has discussed things from the386 GC's very low-level perspective. From a much higher point of387 view, lisp functions accept nodes as arguments, return nodes388 as values, and (usually) perform some operations on those389 arguments in order to produce those results. (In many cases,390 the operations in question involve raw non-node values.)391 Higher-level parts of the lisp type system (functions like392 TYPE-OF and CLASS-OF, etc.) depend on the <xref393 linkend="Tagging-scheme"/>.</para>386 a <xref linkend="Tagging-scheme"/> describes how the node's 387 value and type are encoded in that machine word.</para> 388 <para>Most of this discussion—so far—has treated 389 things from the GC's very low-level perspective. From a much 390 higher point of view, lisp functions accept nodes as 391 arguments, return nodes as values, and (usually) perform 392 some operations on those arguments in order to produce those 393 results. (In many cases, the operations in question involve 394 raw non-node values.) Higher-level parts of the lisp type 395 system (functions like TYPE-OF and CLASS-OF, etc.) depend on 396 the <xref linkend="Tagging-scheme"/>.</para> 394 397 </sect2> 395 398 396 399 <sect2 id="pc-locatives-on-the-PPC"> 397 <title>pc-locatives on the PPC</title>400 <title>pc-locatives on the PPC</title> 398 401 <para>On the PPC, there's a third case (besides "node" and 399 "immediate" values). As discussed below, a node that denotes400 a memory-allocated lisp object is a biased (tagged) pointer401 -to- that object; it's not generally possible to point -into-402 some composite (multi-element) object (such a pointer would403 not be a node, and the GC would have no way to update the404 pointer if it were to move the underlying object.)</para>402 "immediate" values). As discussed below, a node that denotes 403 a memory-allocated lisp object is a biased (tagged) pointer 404 -to- that object; it's not generally possible to point -into- 405 some composite (multi-element) object (such a pointer would 406 not be a node, and the GC would have no way to update the 407 pointer if it were to move the underlying object.)</para> 405 408 <para>Such a pointer ("into" the interior of a heap-allocated 406 object) is often called a <emphasis>locative</emphasis>; the407 cases where locatives are allowed in &CCL; mostly involve408 the behavior of function call and return instructions. (To be409 technically accurate, the other case also arises on x86-64, but410 that case isn't as user-visible.)</para>409 object) is often called a <emphasis>locative</emphasis>; the 410 cases where locatives are allowed in &CCL; mostly involve 411 the behavior of function call and return instructions. (To be 412 technically accurate, the other case also arises on x86-64, but 413 that case isn't as user-visible.)</para> 411 414 <para>On the PowerPC (both PPC32 and PPC64), all machine 412 instructions are 32 bits wide and all instruction words are413 allocated on 32-bit boundaries. In PPC &CCL;, a CODE-VECTOR414 is a specialized type of vector-like object; its elements are415 32-bit PPC machine instructions. A CODE-VECTOR is an416 attribute ofFUNCTION object; a function call involves417 accessing the function's code-vector and jumping to the418 address of its first instruction.</para>415 instructions are 32 bits wide and all instruction words are 416 allocated on 32-bit boundaries. In PPC &CCL;, a CODE-VECTOR 417 is a specialized type of vector-like object; its elements 418 are 32-bit PPC machine instructions. A CODE-VECTOR is an 419 attribute of a FUNCTION object; a function call involves 420 accessing the function's code-vector and jumping to the 421 address of its first instruction.</para> 419 422 <para>As each instruction in the code vector sequentially 420 executes, the hardware program counter (PC) register advances421 to the address of the next instruction (a locative into the422 code vector); since PPC instructions are always 32 bits wide423 and aligned on 32-bit boundaries, the low two bits of the PC424 are always 0. If the function executes a call (simple call425 instructions have the mnemonic "bl" on the PPC, which stands426 for "branch and link"), the address of the next instruction427 (also a word-aligned locative into a code-vector) is copied428 into the special- purpose PPC "link register" (lr); a function429 returns to its caller via a "branch to link register" (blr)430 instruction. Some cases of function call and return might431 also use the PPC's "count register" (ctr), and if either the432 lr or ctr needs to be stored in memory it needs to first be433 copied to a general-purpose register.</para>423 executes, the hardware program counter (PC) register advances 424 to the address of the next instruction (a locative into the 425 code vector); since PPC instructions are always 32 bits wide 426 and aligned on 32-bit boundaries, the low two bits of the PC 427 are always 0. If the function executes a call (simple call 428 instructions have the mnemonic "bl" on the PPC, which stands 429 for "branch and link"), the address of the next instruction 430 (also a word-aligned locative into a code-vector) is copied 431 into the special- purpose PPC "link register" (lr); a function 432 returns to its caller via a "branch to link register" (blr) 433 instruction. Some cases of function call and return might 434 also use the PPC's "count register" (ctr), and if either the 435 lr or ctr needs to be stored in memory it needs to first be 436 copied to a general-purpose register.</para> 434 437 <para>&CCL;'s GC understands that certain registers contain 435 these special "pc-locatives" (locatives that point into 436 CODE-VECTOR objects); it contains special support for finding 437 the containing CODE-VECTOR object and for adjusting all of 438 these "pc-locatives" if the containing object is moved in 439 memory. The first part of that - finding the containing 440 object - is possible and practical on the PPC because of 441 architectural artifacts (fixed-width instructions and arcana 442 of instruction encoding.) It's not possible on x86-64, but 443 fortunately not necessary either (though the second part - 444 adjusting the PC/RIP when the containing object moves) is both 445 necessary and simple.</para> 438 these special "pc-locatives" (locatives that point into 439 CODE-VECTOR objects); it contains special support for 440 finding the containing CODE-VECTOR object and for adjusting 441 all of these "pc-locatives" if the containing object is 442 moved in memory. The first part of that 443 operation—finding the containing object—is 444 possible and practical on the PPC because of architectural 445 artifacts (fixed-width instructions and arcana of 446 instruction encoding.) It's not possible on x86-64, but 447 fortunately not necessary either (though the second part - 448 adjusting the PC/RIP when the containing object moves) is 449 both necessary and simple.</para> 446 450 </sect2> 447 451 448 452 <sect2 id="Register-and-stack-usage-conventions"> 449 453 <title>Register and stack usage conventions</title> 450 454 451 455 <sect3 id="Stack-conventions"> 452 <title>Stack conventions</title>456 <title>Stack conventions</title> 453 457 <para>On both PPC and X86 platforms, each lisp thread uses 3 454 stacks; the ways in which these stacks are used differs455 between the PPC and X86.</para>458 stacks; the ways in which these stacks are used differs 459 between the PPC and X86.</para> 456 460 <para>Each thread has:</para> 457 <itemizedlist>461 <itemizedlist> 458 462 <listitem> 459 <para>A "control stack". On both platforms, this is460 "the stack" used by foreign code. On the PPC, it461 consists of a linked list of frames where the first word462 in each frame points to the first word in the previous463 frame (and the outermost frame points to 0.) Some464 frames on a PPC control stack are lisp frames; lisp465 frames are always 4 words in size and contain (in466 addition to the back pointer to the previous frame) the467 calling function (a node), the return address (a468 "locative" into the calling function's code-vector), and469 the value to which the value-stack pointer (see below)470 should be restored on function exit. On the PPC, the GC471 has to look at control-stack frames, identify which of472 those frames are lisp frames, and treat the contents of473 the saved function slot as a node (and handle the return474 address locative specially.) On x86-64, the control475 stack is used for dynamic-extent allocation of immediate476 objects. Since the control stack never contains nodes477 on x86-64, the GC ignores it on that platform.478 Alignment of the control stack follows the ABI479 conventions of the platform (at least at any point in480 time where foreign code could run.) On PPC, the r1481 register always points to the top of the current482 thread's control stack; on x86-64, the RSP register483 points to the top of the current thread's control stack484 when the thread is running foreign code and the address485 of the top of the control stack is kept in the thread's486 TCR (see <xref linkend="The-Thread-Context-Record"/>487 when not running foreign code. The control stack "grows488 down."</para>489 </listitem>463 <para>A "control stack". On both platforms, this is 464 "the stack" used by foreign code. On the PPC, it 465 consists of a linked list of frames where the first word 466 in each frame points to the first word in the previous 467 frame (and the outermost frame points to 0.) Some 468 frames on a PPC control stack are lisp frames; lisp 469 frames are always 4 words in size and contain (in 470 addition to the back pointer to the previous frame) the 471 calling function (a node), the return address (a 472 "locative" into the calling function's code-vector), and 473 the value to which the value-stack pointer (see below) 474 should be restored on function exit. On the PPC, the GC 475 has to look at control-stack frames, identify which of 476 those frames are lisp frames, and treat the contents of 477 the saved function slot as a node (and handle the return 478 address locative specially.) On x86-64, the control 479 stack is used for dynamic-extent allocation of immediate 480 objects. Since the control stack never contains nodes 481 on x86-64, the GC ignores it on that platform. 482 Alignment of the control stack follows the ABI 483 conventions of the platform (at least at any point in 484 time where foreign code could run.) On PPC, the r1 485 register always points to the top of the current 486 thread's control stack; on x86-64, the RSP register 487 points to the top of the current thread's control stack 488 when the thread is running foreign code and the address 489 of the top of the control stack is kept in the thread's 490 TCR (see <xref linkend="The-Thread-Context-Record"/> 491 when not running foreign code. The control stack "grows 492 down."</para> 493 </listitem> 490 494 <listitem> 491 <para>A "value stack". On both platforms, all values on 492 the value stack are nodes (including "tagged return 493 addresses" on x86-64.) The value stack is always 494 aligned to the native word size; objects are always 495 pushed on the value stack using atomic instructions 496 ("stwu"/"stdu" on PPC, "push" on x86-64), so the 497 contents of the value stack between its bottom and top 498 are always unambiguously nodes; the compiler usually 499 tries to pop or discard nodes from the value stack as 500 soon as possible after their last use (as soon as they 501 may have become garbage.) On x86-64, the RSP register 502 addresses the top of the value stack when running lisp 503 code; that address is saved in the TCR when running 504 foreign code. On the PPC, a dedicated register (VSP, 505 currently r15) is used to address the top of the value 506 stack when running lisp code, and the VSP value is saved 507 in the TCR when running foreign code. The value stack 508 grows down.</para> 509 </listitem> 510 <listitem> 511 <para>A "temp stack". The temp stack consists of a 512 linked list of frames, each of which points to the 513 previous temp stack frame. The number of native machine 514 words in each temp stack frame is always even, so the 515 temp stack is aligned on a two-word (64- or 128-bit) 516 boundary. The temp stack is used for dynamic-extent 517 objects on both platforms; on the PPC, it's used for 518 essentially all such objects (regardless of whether or 519 not the objects contain nodes); on the x86-64, immediate 520 dynamic-extent objects (strings, foreign pointers, etc.) 521 are allocated on the control stack and only 522 node-containing dynamic-extent objects are allocated on 523 the temp stack. Data structures used to implement CATCH 524 and UNWIND-PROTECT are stored on the temp stack on both 525 ppc and x86-64. Temp stack frames are always doublenode 526 aligned and objects within a temp stack frame are 527 aligned on doublenode boundaries. The first word in 528 each frame contains a back pointer to the previous 529 frame; on the PPC, the second word is used to indicate 530 to the GC whether the remaining objects are nodes (if 531 the second word is 0) or immediate (otherwise.) On 532 x86-64, where temp stack frames always contain nodes, 533 the second word is always 0. The temp stack grows down. 534 It usually takes several instructions to allocate and 535 safely initialize a temp stack frame that's intended to 536 contain nodes, and the GC has to recognize the case 537 where a thread is in the process of allocating and 538 initializing a temp stack frame and take care not to 539 interpret any uninitialized words in the frame as nodes. 540 See (someplace). The PPC keeps the current top of the 541 temp stack in a dedicated register (TSP, currently r12) 542 when running lisp code and saves this register's value 543 in the TCR when running foreign code. The x86-64 keeps 544 the address of the top of each thread's temp stack in 545 the thread's TCR.</para> 546 </listitem> 495 <para>A "value stack". On both platforms, all values on 496 the value stack are nodes (including "tagged return 497 addresses" on x86-64.) The value stack is always 498 aligned to the native word size; objects are always 499 pushed on the value stack using atomic instructions 500 ("stwu"/"stdu" on PPC, "push" on x86-64), so the 501 contents of the value stack between its bottom and top 502 are always unambiguously nodes; the compiler usually 503 tries to pop or discard nodes from the value stack as 504 soon as possible after their last use (as soon as they 505 may have become garbage.) On x86-64, the RSP register 506 addresses the top of the value stack when running lisp 507 code; that address is saved in the TCR when running 508 foreign code. On the PPC, a dedicated register (VSP, 509 currently r15) is used to address the top of the value 510 stack when running lisp code, and the VSP value is saved 511 in the TCR when running foreign code. The value stack 512 grows down.</para> 513 </listitem> 514 <listitem> 515 <para>A "temp stack". The temp stack consists of a 516 linked list of frames, each of which points to the 517 previous temp stack frame. The number of native 518 machine words in each temp stack frame is always even, 519 so the temp stack is aligned on a two-word (64- or 520 128-bit) boundary. The temp stack is used for 521 dynamic-extent objects on both platforms; on the PPC, 522 it's used for essentially all such objects (regardless 523 of whether or not the objects contain nodes); on the 524 x86-64, immediate dynamic-extent objects (strings, 525 foreign pointers, etc.) are allocated on the control 526 stack and only node-containing dynamic-extent objects 527 are allocated on the temp stack. Data structures used 528 to implement CATCH and UNWIND-PROTECT are stored on 529 the temp stack on both ppc and x86-64. Temp stack 530 frames are always doublenode aligned and objects 531 within a temp stack frame are aligned on doublenode 532 boundaries. The first word in each frame contains a 533 back pointer to the previous frame; on the PPC, the 534 second word is used to indicate to the GC whether the 535 remaining objects are nodes (if the second word is 0) 536 or immediate (otherwise.) On x86-64, where temp stack 537 frames always contain nodes, the second word is always 538 0. The temp stack grows down. It usually takes 539 several instructions to allocate and safely initialize 540 a temp stack frame that's intended to contain nodes, 541 and the GC has to recognize the case where a thread is 542 in the process of allocating and initializing a temp 543 stack frame and take care not to interpret any 544 uninitialized words in the frame as nodes. The PPC 545 keeps the current top of the temp stack in a dedicated 546 register (TSP, currently r12) when running lisp code 547 and saves this register's value in the TCR when 548 running foreign code. The x86-64 keeps the address of 549 the top of each thread's temp stack in the thread's 550 TCR.</para> 551 </listitem> 547 552 </itemizedlist> 548 553 </sect3> 549 554 550 555 <sect3 id="Register-conventions"> 551 <title>Register conventions</title>556 <title>Register conventions</title> 552 557 <para>If there are a "reasonable" (for some value of 553 "reasonable") number orgeneral-purpose registers and the554 instruction set is "reasonably" orthogonal (most555 instructions that operate on GPRs can operate on any GPR),556 then it's possible to statically partition the GPRs into at557 least two sets: "immediate registers" never contain nodes,558 and "node registers" always contain nodes. (On the PPC, a559 few registers are members of a third set of "PC locatives",560 and on both platforms some registers may have dedicated561 roles as stack or heap pointers; the latter class is treated562 as immediates by the GC proper but may be used to help563 determine the bounds of stack and heap memory areas.)</para>564 <para>The ultimate definition of register partitioning is565 hardwired into the GC in functions like "mark_xp()" and566 "forward_xp()", which process the values of some of the567 registers in an exception frame as nodes and may give some568 sort of special treatment to other register values they569 encounter there.)</para>558 "reasonable") number of general-purpose registers and the 559 instruction set is "reasonably" orthogonal (most 560 instructions that operate on GPRs can operate on any GPR), 561 then it's possible to statically partition the GPRs into at 562 least two sets: "immediate registers" never contain nodes, 563 and "node registers" always contain nodes. (On the PPC, a 564 few registers are members of a third set of "PC locatives", 565 and on both platforms some registers may have dedicated 566 roles as stack or heap pointers; the latter class is treated 567 as immediates by the GC proper but may be used to help 568 determine the bounds of stack and heap memory areas.)</para> 569 <para>The ultimate definition of register partitioning is 570 hardwired into the GC in functions like "mark_xp()" and 571 "forward_xp()", which process the values of some of the 572 registers in an exception frame as nodes and may give some 573 sort of special treatment to other register values they 574 encounter there.)</para> 570 575 <para>On x86-64, the static register partitioning scheme involves:</para> 571 <itemizedlist>576 <itemizedlist> 572 577 <listitem> 573 <para>(only) three "immediate" registers.</para>574 <para>The RAX, RCX, and RDX registers are used as the575 implicit operands and results of some extended-precision576 multiply and divide instructions which generally involve577 non-node values; since their use in these instructions578 means that they can't be guaranteed to contain node579 values at all times, it's natural to put these registers580 in the "immediate" set. RAX is generally given the581 symbolic name "imm0", RDX is given the symbolic name582 "imm1" and RCX is given the symbolic name "imm2"; you583 may see these names in disassembled code, usually in584 operations involving type checking, array indexing, and585 foreign memory and function access.</para>586 </listitem>578 <para>(only) three "immediate" registers.</para> 579 <para>The RAX, RCX, and RDX registers are used as the 580 implicit operands and results of some extended-precision 581 multiply and divide instructions which generally involve 582 non-node values; since their use in these instructions 583 means that they can't be guaranteed to contain node 584 values at all times, it's natural to put these registers 585 in the "immediate" set. RAX is generally given the 586 symbolic name "imm0", RDX is given the symbolic name 587 "imm1" and RCX is given the symbolic name "imm2"; you 588 may see these names in disassembled code, usually in 589 operations involving type checking, array indexing, and 590 foreign memory and function access.</para> 591 </listitem> 587 592 <listitem> 588 <para>(only) two "dedicated" registers.</para>589 <para>RSP and RBP have590 dedicated functionality dictated by the hardware and591 calling conventions.</para>592 </listitem>593 <para>(only) two "dedicated" registers.</para> 594 <para>RSP and RBP have 595 dedicated functionality dictated by the hardware and 596 calling conventions.</para> 597 </listitem> 593 598 <listitem> 594 <para>11 "node" registers.</para> 595 <para>All other registers (RBX, RSI, RDI, and R8-R15) 596 are asserted to contain node values at (almost) all 597 times; legacy "string" operations that implicitly use RSI 598 and/or RDI are not used.</para> 599 </listitem> 600 </itemizedlist> 599 <para>11 "node" registers.</para> 600 <para>All other registers (RBX, RSI, RDI, and R8-R15) 601 are asserted to contain node values at (almost) all 602 times; legacy "string" operations that implicitly use RSI 603 and/or RDI are not used.</para> 604 </listitem> 605 </itemizedlist> 606 601 607 <para>On the PPC, the static register partitioning scheme 602 involves:</para> 603 604 <itemizedlist> 608 involves:</para> 609 <itemizedlist> 605 610 <listitem> 606 <para>6 "immediate" registers.</para>607 <para>Registers r3-r8 are given608 the symbolic names imm0-imm5. As a RISC architecture609 with simpler addressing modes, the PPC probably610 uses immediate registers a bit more often than the CISC611 x86-64 does, but they're generally used for the same sort612 of things (type checking, array indexing, FFI,613 etc.)</para>614 </listitem>615 <listitem>616 <para>9 dedicated registers617 <itemizedlist>618 <listitem>619 <para>r0 (symbolic name rzero) always contains the620 value 0 when running lisp code. Its value is621 sometimes read as 0 when it's used as the base622 register in a memory address; keeping the value 0623 there is sometimes convenient and avoids624 asymmetry.</para>625 </listitem>626 <listitem>627 <para>r1 (symbolic name sp) is the control stack628 pointer, by PPC convention.</para>629 </listitem>630 <listitem>631 <para>r2 is used to hold the current thread's TCR on632 ppc64 systems; it's not used on ppc32.</para>633 </listitem>634 <listitem>635 <para>r9 and r10 (symbolic names allocptr and636 allocbase) are used to do per-thread memory637 allocation</para>638 </listitem>639 <listitem>640 <para>r11 (symbolic name nargs) contains the number641 of function arguments on entry and the number of642 return values in multiple-value returning643 constructs. It's not used more generally as either644 a node or immediate register because of the way that645 certain trap instruction encodings are646 interpreted.</para>647 </listitem>648 <listitem>649 <para>r12 (symbolic name tsp) holds the top of the650 current thread's temp stack.</para>651 </listitem>652 <listitem>653 <para>r13 is used to hold the TCR on PPC32 systems;654 it's not used on PPC64.</para>655 </listitem>656 <listitem>657 <para>r14 (symbolic name loc-pc) is used to copy658 "pc-locative" values between main memory and659 special-purpose PPC registers (LR and CTR) used in660 function-call and return instructions.</para>661 </listitem>662 <listitem>663 <para>r15 (symbolic name vsp) addresses the top of664 the current thread's value stack.</para>665 </listitem>666 <listitem>667 <para>lr and ctr are PPC branch-unit registers used668 in function call and return instructions; they're669 always treated as "pc-locatives", which precludes670 the use of the ctr in some PPC looping671 constructs.</para>672 </listitem>673 674 </itemizedlist>675 </para>676 </listitem>611 <para>6 "immediate" registers.</para> 612 <para>Registers r3-r8 are given 613 the symbolic names imm0-imm5. As a RISC architecture 614 with simpler addressing modes, the PPC probably 615 uses immediate registers a bit more often than the CISC 616 x86-64 does, but they're generally used for the same sort 617 of things (type checking, array indexing, FFI, 618 etc.)</para> 619 </listitem> 620 <listitem> 621 <para>9 dedicated registers 622 <itemizedlist> 623 <listitem> 624 <para>r0 (symbolic name rzero) always contains the 625 value 0 when running lisp code. Its value is 626 sometimes read as 0 when it's used as the base 627 register in a memory address; keeping the value 0 628 there is sometimes convenient and avoids 629 asymmetry.</para> 630 </listitem> 631 <listitem> 632 <para>r1 (symbolic name sp) is the control stack 633 pointer, by PPC convention.</para> 634 </listitem> 635 <listitem> 636 <para>r2 is used to hold the current thread's TCR on 637 ppc64 systems; it's not used on ppc32.</para> 638 </listitem> 639 <listitem> 640 <para>r9 and r10 (symbolic names allocptr and 641 allocbase) are used to do per-thread memory 642 allocation</para> 643 </listitem> 644 <listitem> 645 <para>r11 (symbolic name nargs) contains the number 646 of function arguments on entry and the number of 647 return values in multiple-value returning 648 constructs. It's not used more generally as either 649 a node or immediate register because of the way that 650 certain trap instruction encodings are 651 interpreted.</para> 652 </listitem> 653 <listitem> 654 <para>r12 (symbolic name tsp) holds the top of the 655 current thread's temp stack.</para> 656 </listitem> 657 <listitem> 658 <para>r13 is used to hold the TCR on PPC32 systems; 659 it's not used on PPC64.</para> 660 </listitem> 661 <listitem> 662 <para>r14 (symbolic name loc-pc) is used to copy 663 "pc-locative" values between main memory and 664 special-purpose PPC registers (LR and CTR) used in 665 function-call and return instructions.</para> 666 </listitem> 667 <listitem> 668 <para>r15 (symbolic name vsp) addresses the top of 669 the current thread's value stack.</para> 670 </listitem> 671 <listitem> 672 <para>lr and ctr are PPC branch-unit registers used 673 in function call and return instructions; they're 674 always treated as "pc-locatives", which precludes 675 the use of the ctr in some PPC looping 676 constructs.</para> 677 </listitem> 678 679 </itemizedlist> 680 </para> 681 </listitem> 677 682 <listitem> 678 <para>17 "node" registers</para>679 <para>r15-r31 are always treated as node680 registers</para>681 </listitem>682 683 <para>17 "node" registers</para> 684 <para>r15-r31 are always treated as node 685 registers</para> 686 </listitem> 687 683 688 </itemizedlist> 684 689 </sect3> … … 686 691 687 692 <sect2 id="Tagging-scheme"> 688 <title>Tagging scheme</title>693 <title>Tagging scheme</title> 689 694 <para>&CCL; always allocates lisp objects on double-node 690 (64-bit for 32-bit platforms, 128-bit for 64-bit platforms)691 boundaries; this mean that the low 3 bits (32-bit lisp) or 4692 bits (64-bit lisp) are always 0 and are therefore redundant693 (we only really need to know the upper 29 or 60 bits in order694 to identify the aligned object address.) The extra bits in a695 lisp node can be used to encode at least some information696 about the node's type, and the other 29/60 bits represent697 either an immediate value or a doublenode-aligned memory698 address. The low 3 or 4 bits of a node are called the node's699 "tag bits", and the conventions used to encode type700 information in those tag bits are called a "tagging701 scheme."</para>695 (64-bit for 32-bit platforms, 128-bit for 64-bit platforms) 696 boundaries; this mean that the low 3 bits (32-bit lisp) or 4 697 bits (64-bit lisp) are always 0 and are therefore redundant 698 (we only really need to know the upper 29 or 60 bits in order 699 to identify the aligned object address.) The extra bits in a 700 lisp node can be used to encode at least some information 701 about the node's type, and the other 29/60 bits represent 702 either an immediate value or a doublenode-aligned memory 703 address. The low 3 or 4 bits of a node are called the node's 704 "tag bits", and the conventions used to encode type 705 information in those tag bits are called a "tagging 706 scheme."</para> 702 707 <para>It might be possible to use the same tagging scheme on 703 all platforms (at least on all platforms with the same word704 size and/or the same number of available tag bits), but there705 are often some strong reasons for not doing so. These706 arguments tend to be very machine-specific: sometimes, there707 are fairly obvious machine-dependent tricks that can be708 exploited to make common operations on some types of tagged709 objects faster; other times, there are architectural710 restrictions that make it impractical to use certain tags for711 certain types. (On PPC64, the "ld" (load doubleword) and712 "std" (store doubleword) instructions - which load and store a713 GPR operand at the effective address formed by adding the714 value of another GPR operand and a 16-bit constant operand -715 require that the low two bits of that constant operand be 0.716 Since such instructions would typically be used to access the717 fields of things like CONS cells and structures, it's718 desirable that that the tags chosen for CONS cells and719 structures allow the use of these instructions as opposed to720 more expensive alternatives.)</para>708 all platforms (at least on all platforms with the same word 709 size and/or the same number of available tag bits), but there 710 are often some strong reasons for not doing so. These 711 arguments tend to be very machine-specific: sometimes, there 712 are fairly obvious machine-dependent tricks that can be 713 exploited to make common operations on some types of tagged 714 objects faster; other times, there are architectural 715 restrictions that make it impractical to use certain tags for 716 certain types. (On PPC64, the "ld" (load doubleword) and 717 "std" (store doubleword) instructions - which load and store a 718 GPR operand at the effective address formed by adding the 719 value of another GPR operand and a 16-bit constant operand - 720 require that the low two bits of that constant operand be 0. 721 Since such instructions would typically be used to access the 722 fields of things like CONS cells and structures, it's 723 desirable that that the tags chosen for CONS cells and 724 structures allow the use of these instructions as opposed to 725 more expensive alternatives.)</para> 721 726 <para>One architecture-dependent tagging trick that works well 722 on all architectures is to use a tag of 0 for FIXNUMs: a 723 fixnum basically encodes its value shifted left a few bits and 724 keeps those low bits clear. FIXNUM addition, subtraction, and 725 binary logical operations can operate directly on the node 726 operands, addition and subtraction can exploit hardware-based 727 overflow detection, and (in the absence of overflow) the 728 hardware result of those operations is a node (fixnum). Some 729 other slightly-less-common operations may require a few extra 730 instructions, but arithmetic operations on FIXNUMs should be 731 as cheap as possible and using a tag of zero for FIXNUMs helps 732 to ensure that it will be.</para> 733 <para>If we have N available tag bits (N = 3 for 32-bit 734 &CCL; and N = 4 for 64-bit &CCL;), this way of 735 representing fixnums with the low M bits forced to 0 works as 736 long as M <= N. The smaller we make M, the larger the 737 values of MOST-POSITIVE-FIXNUM and MOST-NEGATIVE become; the 738 larger we make N, the more distinct non-FIXNUM tags become 739 available. A reasonable compromise is to choose M = N-1; this 740 basically yields two distinct FIXNUM tags (one for even 741 fixnums, one for odd fixnums), gives 30-bit fixnums on 32-bit 742 platforms and 61-bit fixnums on 64-bit platforms, and leaves 743 us with 6 or 14 tags to encoded other types.</para> 727 on all architectures is to use a tag of 0 for FIXNUMs: a 728 fixnum basically encodes its value shifted left a few bits 729 and keeps those low bits clear. FIXNUM addition, 730 subtraction, and binary logical operations can operate 731 directly on the node operands, addition and subtraction can 732 exploit hardware-based overflow detection, and (in the 733 absence of overflow) the hardware result of those operations 734 is a node (fixnum). Some other slightly-less-common 735 operations may require a few extra instructions, but 736 arithmetic operations on FIXNUMs should be as cheap as 737 possible and using a tag of zero for FIXNUMs helps to ensure 738 that it will be.</para> 739 <para>If we have N available tag bits (N = 3 for 32-bit &CCL; 740 and N = 4 for 64-bit &CCL;), this way of representing 741 fixnums with the low M bits forced to 0 works as long as M 742 <= N. The smaller we make M, the larger the values of 743 MOST-POSITIVE-FIXNUM and MOST-NEGATIVE become; the larger we 744 make N, the more distinct non-FIXNUM tags become available. 745 A reasonable compromise is to choose M = N-1; this basically 746 yields two distinct FIXNUM tags (one for even fixnums, one 747 for odd fixnums), gives 30-bit fixnums on 32-bit platforms 748 and 61-bit fixnums on 64-bit platforms, and leaves us with 6 749 or 14 tags to encoded other types.</para> 744 750 <para>Once we get past the assignment of FIXNUM tags, things 745 quickly devolve into machine-dependencies. We can fairly 746 easily see that we can't directly all other primitive lisp 747 object types with only 6 or 14 available tag values; the 748 details of how types are encoded vary between the ppc32, 749 ppc64, and x86-64 implementations, but there are some general 750 common principles:</para> 751 752 <itemizedlist> 753 <listitem> 754 <para>CONS cells always contain exactly 2 elements and are 755 usually fairly common.It therefore makes sense to give 756 CONS cells their own tag. Unlike the fixnum case - where a 757 tag value of 0 had positive implications - there doesn't 758 seem to be any advantage to using any particular value. 759 (A longtime ago - in the case of 68K MCL - the CONS tag 760 and the order of CAR and CDR in memory were chosen to allow 761 smaller, cheaper addressing modes to be used to "cdr down a 762 list." That's not a factor on ppc or x86-64,but all 763 versions of &CCL; still store the CDR of a CONS cell 764 first in memory. It doesn't matter, but doing it the way 765 that the host system did made boostrapping to a new target 766 system a little easier.) 767 </para> 768 </listitem> 769 <listitem> 770 <para>Any way you look at it, NIL is a bit ... unusual. NIL 771 is both a SYMBOL and a LIST (as well as being a canonical 772 truth value and probably a few other things.) Its role as 773 a LIST is probably much more important to most programs 774 than its role as a SYMBOL is:LISTP has to be true of NIL 775 and primitives like CAR and CDR do LISTP implicitly when 776 safe and want that operation to be fast.There are several 777 possible approaches to this; &CCL; uses two of them. On 778 PPC32 and X86-64, NIL is basically a weird CONS cell that 779 straddles two doublenodes; the tag of NIL is unique and 780 congruent modulo 4 (modulo 8 on 64-bit) with the tag used 781 for CONS cells. LISTP is therefore true of any node whose 782 low 2 (or 3) bits contain the appropriate tag value (it's 783 not otherwise necessary to special-case NIL.) 784 SYMBOL accessors (SYMBOL-NAME, SYMBOL-VALUE, SYMBOL-PLIST 785 ..) -do- have to special-case NIL (and access the 786 components of an internal proxy symbol.) On PPC64 (where 787 architectural restrictions dictate the set of tags that can 788 be used to access fixed components of an object), 789 that approach wasn't practical. NIL is just a 790 distinguished SYMBOL,and it just happens to be the case 791 that its pname slot and values lots are at the same offsets 792 from a tagged pointer as a CONS cell's CDR and CAR would be. 793 NIL's pname is set to NIL (SYMBOL-NAME checks for this and 794 returns the string "NIL"), and LISTP (and therefore safe 795 CAR and CDR) have to check for (OR NULL CONSP). At least in 796 the case of CAR and CDR, the fact that the PPC has multiple 797 condition-code fields keeps that extra test from 798 being prohibitively expensive.</para> 799 </listitem> 800 <listitem> 801 <para>Some objects are immediate (but not FIXNUMs).This is 802 true of CHARACTERs and, on 64-bit platforms, 803 SINGLE-FLOATs.It's also true of some nodes used in the 804 runtime system (special values used to indicate unbound 805 variables and slots, for instance.) On 64-bit platforms, 806 SINGLE-FLOATs have their own unique tag (making them a 807 little easier to recognize; on all platforms, CHARACTERs 808 share a tag with other immediate objects (unbound markers) 809 but are easy to recognize (by looking at several of their 810 low bits.) The GC treats any node with an immediate tag 811 (and any node with a fixnum tag) as a leaf.</para> 812 </listitem> 751 quickly devolve into machine-dependencies. We can fairly 752 easily see that we can't directly tag all other primitive 753 lisp object types with only 6 or 14 available tag values; 754 the details of how types are encoded vary between the ppc32, 755 ppc64, and x86-64 implementations, but there are some 756 general common principles:</para> 757 758 <itemizedlist> 759 <listitem> 760 <para>CONS cells always contain exactly 2 elements and are 761 usually fairly common.It therefore makes sense to give 762 CONS cells their own tag. Unlike the fixnum case - 763 where a tag value of 0 had positive implications - there 764 doesn't seem to be any advantage to using any particular 765 value. (A longtime ago - in the case of 68K MCL - the 766 CONS tag and the order of CAR and CDR in memory were 767 chosen to allow smaller, cheaper addressing modes to be 768 used to "cdr down a list." That's not a factor on ppc 769 or x86-64, but all versions of &CCL; still store the CDR 770 of a CONS cell first in memory. It doesn't matter, but 771 doing it the way that the host system did made 772 boostrapping to a new target system a little easier.) 773 </para> 774 </listitem> 775 <listitem> 776 <para>Any way you look at it, NIL is a bit 777 ... unusual. NIL is both a SYMBOL and a LIST (as well as 778 being a canonical truth value and probably a few other 779 things.) Its role as a LIST is probably much more 780 important to most programs than its role as a SYMBOL is: 781 LISTP has to be true of NIL and primitives like CAR and 782 CDR do LISTP implicitly when safe and want that 783 operation to be fast. There are several possible 784 approaches to this problem; &CCL; uses two of them. On 785 PPC32 and X86-64, NIL is basically a weird CONS cell 786 that straddles two doublenodes; the tag of NIL is unique 787 and congruent modulo 4 (modulo 8 on 64-bit) with the tag 788 used for CONS cells. LISTP is therefore true of any 789 node whose low 2 (or 3) bits contain the appropriate tag 790 value (it's not otherwise necessary to special-case 791 NIL.) SYMBOL accessors (SYMBOL-NAME, SYMBOL-VALUE, 792 SYMBOL-PLIST ..) -do- have to special-case NIL (and 793 access the components of an internal proxy symbol.) On 794 PPC64 (where architectural restrictions dictate the set 795 of tags that can be used to access fixed components of 796 an object), that approach wasn't practical. NIL is just 797 a distinguished SYMBOL,and it just happens to be the 798 case that its pname slot and values slot are at the same 799 offsets from a tagged pointer as a CONS cell's CDR and 800 CAR would be. NIL's pname is set to NIL (SYMBOL-NAME 801 checks for this and returns the string "NIL"), and LISTP 802 (and therefore safe CAR and CDR) has to check for (OR 803 NULL CONSP). At least in the case of CAR and CDR, the 804 fact that the PPC has multiple condition-code fields 805 keeps that extra test from being prohibitively 806 expensive.</para> 807 </listitem> 808 <listitem> 809 <para>Some objects are immediate (but not FIXNUMs). This 810 is true of CHARACTERs and, on 64-bit platforms, 811 SINGLE-FLOATs. It's also true of some nodes used in the 812 runtime system (special values used to indicate unbound 813 variables and slots, for instance.) On 64-bit platforms, 814 SINGLE-FLOATs have their own unique tag (making them a 815 little easier to recognize; on all platforms, CHARACTERs 816 share a tag with other immediate objects (unbound 817 markers) but are easy to recognize (by looking at 818 several of their low bits.) The GC treats any node with 819 an immediate tag (and any node with a fixnum tag) as a 820 leaf.</para> 821 </listitem> 813 822 <listitem> 814 <para>There are some advantages to treating everything 815 else - memory-allocated objects that aren't CONS cells - 816 uniformly.There are some disadvantages to that uniform 817 treatment as well, and the treatment of "memory-allocated 818 non-CONS objects" isn't entirely uniform across all 819 &CCL; implementations. Let's first pretend that 820 the treatment is uniform, then discuss the ways in which it 821 isn't.The "uniform approach" is to treat all 822 memory-allocated non-CONS objects as if they were vectors; 823 this use of the term is a little looser than what's implied 824 by the CL VECTOR type. &CCL; actually uses the 825 term "uvector" to mean "a memory-allocated lisp object 826 other than a CONS cell,whose first word is a header which 827 describes the object's type and the number of elements that 828 it contains." In this view, a SYMBOL is a UVECTOR, as is a 829 STRING, a STANDARD-INSTANCE, a CL array or vector,a 830 FUNCTION, and even a DOUBLE-FLOAT.In the PPC 831 implementations (where things are a little more 832 ... uniform),a single tag value is used to denote any 833 uvector; in order to determine something more specific 834 about the type of the object in question, it's necessary to 835 fetch the low byte of the header word from memory. On 836 the x86-64 platform, certain types of uvectors - SYMBOLs 837 and FUNCTIONs -are given their own unique tags. The good 838 news about the x86-64 approach is that SYMBOLs and 839 FUNCTIONs can be recognized without referencing memory; the 840 slightly bad news is that primitive operations that work on 841 UVECTOR-tagged objects - like the function CCL:UVREF - 842 don't work on SYMBOLs or FUNCTIONs on x86-64 (but -do- work 843 on those types of objects in the PPC ports.) The header word 844 which precedes a UVECTOR's data in memory contains 8 bits 845 of type information in the low byte and either 24 or 56 846 bits of"element-count" information in the rest of the 847 word. (This is where the sometimes-limiting value of 2^24 848 for ARRAY-TOTAL-SIZE-LIMIT on PPC32 platforms comes from.) 849 The low byte of the header - sometimes called the uvector's 850 subtag - is itself tagged (which means that the header is 851 tagged.) The (3 or 4) tag bits in the subtag are used to 852 determine whether the uvector's elements are nodes or 853 immediates.(A UVECTOR whose elements are nodes is called a 854 GVECTOR; a UVECTOR whose elements are immediates is called 855 an IVECTOR. This terminology came from Spice Lisp, which 856 was a predecessor of CMUCL.) Even though a uvector header 857 is tagged, a header is not a node. There's no (supported) 858 way to get your hands on one in lisp and doing so could be 859 dangerous. (If the value of a header wound up in a lisp 860 node register and that register wound up getting pushed on 861 a thread's value stack, the GC might misinterpret that 862 situation to mean that there was a stack-allocated UVECTOR 863 on the value stack.)</para> 864 </listitem> 865 866 </itemizedlist> 823 <para>There are some advantages to treating everything 824 else—memory-allocated objects that aren't CONS 825 cells—uniformly.There are some disadvantages to 826 that uniform treatment as well, and the treatment of 827 "memory-allocated non-CONS objects" isn't entirely 828 uniform across all &CCL; implementations. Let's first 829 pretend that the treatment is uniform, then discuss the 830 ways in which it isn't.The "uniform approach" is to 831 treat all memory-allocated non-CONS objects as if they 832 were vectors; this use of the term is a little looser 833 than what's implied by the CL VECTOR type. &CCL; 834 actually uses the term "uvector" to mean "a 835 memory-allocated lisp object other than a CONS cell, 836 whose first word is a header that describes the object's 837 type and the number of elements that it contains." In 838 this view, a SYMBOL is a UVECTOR, as is a STRING, a 839 STANDARD-INSTANCE, a CL array or vector, a FUNCTION, and 840 even a DOUBLE-FLOAT. In the PPC implementations (where 841 things are a little more ... uniform), a single tag 842 value is used to denote any uvector; in order to 843 determine something more specific about the type of the 844 object in question, it's necessary to fetch the low byte 845 of the header word from memory. On the x86-64 platform, 846 certain types of uvectors - SYMBOLs and FUNCTIONs -are 847 given their own unique tags. The good news about the 848 x86-64 approach is that SYMBOLs and FUNCTIONs can be 849 recognized without referencing memory; the slightly bad 850 news is that primitive operations that work on 851 UVECTOR-tagged objects—like the function 852 CCL:UVREF—don't work on SYMBOLs or FUNCTIONs on 853 x86-64 (but -do- work on those types of objects in the 854 PPC ports.) The header word that precedes a UVECTOR's 855 data in memory contains 8 bits of type information in 856 the low byte and either 24 or 56 bits of "element-count" 857 information in the rest of the word. (This is where the 858 sometimes-limiting value of 2^24 for 859 ARRAY-TOTAL-SIZE-LIMIT on PPC32 platforms comes from.) 860 The low byte of the header—sometimes called the 861 uvector's subtag—is itself tagged (which means 862 that the header is tagged.) The (3 or 4) tag bits in 863 the subtag are used to determine whether the uvector's 864 elements are nodes or immediates. (A UVECTOR whose 865 elements are nodes is called a GVECTOR; a UVECTOR whose 866 elements are immediates is called an IVECTOR. This 867 terminology came from Spice Lisp, which was a 868 predecessor of CMUCL.) Even though a uvector header is 869 tagged, a header is not a node. There's no (supported) 870 way to get your hands on one in lisp and doing so could 871 be dangerous. (If the value of a header wound up in a 872 lisp node register and that register wound up getting 873 pushed on a thread's value stack, the GC might 874 misinterpret that situation to mean that there was a 875 stack-allocated UVECTOR on the value stack.)</para> 876 </listitem> 877 878 </itemizedlist> 867 879 </sect2> 868 880 </sect1> … … 870 882 <sect1 id="Heap-Allocation"> 871 883 <title>Heap Allocation</title> <para>When the &CCL; kernel first 872 starts up, a large contiguous chunk of the process's address 873 space is mapped as "anonymous, no access" memory. ("Large" means 874 different things in different contexts; on LinuxPPC32, it means 875 "about 1 gigabyte", on DarwinPPC32, it means "about 2 876 gigabytes", and on current 64-bit platforms it ranges from 128 877 to 512 gigabytes, depending on OS. These values are both 878 defaults and upper limits; the --heap-reserve argument can be 879 used to try to reserve less than the default.)</para> 884 starts up, a large contiguous chunk of the process's address 885 space is mapped as "anonymous, no access" memory. ("Large" 886 means different things in different contexts; on LinuxPPC32, 887 it means "about 1 gigabyte", on DarwinPPC32, it means "about 2 888 gigabytes", and on current 64-bit platforms it ranges from 128 889 to 512 gigabytes, depending on OS. These values are both 890 defaults and upper limits; 891 the <literal>--heap-reserve</literal> argument can be used to 892 try to reserve less than the default.)</para> 880 893 <para>Reserving address space that can't (yet) be read or 881 written to doesn't cost much; in particular, it doesn't require882 that corresponding swap space or physical memory be available.883 Marking the address range as being "mapped" helps to ensure that884 other things (results from random calls to malloc(), dynamically885 loaded shared libraries) won't be allocated in this region that886 lisp has reserved for its own heap growth.</para>894 written to doesn't cost much; in particular, it doesn't require 895 that corresponding swap space or physical memory be available. 896 Marking the address range as being "mapped" helps to ensure that 897 other things (results from random calls to malloc(), dynamically 898 loaded shared libraries) won't be allocated in this region that 899 lisp has reserved for its own heap growth.</para> 887 900 <para>A small portion (around 1/32 on 32-bit platforms and 1/64 888 on 64-bit platforms) of that large chunk of address space is889 reserved for GC data structures. Memory pages reserved for890 these data structures are mapped read-write as pagesmade891 writable in the main portion of the heap.</para>901 on 64-bit platforms) of that large chunk of address space is 902 reserved for GC data structures. Memory pages reserved for 903 these data structures are mapped read-write as pages are made 904 writable in the main portion of the heap.</para> 892 905 <para>The initial heap image is mapped into this reserved 893 address space and an additional (LISP-HEAP-GC-THRESHOLD) bytes894 are mapped read-write. GC data structures grow to match the895 amount of GC-able memory in the initial image +the gc896 threshold, and control is transferred to lisp code. Inevitably,897 that code spoils everything and starts consing; there are898 basically three layers of memory allocation that can go899 on.</para>906 address space and an additional (LISP-HEAP-GC-THRESHOLD) bytes 907 are mapped read-write. GC data structures grow to match the 908 amount of GC-able memory in the initial image plus the gc 909 threshold, and control is transferred to lisp code. 910 Inevitably, that code spoils everything and starts consing; 911 there are basically three layers of memory allocation that can 912 go on.</para> 900 913 901 914 <sect2 id="Per-thread-object-allocation"> 902 <title>Per-thread object allocation</title>915 <title>Per-thread object allocation</title> 903 916 <para>Each lisp thread has a private "reserved memory 904 segment"; when a thread starts up, its reserved memory segment905 is empty. PPC ports maintain the highest unallocated address906 and the lowest allocatable address in the current segment in907 registers when running lisp code; on x86-664, these values are908 maintained in the current threads's TCR. (An "empty" heap909 segment is one whose high pointer and low pointer are equal.)910 When a thread is not in the middle of allocating something, the911 low 3 or 4 bits of the high and low pointers are clear (the912 pointers are doublenode-aligned.)</para>917 segment"; when a thread starts up, its reserved memory segment 918 is empty. PPC ports maintain the highest unallocated address 919 and the lowest allocatable address in the current segment in 920 registers when running lisp code; on x86-664, these values are 921 maintained in the current threads's TCR. (An "empty" heap 922 segment is one whose high pointer and low pointer are equal.) 923 When a thread is not in the middle of allocating something, the 924 low 3 or 4 bits of the high and low pointers are clear (the 925 pointers are doublenode-aligned.)</para> 913 926 <para>A thread tries to allocate an object whose physical size 914 in bytes is X and whose tag is Y by:</para>915 <orderedlist>916 <listitem>917 <para>decrementing the "high" pointer by (- X Y)</para>918 </listitem>919 <listitem>920 <para>trapping if the high pointer is less than the low921 pointer</para>922 </listitem>923 <listitem>924 <para>using the (tagged) high pointer to initialize the925 object, if necessary</para>926 </listitem>927 <listitem>928 <para>clearing the low bits of the high pointer</para>929 </listitem>930 </orderedlist>927 in bytes is X and whose tag is Y by:</para> 928 <orderedlist> 929 <listitem> 930 <para>decrementing the "high" pointer by (- X Y)</para> 931 </listitem> 932 <listitem> 933 <para>trapping if the high pointer is less than the low 934 pointer</para> 935 </listitem> 936 <listitem> 937 <para>using the (tagged) high pointer to initialize the 938 object, if necessary</para> 939 </listitem> 940 <listitem> 941 <para>clearing the low bits of the high pointer</para> 942 </listitem> 943 </orderedlist> 931 944 <para>On PPC32, where the size of a CONS cell is 8 bytes and 932 the tag of a CONS cell is 1, machine code which sets the arg_z933 register to the result of doing (CONS arg_y arg_z) looks934 like:</para>945 the tag of a CONS cell is 1, machine code which sets the arg_z 946 register to the result of doing (CONS arg_y arg_z) looks 947 like:</para> 935 948 <programlisting> 936 949 (SUBI ALLOCPTR ALLOCPTR 7) ; decrement the high pointer by (- 8 1) … … 940 953 (MR ARG_Z ALLOCPTR) ; arg_z is the new CONS cell 941 954 (RLWINM ALLOCPTR ALLOCPTR 0 0 28) ; clear tag bits 942 </programlisting>943 <para>On x86-64, the idea's similar but the implementation is944 different. The high and low pointers to the current thread's945 reserved segment are kept in the TCR, which is addressed by946 the gs segment register. An x86-64 CONS cell is 16 bytes wide947 and has a tag of 3; we canonically use the temp0 register to948 initialize the object</para>955 </programlisting> 956 <para>On x86-64, the idea's similar but the implementation is 957 different. The high and low pointers to the current thread's 958 reserved segment are kept in the TCR, which is addressed by 959 the gs segment register. An x86-64 CONS cell is 16 bytes wide 960 and has a tag of 3; we canonically use the temp0 register to 961 initialize the object</para> 949 962 <programlisting> 950 963 (subq ($ 13) ((% gs) 216)) ; decrement allocptr … … 958 971 (movq (% arg_z) (-3 (% temp0))); set the cdr 959 972 (movq (% temp0) (% arg_z)) ; return the cons 960 </programlisting>973 </programlisting> 961 974 <para>If we don't take the trap (if allocating 8-16 bytes 962 doesn't exhaust the thread's reserved memory segment), that's963 a fairly short and simple instruction sequence. If we do take964 the trap, we'll have to do some additional work in order to965 get a new segment for the current thread.</para>975 doesn't exhaust the thread's reserved memory segment), that's 976 a fairly short and simple instruction sequence. If we do take 977 the trap, we'll have to do some additional work in order to 978 get a new segment for the current thread.</para> 966 979 </sect2> 967 980 968 981 <sect2 id="Allocation-of-reserved-heap-segments"> 969 <title>Allocation of reserved heap segments</title>982 <title>Allocation of reserved heap segments</title> 970 983 <para>After the lisp image is first mapped into memory - and after 971 each full GC - the lisp kernel ensures that972 (LISP-HEAP-GC-TRESHOLD) additional bytes beyond the current973 end of the heap are mapped read-write.</para>984 each full GC - the lisp kernel ensures that 985 (LISP-HEAP-GC-TRESHOLD) additional bytes beyond the current 986 end of the heap are mapped read-write.</para> 974 987 <para>If a thread traps while trying to allocate memory, the 975 thread goes through the usual exception-handling protocol (to976 ensure that any other thread that GCs "sees" the state of the977 trapping thread and to serialize exception handling.) When978 the exception handler runs, it determines the nature and size979 of the failed allocation and tries to complete the allocation980 on the thread's behalf (and leave it with a reasonably large981 thread-specific memory segment so that the next small982 allocation is unlikely to trap.</para>988 thread goes through the usual exception-handling protocol (to 989 ensure that any other thread that GCs "sees" the state of the 990 trapping thread and to serialize exception handling.) When 991 the exception handler runs, it determines the nature and size 992 of the failed allocation and tries to complete the allocation 993 on the thread's behalf (and leave it with a reasonably large 994 thread-specific memory segment so that the next small 995 allocation is unlikely to trap.</para> 983 996 <para>Depending on the size of the requested segment 984 allocation, the number of segment allocations that have985 occurred since the last GC, and the EGC and GC thresholds, the986 segment allocation trap handler may invoke a full or ephemeral987 GC before returning a new segment. It's worth noting that the988 [E]GC is triggered based on the number of and size of these989 segments that have been allocated since the last GC; it doesn't990 have much to do with how "full" each of those per-thread991 segments are. It's possible for a large number of threads to992 do fairly incidental memory allocation and trigger the GC as a993 result; avoiding this involves tuning the per-thread994 allocation quantum and the GC/EGC thresholds995 appropriately.</para>997 allocation, the number of segment allocations that have 998 occurred since the last GC, and the EGC and GC thresholds, the 999 segment allocation trap handler may invoke a full or ephemeral 1000 GC before returning a new segment. It's worth noting that the 1001 [E]GC is triggered based on the number of and size of these 1002 segments that have been allocated since the last GC; it doesn't 1003 have much to do with how "full" each of those per-thread 1004 segments are. It's possible for a large number of threads to 1005 do fairly incidental memory allocation and trigger the GC as a 1006 result; avoiding this involves tuning the per-thread 1007 allocation quantum and the GC/EGC thresholds 1008 appropriately.</para> 996 1009 </sect2> 997 1010 998 1011 <sect2 id="Heap-growth"> 999 <title>Heap growth</title>1012 <title>Heap growth</title> 1000 1013 <para>All OSes on which &CCL; currently runs use an 1001 "overcommit" memory allocation strategy by default (though1002 some of them provide ways of overriding that default.) What1003 this means in general is that the OS doesn't necessarily1004 ensure that backing store is available when asked to map pages1005 as read-write; it'll often return a success indicator from the1006 mapping attempt (mapping the pages as "zero-fill,1007 copy-on-write"), and only try to allocate the backing store1008 (swap space and/or physical memory) when non-zero contents are1009 written to the pages.</para>1014 "overcommit" memory allocation strategy by default (though 1015 some of them provide ways of overriding that default.) What 1016 this means in general is that the OS doesn't necessarily 1017 ensure that backing store is available when asked to map pages 1018 as read-write; it'll often return a success indicator from the 1019 mapping attempt (mapping the pages as "zero-fill, 1020 copy-on-write"), and only try to allocate the backing store 1021 (swap space and/or physical memory) when non-zero contents are 1022 written to the pages.</para> 1010 1023 <para>It -sounds- like it'd be better to have the mmap() call 1011 fail immediately, but it's actually a complicated issue.1012 (It's possible that other applications will stop using some1013 backing store before lisp code actually touches the pages that1014 need it, for instance.) It's also not guaranteed that lisp1015 code would be able to "cleanly" signal an out-of-memory1016 condition if lisp is ... out of memory</para>1017 <para>I don't know that I've ever seen an abrupt out-of-memory1018 failure that wasn't preceded by several minutes of excessive1019 paging activity. The most expedient course in cases like this1020 is to either (a) use less memory or (b) get more memory; it's1021 generally hard to use memory that you don't have.</para>1024 fail immediately, but it's actually a complicated issue. 1025 (It's possible that other applications will stop using some 1026 backing store before lisp code actually touches the pages that 1027 need it, for instance.) It's also not guaranteed that lisp 1028 code would be able to "cleanly" signal an out-of-memory 1029 condition if lisp is ... out of memory</para> 1030 <para>I don't know that I've ever seen an abrupt out-of-memory 1031 failure that wasn't preceded by several minutes of excessive 1032 paging activity. The most expedient course in cases like this 1033 is to either (a) use less memory or (b) get more memory; it's 1034 generally hard to use memory that you don't have.</para> 1022 1035 </sect2> 1023 1036 </sect1> … … 1026 1039 <title>GC details</title> 1027 1040 <para>The GC uses a Mark/Compact algorithm; its 1028 execution time is essentially a factor of the amount of live1029 data in the heap. (The somewhat better-known Mark/Sweep1030 algorithms don't compact the live data but instead traverse the1031 garbage to rebuild free-lists; their execution time is therefore1032 a factor of the total heap size.)</para>1041 execution time is essentially a factor of the amount of live 1042 data in the heap. (The somewhat better-known Mark/Sweep 1043 algorithms don't compact the live data but instead traverse the 1044 garbage to rebuild free-lists; their execution time is therefore 1045 a factor of the total heap size.)</para> 1033 1046 <para>As mentioned in <xref linkend="Heap-Allocation"/>, two 1034 auxiliary data structures (proportional to the size of the lisp1035 heap) are maintained. These are</para>1047 auxiliary data structures (proportional to the size of the lisp 1048 heap) are maintained. These are</para> 1036 1049 <orderedlist> 1037 <listitem>1038 <para>the markbits bitvector, which contains a bit for1039 every doublenode in the dynamic heap (plus a few extra words1040 for alignment and so that sub-bitvectors can start on word1041 boundaries.)</para>1042 </listitem>1043 <listitem>1044 <para>the relocation table, which contains a native word for1045 every 32 or 64 doublenodes in the dynamic heap, plus an1046 extra word used to keep track of the end of the heap.</para>1047 </listitem>1050 <listitem> 1051 <para>the markbits bitvector, which contains a bit for 1052 every doublenode in the dynamic heap (plus a few extra words 1053 for alignment and so that sub-bitvectors can start on word 1054 boundaries.)</para> 1055 </listitem> 1056 <listitem> 1057 <para>the relocation table, which contains a native word for 1058 every 32 or 64 doublenodes in the dynamic heap, plus an 1059 extra word used to keep track of the end of the heap.</para> 1060 </listitem> 1048 1061 </orderedlist> 1049 1062 <para>The total GC space overhead is therefore on the order of 1050 3% (2/64 or 1/32).</para>1063 3% (2/64 or 1/32).</para> 1051 1064 <para>The general algorithm proceeds as follows:</para> 1052 1065 1053 1066 <sect2 id="Mark-phase"> 1054 <title>Mark phase</title>1067 <title>Mark phase</title> 1055 1068 <para>Each doublenode in the dynamic heap has a corresponding 1056 bit in the markbits vector. (For any doublenode in the heap,1057 the index of its mark bit is determined by subtracting the1058 address of the start of the heap from the address of the1059 object and dividing the result by 8 or 16.) The GC knows the1060 markbit index of the free pointer, so determining that the1061 markbit index of a doubleword address is between the start of1062 the heap and the free pointer can be done with a single1063 unsigned comparison.</para>1069 bit in the markbits vector. (For any doublenode in the heap, 1070 the index of its mark bit is determined by subtracting the 1071 address of the start of the heap from the address of the 1072 object and dividing the result by 8 or 16.) The GC knows the 1073 markbit index of the free pointer, so determining that the 1074 markbit index of a doubleword address is between the start of 1075 the heap and the free pointer can be done with a single 1076 unsigned comparison.</para> 1064 1077 <para>The markbits of all doublenodes in the dynamic heap are 1065 zeroed before the mark phase begins. An object is1066 <emphasis>marked</emphasis> if the markbits of all of its1067 constituent doublewords are set and unmarked otherwise;1068 setting an object's markbits involves setting the corresponding1069 markbits of all constituent doublenodes in the object.</para>1078 zeroed before the mark phase begins. An object is 1079 <emphasis>marked</emphasis> if the markbits of all of its 1080 constituent doublewords are set and unmarked otherwise; 1081 setting an object's markbits involves setting the corresponding 1082 markbits of all constituent doublenodes in the object.</para> 1070 1083 <para>The mark phase traverses each root. If the tag of the 1071 value of the root indicates that it's a non-immediate node1072 whose address lies in the lisp heap, then:</para>1073 <orderedlist>1074 <listitem>1075 <para>If the object is already marked, do nothing.</para>1076 </listitem>1077 <listitem>1078 <para>Set the object's markbit(s).</para>1079 </listitem>1080 <listitem>1081 <para>If the object is an ivector, do nothing further.</para>1082 </listitem>1083 <listitem>1084 <para>If the object is a cons cell, recursively mark its1085 car and cdr.</para>1086 </listitem>1087 <listitem>1088 <para>Otherwise, the object is a gvector. Recursively mark1089 its elements.</para>1090 </listitem>1091 </orderedlist>1084 value of the root indicates that it's a non-immediate node 1085 whose address lies in the lisp heap, then:</para> 1086 <orderedlist> 1087 <listitem> 1088 <para>If the object is already marked, do nothing.</para> 1089 </listitem> 1090 <listitem> 1091 <para>Set the object's markbit(s).</para> 1092 </listitem> 1093 <listitem> 1094 <para>If the object is an ivector, do nothing further.</para> 1095 </listitem> 1096 <listitem> 1097 <para>If the object is a cons cell, recursively mark its 1098 car and cdr.</para> 1099 </listitem> 1100 <listitem> 1101 <para>Otherwise, the object is a gvector. Recursively mark 1102 its elements.</para> 1103 </listitem> 1104 </orderedlist> 1092 1105 <para>Marking an object thus involves ensuring that its mark 1093 bits are set and then recursively marking any pointers1094 contained within the object if the object was originally1095 unmarked. If this recursive step was implemented in the1096 obvious manner, marking an object would take stack space1097 proportional to the length of the pointer chain from some root1098 to that object. Rather than storing that pointer chain1099 implicitly on the stack (in a series of recursive calls to the1100 mark subroutine), the &CCL; marker uses mixture of recursion1101 and a technique called <emphasis>link inversion</emphasis> to1102 store the pointer chain in the objects themselves. (Recursion1103 tends to be simpler and faster; if a recursive step notes that1104 stack space is becoming limited, the link-inversion technique1105 is used.)</para>1106 bits are set and then recursively marking any pointers 1107 contained within the object if the object was originally 1108 unmarked. If this recursive step was implemented in the 1109 obvious manner, marking an object would take stack space 1110 proportional to the length of the pointer chain from some root 1111 to that object. Rather than storing that pointer chain 1112 implicitly on the stack (in a series of recursive calls to the 1113 mark subroutine), the &CCL; marker uses mixture of recursion 1114 and a technique called <emphasis>link inversion</emphasis> to 1115 store the pointer chain in the objects themselves. (Recursion 1116 tends to be simpler and faster; if a recursive step notes that 1117 stack space is becoming limited, the link-inversion technique 1118 is used.)</para> 1106 1119 <para>Certain types of objects are treated a little specially:</para> 1107 <orderedlist>1108 <listitem>1109 <para>To support a feature called <emphasis>GCTWA1110 <footnote>1111 <para>I believe that the acronym comes from MACLISP,1112 where it stood for "Garbage Collection of Truly1113 Worthless Atoms".</para>1114 </footnote>1115 , </emphasis>the vector which contains the1116 internal symbols of the current package is marked on1117 entry to the mark phase, but the symbols themselves are1118 not marked at this time. Near the end of the mark phase,1119 symbols referenced from this vector which are1120 not otherwise marked are marked if and only if they're1121 somehow distinguishable from newly created symbols (by1122 virtue of their having function bindings, value bindings,1123 plists,or other attributes.)</para>1124 </listitem>1125 <listitem>1126 <para>Pools have their first element set to NIL before any1127 other elements are marked.</para>1128 </listitem>1129 <listitem>1130 <para>All hash tables have certain fields (used to cache1131 previous results) invalidated.</para>1132 </listitem>1133 <listitem>1134 <para>Weak Hash Tables and other weak objects are put on a1135 linkedlist as they're encountered; their contents are only1136 retained if there are other (non-weak) references to1137 them.</para>1138 </listitem>1139 </orderedlist>1120 <orderedlist> 1121 <listitem> 1122 <para>To support a feature called <emphasis>GCTWA 1123 <footnote> 1124 <para>I believe that the acronym comes from MACLISP, 1125 where it stood for "Garbage Collection of Truly 1126 Worthless Atoms".</para> 1127 </footnote> 1128 , </emphasis>the vector that contains the internal 1129 symbols of the current package is marked on entry to the 1130 mark phase, but the symbols themselves are not marked at 1131 this time. Near the end of the mark phase, symbols 1132 referenced from this vector which are not otherwise 1133 marked are marked if and only if they're somehow 1134 distinguishable from newly created symbols (by virtue of 1135 their having function bindings, value bindings, plists, 1136 or other attributes.)</para> 1137 </listitem> 1138 <listitem> 1139 <para>Pools have their first element set to NIL before any 1140 other elements are marked.</para> 1141 </listitem> 1142 <listitem> 1143 <para>All hash tables have certain fields (used to cache 1144 previous results) invalidated.</para> 1145 </listitem> 1146 <listitem> 1147 <para>Weak Hash Tables and other weak objects are put on a 1148 linkedlist as they're encountered; their contents are only 1149 retained if there are other (non-weak) references to 1150 them.</para> 1151 </listitem> 1152 </orderedlist> 1140 1153 <para>At the end of the mark phase, the markbits of all 1141 objects whichare transitively reachable from the roots are1142 set and all other markbits are clear.</para>1154 objects that are transitively reachable from the roots are 1155 set and all other markbits are clear.</para> 1143 1156 </sect2> 1144 1157 1145 1158 <sect2 id="Relocation-phase"> 1146 <title>Relocation phase</title>1147 <para>The <emphasis>forwarding address</emphasis> of a1148 doublenode in the dynamic heap is (<its current address> -1149 (size_of_doublenode * <the number of unmarked markbits that1150 precede it>)) or alternately (<the base of the heap> +1151 (size_of_doublenode * <the number of marked markbits that1152 precede it >)). Rather than count the number of preceding1153 markbits each time, the relocation table is used to precompute1154 an approximation of the forwarding addresses for all1155 doublewords. Given this approximate address and a pointer into1156 the markbits vector, it's relatively easy to compute the exact1157 forwarding address.</para>1158 <para>The relocation table contains the forwarding addresses1159 of each <emphasis>pagelet</emphasis>, where a pagelet is 2561160 bytes (or 32 doublenodes). The forwarding address of the first1161 pagelet is the base of the heap. The forwarding address of the1162 second pagelet is the sum of the forwarding address of the1163 first and 8 bytes for each mark bit set in the first 32-bit1164 word in the markbits table. The last entry in the relocation1165 table contains the forwarding address that the freepointer1166 would have, e.g., the new value of the freepointer after1167 compaction.</para>1168 <para>In many programs, old objects rarely become garbage and1169 new objects often do. When building the relocation table, the1170 relocation phase notes the address of the first unmarked1171 object in the dynamic heap. Only the area of the heap between1172 the first unmarked object and the freepointer needs to be1173 compacted; only pointers to this area will need to be1174 forwarded (the forwarding address of all other pointers to the1175 dynamic heap is the address of that pointer.) Often, the1176 first unmarked object is much nearer the free pointer than it1177 is to the base of the heap.</para>1159 <title>Relocation phase</title> 1160 <para>The <emphasis>forwarding address</emphasis> of a 1161 doublenode in the dynamic heap is (<its current address> - 1162 (size_of_doublenode * <the number of unmarked markbits that 1163 precede it>)) or alternately (<the base of the heap> + 1164 (size_of_doublenode * <the number of marked markbits that 1165 precede it >)). Rather than count the number of preceding 1166 markbits each time, the relocation table is used to precompute 1167 an approximation of the forwarding addresses for all 1168 doublewords. Given this approximate address and a pointer into 1169 the markbits vector, it's relatively easy to compute the exact 1170 forwarding address.</para> 1171 <para>The relocation table contains the forwarding addresses 1172 of each <emphasis>pagelet</emphasis>, where a pagelet is 256 1173 bytes (or 32 doublenodes). The forwarding address of the first 1174 pagelet is the base of the heap. The forwarding address of the 1175 second pagelet is the sum of the forwarding address of the 1176 first and 8 bytes for each mark bit set in the first 32-bit 1177 word in the markbits table. The last entry in the relocation 1178 table contains the forwarding address that the freepointer 1179 would have, e.g., the new value of the freepointer after 1180 compaction.</para> 1181 <para>In many programs, old objects rarely become garbage and 1182 new objects often do. When building the relocation table, the 1183 relocation phase notes the address of the first unmarked 1184 object in the dynamic heap. Only the area of the heap between 1185 the first unmarked object and the freepointer needs to be 1186 compacted; only pointers to this area will need to be 1187 forwarded (the forwarding address of all other pointers to the 1188 dynamic heap is the address of that pointer.) Often, the 1189 first unmarked object is much nearer the free pointer than it 1190 is to the base of the heap.</para> 1178 1191 </sect2> 1179 1192 1180 1193 <sect2 id="Forwarding-phase"> 1181 <title>Forwarding phase</title>1194 <title>Forwarding phase</title> 1182 1195 <para>The forwarding phase traverses all roots and the "old" 1183 part of the dynamic heap (the part between the base of the1184 heap and the first unmarked object.) All references to objects1185 whose address is between the first unmarked object and the1186 free pointer are updated to point to the address the object1187 will have after compaction by using the relocation table and1188 the markbits vector and interpolating.</para>1189 <para>The relocation table entry for the pagelet nearest the1190 object is found. If the pagelet's address is less than the1191 object's address, the number of set markbits that precede the1192 object on the pagelet is used to determine the object's1193 address; otherwise, the number of set markbits the follow the1194 object on the pagelet is used.</para>1196 part of the dynamic heap (the part between the base of the 1197 heap and the first unmarked object.) All references to objects 1198 whose address is between the first unmarked object and the 1199 free pointer are updated to point to the address the object 1200 will have after compaction by using the relocation table and 1201 the markbits vector and interpolating.</para> 1202 <para>The relocation table entry for the pagelet nearest the 1203 object is found. If the pagelet's address is less than the 1204 object's address, the number of set markbits that precede 1205 the object on the pagelet is used to determine the object's 1206 address; otherwise, the number of set markbits that follow 1207 the object on the pagelet is used.</para> 1195 1208 <para>Since forwarding views the heap as a set of doublewords, 1196 locatives are (mostly) treated like any other pointers. (The1197 basic difference is that locatives may appear to be tagged as1198 fixnums, in which case they're treated as word-aligned1199 pointers into the object.)</para>1209 locatives are (mostly) treated like any other pointers. (The 1210 basic difference is that locatives may appear to be tagged as 1211 fixnums, in which case they're treated as word-aligned 1212 pointers into the object.)</para> 1200 1213 <para>If the forward phase changes the address of any hash 1201 table key in a hash table that hashes by address (e.g., an EQ1202 hash table), it sets a bit in the hash table's header. The1203 hash table code will rehash the hash table's contents if it1204 tries to do a lookup on a key in such a table.</para>1214 table key in a hash table that hashes by address (e.g., an EQ 1215 hash table), it sets a bit in the hash table's header. The 1216 hash table code will rehash the hash table's contents if it 1217 tries to do a lookup on a key in such a table.</para> 1205 1218 <para>Profiling reveals that about half of the total time 1206 spent in the GC is spent in the subroutine which determines a1207 pointer's forwarding address. Exploiting GCC-specific idioms,1208 hand-coding the routine, and inlining calls to it could all be1209 expected to improve GC performance.</para>1219 spent in the GC is spent in the subroutine which determines a 1220 pointer's forwarding address. Exploiting GCC-specific idioms, 1221 hand-coding the routine, and inlining calls to it could all be 1222 expected to improve GC performance.</para> 1210 1223 </sect2> 1211 1224 1212 1225 <sect2 id="Compact-phase"> 1213 <title>Compact phase</title>1226 <title>Compact phase</title> 1214 1227 <para>The compact phase compacts the area between the first 1215 unmarked object and the freepointer so that it contains only1216 marked objects. While doing so, it forwards any pointers it1217 finds in the objects it copies.</para>1228 unmarked object and the freepointer so that it contains only 1229 marked objects. While doing so, it forwards any pointers it 1230 finds in the objects it copies.</para> 1218 1231 <para>When the compact phase is finished, so is the GC (more 1219 or less): the free pointer and some other data structures are1220 updated and control returns to the exception handler that1221 invoked the GC. If sufficient memory has been freed to satisfy1222 any allocation request that may have triggered the GC, the1223 exception handler returns; otherwise, a "seriously low on1224 memory" condition is signaled, possibly after releasing a1225 small emergency pool of memory.</para>1232 or less): the free pointer and some other data structures are 1233 updated and control returns to the exception handler that 1234 invoked the GC. If sufficient memory has been freed to satisfy 1235 any allocation request that may have triggered the GC, the 1236 exception handler returns; otherwise, a "seriously low on 1237 memory" condition is signaled, possibly after releasing a 1238 small emergency pool of memory.</para> 1226 1239 </sect2> 1227 1240 </sect1> … … 1230 1243 <title>The ephemeral GC</title> 1231 1244 <para>In the &CCL; memory management scheme, the relative age 1232 of two objects in the dynamic heap can be determined by their1233 addresses: if addresses X and Y are both addresses in the1234 dynamic heap, X is younger than Y (X was created more recently1235 than Y) if it is nearer to the free pointer (and farther from1236 the base of the heap) than Y.</para>1245 of two objects in the dynamic heap can be determined by their 1246 addresses: if addresses X and Y are both addresses in the 1247 dynamic heap, X is younger than Y (X was created more recently 1248 than Y) if it is nearer to the free pointer (and farther from 1249 the base of the heap) than Y.</para> 1237 1250 <para>Ephemeral (or generational) garbage collectors attempt to 1238 exploit the following assumptions:</para>1251 exploit the following assumptions:</para> 1239 1252 <itemizedlist> 1240 <listitem>1241 <para>most newly created objects become garbage soon after1242 they'recreated.</para>1243 </listitem>1244 <listitem>1245 <para>most objects that have already survived several GCs1246 are unlikely to ever become garbage.</para>1247 </listitem>1248 <listitem>1249 <para>old objects can only point to newer objects as the1250 result of a destructive modification (e.g., via1251 SETF.)</para>1252 </listitem>1253 <listitem> 1254 <para>most newly created objects become garbage soon after 1255 they'recreated.</para> 1256 </listitem> 1257 <listitem> 1258 <para>most objects that have already survived several GCs 1259 are unlikely to ever become garbage.</para> 1260 </listitem> 1261 <listitem> 1262 <para>old objects can only point to newer objects as the 1263 result of a destructive modification (e.g., via 1264 SETF.)</para> 1265 </listitem> 1253 1266 </itemizedlist> 1254 1267 1255 1268 <para>By concentrating its efforts on (frequently and quickly) 1256 reclaiming newly created garbage, an ephemeral collector hopes1257 to postpone the more costly full GC as long as possible. It's1258 important to note that most programs create some long-lived1259 garbage, so an EGC can't typically eliminate the need for full1260 GC.</para>1269 reclaiming newly created garbage, an ephemeral collector hopes 1270 to postpone the more costly full GC as long as possible. It's 1271 important to note that most programs create some long-lived 1272 garbage, so an EGC can't typically eliminate the need for full 1273 GC.</para> 1261 1274 <para>An EGC views each object in the heap as belonging to 1262 exactly one <emphasis>generation</emphasis>; generations are1263 sets of objects that are related to each other by age: some1264 generation is the youngest, some the oldest, and there's an age1265 relationship between any intervening generations. Objects are1266 typically assigned to the youngest generation when first1267 allocated; any object that has survived some number of GCs in1268 its current generation is promoted (or1269 <emphasis>tenured</emphasis>) into an older generation.</para>1275 exactly one <emphasis>generation</emphasis>; generations are 1276 sets of objects that are related to each other by age: some 1277 generation is the youngest, some the oldest, and there's an age 1278 relationship between any intervening generations. Objects are 1279 typically assigned to the youngest generation when first 1280 allocated; any object that has survived some number of GCs in 1281 its current generation is promoted (or 1282 <emphasis>tenured</emphasis>) into an older generation.</para> 1270 1283 <para>When a generation is GCed, the roots consist of the 1271 stacks, registers, and global variables as always and also of1272 any pointers to objects in that generation from other1273 generations. To avoid the need to scan those (often large) other1274 generations looking for such intergenerational references, the1275 runtime system must note all such intergenerational references1276 at the point where they're created (via Setf).<footnote><para>This is1277 sometimes called "The Write Barrier": all assignments which1278 might result in intergenerational references must be noted, as1279 if the other generations were write-protected.</para></footnote> The1280 set of pointers that may contain intergenerational references is1281 sometimes called <emphasis>the remembered set</emphasis>.</para>1284 stacks, registers, and global variables as always and also of 1285 any pointers to objects in that generation from other 1286 generations. To avoid the need to scan those (often large) other 1287 generations looking for such intergenerational references, the 1288 runtime system must note all such intergenerational references 1289 at the point where they're created (via Setf).<footnote><para>This is 1290 sometimes called "The Write Barrier": all assignments which 1291 might result in intergenerational references must be noted, as 1292 if the other generations were write-protected.</para></footnote> The 1293 set of pointers that may contain intergenerational references is 1294 sometimes called <emphasis>the remembered set</emphasis>.</para> 1282 1295 <para>In &CCL;'s EGC, the heap is organized exactly the same 1283 as otherwise; "generations" are merely structures which contain1284 pointers to regions of the heap (which is already ordered by1285 age.) When a generation needs to be GCed, any younger generation1286 is incorporated into it; all objects which survive a GC of a1287 given generation are promoted into the next older1288 generation. The only intergenerational references that can exist1289 are therefore those where an old object is modified to contain a1290 pointer to a new object.</para>1296 as otherwise; "generations" are merely structures which contain 1297 pointers to regions of the heap (which is already ordered by 1298 age.) When a generation needs to be GCed, any younger generation 1299 is incorporated into it; all objects which survive a GC of a 1300 given generation are promoted into the next older 1301 generation. The only intergenerational references that can exist 1302 are therefore those where an old object is modified to contain a 1303 pointer to a new object.</para> 1291 1304 <para>The EGC uses exactly the same code as the full GC. When a 1292 given GC is "ephemeral",</para>1305 given GC is "ephemeral",</para> 1293 1306 <itemizedlist> 1294 1307 <listitem> 1295 <para>the "base of the heap" used to determine an object's1296 markbit address is the base of the generation1297 being collected;</para>1298 </listitem>1308 <para>the "base of the heap" used to determine an object's 1309 markbit address is the base of the generation 1310 being collected;</para> 1311 </listitem> 1299 1312 <listitem> 1300 <para>the markbits vector is actually a pointer into the1301 middle of the global markbits table; preceding entries in1302 this table are used to note doubleword addresses in older1303 generations that (may) contain intergenerational1304 references;</para>1305 </listitem>1313 <para>the markbits vector is actually a pointer into the 1314 middle of the global markbits table; preceding entries in 1315 this table are used to note doubleword addresses in older 1316 generations that (may) contain intergenerational 1317 references;</para> 1318 </listitem> 1306 1319 <listitem> 1307 <para>some steps (notably GCTWA and the handling of weak1308 objects) are not performed;</para>1309 </listitem>1320 <para>some steps (notably GCTWA and the handling of weak 1321 objects) are not performed;</para> 1322 </listitem> 1310 1323 <listitem> 1311 <para>the intergenerational references table is used to1312 find additional roots for the mark and forward phases. If a1313 bit is set inthe intergenerational references table, that1314 means that the corresponding doubleword (in some "old"1315 generation, in some "earlier" part of the heap) may have had1316 a pointer to an object in a younger generation stored into1317 it.</para>1318 </listitem>1319 1324 <para>the intergenerational references table is used to 1325 find additional roots for the mark and forward phases. If a 1326 bit is set in the intergenerational references table, that 1327 means that the corresponding doubleword (in some "old" 1328 generation, in some "earlier" part of the heap) may have had 1329 a pointer to an object in a younger generation stored into 1330 it.</para> 1331 </listitem> 1332 1320 1333 </itemizedlist> 1321 1334 <para>With one exception (the implicit setfs that occur on entry 1322 to and exit from the binding of a special variable), all setfs 1323 that might introduce an intergenerational reference must be 1324 memoized.@footnote{Note that the implicit setfs that occur when 1325 initializing an object - as in the case of a call to cons or 1326 vector - can't introduce intergenerational references, since the 1327 newly created object is always younger than the objects used to 1328 initialize it.} It's always safe to push any cons cell or 1329 gvector locative onto the memo stack; it's never safe to push 1330 anything else. 1335 to and exit from the binding of a special variable), all setfs 1336 that might introduce an intergenerational reference must be 1337 memoized. 1338 <footnote><para>Note that the implicit setfs that occur when 1339 initializing an object - as in the case of a call to cons or 1340 vector - can't introduce intergenerational references, since 1341 the newly created object is always younger than the objects 1342 used to initialize it.</para></footnote> It's always safe to 1343 push any cons cell or gvector locative onto the memo stack; 1344 it's never safe to push anything else. 1331 1345 </para> 1332 1346 1333 1347 <para>Typically, the intergenerational references bitvector is 1334 sparse: a relatively small number of old locations are stored1335 into, although some of them may have been stored into many1336 times. The routine that scans the memoization buffer does a lot1337 of work and usually does it fairly often; it uses a simple,1338 brute-force method but might run faster if it was smarter about1339 recognizing addresses that it'd already seen.1348 sparse: a relatively small number of old locations are stored 1349 into, although some of them may have been stored into many 1350 times. The routine that scans the memoization buffer does a lot 1351 of work and usually does it fairly often; it uses a simple, 1352 brute-force method but might run faster if it was smarter about 1353 recognizing addresses that it'd already seen. 1340 1354 </para> 1341 1355 1342 1356 <para>When the EGC mark and forward phases scan the 1343 intergenerational reference bits, they can clear any bits that1344 denote doublewords that definitely do not contain1345 intergenerational references.1357 intergenerational reference bits, they can clear any bits that 1358 denote doublewords that definitely do not contain 1359 intergenerational references. 1346 1360 </para> 1347 1361 </sect1> … … 1350 1364 <title>Fasl files</title> 1351 1365 <para>Saving and loading of Fasl files is implemented in 1352 xdump/faslenv.lisp, level-0/nfasload.lisp, and lib/nfcomp.lisp.1353 The information here is only an overview, which might help when1354 reading the source.</para>1366 xdump/faslenv.lisp, level-0/nfasload.lisp, and lib/nfcomp.lisp. 1367 The information here is only an overview, which might help when 1368 reading the source.</para> 1355 1369 <para>The &CCL; Fasl format is forked from the old MCL Fasl 1356 format; there are a few differences, but they are minor. The1357 name "nfasload" comes from the fact that this is the so-called1358 "new" Fasl system, which was true in 1986 or so. </para>1370 format; there are a few differences, but they are minor. The 1371 name "nfasload" comes from the fact that this is the so-called 1372 "new" Fasl system, which was true in 1986 or so. </para> 1359 1373 <para>A Fasl file begins with a "file header", which contains 1360 version information and a count of the following "blocks".1361 There's typically only one "block" per Fasl file. The blocks1362 are part of a mechanism for combining multiple logical files1363 into a single physical file, in order to simplify the1364 distribution of precompiled programs. </para>1374 version information and a count of the following "blocks". 1375 There's typically only one "block" per Fasl file. The blocks 1376 are part of a mechanism for combining multiple logical files 1377 into a single physical file, in order to simplify the 1378 distribution of precompiled programs. </para> 1365 1379 <para>Each block begins with a header for itself, which just 1366 describes the size of the data that follows.</para>1380 describes the size of the data that follows.</para> 1367 1381 <para>The data in each block is treated as a simple stream of 1368 bytes, which define a bytecode program. The actual bytecodes,1369 "fasl operators", are defined in xdump/faslenv.lisp. The1370 descriptions in the source file are terse, but, according to1371 Gary, "probably accurate".</para>1382 bytes, which define a bytecode program. The actual bytecodes, 1383 "fasl operators", are defined in xdump/faslenv.lisp. The 1384 descriptions in the source file are terse, but, according to 1385 Gary, "probably accurate".</para> 1372 1386 <para>Some of the operators are used to create a per-block 1373 "object table", which is a vector used to keep track of1374 previously-loaded objects and simplify references to them. When1375 the table is created, an index associated with it is set to1376 zero; this is analogous to an array fill-pointer, and allows the1377 table to be treated like a stack.</para>1387 "object table", which is a vector used to keep track of 1388 previously-loaded objects and simplify references to them. When 1389 the table is created, an index associated with it is set to 1390 zero; this is analogous to an array fill-pointer, and allows the 1391 table to be treated like a stack.</para> 1378 1392 <para>The low seven bits of each bytecode are used to specify 1379 the fasl operator; currently, about fifty operators are defined.1380 The high byte, when set, indicates that the result of the1381 operation should be pushed onto the object table.</para>1393 the fasl operator; currently, about fifty operators are defined. 1394 The high byte, when set, indicates that the result of the 1395 operation should be pushed onto the object table.</para> 1382 1396 <para>Most bytecodes are followed by operands; the operand data 1383 is byte-aligned. How many operands there are, and their type,1384 depend on the bytecode. Operands can be indices into the object1385 table, immediate values, or some combination of these.</para>1397 is byte-aligned. How many operands there are, and their type, 1398 depend on the bytecode. Operands can be indices into the object 1399 table, immediate values, or some combination of these.</para> 1386 1400 <para>An exception is the bytecode #xFF, which has the symbolic 1387 name ccl::$faslend; it is used to mark the end of the1388 block.</para>1401 name ccl::$faslend; it is used to mark the end of the 1402 block.</para> 1389 1403 </sect1> 1390 1404 … … 1395 1409 1396 1410 <sect2 id="How-CCL-Recognizes-Objective-C-Objects"> 1397 <title>How &CCL; Recognizes Objective-C Objects</title>1411 <title>How &CCL; Recognizes Objective-C Objects</title> 1398 1412 <para>In most cases, pointers to instances of Objective-C 1399 classes are recognized as such; the recognition is (and1400 probably always will be) slightly heuristic. Basically, any1401 pointer that passes basic sanity checks and whose first word1402 is a pointer to a known ObjC class is considered to be an1403 instance of that class; the Objective-C runtime system would1404 reach the same conclusion.</para>1413 classes are recognized as such; the recognition is (and 1414 probably always will be) slightly heuristic. Basically, any 1415 pointer that passes basic sanity checks and whose first word 1416 is a pointer to a known ObjC class is considered to be an 1417 instance of that class; the Objective-C runtime system would 1418 reach the same conclusion.</para> 1405 1419 <para>It's certainly possible that a random pointer to an 1406 arbitrary memory address could look enough like an ObjC1407 instance to fool the lisp runtime system, and it's possible1408 that pointers could have their contents change so that1409 something that had either been a true ObjC instance (or had1410 looked a lot like one) is changed (possibly by virtue of1411 having been deallocated.)</para>1420 arbitrary memory address could look enough like an ObjC 1421 instance to fool the lisp runtime system, and it's possible 1422 that pointers could have their contents change so that 1423 something that had either been a true ObjC instance (or had 1424 looked a lot like one) is changed (possibly by virtue of 1425 having been deallocated.)</para> 1412 1426 <para>In the first case, we can improve the heuristics 1413 substantially: we can make stronger assertions that a1414 particular pointer is really "of type :ID" when it's a1415 parameter to a function declared to take such a pointer as an1416 argument or a similarly declared function result; we can be1417 more confident of something we obtained via SLOT-VALUE of a1418 slot defined to be of type :ID than if we just dug a pointer1419 out of memory somewhere.</para>1427 substantially: we can make stronger assertions that a 1428 particular pointer is really "of type :ID" when it's a 1429 parameter to a function declared to take such a pointer as an 1430 argument or a similarly declared function result; we can be 1431 more confident of something we obtained via SLOT-VALUE of a 1432 slot defined to be of type :ID than if we just dug a pointer 1433 out of memory somewhere.</para> 1420 1434 <para>The second case is a little more subtle: ObjC memory 1421 management is based on a reference-counting scheme, and it's1422 possible for an object to ... cease to be an object while lisp1423 is still referencing it. If we don't want to deal with this1424 possibility (and we don't), we'll basically have to ensure1425 that the object is not deallocated while lisp is still1426 thinking of it as a first-class object. There's some support1427 for this in the case of objects created with MAKE-INSTANCE,1428 but we may need to give similar treatment to foreign objects1429 that are introduced to the lisp runtime in other ways (as1430 function arguments, return values, SLOT-VALUE results, etc. as1431 well as those instances that are created under lisp1432 control.)</para>1435 management is based on a reference-counting scheme, and it's 1436 possible for an object to ... cease to be an object while lisp 1437 is still referencing it. If we don't want to deal with this 1438 possibility (and we don't), we'll basically have to ensure 1439 that the object is not deallocated while lisp is still 1440 thinking of it as a first-class object. There's some support 1441 for this in the case of objects created with MAKE-INSTANCE, 1442 but we may need to give similar treatment to foreign objects 1443 that are introduced to the lisp runtime in other ways (as 1444 function arguments, return values, SLOT-VALUE results, etc. as 1445 well as those instances that are created under lisp 1446 control.)</para> 1433 1447 <para>This doesn't all work yet (in fact, not much of it works 1434 yet); in practice, this has not yet been as much of a problem1435 as anticipated, but that may be because existing Cocoa code1436 deals primarily with relatively long-lived objects such as1437 windows, views, menus, etc.</para>1448 yet); in practice, this has not yet been as much of a problem 1449 as anticipated, but that may be because existing Cocoa code 1450 deals primarily with relatively long-lived objects such as 1451 windows, views, menus, etc.</para> 1438 1452 </sect2> 1439 1453 1440 1454 <sect2> 1441 <title>Recommended Reading</title>1442 1443 <variablelist>1444 <varlistentry>1445 <term>1446 <ulink url="http://developer.apple.com/documentation/Cocoa/">Cocoa Documentation</ulink>1447 </term>1448 1449 <listitem>1450 <para>1451 This is the top page for all of Apple's documentation on1452 Cocoa. If you are unfamiliar with Cocoa, it is a good1453 place to start.1454 </para>1455 </listitem>1456 </varlistentry>1457 <varlistentry>1458 <term>1459 <ulink url="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/index.html">Foundation Reference for Objective-C</ulink>1460 </term>1461 1462 <listitem>1463 <para>1464 This is one of the two most important Cocoa references; it1465 covers all of the basics, except for GUI programming. This is1466 a reference, not a tutorial.1467 </para>1468 </listitem>1469 </varlistentry>1470 </variablelist>1455 <title>Recommended Reading</title> 1456 1457 <variablelist> 1458 <varlistentry> 1459 <term> 1460 <ulink url="http://developer.apple.com/documentation/Cocoa/">Cocoa Documentation</ulink> 1461 </term> 1462 1463 <listitem> 1464 <para> 1465 This is the top page for all of Apple's documentation on 1466 Cocoa. If you are unfamiliar with Cocoa, it is a good 1467 place to start. 1468 </para> 1469 </listitem> 1470 </varlistentry> 1471 <varlistentry> 1472 <term> 1473 <ulink url="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ObjC_classic/index.html">Foundation Reference for Objective-C</ulink> 1474 </term> 1475 1476 <listitem> 1477 <para> 1478 This is one of the two most important Cocoa references; it 1479 covers all of the basics, except for GUI programming. This is 1480 a reference, not a tutorial. 1481 </para> 1482 </listitem> 1483 </varlistentry> 1484 </variablelist> 1471 1485 </sect2> 1472 1486 </sect1> -
release/1.2/source/doc/src/install.xml
r9071 r9200 15 15 <sect1><title>Releases and System Requirements</title> 16 16 17 <para>There are three active versions of &CCL;. Version 1.0 was a 18 stable release (released in late 2005); it is no longer under 19 active development. Version 1.1 has been under active 20 development since shortly after 1.0 was released; it's been 21 distributed as a series of development "snapshots" and CVS 22 updates. 1.1 snapshots have introduced support for x86-64 23 platforms, internal use of Unicode, and many other features, but 24 have presented something of a moving target. Version 1.2 25 (released in early 2008) is intended to be a more stable release 26 and provide a more predictable release schedule, and to make it 27 a bit easier for users who wish to track the "bleeding edge" of 28 development to do so.</para> 29 30 <para>Version 1.0 is available for three platform configurations:</para> 31 <itemizedlist> 32 <listitem> 33 <para>Linux on PowerPC (32-bit implementation)</para> 34 </listitem> 35 <listitem> 36 <para>Mac OS X on PowerPC (32-bit implementation)</para> 37 </listitem> 38 <listitem> 39 <para>Mac OS X on PowerPC (64-bit implementation)</para> 40 </listitem> 41 </itemizedlist> 42 43 <para>Versions 1.1 and 1.2 are available for five platform 44 configurations:</para> 17 <para>Version 1.2 is the latest release of &CCL; as of April 18 2008. It is intended to be a more stable release and follow a more 19 regular release schedule than previous versions. It is easier for 20 users who wish to track the "bleeding edge" of development to do 21 so.</para> 22 23 <para>Versions 1.2 is available for five platform 24 configurations:</para> 45 25 <itemizedlist> 46 26 <listitem> … … 61 41 <para>A 64-bit version of &CCL; requires a 64-bit processor 62 42 running a 64-bit OS variant.</para> 63 43 64 44 <para>There are ongoing efforts to port &CCL; to the Windows 65 45 operating system and to 32-bit x86 processors.</para> 66 46 67 68 47 <para>Additional platform-specific information is given in the 69 48 following subsections.</para> 70 49 50 <para>Older versions are still available for downloading as 51 tarballs. Version 1.0 was a stable release released in late 2005. 52 Version 1.1 was under active development until late 2007. A final 53 1.1 release was never made. It was distributed as a series of 54 development "snapshots" and CVS updates. 1.1 snapshots introduced 55 support for x86-64 platforms, internal use of Unicode, and many 56 other features, but were a moving target. </para> 57 71 58 <sect2><title>LinuxPPC</title> 72 59 73 <para>&CCL; versions 1.0 and later run under relatively 74 recent versions of LinuxPPC. All versions of &CCL; require 75 version 2.2.13 (or later) of the Linux kernel and version 76 2.1.3 (or later) of the GNU C library (glibc) at a bare 77 minimum.</para> 60 <para>&CCL; requires version 2.2.13 (or later) of the Linux 61 kernel and version 2.1.3 (or later) of the GNU C library (glibc) 62 at a bare minimum.</para> 78 63 </sect2> 79 64 80 65 <sect2><title>Linux X8664</title> 81 66 82 <para>Version 1.1 and later of &CCL; runs on relatively recent 83 Linux distributions for the x86-64 architecture. It requires 84 a Linux with Thread Local Storage support in the toolchain and 85 standard libraries, and the New Posix Thread Library (NPTL). 86 Fortunately, these features seem to be present in all current 87 Linux distributions for x86-64, though there may be some 88 problems with early Linux distributions for x86-64. Some GCC 89 versions older than 4.0 on Linux have been known to have 90 problems compiling some of the C code in the kernel; some very 91 old Linux distributions don't follow the current ABI standards 92 wrt segment register usage; some early Linux kernels for 93 x86-64 had problems mapping large regions of the address 94 space; and so on. It's difficult to enumerate exactly what 95 versions of what Linux distributions have what problems. A 96 rule of thumb is that—because much of the development of 97 &CCL; for x86-64 took place in that time frame—Linux 98 distributions released earlier than early 2006 may have 99 problems running &CCL;. </para> 100 </sect2> 101 102 <sect2><title>FreeBSD-amd64</title> 103 <para>Versions 1.1 and later of &CCL; runs on FreeBSD on x86-64 104 (FreeBSD releases generally call the platform "amd64"). &CCL; 105 should run under FreeBSD 6.0 or later; as of this writing, 106 FreeBSD 7.0 is about to be released and it may be necessary 107 for FreeBSD 7 users to install the "compat6x" package in order 108 to use a version of &CCL; built on FreeBSD 6.x.</para> 67 <para>&CCL; runs on relatively recent Linux distributions for 68 the x86-64 architecture. It requires a Linux with Thread Local 69 Storage support in the toolchain and standard libraries, and the 70 New Posix Thread Library (NPTL). Fortunately, these features 71 seem to be present in all current Linux distributions for 72 x86-64, though there may be some problems with early Linux 73 distributions for x86-64. Some GCC versions older than 4.0 on 74 Linux have been known to have problems compiling some of the C 75 code in the kernel; some very old Linux distributions don't 76 follow the current ABI standards wrt segment register usage; 77 some early Linux kernels for x86-64 had problems mapping large 78 regions of the address space; and so on. It's difficult to 79 enumerate exactly what versions of what Linux distributions have 80 what problems. A rule of thumb is that—because much of 81 the development of &CCL; for x86-64 took place in that time 82 frame—Linux distributions released earlier than early 2006 83 may have problems running &CCL;. </para> 84 </sect2> 85 86 <sect2><title>FreeBSD-amd64</title> <para>&CCL; runs on FreeBSD on 87 x86-64 (FreeBSD releases generally call the platform "amd64"). 88 &CCL; should run under FreeBSD 6.0 or later; as of this writing, 89 FreeBSD 7.0 is about to be released and it may be necessary for 90 FreeBSD 7 users to install the "compat6x" package in order to use 91 a version of &CCL; built on FreeBSD 6.x.</para> 109 92 </sect2> 110 93 111 94 <sect2><title>DarwinPPC-MacOS-X</title> 112 95 113 <para> &CCL; 1.0 runs on MacOS X versions 10.2, 10.3 and 114 10.4 on the PowerPC.</para> 115 116 <para>Current development on version 1.1 and later takes place 117 under OS X versions 10.4 and 10.5 and requires at least 118 version 10.3.9</para> 96 <para> &CCL; runs under OS X versions 10.4 and 10.5 and requires 97 at least version 10.3.9</para> 119 98 120 99 <para>The 64-bit DarwinPPC version of &CCL; requires … … 130 109 </sect2> 131 110 132 <sect2><title>Darwinx8664-MacOS-X</title> 133 <para>Versions 1.1 and later of &CCL; run on 64-bit DarwinX86 134 (MacOS on Intel).</para> 111 <sect2><title>Darwinx8664-MacOS-X</title> <para>&CCL; runs on 112 64-bit DarwinX86 (Mac OS X on Intel).</para> 135 113 136 114 <para>&CCL; Darwinx8664/MacOS X requires a 64-bit processor. … … 148 126 <sect1><title>Obtaining Clozure CL</title> 149 127 <para>There two main ways to obtain Clozure CL. For Mac OS X, 150 there are disk images that can be used to install Clozure CL in 151 the usual Macintosh way. For other OSes, Subversion is the best 152 way to obtain Clozure CL, and Mac OS X users can also use 153 Subversion if they prefer to. Tarballs are available for those 154 who prefer them, but Subversion is simpler and more 155 flexible.</para> 128 there are disk images that can be used to install Clozure CL in 129 the usual Macintosh way. For other OSes, Subversion is the best 130 way to obtain Clozure CL. Mac OS X users can also use Subversion 131 if they prefer. Tarballs are available for those who prefer them, 132 but if you have Subversion installed, it is simpler and more 133 flexible to use Subversion than tarballs. It is easier to keep up 134 with the bleeding edge if you are using Subversion, since disk 135 images and tarballs are generated much less frequently than 136 changes to Subversion. 137 </para> 156 138 157 139 <para> There are three popular ways to use Clozure CL: as a … … 168 150 <ulink url="ftp://clozure.com/pub/testing/"/> </para> 169 151 170 <para>So that &CCL; can locate its source code (and for other152 <para>So that &CCL; can locate its source code, and for other 171 153 reasons explained in 172 <xref linkend="Predefined-Logical-Hosts"/> )you should either put the154 <xref linkend="Predefined-Logical-Hosts"/>, you should either put the 173 155 <literal>ccl</literal> directory in the same directory as the 174 156 Clozure CL application, or else put the Clozure CL application … … 186 168 <sect2><title>Getting Clozure CL with Subversion</title> 187 169 <para>It is very easy to download, install, and build Clozure CL 188 using Subversion. Unless you're using the Mac Way, this is the 189 preferred way to get either the latest, or a specific version 190 of Clozure CL. Subversion is a source code control system 191 that is in wide usage. Most modern OSes come with subversion 192 pre-installed. A complete, buildable and runnable set of 193 Clozure CL sources and binaries can be retrieved by doing one 194 subversion checkout.</para> 195 196 <para>First, make sure that Subversion is installed on your 197 system. Bring up a command line shell and type: 170 using Subversion. This is the preferred way to get either the 171 latest, or a specific version of Clozure CL, unless you prefer 172 the Mac Way. Subversion is a source code control system that is 173 in wide usage. Most modern OSes come with subversion 174 pre-installed. A complete, buildable and runnable set of Clozure 175 CL sources and binaries can be retrieved by doing one subversion 176 checkout.</para> 177 178 179 <para>One subversion command will create a 180 <literal>ccl</literal> directory with runnable binaries, and a 181 complete set of buildable sources. To get the bleeding edge 182 Clozure CL for Darwin x8664, at the command line type:</para> 183 184 <programlisting> 185 <![CDATA[ 186 svn co http://svn.clozure.com/publicsvn/openmcl/trunk/darwinx8664/ccl]]> 187 </programlisting> 188 189 <para>To get the 1.2 version of Clozure CL type:</para> 190 <programlisting> 191 <![CDATA[ 192 svn co http://svn.clozure.com/publicsvn/openmcl/releases/1.2/darwinx8664/ccl]]> 193 </programlisting> 194 195 196 <para>These examples fetch the complete sources and binaries 197 for the Darwin X8664 build of &CCL;. You can fetch a different 198 version by substituting its name in place of 199 "darwinx8664". Current available versions are:</para> 200 201 <itemizedlist> 202 <listitem><para>darwinppc</para></listitem> 203 <listitem><para>darwinx8664</para></listitem> 204 <listitem><para>freebsdx8664</para></listitem> 205 <listitem><para>linuxppc</para></listitem> 206 <listitem><para>linuxx8664</para></listitem> 207 </itemizedlist> 208 209 <para>These distributions contain complete sources and 210 binaries. They use Subversion's "externals" features to share 211 common sources; the majority of source code is the same across 212 all versions.</para> 213 214 <para>Once the checkout is complete you can build Clozure CL by 215 running the lisp kernel and executing 216 the <literal>rebuild-ccl</literal> function. For 217 example:</para> 218 219 <programlisting> 220 <![CDATA[ 221 joe:ccl> ./dx86cl64 222 Welcome to Clozure Common Lisp Version 1.2 (DarwinX8664)! 223 ? (rebuild-ccl :full t) 224 <lots of compilation output> 225 ? (quit) 226 joe:ccl>]]> 227 </programlisting> 228 <sect3 id="Checking-Subversion-Installation"><title>Checking Subversion Installation</title> 229 <para>If <literal>svn co</literal> doesn't work, then make sure 230 that Subversion is installed on your system. Bring up a command 231 line shell and type: 198 232 <programlisting> 199 233 <![CDATA[ … … 215 249 obtaining and installing Subversion at 216 250 the <ulink url="http://subversion.tigris.org/project_packages.html">Subversion 217 Packages page</ulink>.</para> 218 219 <para>Create the directory where Clozure CL will live, <literal>cd</literal> to that directory, then type a Subversion checkout command. For example:</para> 220 221 <programlisting> 222 <![CDATA[ 223 joe:~> mkdir ccl 224 joe:~> cd ccl 225 joe:ccl> svn co http://svn.clozure.com/publicsvn/openmcl/trunk/darwinx8664]]> 226 </programlisting> 227 228 <para>This example fetches the complete sources and binaries 229 for the Darwin X8664 build of &CCL;. You can fetch a different 230 version by substituting its name in place of 231 "darwinx8664". Current available versions are:</para> 232 233 <itemizedlist> 234 <listitem><para>darwinppc</para></listitem> 235 <listitem><para>darwinx8664</para></listitem> 236 <listitem><para>freebsdx8664</para></listitem> 237 <listitem><para>linuxppc</para></listitem> 238 <listitem><para>linuxx8664</para></listitem> 239 </itemizedlist> 240 241 <para>These distributions contain complete sources and 242 binaries. They use Subversion's "externals" features to share 243 common sources; the majority of source code is the same across 244 all versions.</para> 245 246 <para>Once the checkout is complete you can build Clozure CL by 247 running the lisp kernel and executing 248 the <literal>rebuild-ccl</literal> function. For 249 example:</para> 250 251 <programlisting> 252 <![CDATA[ 253 joe:ccl> ./dx86cl64 254 Welcome to Clozure Common Lisp Version 1.2 (DarwinX8664)! 255 ? (rebuild-ccl :full t) 256 <lots of compilation output> 257 ? (quit) 258 joe:ccl>]]> 259 </programlisting> 251 Packages page</ulink>.</para></sect3> 252 260 253 </sect2> 261 254 262 255 <sect2><title>Tarballs</title> 263 <para>Tarballs are available at 264 <ulink url="ftp://clozure.com/pub/testing/"/>. 265 Download and extract one on 266 your local disk. Then edit 267 the &CCL; shell script to set 268 the value of 269 <varname>CCL_DEFAULT_DIRECTORY</varname> and start up the 270 appropriate Clozure CL kernel. See 271 <xref linkend="The-ccl-Shell-Script"/> for more 272 information about the &CCL; shell scripts.</para> 256 <para>Tarballs are available at <ulink 257 url="ftp://clozure.com/pub/testing/"/>. Download and extract 258 one on your local disk. Then edit the &CCL; shell script to set 259 the value of <varname>CCL_DEFAULT_DIRECTORY</varname> and start 260 up the appropriate Clozure CL kernel. See <xref 261 linkend="The-ccl-Shell-Script"/> for more information about the 262 &CCL; shell scripts.</para> 273 263 </sect2> 274 264 </sect1> … … 307 297 <para>To use the script:</para> 308 298 <orderedlist> 299 <listitem> 300 <para>Copy the script to a directory that is on your 301 <varname>PATH</varname>. This is often 302 <literal>/usr/local/bin</literal> or 303 <literal>~/bin</literal>. It is better to do this than to 304 add <literal>ccl/scripts</literal> to your 305 <varname>PATH</varname> since the script needs to be edited, 306 it will show up as modified to Subversion.</para> 307 </listitem> 309 308 <listitem> 310 309 <para>Edit the definition of … … 346 345 </warning></para> 347 346 </listitem> 348 <listitem>349 <para>Install the shell script somewhere on your shell's350 search path, or add the location of the shell script to351 your <literal>PATH</literal> environment variable.</para>352 </listitem>353 347 </orderedlist> 348 349 <para>Note that most people won't need both 350 <literal>ccl</literal> and <literal>ccl64</literal> scripts. 351 You only need both if you sometimes run 32-bit Clozure CL and 352 sometimes run 64-bit Clozure CL. You can rename the script that 353 you use to whatever you want. For example, if you are on a 354 64-bit system, and you only use Clozure CL in 64-bit mode, then 355 you can rename <literal>ccl64</literal> to 356 <literal>ccl</literal> so that you only need to type 357 "<literal>ccl</literal>" to run it.</para> 354 358 355 359 <para>Once this is done, it should be possible to invoke &CCL; … … 358 362 <programlisting> 359 363 > ccl [args ...] 360 Welcome to &CCL; Version whatever(DarwinPPC32)!364 Welcome to &CCL; Version 1.2 (DarwinPPC32)! 361 365 ? 362 366 </programlisting> 367 363 368 <para>The ccl shell script passes all of its arguments to the 364 &CCL; kernel. See <xref linkend="Invocation"/> for more 365 information about these arguments. When invoked this way, the 366 Lisp should be able to initialize the 367 <literal>"ccl:"</literal> logical host so that its 368 translations refer to the <literal>"ccl"</literal> 369 directory. To test this, you can call 370 <literal>probe-file</literal> in &CCL;'s read-eval-print 371 loop:</para> 369 &CCL; kernel. See <xref linkend="Invocation"/> for more 370 information about these arguments. When invoked this way, the 371 Lisp should be able to initialize the <literal>"ccl:"</literal> 372 logical host so that its translations refer to the 373 <literal>"ccl"</literal> directory. To test this, you can call 374 <literal>probe-file</literal> in &CCL;'s read-eval-print 375 loop:</para> 372 376 <programlisting> 373 377 ? (probe-file "ccl:level-1;level-1.lisp") ;returns the physical pathname of the file … … 736 740 <sect1 id="Example-Programs"> 737 741 <title>Example Programs</title> 738 <para>Beginning with release 0.9, a number (ok, a 739 <emphasis>small</emphasis> number, at least initially) of 740 example programs are distributed in the "ccl:examples;" 741 directory of the source distribution. See the 742 README-OPENMCL-EXAMPLES text file in that directory for 743 information about prerequisites and usage.</para> 742 <para>A number (ok, a <emphasis>small</emphasis> number), of 743 example programs are distributed in the "ccl:examples;" directory 744 of the source distribution. See the README-OPENMCL-EXAMPLES text 745 file in that directory for information about prerequisites and 746 usage.</para> 744 747 <para>Some of the example programs are derived from C examples 745 748 in textbooks, etc.; in those cases, the original author and work -
release/1.2/source/doc/src/modifying.xml
r8993 r9200 1 1 <?xml version="1.0" encoding="utf-8"?> 2 2 <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ 3 <!ENTITY rest "<varname>&rest</varname>">4 <!ENTITY key "<varname>&key</varname>">5 <!ENTITY optional "<varname>&optional</varname>">6 <!ENTITY body "<varname>&body</varname>">7 <!ENTITY aux "<varname>&aux</varname>">8 <!ENTITY allow-other-keys "<varname>&allow-other-keys</varname>">9 <!ENTITY CCL "Clozure CL">10 ]>11 12 <chapter id="Modifying-CCL">13 <title>Modifying &CCL;</title>14 15 <sect1 id="Contributing-Code-Back-to-the-CCL-Project">16 <title>Contributing Code Back to the &CCL; Project</title>17 <para>This section is a placeholder, added as of August 2004. The3 <!ENTITY rest "<varname>&rest</varname>"> 4 <!ENTITY key "<varname>&key</varname>"> 5 <!ENTITY optional "<varname>&optional</varname>"> 6 <!ENTITY body "<varname>&body</varname>"> 7 <!ENTITY aux "<varname>&aux</varname>"> 8 <!ENTITY allow-other-keys "<varname>&allow-other-keys</varname>"> 9 <!ENTITY CCL "Clozure CL"> 10 ]> 11 12 <chapter id="Modifying-CCL"> 13 <title>Modifying &CCL;</title> 14 15 <sect1 id="Contributing-Code-Back-to-the-CCL-Project"> 16 <title>Contributing Code Back to the &CCL; Project</title> 17 <para>This section is a placeholder, added as of August 2004. The 18 18 full text is being written, and will be added as soon as it is 19 19 available.</para> 20 </sect1>21 22 <sect1 id="Using-CCL-in--development--and-in--user--mode">23 <title>Using &CCL; in "development" and in "user" mode</title>24 25 <para>As it's distributed, &CCL; starts up with *PACKAGE* set26 t o the CL-USER package and with most predefined functions and20 </sect1> 21 22 <sect1 id="Using-CCL-in--development--and-in--user--mode"> 23 <title>Using &CCL; in "development" and in "user" mode</title> 24 25 <para>As it's distributed, &CCL; starts up with *PACKAGE* set to 26 the CL-USER package and with most predefined functions and 27 27 methods protected against accidental redefinition. The package 28 setting is of course a requirement of ANSI CL, whilethe29 protection protection is intended to catch certain types of30 programming errors (accidentally redefining a CL or CCL31 function) before those errors have a chance to do much32 damage.</para>33 <para>These settings may make using &CCL; to develop &CCL; a34 bit more awkward, since much of that process assumes that the35 CCL package is current (and a primary purpose of that process is36 to redefine some "predefined, builtin functions".) The standard,37 "routine" ways of building &CCL; from sources (see ) -38 COMPILE-CCL, XCOMPILE-CCL, and XLOAD-LEVEL-0 - bind *PACKAGE* to39 the "CCL" package and enable the redefinition of predefined40 functions; the symbols COMPILE-CCL, XCOMPILE-CCL, and28 setting is of course a requirement of ANSI CL, and the 29 protection of predifined functions and methods is intended to 30 catch certain types of programming errors (accidentally 31 redefining a CL or CCL function) before those errors have a 32 chance to do much damage.</para> 33 <para>These settings may make using &CCL; to develop &CCL; a bit 34 awkward, because much of that process assumes you are working in 35 the CCL package is current, and a primary purpose of &CCL; 36 development is to redefine some predefined, builtin functions. 37 The standard, "routine" ways of building &CCL; from sources (see 38 ) - COMPILE-CCL, XCOMPILE-CCL, and XLOAD-LEVEL-0 - bind 39 *PACKAGE* to the "CCL" package and enable the redefinition of 40 predefined functions; the symbols COMPILE-CCL, XCOMPILE-CCL, and 41 41 XLOAD-LEVEL-0 are additionally now exported from the "CCL" 42 42 package.</para> 43 <para>Some other (more ad-hoc) ways of doing development on44 &CCL; -compiling and/or loading individual files,45 incrementally redefining individual functions - may be awkward46 unless one reverts to the mode of operation which was47 traditionally offered in &CCL;. (Some &CCL; source files -43 <para>Some other (more ad-hoc) ways of doing development on 44 &CCL;—compiling and/or loading individual files, 45 incrementally redefining individual functions—may be 46 awkward unless one reverts to the mode of operation which was 47 traditionally offered in &CCL;. Some &CCL; source files - 48 48 especially those that comprise the bootstrapping image sources 49 49 and the first few files in the "cold load" sequence - are 50 50 compiled and loaded in the "CCL" package but don't contain 51 51 (IN-PACKAGE "CCL") forms, since IN-PACKAGE doesn't work until 52 later in the cold load sequence. )</para>53 <para>The somewhat bizarre behavior of both SET-USER-ENVIRONMENT52 later in the cold load sequence.</para> 53 <para>The somewhat bizarre behavior of both SET-USER-ENVIRONMENT 54 54 and SET-DEVELOPMENT-ENVIRONMENT with respect to the special 55 55 variables they affect is intended to allow those constructs to … … 59 59 though using both constructs within the same LOAD call would 60 60 likely be pretty confusing.</para> 61 <para>"user" and "development" are otherwise very generic terms;61 <para>"user" and "development" are otherwise very generic terms; 62 62 here they're intended to enforce the distinction between "using" 63 63 &CCL; and "developing" it.</para> 64 <para>The initial environment from which &CCL; images are64 <para>The initial environment from which &CCL; images are 65 65 saved is one where (SET-USER-ENVIRONMENT T) has just been 66 66 called; in previous versions, it was effectively as if 67 67 (SET-DEVELOPMENT-ENVIRONMENT T) had just been called.</para> 68 <para>Hopefully, most users of &CCL; can safely ignore these68 <para>Hopefully, most users of &CCL; can safely ignore these 69 69 issues most of the time. Note that doing (SET-USER-ENVIRONMENT 70 70 T) after loading one's own code (or 3rd-party code) into &CCL; 71 71 would protect that code (as well as &CCL;'s) from accidental 72 72 redefinition; that may be useful in some cases.</para> 73 </sect1>74 75 <sect1 id="kernel-debugger">76 <title>The Kernel Debugger</title>77 <para> In a perfect world, something like this couldn't73 </sect1> 74 75 <sect1 id="kernel-debugger"> 76 <title>The Kernel Debugger</title> 77 <para> In a perfect world, something like this couldn't 78 78 happen:</para> 79 <programlisting>79 <programlisting> 80 80 Welcome to &CCL; Version x.y! 81 81 ? (defun foo (x) … … 87 87 Unhandled exception 11 at 0x300e90c8, context->regs at #x7ffff6b8 88 88 Continue/Debugger/eXit <enter>? 89 </programlisting>90 91 <para>As you may have noticed, it's not a perfect world; it's rare92 that the cause (attempting to reference the CDR of -1, and therefore93 accessing unmapped memory near location 0) of this effect (an94 "Unhandled exception ..." message) is so obvious.</para>95 <para>The addresses printed in the message above aren't very useful96 unless you're debugging the kernel with GDB (and they're often97 very useful if you are.)</para>98 <para>Aside from causing an exception that the lisp kernel doesn't99 know how to handle, one can also enter the kernel debugger (more)100 deliberately:</para>101 102 <programlisting>89 </programlisting> 90 91 <para>As you may have noticed, it's not a perfect world; it's rare 92 that the cause (attempting to reference the CDR of -1, and therefore 93 accessing unmapped memory near location 0) of this effect (an 94 "Unhandled exception ..." message) is so obvious.</para> 95 <para>The addresses printed in the message above aren't very useful 96 unless you're debugging the kernel with GDB (and they're often 97 very useful if you are.)</para> 98 <para>Aside from causing an exception that the lisp kernel doesn't 99 know how to handle, one can also enter the kernel debugger (more) 100 deliberately:</para> 101 102 <programlisting> 103 103 ? (defun classify (n) 104 (cond ((> n 0) "Greater")105 ((< n 0) "Less")106 (t107 ;;; Sheesh ! What else could it be ?108 (ccl::bug "I give up. How could this happen ?"))))104 (cond ((> n 0) "Greater") 105 ((< n 0) "Less") 106 (t 107 ;; Sheesh ! What else could it be ? 108 (ccl::bug "I give up. How could this happen ?")))) 109 109 CLASSIFY 110 110 … … 114 114 ? for help 115 115 [12345] &CCL; kernel debugger: 116 </programlisting>117 118 <para>CCL::BUG isn't quite the right tool for this example (a119 call to BREAK or PRINT might do a better job of clearing up the120 mystery), but it's sometimes helpful when those other tools121 can't be used. The lisp error system notices, for instance, if122 attempts to signal errors themselves cause errors to be123 signaled; this sort of thing can happen if CLOS or the I/O124 system are broken or missing. After some small number of125 recursive errors, the error system gives up and calls126 CCL::BUG.</para>127 <para>If one enters a '?' at the kernel debugger prompt, one128 will see output like:</para>129 130 <programlisting>116 </programlisting> 117 118 <para>CCL::BUG isn't quite the right tool for this example (a 119 call to BREAK or PRINT might do a better job of clearing up the 120 mystery), but it's sometimes helpful when those other tools 121 can't be used. The lisp error system notices, for instance, if 122 attempts to signal errors themselves cause errors to be 123 signaled; this sort of thing can happen if CLOS or the I/O 124 system are broken or missing. After some small number of 125 recursive errors, the error system gives up and calls 126 CCL::BUG.</para> 127 <para>If one enters a '?' at the kernel debugger prompt, one 128 will see output like:</para> 129 130 <programlisting> 131 131 (S) Find and describe symbol matching specified name 132 132 (B) Show backtrace … … 134 134 (K) Kill &CCL; process 135 135 (?) Show this help 136 </programlisting>137 138 <para>CCL::BUG just does an FF-CALL into the lisp kernel. If139 the kernel debugger was invoked because of an unhandled140 exception (such as an illegal memory reference) the OS kernel141 saves the machine state ("context") in a data structure for us,142 and in that case some additional options can be used to display143 the contents of the registers at the point of the144 exception. Another function - CCL::DBG -causes a special145 exception to be generated and enters the lisp kernel debugger146 with a non-null "context":</para>147 148 <programlisting>136 </programlisting> 137 138 <para>CCL::BUG just does an FF-CALL into the lisp kernel. If 139 the kernel debugger was invoked because of an unhandled 140 exception (such as an illegal memory reference) the OS kernel 141 saves the machine state ("context") in a data structure for us, 142 and in that case some additional options can be used to display 143 the contents of the registers at the point of the 144 exception. Another function—CCL::DBG—causes a special 145 exception to be generated and enters the lisp kernel debugger 146 with a non-null "context":</para> 147 148 <programlisting> 149 149 ? (defun classify2 (n) 150 (cond ((> n 0) "Greater")151 ((< n 0) "Less")152 (t (dbg n))))150 (cond ((> n 0) "Greater") 151 ((< n 0) "Less") 152 (t (dbg n)))) 153 153 CLASSIFY2 154 154 155 155 ? (classify2 0) 156 156 Lisp Breakpoint 157 While executing: #<Function CLASSIFY2 #x08476cfe>157 While executing: #<Function CLASSIFY2 #x08476cfe> 158 158 ? for help 159 159 [12345] &CCL; kernel debugger: ? … … 170 170 (K) Kill &CCL; process 171 171 (?) Show this help 172 </programlisting>173 174 <para>CCL::DBG takes an argument, whose value is copied into the register175 that &CCL; uses to return a function's primary value (arg_z, which176 is r23 on the PowerPC). If we were to choose the (L) option at this point,177 we'd see a dislay like:</para>178 179 <programlisting>172 </programlisting> 173 174 <para>CCL::DBG takes an argument, whose value is copied into the register 175 that &CCL; uses to return a function's primary value (arg_z, which 176 is r23 on the PowerPC). If we were to choose the (L) option at this point, 177 we'd see a dislay like:</para> 178 179 <programlisting> 180 180 rnil = 0x01836015 181 181 nargs = 0 … … 196 196 r25 (save6) = () 197 197 r24 (save7) = () 198 </programlisting> 199 200 <para>From this we can conclude that the problematic argument to CLASSIFY2 201 was 0 (see r23/arg_z), and that I need to work on a better example.</para> 202 <para>The R option shows the values of the ALU (and PPC branch unit) 203 registers in hex; the F option shows the values of the FPU registers.</para> 204 <para>The (B) option shows a raw stack backtrace; it'll try to 205 identify foreign functions as well as lisp functions. (Foreign function 206 names are guesses based on the nearest preceding exported symbol.)</para> 207 <para>If you ever unexpectedly find yourself in the "lisp kernel 208 debugger", the output of the (L) and (B) options are often the most 209 helpful things to include in a bug report.</para> 210 </sect1> 211 212 <sect1 id="Using-AltiVec-in-CCL-LAP-functions"> 213 <title>Using AltiVec in &CCL; LAP functions</title> 214 215 <sect2 id="Overview--16-"> 216 <title>Overview</title> 217 <para>It's now possible to use AltiVec instructions in PPC LAP 218 (assembler) functions.</para> 219 <para>The lisp kernel detects the presence or absence of 220 AltiVec and preserves AltiVec state on lisp thread switch and 221 in response to exceptions, but the implementation doesn't 222 otherwise use vector operations.</para> 223 <para>This document doesn't document PPC LAP programming in 224 general. Ideally, there would be some document that 225 did.</para> 226 <para>This document does explain AltiVec register-usage 227 conventions in &CCL; and explains the use of some lap macros 228 that help to enforce those conventions.</para> 229 <para>All of the global symbols described below are exported 230 from the CCL package. Note that lap macro names, ppc 231 instruction names, and (in most cases) register names are 232 treated as strings, so this only applies to functions and 233 global variable names.</para> 234 <para>Much of the &CCL; support for AltiVec LAP programming 235 is based on work contributed to MCL by Shannon Spires.</para> 236 </sect2> 237 238 <sect2 id="Register-usage-conventions"> 239 <title>Register usage conventions</title> 240 <para>&CCL; LAP functions that use AltiVec instructions must 241 interoperate with each other and with C functions; that 242 suggests that they follow C AltiVec register usage 243 conventions. (vr0-vr1 scratch, vr2-vr13 parameters/return 244 value, vr14-vr19 temporaries, vr20-vr31 callee-save 245 non-volatile registers.)</para> 246 <para>The EABI (Embedded Application Binary Interface) used in 247 LinuxPPC doesn't ascribe particular significance to the vrsave 248 special-purpose register; on other platforms (notably MacOS), 249 it's used as a bitmap which indicates to system-level code 250 which vector registers contain meaningful values.</para> 251 <para>The WITH-ALTIVEC-REGISTERS lapmacro generates code which 252 which saves, updates, and restores VRSAVE on platforms where 253 this is required (as indicated by the value of the special 254 variable which controls this) and ignores VRSAVE on platforms 255 that don't require it to be maintained.</para> 256 <para>On all PPC platforms, it's necessary to save any non-volatile 257 vector registers (vr20 .. vr31) before assigning to them and to restore 258 such registers before returning to the caller.</para> 259 <para>On platforms that require that VRSAVE be maintained, it's not 260 necessary to mention the "use" of vector registers that are 261 used as incoming parameters. It's not incorrect to mention their use 262 in a WITH-ALTIVEC-REGISTERS form, but it may be unnecessary in many 263 interesting cases. One can likewise assume that the caller of any function 264 that returns a vector value (in vr2 has already set the appropriate bit in 265 VRSAVE to indicate that this register is live. One could therefore write a 266 leaf function that added the bytes in vr3 and vr2 and returned the result 267 in vr2 as:</para> 268 269 <programlisting> 198 </programlisting> 199 200 <para>From this we can conclude that the problematic argument to CLASSIFY2 201 was 0 (see r23/arg_z), and that I need to work on a better example.</para> 202 <para>The R option shows the values of the ALU (and PPC branch unit) 203 registers in hex; the F option shows the values of the FPU registers.</para> 204 <para>The (B) option shows a raw stack backtrace; it'll try to 205 identify foreign functions as well as lisp functions. (Foreign function 206 names are guesses based on the nearest preceding exported symbol.)</para> 207 <para>If you ever unexpectedly find yourself in the "lisp kernel 208 debugger", the output of the (L) and (B) options are often the most 209 helpful things to include in a bug report.</para> 210 </sect1> 211 212 <sect1 id="Using-AltiVec-in-CCL-LAP-functions"> 213 <title>Using AltiVec in &CCL; LAP functions</title> 214 215 <sect2 id="Overview--16-"> 216 <title>Overview</title> 217 <para>It's now possible to use AltiVec instructions in PPC LAP 218 (assembler) functions.</para> 219 <para>The lisp kernel detects the presence or absence of 220 AltiVec and preserves AltiVec state on lisp thread switch and 221 in response to exceptions, but the implementation doesn't 222 otherwise use vector operations.</para> 223 <para>This document doesn't document PPC LAP programming in 224 general. Ideally, there would be some document that 225 did.</para> 226 <para>This document does explain AltiVec register-usage 227 conventions in &CCL; and explains the use of some lap macros 228 that help to enforce those conventions.</para> 229 <para>All of the global symbols described below are exported 230 from the CCL package. Note that lap macro names, ppc 231 instruction names, and (in most cases) register names are 232 treated as strings, so this only applies to functions and 233 global variable names.</para> 234 <para>Much of the &CCL; support for AltiVec LAP programming 235 is based on work contributed to MCL by Shannon Spires.</para> 236 </sect2> 237 238 <sect2 id="Register-usage-conventions"> 239 <title>Register usage conventions</title> 240 <para>&CCL; LAP functions that use AltiVec instructions must 241 interoperate with each other and with C functions; that fact 242 suggests that they follow C AltiVec register usage 243 conventions. (vr0-vr1 scratch, vr2-vr13 parameters/return 244 value, vr14-vr19 temporaries, vr20-vr31 callee-save 245 non-volatile registers.)</para> 246 <para>The EABI (Embedded Application Binary Interface) used in 247 LinuxPPC doesn't ascribe particular significance to the vrsave 248 special-purpose register; on other platforms (notably MacOS), 249 it's used as a bitmap which indicates to system-level code 250 which vector registers contain meaningful values.</para> 251 <para>The WITH-ALTIVEC-REGISTERS lap macro generates code that 252 saves, updates, and restores VRSAVE on platforms where this is 253 required (as indicated by the value of the special variable 254 that controls this behavior) and ignores VRSAVE on platforms 255 that don't require it to be maintained.</para> 256 <para>On all PPC platforms, it's necessary to save any non-volatile 257 vector registers (vr20 .. vr31) before assigning to them and to restore 258 such registers before returning to the caller.</para> 259 <para>On platforms that require that VRSAVE be maintained, it's 260 not necessary to mention the "use" of vector registers that 261 are used as incoming parameters. It's not incorrect to mention 262 their use in a WITH-ALTIVEC-REGISTERS form, but it may be 263 unnecessary in many interesting cases. One can likewise assume 264 that the caller of any function that returns a vector value in 265 vr2 has already set the appropriate bit in VRSAVE to indicate 266 that this register is live. One could therefore write a leaf 267 function that added the bytes in vr3 and vr2 and returned the 268 result in vr2 as:</para> 269 270 <programlisting> 270 271 (defppclapfunction vaddubs ((y vr3) (z vr2)) 271 272 (vaddubs z y z) 272 273 (blr)) 273 </programlisting>274 275 <para>When vector registers that aren't incoming parameters are used276 in a LAP function, WITH-ALTIVEC-REGISTERS takes care of maintaining VRSAVE277 and of saving/restoring any non-volatile vector registers:</para>278 279 <programlisting>274 </programlisting> 275 276 <para>When vector registers that aren't incoming parameters are used 277 in a LAP function, WITH-ALTIVEC-REGISTERS takes care of maintaining VRSAVE 278 and of saving/restoring any non-volatile vector registers:</para> 279 280 <programlisting> 280 281 (defppclapfunction load-array ((n arg_z)) 281 282 (check-nargs 1) 282 283 (with-altivec-registers (vr1 vr2 vr3 vr27) ; Clobbers imm0 283 284 (li imm0 arch::misc-data-offset) 284 (lvx vr1 arg_z imm0) ; load MSQ285 (lvsl vr27 arg_z imm0) ; set the permute vector286 (addi imm0 imm0 16) ; address of LSQ287 (lvx vr2 arg_z imm0) ; load LSQ288 (vperm vr3 vr1 vr2 vr27) ; aligned result appears in VR3289 (dbg t)) ; Look at result in some debugger285 (lvx vr1 arg_z imm0) ; load MSQ 286 (lvsl vr27 arg_z imm0) ; set the permute vector 287 (addi imm0 imm0 16) ; address of LSQ 288 (lvx vr2 arg_z imm0) ; load LSQ 289 (vperm vr3 vr1 vr2 vr27) ; aligned result appears in VR3 290 (dbg t)) ; Look at result in some debugger 290 291 (blr)) 291 </programlisting> 292 293 <para>AltiVec registers are not preserved by CATCH and UNWIND-PROTECT. 294 Since AltiVec is only accessible from LAP in &CCL; and since LAP 295 functions rarely use high- level control structures, this should rarely be 296 a problem in practice.</para> 297 <para>LAP functions which use non-volatile vector registers and which call 298 (Lisp ?) code which may use CATCH or UNWIND-PROTECT should save those 299 vector registers before such a call and restore them on return. This is 300 one of the intended uses of the WITH-VECTOR-BUFFER lap macro.</para> 301 </sect2> 302 </sect1> 303 304 <sect1 id="Development-Mode-Dictionary"> 305 <title>Development-Mode Dictionary</title> 306 307 <refentry id="v_warn-if-redefine-kernel"> 308 <indexterm zone="v_warn-if-redefine-kernel"> 309 <primary>*warn-if-redefine-kernel</primary> 310 </indexterm> 311 312 <refnamediv> 313 <refname>*WARN-IF-REDEFINE-KERNEL*</refname> 314 <refpurpose></refpurpose> 315 <refclass>Variable</refclass> 316 </refnamediv> 317 318 <refsect1> 319 <title>Description</title> 320 321 <para>When true, attempts to redefine (via DEFUN or DEFMETHOD) 322 functions and methods that are marked as being 323 "predefined" signal continuable errors.</para> 324 325 <para>Note that these are CERRORs, not warnings, and that 326 no lisp functions or methods have been defined in the kernel 327 in MCL or &CCL; since 1987 or so.</para> 328 </refsect1> 329 </refentry> 330 331 <refentry id="f_set-development-environment"> 332 <indexterm zone="f_set-development-environment"> 333 <primary>set-development-environment</primary> 334 </indexterm> 335 336 <refnamediv> 337 <refname>SET-DEVELOPMENT-ENVIRONMENT</refname> 338 <refpurpose></refpurpose> 339 <refclass>Function</refclass> 340 </refnamediv> 341 342 <refsynopsisdiv> 343 <synopsis><function>set-development-environment</function> 344 &optional; 345 unmark-builtin-functions</synopsis> 346 </refsynopsisdiv> 347 348 <refsect1> 349 <title>Description</title> 350 351 <para>Arranges that the outermost special bindings of *PACKAGE* 352 and *WARN-IF-REDEFINE-KERNEL* restore values of the "CCL" 353 package and NIL to these variables, respectively. If the optional 354 argument is true, marks all globally defined functions and methods 355 as being "not predefined" (this is a fairly expensive 356 operation.)</para> 357 </refsect1> 358 </refentry> 359 360 <refentry id="f_set-user-environment"> 361 <indexterm zone="f_set-user-environment"> 362 <primary>set-user-environment</primary> 363 </indexterm> 364 365 <refnamediv> 366 <refname>SET-USER-ENVIRONMENT</refname> 367 <refpurpose></refpurpose> 368 <refclass>Function</refclass> 369 </refnamediv> 370 371 <refsynopsisdiv> 372 <synopsis><function>set-user-environment</function> 373 &optional; mark-builtin-functions</synopsis> 374 </refsynopsisdiv> 375 376 <refsect1> 377 <title>Description</title> 378 379 <para>Arranges that the outermost special bindings of *PACKAGE* 380 and *WARN-IF-REDEFINE-KERNEL* restore values of the 381 "CL-USER" package and T to these variables, respectively. 382 If the optional argument is true, marks all globally defined 383 functions and methods as being "predefined" (this is a 384 fairly expensive operation.)</para> 385 </refsect1> 386 </refentry> 387 <refentry id="v_altivec-available"> 388 <indexterm zone="v_altivec-available"> 389 <primary>*altivec-available*</primary> 390 </indexterm> 391 392 <refnamediv> 393 <refname>*ALTIVEC-AVAILABLE*</refname> 394 <refpurpose></refpurpose> 395 <refclass>Variable</refclass> 396 </refnamediv> 397 398 <refsect1> 399 <title>Description</title> 400 <para>This variable is initialized each time an &CCL; session 401 starts based on information provided by the lisp kernel. Its value 402 is true if AltiVec is present and false otherwise. This variable 403 shouldn't be set by user code.</para> 404 </refsect1> 405 </refentry> 406 407 <refentry id="f_altivec-available-p"> 408 <indexterm zone="f_altivec-available-p"> 409 <primary>altivec-available-p</primary> 410 </indexterm> 411 412 <refnamediv> 413 <refname>ALTIVEC-AVAILABLE-P</refname> 414 <refpurpose></refpurpose> 415 <refclass>Function</refclass> 416 </refnamediv> 417 418 <refsynopsisdiv> 419 <synopsis><function>altivec-available-p</function></synopsis> 420 </refsynopsisdiv> 421 422 <refsect1> 423 <title>Description</title> 424 425 <para>Returns non-NIL if AltiVec is available.</para> 426 </refsect1> 427 </refentry> 428 429 <refentry id="v_altivec-lapmacros-maintain-vrsave-p"> 430 <indexterm zone="v_altivec-lapmacros-maintain-vrsave-p"> 431 <primary>*altivec-lapmacros-maintain-vrsave-p*</primary> 432 </indexterm> 433 434 <refnamediv> 435 <refname>*ALTIVEC-LAPMACROS-MAINTAIN-VRSAVE-P*</refname> 436 <refpurpose></refpurpose> 437 <refclass>Variable</refclass> 438 </refnamediv> 439 440 <refsect1> 441 <title>Description</title> 442 443 <para>Intended to control the expansion of certain lap macros. 444 Initialized to NIL on LinuxPPC; initialized to T on platforms 445 (such as MacOS X/Darwin) that require that the VRSAVE SPR contain 446 a bitmask of active vector registers at all times.</para> 447 </refsect1> 448 </refentry> 449 450 <refentry id="lapm_with-altivec-registers"> 451 <indexterm zone="lapm_with-altivec-registers"> 452 <primary>with-altivec-registers</primary> 453 </indexterm> 454 455 <refnamediv> 456 <refname>WITH-ALTIVEC-REGISTERS</refname> 457 <refpurpose></refpurpose> 458 <refclass>LAP Macro</refclass> 459 </refnamediv> 460 461 <refsynopsisdiv> 462 <synopsis><function>with-altivec-registers</function> 463 reglist &body; body</synopsis> 464 </refsynopsisdiv> 465 466 <refsect1> 467 <title>Arguments and Values</title> 468 469 <variablelist> 470 <varlistentry> 471 <term>reglist</term> 472 473 <listitem> 474 <para>A list of vector register names (vr0 .. vr31).</para> 475 </listitem> 476 </varlistentry> 477 478 <varlistentry> 479 <term>body</term> 480 481 <listitem> 482 <para>A sequence of PPC LAP instructions.</para> 483 </listitem> 484 </varlistentry> 485 </variablelist> 486 </refsect1> 487 488 <refsect1> 489 <title>Description</title> 490 491 <para>Specifies the set of AltiVec registers used in body. If 492 *altivec-lapmacros-maintain-vrsave-p* is true when the macro is 493 expanded, generates code to save the VRSAVE SPR and updates VRSAVE 494 to include a bitmask generated from the specified register list. 495 Generates code which saves any non-volatile vector registers which 496 appear in the register list, executes body, and restores the saved 497 non-volatile vector registers (and, if 498 *altivec-lapmacros-maintain-vrsave-p* is true, restores VRSAVE as 499 well. Uses the IMM0 register (r3) as a temporary.</para> 500 </refsect1> 501 </refentry> 502 503 <refentry id="lapm_with-vector-buffer"> 504 <indexterm zone="lapm_with-vector-buffer"> 505 <primary>with-vector-buffer</primary> 506 </indexterm> 507 508 <refnamediv> 509 <refname>WITH-VECTOR-BUFFER</refname> 510 <refpurpose></refpurpose> 511 <refclass>LAP Macro</refclass> 512 </refnamediv> 513 514 <refsynopsisdiv> 515 <synopsis>with-vector-buffer base n &body; body</synopsis> 516 </refsynopsisdiv> 517 518 <refsect1> 519 <title>Arguments and Values</title> 520 521 <variablelist> 522 <varlistentry> 523 <term>base</term> 524 525 <listitem> 526 <para>Any available general-purpose register.</para> 527 </listitem> 528 </varlistentry> 529 530 <varlistentry> 531 <term>n</term> 532 533 <listitem> 534 <para>An integer between 1 and 254, inclusive. (Should 535 typically be much, much closer to 1.) Specifies the size of 536 the buffer, in 16-byte units.</para> 537 </listitem> 538 </varlistentry> 539 540 <varlistentry> 541 <term>body</term> 542 543 <listitem> 544 <para>A sequence of PPC LAP instructions.</para> 545 </listitem> 546 </varlistentry> 547 </variablelist> 548 </refsect1> 549 550 <refsect1> 551 <title>Description</title> 552 <para>Generates code which allocates a 16-byte aligned buffer 553 large enough to contain N vector registers; the GPR base points to 554 the lowest address of this buffer. After processing body, the 555 buffer will be deallocated. The body should preserve the value of 556 base as long as it needs to reference the buffer. It's 557 intended that base be used as a base register in stvx and lvx 558 instructions within the body.</para> 559 </refsect1> 560 </refentry> 561 </sect1> 562 </chapter> 292 </programlisting> 293 294 <para>AltiVec registers are not preserved by CATCH and UNWIND-PROTECT. 295 Since AltiVec is only accessible from LAP in &CCL; and since LAP 296 functions rarely use high-level control structures, this should rarely be 297 a problem in practice.</para> 298 <para>LAP functions that use non-volatile vector registers and 299 that call (Lisp ?) code which may use CATCH or UNWIND-PROTECT 300 should save those vector registers before such a call and 301 restore them on return. This is one of the intended uses of 302 the WITH-VECTOR-BUFFER lap macro.</para> 303 </sect2> 304 </sect1> 305 306 <sect1 id="Development-Mode-Dictionary"> 307 <title>Development-Mode Dictionary</title> 308 309 <refentry id="v_warn-if-redefine-kernel"> 310 <indexterm zone="v_warn-if-redefine-kernel"> 311 <primary>*warn-if-redefine-kernel</primary> 312 </indexterm> 313 314 <refnamediv> 315 <refname>*WARN-IF-REDEFINE-KERNEL*</refname> 316 <refpurpose></refpurpose> 317 <refclass>Variable</refclass> 318 </refnamediv> 319 320 <refsect1> 321 <title>Description</title> 322 323 <para>When true, attempts to redefine (via DEFUN or DEFMETHOD) 324 functions and methods that are marked as being 325 "predefined" signal continuable errors.</para> 326 327 <para>Note that these are CERRORs, not warnings, and that 328 no lisp functions or methods have been defined in the kernel 329 in MCL or &CCL; since 1987 or so.</para> 330 </refsect1> 331 </refentry> 332 333 <refentry id="f_set-development-environment"> 334 <indexterm zone="f_set-development-environment"> 335 <primary>set-development-environment</primary> 336 </indexterm> 337 338 <refnamediv> 339 <refname>SET-DEVELOPMENT-ENVIRONMENT</refname> 340 <refpurpose></refpurpose> 341 <refclass>Function</refclass> 342 </refnamediv> 343 344 <refsynopsisdiv> 345 <synopsis><function>set-development-environment</function> 346 &optional; 347 unmark-builtin-functions</synopsis> 348 </refsynopsisdiv> 349 350 <refsect1> 351 <title>Description</title> 352 353 <para>Arranges that the outermost special bindings of *PACKAGE* 354 and *WARN-IF-REDEFINE-KERNEL* restore values of the "CCL" 355 package and NIL to these variables, respectively. If the optional 356 argument is true, marks all globally defined functions and methods 357 as being "not predefined" (this is a fairly expensive 358 operation.)</para> 359 </refsect1> 360 </refentry> 361 362 <refentry id="f_set-user-environment"> 363 <indexterm zone="f_set-user-environment"> 364 <primary>set-user-environment</primary> 365 </indexterm> 366 367 <refnamediv> 368 <refname>SET-USER-ENVIRONMENT</refname> 369 <refpurpose></refpurpose> 370 <refclass>Function</refclass> 371 </refnamediv> 372 373 <refsynopsisdiv> 374 <synopsis><function>set-user-environment</function> 375 &optional; mark-builtin-functions</synopsis> 376 </refsynopsisdiv> 377 378 <refsect1> 379 <title>Description</title> 380 381 <para>Arranges that the outermost special bindings of *PACKAGE* 382 and *WARN-IF-REDEFINE-KERNEL* restore values of the 383 "CL-USER" package and T to these variables, respectively. 384 If the optional argument is true, marks all globally defined 385 functions and methods as being "predefined" (this is a 386 fairly expensive operation.)</para> 387 </refsect1> 388 </refentry> 389 <refentry id="v_altivec-available"> 390 <indexterm zone="v_altivec-available"> 391 <primary>*altivec-available*</primary> 392 </indexterm> 393 394 <refnamediv> 395 <refname>*ALTIVEC-AVAILABLE*</refname> 396 <refpurpose></refpurpose> 397 <refclass>Variable</refclass> 398 </refnamediv> 399 400 <refsect1> 401 <title>Description</title> 402 <para>This variable is initialized each time an &CCL; session 403 starts based on information provided by the lisp kernel. Its value 404 is true if AltiVec is present and false otherwise. This variable 405 shouldn't be set by user code.</para> 406 </refsect1> 407 </refentry> 408 409 <refentry id="f_altivec-available-p"> 410 <indexterm zone="f_altivec-available-p"> 411 <primary>altivec-available-p</primary> 412 </indexterm> 413 414 <refnamediv> 415 <refname>ALTIVEC-AVAILABLE-P</refname> 416 <refpurpose></refpurpose> 417 <refclass>Function</refclass> 418 </refnamediv> 419 420 <refsynopsisdiv> 421 <synopsis><function>altivec-available-p</function></synopsis> 422 </refsynopsisdiv> 423 424 <refsect1> 425 <title>Description</title> 426 427 <para>Returns non-NIL if AltiVec is available.</para> 428 </refsect1> 429 </refentry> 430 431 <refentry id="v_altivec-lapmacros-maintain-vrsave-p"> 432 <indexterm zone="v_altivec-lapmacros-maintain-vrsave-p"> 433 <primary>*altivec-lapmacros-maintain-vrsave-p*</primary> 434 </indexterm> 435 436 <refnamediv> 437 <refname>*ALTIVEC-LAPMACROS-MAINTAIN-VRSAVE-P*</refname> 438 <refpurpose></refpurpose> 439 <refclass>Variable</refclass> 440 </refnamediv> 441 442 <refsect1> 443 <title>Description</title> 444 445 <para>Intended to control the expansion of certain lap macros. 446 Initialized to NIL on LinuxPPC; initialized to T on platforms 447 (such as MacOS X/Darwin) that require that the VRSAVE SPR contain 448 a bitmask of active vector registers at all times.</para> 449 </refsect1> 450 </refentry> 451 452 <refentry id="lapm_with-altivec-registers"> 453 <indexterm zone="lapm_with-altivec-registers"> 454 <primary>with-altivec-registers</primary> 455 </indexterm> 456 457 <refnamediv> 458 <refname>WITH-ALTIVEC-REGISTERS</refname> 459 <refpurpose></refpurpose> 460 <refclass>LAP Macro</refclass> 461 </refnamediv> 462 463 <refsynopsisdiv> 464 <synopsis><function>with-altivec-registers</function> 465 reglist &body; body</synopsis> 466 </refsynopsisdiv> 467 468 <refsect1> 469 <title>Arguments and Values</title> 470 471 <variablelist> 472 <varlistentry> 473 <term>reglist</term> 474 475 <listitem> 476 <para>A list of vector register names (vr0 .. vr31).</para> 477 </listitem> 478 </varlistentry> 479 480 <varlistentry> 481 <term>body</term> 482 483 <listitem> 484 <para>A sequence of PPC LAP instructions.</para> 485 </listitem> 486 </varlistentry> 487 </variablelist> 488 </refsect1> 489 490 <refsect1> 491 <title>Description</title> 492 493 <para>Specifies the set of AltiVec registers used in body. If 494 *altivec-lapmacros-maintain-vrsave-p* is true when the macro is 495 expanded, generates code to save the VRSAVE SPR and updates VRSAVE 496 to include a bitmask generated from the specified register list. 497 Generates code which saves any non-volatile vector registers which 498 appear in the register list, executes body, and restores the saved 499 non-volatile vector registers (and, if 500 *altivec-lapmacros-maintain-vrsave-p* is true, restores VRSAVE as 501 well. Uses the IMM0 register (r3) as a temporary.</para> 502 </refsect1> 503 </refentry> 504 505 <refentry id="lapm_with-vector-buffer"> 506 <indexterm zone="lapm_with-vector-buffer"> 507 <primary>with-vector-buffer</primary> 508 </indexterm> 509 510 <refnamediv> 511 <refname>WITH-VECTOR-BUFFER</refname> 512 <refpurpose></refpurpose> 513 <refclass>LAP Macro</refclass> 514 </refnamediv> 515 516 <refsynopsisdiv> 517 <synopsis>with-vector-buffer base n &body; body</synopsis> 518 </refsynopsisdiv> 519 520 <refsect1> 521 <title>Arguments and Values</title> 522 523 <variablelist> 524 <varlistentry> 525 <term>base</term> 526 527 <listitem> 528 <para>Any available general-purpose register.</para> 529 </listitem> 530 </varlistentry> 531 532 <varlistentry> 533 <term>n</term> 534 535 <listitem> 536 <para>An integer between 1 and 254, inclusive. (Should 537 typically be much, much closer to 1.) Specifies the size of 538 the buffer, in 16-byte units.</para> 539 </listitem> 540 </varlistentry> 541 542 <varlistentry> 543 <term>body</term> 544 545 <listitem> 546 <para>A sequence of PPC LAP instructions.</para> 547 </listitem> 548 </varlistentry> 549 </variablelist> 550 </refsect1> 551 552 <refsect1> 553 <title>Description</title> 554 <para>Generates code which allocates a 16-byte aligned buffer 555 large enough to contain N vector registers; the GPR base points to 556 the lowest address of this buffer. After processing body, the 557 buffer will be deallocated. The body should preserve the value of 558 base as long as it needs to reference the buffer. It's 559 intended that base be used as a base register in stvx and lvx 560 instructions within the body.</para> 561 </refsect1> 562 </refentry> 563 </sect1> 564 </chapter> -
release/1.2/source/doc/src/using.xml
r9071 r9200 514 514 515 515 <para>&CCL; supports character names of the form 516 <literal>u+xxxx</literal> -where <literal>x</literal> is a516 <literal>u+xxxx</literal>—where <literal>x</literal> is a 517 517 sequence of one or more hex digits. The value of the hex digits 518 518 denotes the code of the character. The <literal>+</literal> … … 530 530 character names, look just below the definition for 531 531 <function>register-character-name</function> in 532 <literal>ccl:level-1;l1-reader.lisp</literal> see the complete 533 list of char</para> 532 <literal>ccl:level-1;l1-reader.lisp</literal>.</para> 534 533 </sect2> 535 534 … … 545 544 keyword (see <xref linkend="Character-Encodings"/>), an 546 545 external-format object created using 547 <function>CCL::MAKE-EXTERNAL-FORMAT</function> (see <xref546 <function>CCL::MAKE-EXTERNAL-FORMAT</function> (see <xref 548 547 linkend="f_make-external-format"/>), or a plist with keys: 549 548 <literal>:DOMAIN</literal>, <literal>:CHARACTER-ENCODING</literal> … … 650 649 </varlistentry> 651 650 <varlistentry> 652 <term> [result]</term>653 <listitem> 654 <para> [description]</para>651 <term>external-format</term> 652 <listitem> 653 <para>An external-format object as described above.</para> 655 654 </listitem> 656 655 </varlistentry> … … 661 660 <title>Description</title> 662 661 663 <para>Despite the function's name, it doesn't necessarily 664 create anew, unique EXTERNAL-FORMAT object: two calls to665 MAKE-EXTERNAL-FORMAT with the same arguments made in the 666 same dynamic environment willreturn the same (eq) object.662 <para>Despite the function's name, it doesn't necessarily create a 663 new, unique EXTERNAL-FORMAT object: two calls to 664 MAKE-EXTERNAL-FORMAT with the same arguments made in the same 665 dynamic environment return the same (eq) object. 667 666 </para> 668 667 </refsect1> … … 769 768 <sect3><title>Encoding Problems</title> 770 769 <para>On output to streams with character encodings that can 771 encode the full range of Unicode - and on input from any stream772 - "unencodable characters" are represented using the Unicode773 #\Replacement_Character (= #\U+fffd); the presence of such a774 character usually indicates that something got lost in770 encode the full range of Unicode—and on input from any 771 stream—"unencodable characters" are represented using the 772 Unicode #\Replacement_Character (= #\U+fffd); the presence of 773 such a character usually indicates that something got lost in 775 774 translation. Either data wasn't encoded properly or there was a 776 775 bug in the decoding process.</para> … … 788 787 indicate that the encoding is UTF-8.)</para> 789 788 790 <para>Clozure CL w ill write a byte order mark as the first791 character of a file or socket stream when the endianness of the792 character encoding is not explicit. Clozure CL also expects a793 byte order mark on input from streams where the endianness is794 not explicit. If a byte order mark is missing from input data,795 thatdata is assumed to be in big-endian order.</para>789 <para>Clozure CL writes a byte order mark as the first character 790 of a file or socket stream when the endianness of the character 791 encoding is not explicit. Clozure CL also expects a byte order 792 mark on input from streams where the endianness is not 793 explicit. If a byte order mark is missing from input data, that 794 data is assumed to be in big-endian order.</para> 796 795 797 796 <para>A byte order mark from a UTF-8 encoded input stream is not 798 treated specially and and will just appear as normal character799 from the input stream. It is probably a good idea to skip over800 thischaracter.</para>797 treated specially and just appears as a normal character from 798 the input stream. It is probably a good idea to skip over this 799 character.</para> 801 800 </sect3> 802 801 -
release/1.2/source/examples/opengl-ffi.lisp
r5726 r9200 135 135 ;;; Set the OSX Window Server's notion of the name of the 136 136 ;;; current process. 137 ( %stack-block ((psn 8))138 ( ccl::external-call "_GetCurrentProcess" :address psn)137 (rlet ((psn #>ProcessSerialNumber)) 138 (#_GetCurrentProcess psn) 139 139 (with-cstrs ((name "simple OpenGL example")) 140 (ccl::external-call "_CPSSetProcessName" :address psn :address name ))))140 (ccl::external-call "_CPSSetProcessName" :address psn :address name :void)))) 141 141 (main))) 142 142 -
release/1.2/source/examples/rubix/rubix.lisp
r6230 r9200 221 221 222 222 (defun run-rubix-demo () 223 (let* ((w ( ccl::new-cocoa-window :class (find-class 'rubix-window)223 (let* ((w (gui::new-cocoa-window :class (find-class 'rubix-window) 224 224 :title "Rubix Cube" 225 225 :height 250 -
release/1.2/source/level-1/l1-clos-boot.lisp
r9049 r9200 1053 1053 1054 1054 1055 (defparameter dcode-proto-alist1056 (list (cons #'%%one-arg-dcode *gf-proto-one-arg*)1057 (cons #'%%1st-two-arg-dcode *gf-proto-two-arg*)))1058 1059 1055 (defun compute-dcode (gf &optional dt) 1060 1056 (setq gf (require-type gf 'standard-generic-function)) -
release/1.2/source/level-1/l1-clos.lisp
r8909 r9200 1810 1810 (%slot-ref (instance.slots instance) location) 1811 1811 (no-applicable-method (%gf-dispatch-table-gf dt) instance)))) 1812 (register-dcode-proto #'singleton-reader-dcode *gf-proto-one-arg*) 1812 1813 1813 1814 ;;; Dcode for a GF whose methods are all reader-methods which access a … … 1823 1824 (%slot-ref (instance.slots instance) location) 1824 1825 (no-applicable-method (%gf-dispatch-table-gf dt) instance)))) 1826 (register-dcode-proto #'reader-constant-location-dcode *gf-proto-one-arg*) 1825 1827 1826 1828 ;;; Dcode for a GF whose methods are all reader-methods which access a … … 1839 1841 (%slot-ref (instance.slots instance) location) 1840 1842 (no-applicable-method (%gf-dispatch-table-gf dt) instance)))) 1843 (register-dcode-proto #'reader-constant-location-inherited-from-single-class-dcode *gf-proto-one-arg*) 1841 1844 1842 1845 ;;; Dcode for a GF whose methods are all reader-methods which access a … … 1855 1858 (%slot-ref (instance.slots instance) location) 1856 1859 (no-applicable-method (%gf-dispatch-table-gf dt) instance)))) 1860 (register-dcode-proto #'reader-constant-location-inherited-from-multiple-classes-dcode *gf-proto-one-arg*) 1857 1861 1858 1862 … … 1870 1874 (%slot-ref (instance.slots instance) location) 1871 1875 (no-applicable-method (%gf-dispatch-table-gf dt) instance)))) 1876 (register-dcode-proto #'reader-variable-location-dcode *gf-proto-one-arg*) 1872 1877 1873 1878 (defun class-and-slot-location-alist (classes slot-name) … … 1994 1999 (funcall mf arg1 arg2) 1995 2000 (%%1st-two-arg-dcode dt arg1 arg2)))) 2001 (register-dcode-proto #'reader-variable-location-dcode *gf-proto-two-arg*) 1996 2002 1997 2003 (defun %%one-arg-eql-method-hack-dcode (dt arg) … … 1999 2005 (if mf 2000 2006 (funcall mf arg)))) 2007 (register-dcode-proto #'%%one-arg-eql-method-hack-dcode *gf-proto-one-arg*) 2001 2008 2002 2009 (defun install-eql-method-hack-dcode (gf) -
release/1.2/source/level-1/l1-dcode.lisp
r8667 r9200 781 781 ;;;;;;;;;;;;;;;;;;;;;;;;; generic-function dcode ;;;;;;;;;;;;;;;;;;;;;;;;;;; 782 782 783 ;; dcode functions using other than *gf-proto* 784 (defparameter dcode-proto-alist ()) 785 786 (defun register-dcode-proto (dcode proto) 787 (let ((a (assoc dcode dcode-proto-alist))) 788 (if a 789 (setf (cdr a) proto) 790 (push (cons dcode proto) dcode-proto-alist)))) 791 792 783 793 ;;; Simple case for generic-functions with no specializers 784 794 ;;; Why anyone would want to do this I can't imagine. … … 817 827 (let ((method (%find-1st-arg-combined-method dt arg))) 818 828 (funcall method arg))) 829 (register-dcode-proto #'%%one-arg-dcode *gf-proto-one-arg*) 819 830 820 831 ;;; two args - specialized on first … … 822 833 (let ((method (%find-1st-arg-combined-method dt arg1))) 823 834 (funcall method arg1 arg2))) 824 835 (register-dcode-proto #'%%1st-two-arg-dcode *gf-proto-two-arg*) 825 836 826 837 -
release/1.2/source/level-1/l1-streams.lisp
r9047 r9200 4372 4372 (incf (ioblock-charpos ioblock) num-chars)) 4373 4373 num-chars) 4374 (declare (fixnum src dest end)) 4374 4375 (let* ((char (schar string src))) 4375 4376 (if (eql char #\Newline) 4376 (setq nlpos src))4377 (setq nlpos (the fixnum (1+ src)))) 4377 4378 (setf (schar out dest) char))))) 4378 4379 -
release/1.2/source/lib/compile-ccl.lisp
r9051 r9200 600 600 (cwd ,wd))))) 601 601 602 (defun ensure-tests-loaded (&key force full)602 (defun ensure-tests-loaded (&key force update) 603 603 (unless (and (find-package "REGRESSION-TEST") (not force)) 604 604 (if (probe-file "ccl:tests;ansi-tests;") 605 (when full605 (when update 606 606 (cwd "ccl:tests;") 607 607 (run-program "svn" '("update"))) 608 608 (let* ((svn (probe-file "ccl:.svn;entries")) 609 (repo (and svn 610 (with-open-file (s svn) 611 (loop as line = (read-line s nil) while line 612 do (when (search "://" line) 613 (setq line (read-line s)) 614 (return (and (search "://" line) line))))))) 609 (repo (and svn (svn-repository))) 615 610 (s (make-string-output-stream))) 616 611 (when repo … … 631 626 ;; it without making the test suite non-portable across platforms... 632 627 (handler-bind ((warning (lambda (c) 633 (when (and (typep c 'compiler-warning) 634 (eq (compiler-warning-warning-type c) :program-error) 635 (typep (car (compiler-warning-args c)) 'simple-warning) 636 (or 637 (string-equal 638 (simple-condition-format-control (car (compiler-warning-args c))) 639 "Clause ~S ignored in ~S form - shadowed by ~S .") 640 ;; Might as well ignore these as well, they're intentional. 641 (string-equal 642 (simple-condition-format-control (car (compiler-warning-args c))) 643 "Duplicate keyform ~s in ~s statement."))) 628 (when (let ((w (or (and (typep c 'compiler-warning) 629 (eq (compiler-warning-warning-type c) :program-error) 630 (car (compiler-warning-args c))) 631 c))) 632 (and (typep w 'simple-warning) 633 (or 634 (string-equal 635 (simple-condition-format-control w) 636 "Clause ~S ignored in ~S form - shadowed by ~S .") 637 ;; Might as well ignore these as well, they're intentional. 638 (string-equal 639 (simple-condition-format-control w) 640 "Duplicate keyform ~s in ~s statement.")))) 644 641 (muffle-warning c))))) 645 642 ;; This loads the infrastructure 646 643 (load "ccl:tests;ansi-tests;gclload1.lsp") 647 644 ;; This loads the actual tests 648 (load "ccl:tests;ansi-tests;gclload2.lsp")))) 649 650 (defun test-ccl (&key force full verbose (catch-errors t)) 645 (load "ccl:tests;ansi-tests;gclload2.lsp") 646 ;; And our own tests 647 (load "ccl:tests;ansi-tests;ccl.lsp")))) 648 649 (defun test-ccl (&key force (update t) verbose (catch-errors t)) 651 650 (with-preserved-working-directory () 652 (ensure-tests-loaded :force force : full full)651 (ensure-tests-loaded :force force :update update) 653 652 (cwd "ccl:tests;ansi-tests;") 654 653 (let ((do-tests (find-symbol "DO-TESTS" "REGRESSION-TEST")) -
release/1.2/source/lib/macros.lisp
r9049 r9200 543 543 (default-setf form value env)))))))))) 544 544 ((oddp temp) 545 (error "Odd number of args to SETF : ~s." args))545 (signal-program-error "Odd number of args to SETF : ~s." args)) 546 546 (t (do* ((a args (cddr a)) (l nil)) 547 547 ((null a) `(progn ,@(nreverse l))) … … 869 869 otherwise-seen-p) 870 870 (flet ((bad-clause (c) 871 ( error "Invalid clause ~S in ~S form." c construct)))871 (signal-program-error "Invalid clause ~S in ~S form." c construct))) 872 872 (dolist (clause clauses) 873 873 (if (atom clause) 874 874 (bad-clause clause)) 875 875 (if otherwise-seen-p 876 ( error "OTHERWISE must be final clause in ~S form." construct))876 (signal-program-error "OTHERWISE must be final clause in ~S form." construct)) 877 877 (destructuring-bind (typespec &body consequents) clause 878 878 (when (eq construct 'typecase) … … 994 994 (when (nth-value 1 (macroexpand-1 sym env)) 995 995 (return `(psetf ,@pairs)))) 996 ( error "Uneven number of args in the call ~S" call))))996 (signal-program-error "Uneven number of args in the call ~S" call)))) 997 997 998 998 ; generates body for psetq. … … 1677 1677 (defun with-specs-aux (name spec-list original-body) 1678 1678 (multiple-value-bind (body decls) (parse-body original-body nil) 1679 (when decls ( error "declarations not allowed in ~s" original-body))1679 (when decls (signal-program-error "declarations not allowed in ~s" original-body)) 1680 1680 (setq body (cons 'progn body)) 1681 1681 (dolist (spec (reverse spec-list)) … … 2098 2098 (unless (and (consp option) 2099 2099 (consp (%cdr option))) 2100 ( error "Invalid option ~s ." option))2100 (signal-program-error "Invalid option ~s ." option)) 2101 2101 (ecase (%car option) 2102 2102 (:default-initargs … … 2108 2108 (:documentation 2109 2109 (unless (null (%cddr option)) 2110 ( error "Invalid option ~s ." option))2110 (signal-program-error "Invalid option ~s ." option)) 2111 2111 (if docp 2112 2112 (setq duplicate t) … … 2114 2114 (:report 2115 2115 (unless (null (%cddr option)) 2116 ( error "Invalid option ~s ." option))2116 (signal-program-error "Invalid option ~s ." option)) 2117 2117 (if reporter 2118 2118 (setq duplicate t) … … 2123 2123 (if (stringp reporter) 2124 2124 (setq reporter `(function (lambda (c s) (declare (ignore c)) (write-string ,reporter s)))) 2125 ( error "~a expression is not a string, symbol, or lambda expression ." (%car option))))2125 (signal-program-error "~a expression is not a string, symbol, or lambda expression ." (%car option)))) 2126 2126 (setq reporter `((defmethod report-condition ((c ,name) s) 2127 2127 (funcall ,reporter c s)))))))) 2128 (if duplicate ( error "Duplicate option ~s ." option)))2128 (if duplicate (signal-program-error "Duplicate option ~s ." option))) 2129 2129 `(progn 2130 2130 (defclass ,name ,(or supers '(condition)) ,slots ,@classopts) … … 2759 2759 (symbolp (car slot-entry)) (symbolp (cadr slot-entry))) 2760 2760 (setq var (car slot-entry) slot-name (cadr slot-entry))) 2761 (t ( error "Malformed slot-entry: ~a to with-slot-values.~@2762 Should be a symbol or a list of two symbols."2763 slot-entry)))2761 (t (signal-program-error "Malformed slot-entry: ~a to with-slot-values.~@ 2762 Should be a symbol or a list of two symbols." 2763 slot-entry))) 2764 2764 (push `(,var (slot-value ,instance ',slot-name)) bindings)) 2765 2765 `(let ((,instance ,instance-form)) … … 2780 2780 (symbolp (car slot-entry)) (symbolp (cadr slot-entry))) 2781 2781 (setq var (car slot-entry) slot-name (cadr slot-entry))) 2782 (t ( error "Malformed slot-entry: ~a to with-slots.~@2783 Should be a symbol or a list of two symbols."2784 slot-entry)))2782 (t (signal-program-error "Malformed slot-entry: ~a to with-slots.~@ 2783 Should be a symbol or a list of two symbols." 2784 slot-entry))) 2785 2785 (push `(,var (slot-value ,instance ',slot-name)) bindings)) 2786 2786 `(let ((,instance ,instance-form)) … … 2801 2801 (symbolp (car slot-entry)) (symbolp (cadr slot-entry))) 2802 2802 (setq var (car slot-entry) reader (cadr slot-entry))) 2803 (t ( error "Malformed slot-entry: ~a to with-accessors.~@2804 Should be a list of two symbols."2805 slot-entry)))2803 (t (signal-program-error "Malformed slot-entry: ~a to with-accessors.~@ 2804 Should be a list of two symbols." 2805 slot-entry))) 2806 2806 (push `(,var (,reader ,instance)) bindings)) 2807 2807 `(let ((,instance ,instance-form)) … … 2939 2939 `((setf ,(%foreign-access-form name ftype 0 nil) 2940 2940 ,(car inits))))) 2941 ( error "Unexpected or malformed initialization forms: ~s in field type: ~s"2942 inits record-name))))))))2941 (signal-program-error "Unexpected or malformed initialization forms: ~s in field type: ~s" 2942 inits record-name)))))))) 2943 2943 2944 2944 (defun %foreign-record-field-forms (ptr record-type record-name inits) 2945 2945 (unless (evenp (length inits)) 2946 ( error "Unexpected or malformed initialization forms: ~s in field type: ~s"2947 inits record-name))2946 (signal-program-error "Unexpected or malformed initialization forms: ~s in field type: ~s" 2947 inits record-name)) 2948 2948 (let* ((result ())) 2949 2949 (do* () … … 2976 2976 (bytes (if bits 2977 2977 (ceiling bits 8) 2978 ( error "Unknown size for foreign type ~S."2979 (unparse-foreign-type ftype))))2978 (signal-program-error "Unknown size for foreign type ~S." 2979 (unparse-foreign-type ftype)))) 2980 2980 (p (gensym)) 2981 2981 (bzero (read-from-string "#_bzero"))) … … 3154 3154 (%symbol-binding-address ',place) 3155 3155 (%atomic-incf-node ,delta ,base ,offset))) 3156 ( error "~S is not a special variable" place))))3156 (signal-program-error "~S is not a special variable" place)))) 3157 3157 3158 3158 (defmacro atomic-incf (place) … … 3173 3173 (unless (and (listp x) 3174 3174 (= (length x) 2)) 3175 ( error "Malformed iterate variable spec: ~S." x)))3175 (signal-program-error "Malformed iterate variable spec: ~S." x))) 3176 3176 3177 3177 `(labels ((,name ,(mapcar #'first binds) ,@body)) … … 3211 3211 (let ((spec (first specs))) 3212 3212 (when (/= (length spec) 2) 3213 ( error "Malformed Once-Only binding spec: ~S."spec))3213 (signal-program-error "Malformed ~s binding spec: ~S." 'once-only spec)) 3214 3214 (let ((name (first spec)) 3215 3215 (exp-temp (gensym))) … … 3272 3272 (dolist (spec collections) 3273 3273 (unless (<= 1 (length spec) 3) 3274 ( error "Malformed collection specifier: ~S." spec))3274 (signal-program-error "Malformed collection specifier: ~S." spec)) 3275 3275 (let ((n-value (gensym)) 3276 3276 (name (first spec)) … … 3333 3333 (if (and (consp (%cdr p)) (null (%cddr p))) 3334 3334 (values (require-global-symbol (%car p) env) (%cadr p)) 3335 ( error "Invalid variable initialization form : ~s")))))3335 (signal-program-error "Invalid variable initialization form : ~s"))))) 3336 3336 (declare (inline pair-name-value)) 3337 3337 (dolist (v vars) … … 3370 3370 (ccl::%symbol-binding-address ',place) 3371 3371 (ccl::%store-node-conditional ,offset ,base ,old-value ,new-value))) 3372 ( error "~s is not a special variable ." place))3372 (signal-program-error "~s is not a special variable ." place)) 3373 3373 (let* ((sym (car place)) 3374 3374 (struct-transform (or (ccl::environment-structref-info sym env) … … 3382 3382 (ccl::store-gvector-conditional ,(caddr place) 3383 3383 ,v ,old-value ,new-value))) 3384 ( error "Don't know how to do conditional store to ~s" place)))))3384 (signal-program-error "Don't know how to do conditional store to ~s" place))))) 3385 3385 3386 3386 (defmacro step (form) -
release/1.2/source/lib/nfcomp.lisp
r8995 r9200 907 907 (let* ((*fasdump-hash* (make-hash-table :size (length forms) ; Crude estimate 908 908 :rehash-threshold 0.9 909 :test 'eq)) 909 :test 'eq 910 :shared nil)) 910 911 (*make-load-form-hash* (make-hash-table :test 'eq)) 911 912 (*fasdump-read-package* nil) -
release/1.2/source/lib/pprint.lisp
r6923 r9200 1563 1563 (cond ((vectorp array) (pretty-vector xp array)) 1564 1564 ((zerop (array-rank array)) 1565 (write-string++ "#0A " xp 0 4)1565 (write-string++ "#0A" xp 0 3) 1566 1566 (write+ (aref array) xp)) 1567 1567 (T (pretty-non-vector xp array)))) -
release/1.2/source/library/chud-metering.lisp
r5851 r9200 1 1 ;;;-*-Mode: LISP; Package: (CHUD (:USE CL CCL)) -*- 2 2 ;;; 3 ;;; Copyright (C) 2005 Clozure Associates and contributors3 ;;; Copyright (C) 2005,2008 Clozure Associates and contributors 4 4 ;;; This file is part of OpenMCL. 5 5 ;;; … … 25 25 (defpackage "CHUD" 26 26 (:use "CL" "CCL") 27 (:export "METER" "PREPARE-METERING" "*SPATCH-DIRECTORY-PATH*" 28 "LAUNCH-SHARK" "CLEANUP-SPATCH-FILES" "RESET-METERING")) 27 (:export "METER" "*SHARK-CONFIG-FILE*")) 29 28 30 29 (in-package "CHUD") 31 30 32 33 (defparameter *CHUD-library-path* 34 "/System/Library/PrivateFrameworks/CHUD.Framework/CHUD" 35 "This seems to move around with every release.") 36 37 (defparameter *shark-app-path* "/Developer/Applications/Performance\ Tools/Shark.app") 38 39 (defparameter *spatch-directory-path* nil 40 "If non-NIL, should be a pathname whose directory component matches the 41 \"Patch FIles\" search path in Shark's Preferences. When this variable 42 is NIL, USER-HOMEDIR-PATHNAME is used instead.") 43 44 (eval-when (:load-toplevel :execute) 45 (open-shared-library (namestring *CHUD-library-path*))) 46 47 (eval-when (:compile-toplevel :execute) 48 (use-interface-dir :chud)) 49 50 ;;; CHUD apparently has this notion of global, persistent 51 ;;; "status" (the result returned by the last operation.) 52 ;;; I have not idea whether or not that's thread-specific; 53 ;;; there doesn't seem to be any other way of getting a 54 ;;; string that describes an error code. 55 (defun chud-get-status-string () 56 (with-macptrs ((s (#_chudGetStatusStr))) 57 (if (%null-ptr-p s) 58 "" 59 (%get-cstring s)))) 60 61 (defun chud-check-error (result context) 62 (or (eql result #$chudSuccess) 63 (error "CHUD error ~d (~a) while ~a. " result (chud-get-status-string) context))) 31 (eval-when (:compile-toplevel :load-toplevel :execute) 32 (progn 33 #-darwin-target 34 (error "This code is Darwin/MacOSX-specific."))) 35 36 37 (defparameter *shark-session-path* nil) 38 39 (defloadvar *written-spatch-file* nil) 40 41 (defparameter *shark-session-native-namestring* nil) 42 43 (defparameter *shark-config-file* nil "Full pathname of .cfg file to use for profiling, or NIL.") 44 45 (defun finder-open-file (namestring) 46 "Open the file named by NAMESTRING, as if it was double-clicked on 47 in the finder" 48 (run-program "/usr/bin/open" (list namestring) :output nil)) 49 50 (defun ensure-shark-session-path () 51 (unless *shark-session-path* 52 (multiple-value-bind (second minute hour date month year) 53 (decode-universal-time (get-universal-time)) 54 (let* ((subdir (format nil "profiling-session-~A-~d_~d-~d-~d_~d.~d.~d" 55 (pathname-name 56 (car 57 ccl::*command-line-argument-list*)) 58 (ccl::getpid) 59 month 60 date 61 year 62 hour 63 minute 64 second)) 65 (dir (make-pathname :directory (append (pathname-directory (user-homedir-pathname)) (list subdir)) :defaults nil)) 66 (native-name (ccl::native-untranslated-namestring dir))) 67 (ensure-directories-exist dir) 68 (setenv "SHARK_SEARCH_PATH_PATCH_FILES" native-name) 69 (setq *shark-session-native-namestring* 70 native-name 71 *shark-session-path* dir)))) 72 *shark-session-path*) 73 74 64 75 65 (defun chud-is-initialized () 66 (not (eql (#_chudIsInitialized) 0))) 67 68 (defparameter *chud-supported-major-version* 4) 69 (defparameter *chud-supported-minor-version* 1) 70 71 ;; Don't know if it makes sense to worry about max supported versions 72 ;; as well. 73 74 (defun check-chud-version () 75 (let* ((version (#_chudFrameworkVersion)) 76 (major (ldb (byte 8 24) version)) 77 (minor (ldb (byte 8 12) version))) 78 (or (and (>= major *chud-supported-major-version*) 79 (when (= major *chud-supported-major-version*) 80 (>= minor *chud-supported-minor-version*))) 81 (warn "The installed CHUD framework is version ~d.~d. ~ 82 The minimum version supported by this interface is ~d.~d." 83 major minor *chud-supported-major-version* 84 *chud-supported-minor-version*)))) 85 86 87 (defun initialize-chud () 88 (or (chud-is-initialized) 89 (and (check-chud-version) 90 (chud-check-error (#_chudInitialize) "initializing CHUD")))) 91 92 (defun acquired-remote-access () 93 (eql #$true (#_chudIsRemoteAccessAcquired))) 94 95 ;;; If we've already successfully called (#_chudAcquireRemoteAccess), 96 ;;; we can call it again without error (e.g., it's a no-op in that 97 ;;; case.) However, we can successfully release it at most once. 98 99 (defun acquire-remote-access () 100 (or (acquired-remote-access) 101 (chud-check-error (#_chudAcquireRemoteAccess) "acquiring remote access"))) 102 103 (defun release-remote-access () 104 (chud-check-error (#_chudReleaseRemoteAccess) "releasing remote access")) 105 106 (defun start-remote-perf-monitor (label) 107 (with-cstrs ((clabel (format nil "~a" label))) 108 (chud-check-error (#_chudStartRemotePerfMonitor clabel) 109 "starting performance monitor"))) 110 111 (defun stop-remote-perf-monitor () 112 (chud-check-error (#_chudStopRemotePerfMonitor) 113 "stopping performance monitor")) 114 115 (defun setup-timer (duration frequency) 116 (#_chudSetupTimer frequency 117 #$chudMicroSeconds 118 0 119 #$chudMicroSeconds 120 duration)) 121 122 (defun get-readonly-area-bounds () 123 (ccl::do-gc-areas (a) 124 (when (eql(ccl::%fixnum-ref a target::area.code) 125 #+ppc-target ccl::area-readonly 126 #+x8664-target ccl::area-managed-static) 127 (return 128 (values (ash (ccl::%fixnum-ref a target::area.low) target::fixnumshift) 129 (ash (ccl::%fixnum-ref a target::area.active) target::fixnumshift)))))) 76 77 (defloadvar *shark-process* nil) 78 (defloadvar *sampling* nil) 79 80 (defloadvar *debug-shark-process-output* nil) 81 130 82 131 83 (defun safe-shark-function-name (function) … … 134 86 135 87 (defun print-shark-spatch-record (fn &optional (stream t)) 136 (let* ((code-vector (uvref fn 0))88 (let* ((code-vector #+ppc-target (uvref fn 0) #-ppc-target fn) 137 89 (startaddr (+ (ccl::%address-of code-vector) 138 target::misc-data-offset)) 139 (endaddr (+ startaddr (* target::node-size (uvsize code-vector))))) 90 #+x8664-target 0 91 #+ppc32-target target::misc-data-offset 92 #-ppc32-target 0)) 93 (endaddr (+ startaddr 94 #+x8664-target 95 (1+ (ash (1- (ccl::%function-code-words fn) 96 ) target::word-shift)) 97 #+ppc-target 98 (* 4 (- (uvsize code-vector) 99 #+ppc64-target 2 100 #-ppc64-target 1))))) 140 101 ;; i hope all lisp sym characters are allowed... we'll see 141 102 (format stream "{~%~@ … … 150 111 endaddr))) 151 112 152 (defun identify-functions-with-pure-code (pure-low pure-high) 153 (let* ((hash (make-hash-table :test #'eq))) 154 (ccl::%map-lfuns #'(lambda (f) 155 (let* ((code-vector #+ppc-target (ccl:uvref f 0) 156 #+x8664-target (ccl::function-to-function-vector f)) 157 (startaddr (+ (ccl::%address-of code-vector) 158 target::misc-data-offset))) 159 (when (and (>= startaddr pure-low) 160 (< startaddr pure-high)) 161 (push f (gethash code-vector hash)))))) 162 (let* ((n 0)) 163 (declare (fixnum n)) 164 (maphash #'(lambda (k v) 165 (declare (ignore k)) 166 (if (null (cdr v)) 167 (incf n))) 168 hash) 169 (let* ((functions (make-array n)) 170 (i 0)) 113 #+x8664-target 114 (ccl::defx86lapfunction dynamic-dnode ((x arg_z)) 115 (movq (% x) (% imm0)) 116 (ref-global x86::heap-start arg_y) 117 (subq (% arg_y) (% imm0)) 118 (shrq ($ x8664::dnode-shift) (% imm0)) 119 (box-fixnum imm0 arg_z) 120 (single-value-return)) 121 122 #+x8664-target 123 (defun identify-functions-with-pure-code () 124 (ccl::freeze) 125 (ccl::collect ((functions)) 126 (block walk 127 (let* ((frozen-dnodes (ccl::frozen-space-dnodes))) 128 (ccl::%map-areas (lambda (o) 129 (when (>= (dynamic-dnode o) frozen-dnodes) 130 (return-from walk nil)) 131 (when (typep o 'ccl::function-vector) 132 (functions (ccl::function-vector-to-function o)))) 133 ccl::area-dynamic 134 ccl::area-dynamic 135 ))) 136 (functions))) 137 138 #+ppc-target 139 (defun identify-functions-with-pure-code () 140 (ccl:purify) 141 (multiple-value-bind (pure-low pure-high) 142 143 (ccl::do-gc-areas (a) 144 (when (eql(ccl::%fixnum-ref a target::area.code) 145 ccl::area-readonly) 146 (return 147 (values (ash (ccl::%fixnum-ref a target::area.low) target::fixnumshift) 148 (ash (ccl::%fixnum-ref a target::area.active) target::fixnumshift))))) 149 (let* ((hash (make-hash-table :test #'eq))) 150 (ccl::%map-lfuns #'(lambda (f) 151 (let* ((code-vector (ccl:uvref f 0)) 152 (startaddr (+ (ccl::%address-of code-vector) 153 target::misc-data-offset))) 154 (when (and (>= startaddr pure-low) 155 (< startaddr pure-high)) 156 (push f (gethash code-vector hash)))))) 157 (let* ((n 0)) 158 (declare (fixnum n)) 171 159 (maphash #'(lambda (k v) 172 160 (declare (ignore k)) 173 (when (null (cdr v)) 174 (setf (svref functions i) (car v) 175 i (1+ i)))) 161 (if (null (cdr v)) 162 (incf n))) 176 163 hash) 177 (sort functions 178 #'(lambda (x y) 179 (< (ccl::%address-of #+ppc-target (uvref x 0) 180 #+x8664-target x) 181 (ccl::%address-of #+ppc-target (uvref y 0) 182 #+x8664-target y)))))))) 164 (let* ((functions ())) 165 (maphash #'(lambda (k v) 166 (declare (ignore k)) 167 (when (null (cdr v)) 168 (push (car v) functions))) 169 hash) 170 (sort functions 171 #'(lambda (x y) 172 (< (ccl::%address-of (uvref x 0) ) 173 (ccl::%address-of (uvref y 0)))))))))) 183 174 184 175 176 177 185 178 (defun generate-shark-spatch-file () 186 (ccl::purify) 187 (multiple-value-bind (pure-low pure-high) 188 (get-readonly-area-bounds) 189 (let* ((functions (identify-functions-with-pure-code pure-low pure-high))) 190 (with-open-file (f (make-pathname 191 :host nil 192 :directory (pathname-directory 193 (or *spatch-directory-path* 194 (user-homedir-pathname))) 195 :name (format nil "~a_~D" 196 (pathname-name 197 (car 198 ccl::*command-line-argument-list*)) 199 (ccl::getpid)) 200 :type "spatch") 201 :direction :output 202 :if-exists :supersede) 203 (format f "!SHARK_SPATCH_BEGIN~%") 204 (dotimes (i (length functions)) 205 (print-shark-spatch-record (svref functions i) f)) 206 (format f "!SHARK_SPATCH_END~%"))) t)) 207 208 (defun cleanup-spatch-files () 209 (dolist (f (directory 210 (make-pathname 211 :host nil 212 :directory 213 (pathname-directory 214 (or *spatch-directory-path* 215 (user-homedir-pathname))) 216 :name :wild 217 :type "spatch"))) 218 (delete-file f))) 219 220 221 (defun launch-shark () 222 (run-program "/usr/bin/open" (list *shark-app-path*))) 223 224 225 (defun reset-metering () 226 (when (acquired-remote-access) 227 (release-remote-access) 228 (format t "~&Note: it may be desirable to quit and restart Shark.") 229 t)) 179 (let* ((functions (identify-functions-with-pure-code))) 180 (with-open-file (f (make-pathname 181 :host nil 182 :directory (pathname-directory 183 (ensure-shark-session-path)) 184 :name (format nil "~a_~D" 185 (pathname-name 186 (car 187 ccl::*command-line-argument-list*)) 188 (ccl::getpid)) 189 :type "spatch") 190 :direction :output 191 :if-exists :supersede) 192 (format f "!SHARK_SPATCH_BEGIN~%") 193 (dolist (fun functions) 194 (print-shark-spatch-record fun f)) 195 (format f "!SHARK_SPATCH_END~%")))) 196 197 (defun terminate-shark-process () 198 (when *shark-process* 199 (signal-external-process *shark-process* #$SIGUSR2)) 200 (setq *shark-process* nil 201 *sampling* nil)) 202 203 (defun toggle-sampling () 204 (if *shark-process* 205 (progn 206 (signal-external-process *shark-process* #$SIGUSR1) 207 (setq *sampling* (not *sampling*))) 208 (warn "No active shark procsss"))) 209 210 (defun enable-sampling () 211 (unless *sampling* (toggle-sampling))) 212 213 (defun disable-sampling () 214 (when *sampling* (toggle-sampling))) 215 216 (defun ensure-shark-process (reset hook) 217 (when (or (null *shark-process*) reset) 218 (terminate-shark-process) 219 (when (or reset (not *written-spatch-file*)) 220 (generate-shark-spatch-file)) 221 (let* ((args (list "-b" "-1" "-a" (format nil "~d" (ccl::getpid)) 222 "-d" *shark-session-native-namestring*))) 223 (when *shark-config-file* 224 (push (ccl::native-untranslated-namestring *shark-config-file*) 225 args) 226 (push "-m" args)) 227 (setq *shark-process* 228 (run-program "/usr/bin/shark" 229 args 230 :output :stream 231 :status-hook hook 232 :wait nil)) 233 (let* ((output (external-process-output-stream *shark-process*))) 234 (do* ((line (read-line output nil nil) (read-line output nil nil))) 235 ((null line)) 236 (when *debug-shark-process-output* 237 (format t "~&~a" line)) 238 (when (search "ready." line :key #'char-downcase) 239 (sleep 1) 240 (return))))))) 241 242 (defun display-shark-session-file (line) 243 (let* ((last-quote (position #\' line :from-end t)) 244 (first-quote (and last-quote (position #\' line :end (1- last-quote) :from-end t))) 245 (path (and first-quote (subseq line (1+ first-quote) last-quote)))) 246 (when path (finder-open-file path)))) 230 247 231 (defun prepare-metering () 232 (launch-shark) 233 (generate-shark-spatch-file) 234 (initialize-chud) 235 (loop 236 (when (ignore-errors (acquire-remote-access)) 237 (return)) 238 ;; Yes, this is lame. 239 (loop (when (y-or-n-p "Is Shark in Remote mode yet?") 240 (return))))) 241 242 (defmacro meter (form &key (duration 0) (frequency 1)) 243 (let* ((started (gensym))) 244 `(let* ((,started nil)) 245 (unless (and (chud-is-initialized) 246 (acquired-remote-access)) 247 (prepare-metering)) 248 (setup-timer ,duration ,frequency) 249 (unwind-protect 250 (progn 251 (setq ,started (start-remote-perf-monitor ',form)) 252 ,form) 253 (when ,started (stop-remote-perf-monitor)))))) 254 255 (defun chud-cleanup () 256 (when (chud-is-initialized) 257 (when (acquired-remote-access) 258 (ignore-errors (release-remote-access))) 259 (#_chudCleanup)) 260 (cleanup-spatch-files)) 261 262 (pushnew 'chud-cleanup *lisp-cleanup-functions*) 248 (defun scan-shark-process-output (p) 249 (with-interrupts-enabled 250 (let* ((out (ccl::external-process-output p))) 251 (do* ((line (read-line out nil nil) (read-line out nil nil))) 252 ((null line)) 253 (when *debug-shark-process-output* 254 (format t "~&~a" line)) 255 (when (search "Created session file:" line) 256 (display-shark-session-file line) 257 (return)))))) 258 259 260 261 (defmacro meter (form &key reset debug-output) 262 (let* ((hook (gensym)) 263 (block (gensym)) 264 (process (gensym))) 265 `(block ,block 266 (flet ((,hook (p) 267 (when (or (eq (external-process-status p) :exited) 268 (eq (external-process-status p) :signaled)) 269 (setq *shark-process* nil 270 *sampling* nil)))) 271 (let* ((*debug-shark-process-output* ,debug-output)) 272 (ensure-shark-process ,reset #',hook) 273 (unwind-protect 274 (progn 275 (enable-sampling) 276 ,form) 277 (disable-sampling) 278 (let* ((,process *shark-process*)) 279 (when ,process 280 (scan-shark-process-output ,process))))))))) 281 282 ;;; Try to clean up after ourselves when the lisp quits. 283 (pushnew 'terminate-shark-process ccl::*save-exit-functions*) -
release/1.2/source/library/chud-metering.txt
r2594 r9200 1 Using Apple's CHUD metering tools from OpenMCL 1 Using Apple's CHUD metering tools from CCL 2 ========================================== 2 3 3 Prerequisites 4 Prerequisites 5 ------------- 4 6 5 7 Apple's CHUD metering tools are available (as of this writing) from: … … 7 9 <ftp://ftp.apple.com/developer/Tool_Chest/Testing_-_Debugging/Performance_tools/>. 8 10 9 The re are also some CHUD packages distributed with some recent10 versions of Xcode; the standalone versions available via FTP seem to 11 w ork much better with the OpenMCL interface. Both versions 4.1.1 and12 4.2.2 of the CHUD tools seem to work reasonably well; earlierversions13 provide a different ABI, and it's not known whether any future 14 versions will be compatible.11 The CHUD tools are also generally bundled with Apple's XCode tools. 12 CBUD 4.5.0 (which seems to be bundled with XCode 3.0) seems to work 13 well with this interface; later versions may have problems. 14 Versions of CHUD as old as 4.1.1 may work with 32-bit PPC versions 15 of CCL; later versions (not sure exactly -what- versions) added 16 x86, ppc64, and x86-64 support. 15 17 16 There don't seem to be any versions of CHUD that can deal with 64-bit 17 processes. 18 One way to tell whether any version of the CHUD tools is installed 19 is to try to invoke the "shark" command-line program (/usr/bin/shark) 20 from the shell: 18 21 19 Ensure that either version 4.1.1 or 4.2.2 of the CHUD tools are 20 installed. One side-effect of installation is that the folder " 21 /Developer/Applications/Performance Tools" will have been created and 22 will contain an application called "Shark". Double-click on Shark; in 23 its "Preferences" window's "Search Paths" pane, use the "+" button to 24 add your home directory to the "Patch Files" search path. 22 shell> shark --help 25 23 26 Background 24 and verifying that that prints a usage summary. 27 25 28 CHUD 's Shark application is a user interface to its low-level29 performance monitoring facilities; those facilities provide access to 30 high-resolution timers, on-chip debugging information, and OS 31 performance counters. Shark allows the user to run sampling sessions, 32 which record information about the context in which sampling events 33 (such as timer interrupts) occur; at the end of the session, Shark 34 processes the sampled data and presents a browsable interface which 35 s hows the processes, threads, and functions associated with those36 events.26 CHUD consists of several components, including command-line programs, 27 GUI applications, kernel extensions, and "frameworks" (collections of 28 libraries, headers, and other resources which applications can use to 29 access functionality provided by the other components.) Past versions 30 of CCL/OpenMCL have used the CHUD framework libraries to control the 31 CHUD profiler. Even though the rest of CHUD is currently 64-bit aware, 32 the frameworks are unfortunately still only available as 32-bit libraries, 33 so the traditional way of controlling the profiling facility from OpenMCL 34 has only worked from DarwinPPC32 versions. 37 35 38 For many processes, Shark can identify functions (the range of 39 addresses corresponding to the address of the first and last 40 instructions in the function) by interpreting symbolic information 41 contained in the executable file. This strategy enables it to identify 42 C and assembler functions in OpenMCL's lisp kernel, but doesn't help 43 much in identifying Lisp functions. Fortunately, Shark does have the 44 ability to read "patch files" , which associate symbolic names to 45 regions of a process's address space), and fortunately OpenMCL can be 46 told to move the machine code (the "code vector") associated with a 47 compiled function to a static memory area (so that the addresses of 48 the first and last instructions in a compiled lisp function remain 49 constant); it's possible to assign fixed addresses to the code vectors 50 of all functions in the lisp at a given time, and to give symbolic 51 names to the memory regions that delimit those code vectors. 36 Two of the CHUD component programs are of particular interest: 52 37 53 The process of moving code vectors to a static (and incidentally 54 read-only) memory area is sometimes referred to as "purification". 38 1) The "Shark" application (often installed in 39 "/Developer/Applications/Performance Tools/Shark.app"), which provides 40 a graphical user interface for exploring and analyzing profiling results 41 and provides tools for creating "sampling configurations" (see below), 42 among other things. 55 43 56 A Sampling Sample 44 2) the "shark" program ("/usr/bin/shark"), which can be used to control 45 the CHUD profiling facility and to collect sampling data, which can then 46 be displayed and analyzed in Shark.app. 57 47 58 There's a little bit of flexibility in the order in which these steps 59 are performed, but for the sake of argument we'll pretend here that 60 there isn't. 48 The fact that these two (substantially different) programs have names that 49 differ only in alphabetic case may be confusing. The discussion below 50 tries to consistently distinguish between "the shark program" and "the 51 Shark application". 61 52 62 1) Run Shark, and put it in "remote" mode. 53 Usage synopsis 54 -------------- 63 55 64 Run Shark. Ensure that it's in "Programmatic (Remote)" mode by 65 selecting that option from the "Sampling" menu, or by pressing the key 66 equivalent "command-shift-R". In the main Shark window, ensure that 67 the sampling type is set to "Time Profile", select "Process" (instead 68 of "Everything" ) from the next popup, and doing so should cause the 69 third popup to select "Remote Client". 56 ? (defun fact (n) (if (zerop n) 1 (* n (fact (1- n))))) 57 FACT 58 ? (require "CHUD-METERING") 59 "CHUD-METERING" 60 ("CHUD-METERING") 61 ? (chud:meter (null (fact 10000))) 62 NIL ; since that large number is not NULL 70 63 71 2) Meter some code in OpenMCL. 64 and, a few seconds after the result is returned, a file whose 65 name is of the form "session_nnn.mshark" will open in Shark.app. 72 66 73 In OpenMCL, do: 67 The fist time that CHUD:METER is used in a lisp session, it'll do a 68 few things to prepare subsequent profiling sessions. Those things 69 include: 74 70 75 ? (require "CHUD-METERING") 71 1) creating a directory to store files that are related to using 72 the CHUD tools in this lisp session. This directory is created in 73 the user's home directory and has a name of the form: 76 74 77 and ensure that the code that you want to profile is defined. 75 profiling-session-<lisp-kernel>-<pid>_<mm>-<dd>-<yyyy>_<h>.<m>.<s> 78 76 79 ? (defun fact (n) 80 (if (zerop n) 81 1 82 (* n (fact (1- n))))) 83 FACT 84 ? (defun fact-n-m-times (m n) 85 (dotimes (i m) 86 (fact n))) 87 FACT-N-M-TIMES 77 where <pid> is the lisp's process id, <lisp-kernel> is the name of 78 the lisp kernel (of all things ...), and the other values provide 79 a timestamp. 88 80 89 Then run something with metering enabled: 81 2) does whatever needs to be done to ensure that currently-defined 82 lisp functions don't move around as the result of GC activity, then 83 writes a text file describing the names and addresses of those functions 84 to the profiling-session directory created above. (The naming conventions 85 for and format of that file are described in 90 86 91 ? (CHUD:METER (fact-n-m-times 1000 1000)) 87 <http://developer.apple.com/documentation/DeveloperTools/Conceptual/SharkUserGuide/MiscellaneousTopics/chapter_951_section_4.html#//apple_ref/doc/uid/TP40005233-CH14-DontLinkElementID_42> 92 88 93 The first time that CHUD:METER is invoked in a lisp session, it'll: 89 3) run the shark program ("/usr/bin/shark") and wait until it's ready to 90 receive signals that control its operation. 94 91 95 1. Ensure that Shark is running 92 This startup activity typically takes a few seconds; after it's been 93 completed, subsequent use of CHUD:METER doesn't involve that overhead. 94 (See the discussion of :RESET below.) 96 95 97 2. Move the code vectors of all functions to a static 98 memory area. 96 After any startup activity is complete, CHUD:METER arranges to send 97 a "start profiling" signal to the running shark program, executes 98 the form, sends a "stop profiling" signal to the shark program, and 99 reads its diagnostic output, looking for the name of the ".mshark" 100 file it produces. If it's able to find this filename, it arranges 101 for "Shark.app" to open it 99 102 100 3. Write a Shark "spatch" file to the user's home 101 directory (which is where we configure Shark to look 102 for such files back in the "Prerequisites" section.) 103 See also CHUD:*SPATCH-DIRECTORY-PATH*. 103 Profiling "configurations". 104 -------------------------- 104 105 105 4. Try to ensure that Shark is running in "remote" mode. 106 (I don't know of any way in which this can be ensured 107 programatically, so it'll just keep asking whether or 108 not Shark's in remote mode until you say "y" and the 109 lisp metering code detects that that's the case.) 106 By default, a shark profiling session will: 107 a) use "time based" sampling, to periodically interrupt the lisp 108 process and note the value of the program counter and at least 109 a few levels of call history. 110 b) do this sampling once every millisecond 111 c) run for up to 30 seconds, unless told to stop earlier. 110 112 111 Those steps may take anywhere from "a few" to "several" seconds; steps 112 2 and 3 are probably the most expensive and depend on how many 113 functions are in the lisp image, how big they are, etc. 113 This is known as "the default configuration"; it's possible to use 114 items on the "Config" menu in the Shark application to create alternate 115 configurations which provide different kinds of profiling parameters 116 and to save these configurations in files for subsequent reuse. 117 (The set of things that CHUD knows how to monitor is large and interesting.) 114 118 115 On every invocation of CHUD:METER, it'll tell Shark to start a 116 metering session, execute the form which is its required argument, 117 tell Shark to stop the session, and return the form's result(s). 119 You use alternate profiling configurations (created and "exported" via 120 Shark.app) with CHUD:METER, but the interface is a little awkward. 118 121 119 After it's been told to stop the sampling session, Shark will analyze 120 the sampling data it obtained and display the results. In this 121 example, it's reasonable to assume that some CCL package functions 122 related to bignum multiplication dominate the execution time. Lisp 123 functions that show up in Shark's session window will claim to be 124 defined in the SPATCH library; their "names" will generally look like 125 their printed representations. 122 Reference 123 --------- 126 124 127 Limitations 125 CHUD:*SHARK-CONFIG-FILE* [Variable] 128 126 129 It's generally tempting to start redefining functions that have 130 longer-than-expected execution times. That's possibly the right thing 131 to do in general, but (because of the way that the spatch mechanism 132 works) it's hard to get meaningful results: Shark can only give names 133 to lisp functions that're in its .spatch file, and will continue to 134 use cached informaton from that .spatch file until it quits. General 135 (GC-able) lisp functions - whose code-vectors might move around in 136 memory - tend to confuse Shark (and at least some versions get 137 confused enough that they may crash while trying to report time spent 138 in functions that aren't where they used to be ...) 127 When non-null, this should be the pathname of an alternate profiling 128 configuration file created by the "Config Editor" in Shark.app. 139 129 140 After things get a little bit out-of-whack (in terms of newly defined 141 lisp functions), it's often necessary to quit both Shark and OpenMCL, 142 load the new-and-improved code into the lisp, and try again, hoping 143 for better results. 130 (CHUD:METER form &key (reset nil) (debug-output nil)) [Macro] 144 131 145 After CHUD:METER has done its first-time setup, it's generally 146 necessary to quit both Shark and OpenMCL if either quits in order to 147 get them back in synch again. 132 Executes FORM (an arbitrary lisp form) and returns whatever result(s) 133 it returns, with CHUD profiling enabled during the form's execution. 134 Tries to determine the name of the session file (*.mshark) to which 135 the shark program wrote profiling data and opens this file in the 136 Shark application. 148 137 149 Despite these limitations, it's probably fair to say that this is way, 150 way better than nothing. 138 Arguments: 151 139 152 Reference 140 debug-output - when non-nil, causes output generated by the shark program to 141 be echoed to *TERMINAL-IO*. For debugging. 142 reset - when non-nil, terminates any running instance of the 143 shark program created by previous invocations of CHUD:METER 144 in this lisp session, generates a new .spatch file 145 (describing the names and addresses of lisp functions), 146 and starts a new instance of the shark program; if 147 CHUD:*SHARK-CONFIG-FILE* is non-NIL when this new instance 148 is started, that instance is told to use the specified 149 config file for profiling (in lieu of the default profiling 150 configuration.) 153 151 154 (CHUD:METER form &key (duration 0) (frequency 1)) [Macro] 155 156 Ensures that access to the "remote sampling facility" (Shark, usually) 157 has been acquired, ensure that code vectors have been purified and 158 that an spatch file for the current process is writen to the directory 159 named by CHUD:*SPATCH-DIRECTORY-PATH* (or the user's home directory), 160 and starts and stops the sampling facility around execution of <form>. 161 Returns whatever values execution of <form> returns. 162 163 Arguments 164 <form> an arbitrary lisp expression 165 <frequency> sampling frequency in milliseconds 166 <duration> total number of sampling intervals, 0 implies "infinite". 167 168 It seems that the <frequency> and <duration> arguments have no effect; 169 the sampling frequency and duration can be set via Shark's "configuration 170 editor" dialog. 171 172 CHUD:*SPATCH-DIRECTORY-PATH* [Special Variable] 173 174 If non-NIL, should be a pathname whose directory component matches the 175 "Patch FIles" search path in Shark's Preferences. When this variable 176 is NIL, USER-HOMEDIR-PATHNAME is used instead. 177 178 179 Acknowledgments 152 Acknowledgments 153 --------------- 180 154 181 155 Both Dan Knapp and Hamilton Link have posted similar CHUD interfaces -
release/1.2/source/objc-bridge/objc-clos.lisp
r8379 r9200 742 742 instance)) 743 743 744 (defmethod terminate ((instance objc:objc-object))745 (objc-message-send instance "release"))746 744 747 745 -
release/1.2/source/objc-bridge/objc-support.lisp
r7005 r9200 187 187 (#/retain instance)) 188 188 189 189 ;;; May have to create/release autorelease pools before the bridge 190 ;;; is fully reinitialized, so use low-level OBJC-MESSAGE-SEND 191 ;;; and @class. 190 192 (defun create-autorelease-pool () 191 (#/init (#/alloc ns:ns-autorelease-pool))) 193 (objc-message-send 194 (objc-message-send (@class "NSAutoreleasePool") "alloc") "init")) 192 195 193 196 (defun release-autorelease-pool (p) 194 ( #/release p))197 (objc-message-send p "release" :void)) 195 198 196 199 … … 486 489 487 490 491 (defmethod terminate ((instance objc:objc-object)) 492 (objc-message-send instance "release")) 488 493 489 494
Note:
See TracChangeset
for help on using the changeset viewer.
