| 109 | | stack frames try to present the frame's contents in a way that's |
| 110 | | (hopefully) more meaningful and useful. For each stack frame |
| 111 | | shown in detail, the corresponding function's argument list |
| 112 | | is printed, followed by the current values of the function's |
| 113 | | arguments (indented slightly), a blank line, and the current |
| 114 | | values of the function's local variables (outdented slightly.) |
| 115 | | The old method of showing a stack frame's "raw" contents is |
| 116 | | still available as the :RAW break loop command. |
| 117 | | |
| 118 | | The new style of presenting a stack-frame's contents is also |
| 119 | | used in the Cocoa IDE. |
| | 109 | stack frames try to present the frame's contents in a way that's |
| | 110 | (hopefully) more meaningful and useful. For each stack frame |
| | 111 | shown in detail, the corresponding function's argument list |
| | 112 | is printed, followed by the current values of the function's |
| | 113 | arguments (indented slightly), a blank line, and the current |
| | 114 | values of the function's local variables (outdented slightly.) |
| | 115 | The old method of showing a stack frame's "raw" contents is |
| | 116 | still available as the :RAW break loop command. |
| | 117 | |
| | 118 | The new style of presenting a stack-frame's contents is also |
| | 119 | used in the Cocoa IDE. |
| 122 | | other than the original one) whose size exceeds the nominal |
| 123 | | OS resource limits for a stack's size. (OpenMCL's threads |
| 124 | | use multiple stacks; the stack in question is the one that |
| 125 | | OpenMCL generally refers to as the "control" or "C" stack.) |
| 126 | | It's not entirely clear what (if anything) the consequences |
| 127 | | of exceeding these limits have been, but OpenMCL's GC can |
| 128 | | use all of the available (C) stack space that it thinks it |
| 129 | | has under some conditions, and, under OSX/Mach/Darwin, there |
| 130 | | have been reports of excessive page file creation and paging |
| 131 | | activity that don't seem related to heap behavior in environments |
| 132 | | where the GC is running on (and possibly using much of) a stack |
| 133 | | whose size greatly exceeds the hard resource limit on stack |
| 134 | | size. |
| 135 | | |
| 136 | | Trying to determine exactly what was causing the excessive |
| 137 | | pages got me trapped in a twisty maze of Mach kernel sources, |
| 138 | | all alike. I tried to pin C stack size to the hard resource |
| 139 | | limit on stack size and have not been able to provoke the |
| 140 | | excessive paging problems since, but am not confident in |
| 141 | | concluding (yet) that the problems had to do with resource |
| 142 | | limits being exceeded. |
| 143 | | |
| 144 | | The hard resource limits on stack size for the OS versions |
| 145 | | that I have readily available (in bash, do "ulimit -s -H"; |
| 146 | | in tcsh, it's "limit -h s", don't know offhand about other |
| 147 | | shells) are: |
| 148 | | |
| 149 | | unlimited on Linux |
| 150 | | ~512M on FreeBSD |
| 151 | | ~64M on Darwin |
| 152 | | |
| 153 | | The effect of observing (rather than exceeding) this limit |
| 154 | | on the maximum depth of lisp recursion in OpenMCL is: |
| 155 | | |
| 156 | | * nothing, on x86-64 (the C stack is not used by lisp code |
| 157 | | on x86-64) |
| 158 | | |
| 159 | | * visible on ppc32, which uses 4 32-bit words on the control |
| 160 | | stack for each lisp function invocation |
| 161 | | |
| 162 | | * more visible on ppc64, which uses 4 64-bit words of control |
| 163 | | stack for each lisp function invocation. |
| 164 | | |
| 165 | | That seems to suggest that (given that the actual stack resource |
| 166 | | limit is a bit under 64M and that OpenMCL signals stack overflow |
| 167 | | when the stack pointer gets within a few hundred KB of the actual |
| 168 | | limit) that ppc64 threads are now limited to a maximum of about |
| 169 | | 2000000 function calls. |
| 170 | | |
| 171 | | (All of this only matters if attempts are made to create threads |
| 172 | | with large stacks; the default stack sizes in OpenMCL are usually |
| 173 | | 1-2 MB.) |
| | 122 | other than the original one) whose size exceeds the nominal |
| | 123 | OS resource limits for a stack's size. (OpenMCL's threads |
| | 124 | use multiple stacks; the stack in question is the one that |
| | 125 | OpenMCL generally refers to as the "control" or "C" stack.) |
| | 126 | It's not entirely clear what (if anything) the consequences |
| | 127 | of exceeding these limits have been, but OpenMCL's GC can |
| | 128 | use all of the available (C) stack space that it thinks it |
| | 129 | has under some conditions, and, under OSX/Mach/Darwin, there |
| | 130 | have been reports of excessive page file creation and paging |
| | 131 | activity that don't seem related to heap behavior in environments |
| | 132 | where the GC is running on (and possibly using much of) a stack |
| | 133 | whose size greatly exceeds the hard resource limit on stack |
| | 134 | size. |
| | 135 | |
| | 136 | Trying to determine exactly what was causing the excessive |
| | 137 | pages got me trapped in a twisty maze of Mach kernel sources, |
| | 138 | all alike. I tried to pin C stack size to the hard resource |
| | 139 | limit on stack size and have not been able to provoke the |
| | 140 | excessive paging problems since, but am not confident in |
| | 141 | concluding (yet) that the problems had to do with resource |
| | 142 | limits being exceeded. |
| | 143 | |
| | 144 | The hard resource limits on stack size for the OS versions |
| | 145 | that I have readily available (in bash, do "ulimit -s -H"; |
| | 146 | in tcsh, it's "limit -h s", don't know offhand about other |
| | 147 | shells) are: |
| | 148 | |
| | 149 | * unlimited on Linux |
| | 150 | * ~512M on FreeBSD |
| | 151 | * ~64M on Darwin |
| | 152 | |
| | 153 | The effect of observing (rather than exceeding) this limit |
| | 154 | on the maximum depth of lisp recursion in OpenMCL is: |
| | 155 | |
| | 156 | * nothing, on x86-64 (the C stack is not used by lisp code on x86-64) |
| | 157 | |
| | 158 | * visible on ppc32, which uses 4 32-bit words on the control stack for each lisp function invocation |
| | 159 | |
| | 160 | * more visible on ppc64, which uses 4 64-bit words of control stack for each lisp function invocation. |
| | 161 | |
| | 162 | That seems to suggest that (given that the actual stack resource |
| | 163 | limit is a bit under 64M and that OpenMCL signals stack overflow |
| | 164 | when the stack pointer gets within a few hundred KB of the actual |
| | 165 | limit) that ppc64 threads are now limited to a maximum of about |
| | 166 | 2000000 function calls. |
| | 167 | |
| | 168 | (All of this only matters if attempts are made to create threads |
| | 169 | with large stacks; the default stack sizes in OpenMCL are usually |
| | 170 | 1-2 MB.) |
| 176 | | years, OpenMCL has shipped with an extended example which provides an |
| 177 | | integrated development environment (IDE) based on Cocoa; that's often |
| 178 | | been described as "the demo IDE" and could also be fairly described as |
| 179 | | "slow", "buggy", "incomplete", and "little more than a proof of |
| 180 | | concept." |
| 181 | | |
| 182 | | I think that it's fair to describe the current state of the IDE as |
| 183 | | being "less slow", "less buggy", "less incomplete", and "much more |
| 184 | | than a proof of concept" than it has been (e.g., there's been some |
| 185 | | actual progress over the last few months and there are plans to |
| 186 | | try to continue working on the IDE and related tools.) It'd probably |
| 187 | | be optimistic to call it "usable" in its current state (that may |
| 188 | | depend on how low one's threshold of usability is), but I hope that |
| 189 | | people who've been discouraged by the lack of IDE progress over the |
| 190 | | last few years will see reason to be encouraged (and that anyone |
| 191 | | interested will submit bug reports, patches, feature requests, code ...) |
| | 173 | years, OpenMCL has shipped with an extended example which provides an |
| | 174 | integrated development environment (IDE) based on Cocoa; that's often |
| | 175 | been described as "the demo IDE" and could also be fairly described as |
| | 176 | "slow", "buggy", "incomplete", and "little more than a proof of |
| | 177 | concept." |
| | 178 | |
| | 179 | I think that it's fair to describe the current state of the IDE as |
| | 180 | being "less slow", "less buggy", "less incomplete", and "much more |
| | 181 | than a proof of concept" than it has been (e.g., there's been some |
| | 182 | actual progress over the last few months and there are plans to |
| | 183 | try to continue working on the IDE and related tools.) It'd probably |
| | 184 | be optimistic to call it "usable" in its current state (that may |
| | 185 | depend on how low one's threshold of usability is), but I hope that |
| | 186 | people who've been discouraged by the lack of IDE progress over the |
| | 187 | last few years will see reason to be encouraged (and that anyone |
| | 188 | interested will submit bug reports, patches, feature requests, code ...) |
| 208 | | used on x86-64. In very general terms, some kinds of function-call |
| 209 | | intensive code may see a significant performance boost, most code |
| 210 | | should see a slight improvement, some code might see a (hopefully |
| 211 | | very slight) degradation, and anything significantly slower than |
| 212 | | previous releases should be reported as a bug. |
| 213 | | It is -possible- that some of these changes may cause errors to |
| 214 | | be reported differently (the function reported as the function |
| 215 | | executing when the error ocurred might be different/wrong). I |
| 216 | | have not seen as many cases of this as I expected to when making |
| 217 | | the change, but am also not sure that I fixed all possible cases. |
| | 206 | used on x86-64. In very general terms, some kinds of function-call |
| | 207 | intensive code may see a significant performance boost, most code |
| | 208 | should see a slight improvement, some code might see a (hopefully |
| | 209 | very slight) degradation, and anything significantly slower than |
| | 210 | previous releases should be reported as a bug. |
| | 211 | |
| | 212 | It is -possible- that some of these changes may cause errors to |
| | 213 | be reported differently (the function reported as the function |
| | 214 | executing when the error ocurred might be different/wrong). I |
| | 215 | have not seen as many cases of this as I expected to when making |
| | 216 | the change, but am also not sure that I fixed all possible cases. |
| | 217 | |
| 219 | | foreign function, constant, or variable name from the input stream |
| 220 | | and try to find the corresponding definition in the interface files. |
| 221 | | If the name is prefixed with a #\? - as in #_?foo - the macros |
| 222 | | return true if the definition could be found and false otherwise. |
| 223 | | (The general idea is that this might be useful for conditionalizing |
| 224 | | code in some cases, and there should be -some- way of quietly testing |
| 225 | | that something's defined.) |
| | 219 | foreign function, constant, or variable name from the input stream |
| | 220 | and try to find the corresponding definition in the interface files. |
| | 221 | If the name is prefixed with a #\? - as in #_?foo - the macros |
| | 222 | return true if the definition could be found and false otherwise. |
| | 223 | (The general idea is that this might be useful for conditionalizing |
| | 224 | code in some cases, and there should be -some- way of quietly testing |
| | 225 | that something's defined.) |
| | 226 | |
| 242 | | "element-type" should be a type specifier such that |
| 243 | | (UPGRADED-ARRAY-ELEMENT-TYPE element-type) is a subtype |
| 244 | | of either SIGNED-BYTE or UNSIGNED-BYTE. |
| 245 | | |
| 246 | | Tries to open the file named by "pathname" for reading and to |
| 247 | | map its contents into the process's address space via #_mmap; |
| 248 | | if successful, returns a lisp vector of element-type |
| 249 | | (UPGRADED-ARRAY-ELEMENT-TYPE element-type) which is displaced |
| 250 | | to an underlying (SIMPLE-ARRAY element-type (*)) whose contents |
| 251 | | match the mapped file's. |
| 252 | | |
| 253 | | Because of alignment issues, the mapped file's contents will |
| 254 | | start a few bytes (4 bytes on 32-bit platforms, 8 bytes on 64-bit |
| 255 | | platforms) "into" the vector; the displaced array returned by |
| 256 | | CCL:MAP-FILE-TO-IVECTOR hides this overhead, but its usually |
| 257 | | more efficient to operate on the underlying simple 1-dimensional |
| 258 | | array. Given a displaced array (like the value returned by |
| 259 | | CCL:MAP-FILE-TO-IVECTOR), the CL function ARRAY-DISPLACEMENT |
| 260 | | returns the underlying array and the displacement index in elements. |
| 261 | | |
| 262 | | Currently, only read-only file mapping is supported; the underlying |
| 263 | | vector will be allocated in read-only memory, and attempts to use |
| 264 | | (e.g.) (SETF (AREF ...) ...) to modify the mapped vector's contents |
| 265 | | will result in memory faults. |
| | 243 | "element-type" should be a type specifier such that |
| | 244 | (UPGRADED-ARRAY-ELEMENT-TYPE element-type) is a subtype |
| | 245 | of either SIGNED-BYTE or UNSIGNED-BYTE. |
| | 246 | |
| | 247 | Tries to open the file named by "pathname" for reading and to |
| | 248 | map its contents into the process's address space via #_mmap; |
| | 249 | if successful, returns a lisp vector of element-type |
| | 250 | (UPGRADED-ARRAY-ELEMENT-TYPE element-type) which is displaced |
| | 251 | to an underlying (SIMPLE-ARRAY element-type (*)) whose contents |
| | 252 | match the mapped file's. |
| | 253 | |
| | 254 | Because of alignment issues, the mapped file's contents will |
| | 255 | start a few bytes (4 bytes on 32-bit platforms, 8 bytes on 64-bit |
| | 256 | platforms) "into" the vector; the displaced array returned by |
| | 257 | CCL:MAP-FILE-TO-IVECTOR hides this overhead, but its usually |
| | 258 | more efficient to operate on the underlying simple 1-dimensional |
| | 259 | array. Given a displaced array (like the value returned by |
| | 260 | CCL:MAP-FILE-TO-IVECTOR), the CL function ARRAY-DISPLACEMENT |
| | 261 | returns the underlying array and the displacement index in elements. |
| | 262 | |
| | 263 | Currently, only read-only file mapping is supported; the underlying |
| | 264 | vector will be allocated in read-only memory, and attempts to use |
| | 265 | (e.g.) (SETF (AREF ...) ...) to modify the mapped vector's contents |
| | 266 | will result in memory faults. |
| 267 | | {{{CCL:MAP-FILE-TO-OCTET-VECTOR pathname [Function]}}} |
| 268 | | |
| 269 | | Equivalent to (CCL:MAP-FILE-TO-IVECTOR pathname '(UNSIGNED-BYTE 8)). |
| 270 | | |
| 271 | | {{{CCL:UNMAP-IVECTOR displaced-vector}}} |
| 272 | | |
| 273 | | If the argument is a mapped vector (as returned by |
| 274 | | MAP-FILE-TO-IVECTOR) that has not yet been "unmapped" by this |
| 275 | | function, undoes the memory mapping, closes the mapped file, and |
| 276 | | adjusts its argument so that it's displaced to a 0-length vector. |
| 277 | | |
| 278 | | CCL:UNMAP-OCTET-VECTOR is an alias for CCL:UNMAP-IVECTOR |
| 279 | | |
| 280 | | Note that whether a vector's created by MAKE-ARRAY or by mapping |
| 281 | | a file's contents, it can't have ARRAY-TOTAL-SIZE-LIMIT or more |
| 282 | | elements. (ARRAY-TOTAL-SIZE-LIMIT is (EXPT 2 24) in 32-bit OpenMCL |
| 283 | | and (EXPT 2 56) in 64-bit versions. |
| | 268 | {{{CCL:MAP-FILE-TO-OCTET-VECTOR pathname [Function]}}} |
| | 269 | |
| | 270 | Equivalent to (CCL:MAP-FILE-TO-IVECTOR pathname '(UNSIGNED-BYTE 8)). |
| | 271 | |
| | 272 | {{{CCL:UNMAP-IVECTOR displaced-vector}}} |
| | 273 | |
| | 274 | If the argument is a mapped vector (as returned by |
| | 275 | MAP-FILE-TO-IVECTOR) that has not yet been "unmapped" by this |
| | 276 | function, undoes the memory mapping, closes the mapped file, and |
| | 277 | adjusts its argument so that it's displaced to a 0-length vector. |
| | 278 | |
| | 279 | CCL:UNMAP-OCTET-VECTOR is an alias for CCL:UNMAP-IVECTOR |
| | 280 | |
| | 281 | Note that whether a vector's created by MAKE-ARRAY or by mapping |
| | 282 | a file's contents, it can't have ARRAY-TOTAL-SIZE-LIMIT or more |
| | 283 | elements. (ARRAY-TOTAL-SIZE-LIMIT is (EXPT 2 24) in 32-bit OpenMCL |
| | 284 | and (EXPT 2 56) in 64-bit versions. |
| 299 | | The fact that things are handled this way (rather than going |
| 300 | | into the kernel debugger with no easy way of recovering) makes |
| 301 | | it possible to continue a session without losing work in many |
| 302 | | cases. In a trivial example like the one above, it's relatively |
| 303 | | easy to see that no harm has been done and the error should |
| 304 | | not be hard to recover from. In some other cases, it may be |
| 305 | | true that a buggy function has been scribbling ofer memory for |
| 306 | | a while before that scribbling resulted in a machine exception. |
| 307 | | |
| 308 | | Moral: if you get an unexpected "memory fault" error (the |
| 309 | | condition type is actually CCL::INVALID-MEMORY-ACCESS) and |
| 310 | | don't understand why the fault occurred and the consequences |
| 311 | | of continuing in the lisp session where the fault occurred, |
| 312 | | you should view the state of that session with some suspicion. |
| 313 | | |
| 314 | | Faults in foreign code (should) still trap into the kernel |
| 315 | | debugger. (It'd be nice to be able to treat these as lisp |
| 316 | | errors with the same caveats as described above, but that |
| 317 | | is more complicated in some cases and isn't yet implemented.) |
| | 300 | The fact that things are handled this way (rather than going |
| | 301 | into the kernel debugger with no easy way of recovering) makes |
| | 302 | it possible to continue a session without losing work in many |
| | 303 | cases. In a trivial example like the one above, it's relatively |
| | 304 | easy to see that no harm has been done and the error should |
| | 305 | not be hard to recover from. In some other cases, it may be |
| | 306 | true that a buggy function has been scribbling ofer memory for |
| | 307 | a while before that scribbling resulted in a machine exception. |
| | 308 | |
| | 309 | Moral: if you get an unexpected "memory fault" error (the |
| | 310 | condition type is actually CCL::INVALID-MEMORY-ACCESS) and |
| | 311 | don't understand why the fault occurred and the consequences |
| | 312 | of continuing in the lisp session where the fault occurred, |
| | 313 | you should view the state of that session with some suspicion. |
| | 314 | |
| | 315 | Faults in foreign code (should) still trap into the kernel |
| | 316 | debugger. (It'd be nice to be able to treat these as lisp |
| | 317 | errors with the same caveats as described above, but that |
| | 318 | is more complicated in some cases and isn't yet implemented.) |
| 341 | | (CCL:DEFSTATIC var value &optional doc-string) |
| 342 | | is like DEFPARAMETER in that it proclaims the variable "var" to |
| 343 | | be special, sets its value to "value", and sets the symbol's |
| 344 | | VARIABLE documentation to the optional doc-string. It differs |
| 345 | | from DEFPARAMETER in that it further asserts that the variable |
| 346 | | should never be bound dynamically in any thread (via LET/LAMBDA/etc.); |
| 347 | | the compiler treats any attempts to bind a "static" variable as an |
| 348 | | error. |
| 349 | | It is legal to change the value of a "static" variable, but since |
| 350 | | all threads see the same (static) binding of that variable it may |
| 351 | | be necessary to synchronize assignments made from multiple threads. |
| 352 | | (A "static" variable binding is effectively a shared, global resource; |
| 353 | | a dynamic binding is thread-private.) |
| 354 | | Access to the value of a static variable is typically faster than |
| 355 | | is access to the value a special variable that's not proclaimed to |
| 356 | | be "static". |
| 357 | | This functionality has been in MCL/OpenMCL for a long time under |
| 358 | | the name CCL:DEFGLOBAL; CCL:DEFGLOBAL is an alias for CCL:DEFSTATIC, |
| 359 | | but the latter seemed to be a better name. |
| | 344 | {{{(CCL:DEFSTATIC var value &optional doc-string)}}} |
| | 345 | is like DEFPARAMETER in that it proclaims the variable "var" to |
| | 346 | be special, sets its value to "value", and sets the symbol's |
| | 347 | VARIABLE documentation to the optional doc-string. It differs |
| | 348 | from DEFPARAMETER in that it further asserts that the variable |
| | 349 | should never be bound dynamically in any thread (via LET/LAMBDA/etc.); |
| | 350 | the compiler treats any attempts to bind a "static" variable as an |
| | 351 | error. |
| | 352 | |
| | 353 | It is legal to change the value of a "static" variable, but since |
| | 354 | all threads see the same (static) binding of that variable it may |
| | 355 | be necessary to synchronize assignments made from multiple threads. |
| | 356 | (A "static" variable binding is effectively a shared, global resource; |
| | 357 | a dynamic binding is thread-private.) |
| | 358 | |
| | 359 | Access to the value of a static variable is typically faster than |
| | 360 | is access to the value a special variable that's not proclaimed to |
| | 361 | be "static". |
| | 362 | |
| | 363 | This functionality has been in MCL/OpenMCL for a long time under |
| | 364 | the name CCL:DEFGLOBAL; CCL:DEFGLOBAL is an alias for CCL:DEFSTATIC, |
| | 365 | but the latter seemed to be a better name. |
| | 366 | |
| 361 | | asserted (this means that a MACPTR object can contain a small |
| 362 | | integer which identifies the alleged FOREIGN-TYPE of the object that |
| 363 | | the points to. RLET, MAKE-RECORD, and MAKE-GCABLE-RECORD (see below) |
| 364 | | assert the foreign type of the object that the MACPTR object they |
| 365 | | create (as do some new features of the ObjC bridge, described further |
| 366 | | below.) |
| 367 | | PRINT-OBJECT on a MACPTR will try to print information about the |
| 368 | | asserted type of that pointer, as well as information about where |
| 369 | | the pointer was allocated (heap, stack) and whether it's scheduled |
| 370 | | for automatic reclamation by the GC. |
| 371 | | A few constructs that conceivable should assert the type of the |
| 372 | | pointers they create (e.g., some flavor of PREF, SLOT-VALUE in |
| 373 | | the ObjC bridge) don't yet do so. |
| 374 | | A rather obvious way of exploiting typed pointers - namely, extending |
| 375 | | DESCRIBE and INSPECT to show the contents of foreign records - is |
| 376 | | not yet implemented. |
| | 368 | asserted (this means that a MACPTR object can contain a small |
| | 369 | integer which identifies the alleged FOREIGN-TYPE of the object that |
| | 370 | the points to. RLET, MAKE-RECORD, and MAKE-GCABLE-RECORD (see below) |
| | 371 | assert the foreign type of the object that the MACPTR object they |
| | 372 | create (as do some new features of the ObjC bridge, described further |
| | 373 | below.) |
| | 374 | |
| | 375 | PRINT-OBJECT on a MACPTR will try to print information about the |
| | 376 | asserted type of that pointer, as well as information about where |
| | 377 | the pointer was allocated (heap, stack) and whether it's scheduled |
| | 378 | for automatic reclamation by the GC. |
| | 379 | |
| | 380 | A few constructs that conceivable should assert the type of the |
| | 381 | pointers they create (e.g., some flavor of PREF, SLOT-VALUE in |
| | 382 | the ObjC bridge) don't yet do so. |
| | 383 | |
| | 384 | A rather obvious way of exploiting typed pointers - namely, extending |
| | 385 | DESCRIBE and INSPECT to show the contents of foreign records - is |
| | 386 | not yet implemented. |
| | 387 | |
| 378 | | of a foreign record type". (Or, to be more banal about it, uses |
| 379 | | #_malloc to allocate a block of foreign memory of the size of the |
| 380 | | foreign record type named by its argument.) MAKE-GCABLE-RECORD |
| 381 | | additionally tells the lisp garbage collector that it should free |
| 382 | | the foreign memory when the MACPTR object that describes it becomes |
| 383 | | garbage. |
| 384 | | When using "gcable pointers", it's important to remember the |
| 385 | | distinction between a MACPTR object (which is a lisp object, more- |
| 386 | | or-less like any other) and the block of foreign memory that the |
| 387 | | MACPTR object points to. If a gcable MACPTR is the only thing |
| 388 | | in the world ("lisp world" or "foreign world") that references |
| 389 | | the underlying block of foreign memory, then freeing the foreign |
| 390 | | memory when it becomes impossible to reference it is convenient |
| 391 | | and sane. If other lisp MACPTRs reference the underlying block |
| 392 | | of foreign memory or if the address of that foreign memory is |
| 393 | | passed to and retained by foreign code, having the GC free the |
| 394 | | memory may have unpleasant consequences if those other references |
| 395 | | are used. |
| | 389 | of a foreign record type". (Or, to be more banal about it, uses |
| | 390 | #_malloc to allocate a block of foreign memory of the size of the |
| | 391 | foreign record type named by its argument.) MAKE-GCABLE-RECORD |
| | 392 | additionally tells the lisp garbage collector that it should free |
| | 393 | the foreign memory when the MACPTR object that describes it becomes |
| | 394 | garbage. |
| | 395 | |
| | 396 | When using "gcable pointers", it's important to remember the |
| | 397 | distinction between a MACPTR object (which is a lisp object, more- |
| | 398 | or-less like any other) and the block of foreign memory that the |
| | 399 | MACPTR object points to. If a gcable MACPTR is the only thing |
| | 400 | in the world ("lisp world" or "foreign world") that references |
| | 401 | the underlying block of foreign memory, then freeing the foreign |
| | 402 | memory when it becomes impossible to reference it is convenient |
| | 403 | and sane. If other lisp MACPTRs reference the underlying block |
| | 404 | of foreign memory or if the address of that foreign memory is |
| | 405 | passed to and retained by foreign code, having the GC free the |
| | 406 | memory may have unpleasant consequences if those other references |
| | 407 | are used. |
| | 408 | |
| 411 | | device) has traditionally caused an exit to the outer break loop |
| 412 | | (or had no effect if the REPL was not in a break loop). If |
| 413 | | CCL:*QUIT-ON-EOF* is set, an EOF causes the lisp to quit. (It |
| 414 | | actually invokes a listener-specific method, so in a multi-listener |
| 415 | | window system environemt, it might simply cause the listener which |
| 416 | | receives the EOF to exit.) |
| 417 | | None of this has any effect when running under environments like |
| 418 | | SLIME, and (as mentioned above) only matters if the standard input |
| 419 | | devices is a tty or pseudo-tty (where it's possible to continue |
| 420 | | reading after an EOF has been read.) If running under an xterm |
| 421 | | or OSX Terminal.app, standard input is probably a pty; if running |
| 422 | | in an Emacs shell buffer or under other means under emacs, different |
| 423 | | types of IPC mechanisms (pipes, sockets) might be used. |
| | 426 | device) has traditionally caused an exit to the outer break loop |
| | 427 | (or had no effect if the REPL was not in a break loop). If |
| | 428 | CCL:*QUIT-ON-EOF* is set, an EOF causes the lisp to quit. (It |
| | 429 | actually invokes a listener-specific method, so in a multi-listener |
| | 430 | window system environemt, it might simply cause the listener which |
| | 431 | receives the EOF to exit.) |
| | 432 | |
| | 433 | None of this has any effect when running under environments like |
| | 434 | SLIME, and (as mentioned above) only matters if the standard input |
| | 435 | devices is a tty or pseudo-tty (where it's possible to continue |
| | 436 | reading after an EOF has been read.) If running under an xterm |
| | 437 | or OSX Terminal.app, standard input is probably a pty; if running |
| | 438 | in an Emacs shell buffer or under other means under emacs, different |
| | 439 | types of IPC mechanisms (pipes, sockets) might be used. |
| | 440 | |
| 436 | | streams in the value of CCL:*OPEN-FILE-STREAMS*; maintaining this |
| 437 | | list helps to ensure that streams get closed in as orderly a manner |
| 438 | | as possible when the lisp exits. The code which accessed this list |
| 439 | | didn't do so in a thread-safe manner. |
| 440 | | The list is now maintained in a lexical variable; the function |
| 441 | | CCL:OPEN-FILE-STREAMS returns a copy of that list, |
| 442 | | CCL:NOTE-OPEN-FILE-STREAM adds its argument (a file stream) to the |
| 443 | | list, and CCL:REMOVE-OPEN-FILE-STREAM removes its argument (a file stream) |
| 444 | | from the list. (All of these functions use appropriate locking.) |
| | 455 | streams in the value of CCL:*OPEN-FILE-STREAMS*; maintaining this |
| | 456 | list helps to ensure that streams get closed in as orderly a manner |
| | 457 | as possible when the lisp exits. The code which accessed this list |
| | 458 | didn't do so in a thread-safe manner. |
| | 459 | |
| | 460 | The list is now maintained in a lexical variable; the function |
| | 461 | CCL:OPEN-FILE-STREAMS returns a copy of that list, |
| | 462 | CCL:NOTE-OPEN-FILE-STREAM adds its argument (a file stream) to the |
| | 463 | list, and CCL:REMOVE-OPEN-FILE-STREAM removes its argument (a file stream) |
| | 464 | from the list. (All of these functions use appropriate locking.) |
| | 465 | |
| 466 | | A lot of macros/functions/other things that really should have been |
| 467 | | exported from some package for the last few years finally have been |
| 468 | | exported from the OBJC or NS packages (and a lot of things that have |
| 469 | | historically been internal to CCL are re-imported into CCL). |
| 470 | | |
| 471 | | Cocoa (and the underlying Core Graphics libraries) have historically |
| 472 | | used 32-bit floats and 32-bit integers in data structures that describe |
| 473 | | geometry, font sizes and metrics, and elsewhere. 64-bit Cocoa will |
| 474 | | use 64-bit floats and 64-bit integers in many cases. |
| 475 | | |
| 476 | | The bridge defines the type NS:CGFLOAT as the lisp type of the |
| 477 | | preferred float type on the platform, and the constant NS:+CGFLOAT+. |
| 478 | | On DarwinPPC32, the foreign types :cgfloat, :<NSUI>nteger, and |
| 479 | | :<NSI>nteger are defined by the bridge (as 32-bit float, 32-bit |
| 480 | | unsigned integer, and 32-bit signed integer, respectively.); these |
| 481 | | types are defined (as 64-bit variants) in the 64-bit interfaces. |
| 482 | | |
| 483 | | All ObjC classes are properly named, either with a name exported |
| 484 | | from the NS package (in the case of a predefined class declared in |
| 485 | | the interface files) or with the name provided in the DEFCLASS |
| 486 | | form (with :METACLASS NS:+NS-OBJECT) which defines the class from |
| 487 | | lisp. The class's lisp name is now proclaimed to be a "static" |
| 488 | | variable (as if by DEFSTATIC, as described above) and given the |
| 489 | | class object as its value. In other words: |
| | 491 | A lot of macros/functions/other things that really should have been |
| | 492 | exported from some package for the last few years finally have been |
| | 493 | exported from the OBJC or NS packages (and a lot of things that have |
| | 494 | historically been internal to CCL are re-imported into CCL). |
| | 495 | |
| | 496 | Cocoa (and the underlying Core Graphics libraries) have historically |
| | 497 | used 32-bit floats and 32-bit integers in data structures that describe |
| | 498 | geometry, font sizes and metrics, and elsewhere. 64-bit Cocoa will |
| | 499 | use 64-bit floats and 64-bit integers in many cases. |
| | 500 | |
| | 501 | The bridge defines the type NS:CGFLOAT as the lisp type of the |
| | 502 | preferred float type on the platform, and the constant NS:+CGFLOAT+. |
| | 503 | On DarwinPPC32, the foreign types :cgfloat, :<NSUI>nteger, and |
| | 504 | :<NSI>nteger are defined by the bridge (as 32-bit float, 32-bit |
| | 505 | unsigned integer, and 32-bit signed integer, respectively.); these |
| | 506 | types are defined (as 64-bit variants) in the 64-bit interfaces. |
| | 507 | |
| | 508 | All ObjC classes are properly named, either with a name exported |
| | 509 | from the NS package (in the case of a predefined class declared in |
| | 510 | the interface files) or with the name provided in the DEFCLASS |
| | 511 | form (with :METACLASS NS:+NS-OBJECT) which defines the class from |
| | 512 | lisp. The class's lisp name is now proclaimed to be a "static" |
| | 513 | variable (as if by DEFSTATIC, as described above) and given the |
| | 514 | class object as its value. In other words: |
| 507 | | (including colons) from the stream on which it appears and interns |
| 508 | | that sequence - with case preserved and colons intact - in a new package |
| 509 | | whose name is NEXTSTEP-FUNCTIONS, exporting the symbol from that package. |
| 510 | | This means that the act of reading "#/alloc" returns the the symbol |
| 511 | | NEXTSTEP-FUNCTIONS:|alloc|, and the act of reading "#/initWithFrame:" |
| 512 | | returns the symbol NEXTSTEP-FUNCTIONS:|initWithFrame:|. The intent |
| 513 | | is that the reader macro can be used to construct symbols whose names |
| 514 | | match ObjC message names; the reader macro tries to do some sanity |
| 515 | | checks (such as insisting that a name that contains at least one |
| 516 | | colon ends in a colon), but isn't totally rigourous about enforcing |
| 517 | | ObjC message name conventions. |
| 518 | | |
| 519 | | A symbol read using this macro can be used as an operand in |
| 520 | | most places where an ObjC message name can be used, such as |
| 521 | | in the (@SELECTOR ...) construct (which is now OBJC:@SELECTOR, |
| 522 | | btw.) |
| 523 | | |
| 524 | | Marco Baringer proposed the idea of using a reader macro to |
| 525 | | construct lisp symbols which matched ObjC message names. |
| | 532 | (including colons) from the stream on which it appears and interns |
| | 533 | that sequence - with case preserved and colons intact - in a new package |
| | 534 | whose name is NEXTSTEP-FUNCTIONS, exporting the symbol from that package. |
| | 535 | This means that the act of reading "#/alloc" returns the the symbol |
| | 536 | NEXTSTEP-FUNCTIONS:|alloc|, and the act of reading "#/initWithFrame:" |
| | 537 | returns the symbol NEXTSTEP-FUNCTIONS:|initWithFrame:|. The intent |
| | 538 | is that the reader macro can be used to construct symbols whose names |
| | 539 | match ObjC message names; the reader macro tries to do some sanity |
| | 540 | checks (such as insisting that a name that contains at least one |
| | 541 | colon ends in a colon), but isn't totally rigourous about enforcing |
| | 542 | ObjC message name conventions. |
| | 543 | |
| | 544 | A symbol read using this macro can be used as an operand in |
| | 545 | most places where an ObjC message name can be used, such as |
| | 546 | in the (@SELECTOR ...) construct (which is now OBJC:@SELECTOR, |
| | 547 | btw.) |
| | 548 | |
| | 549 | Marco Baringer proposed the idea of using a reader macro to |
| | 550 | construct lisp symbols which matched ObjC message names. |
| 528 | | package triggers an interface database lookup of Objc methods |
| 529 | | with the corresponding message name. If any such information |
| 530 | | is found, a special type of dispatching function is created |
| 531 | | and initialized and the weird-looking symbol is given that |
| 532 | | dispatching function as its function definition. |
| 533 | | |
| 534 | | The dispatching knows how to call declared ObjC methods defined on |
| 535 | | the message. In many cases, all methods have the same foreign type |
| 536 | | signature, and the dispatching function merely passes any arguments |
| 537 | | that it receives to a function that does an ObjC message send with |
| 538 | | the indicated foreign argument and return types. In other cases, |
| 539 | | where different ObjC messages have different type signatures, the |
| 540 | | dispatching function tries to choose a function that handles the |
| 541 | | right type signature based on the class of the dispatching function's |
| 542 | | first argument. |
| 543 | | |
| 544 | | If new information about ObjC methods is introduced (e.g., by |
| 545 | | using additional interface files or as ObjC methods are defined |
| 546 | | from lisp), the dispatch function is reinitialized to recognize |
| 547 | | newly-introduced foreign type signatures. |
| 548 | | |
| 549 | | The argument and result coercion that the bridge has tradionally |
| 550 | | supported is supported by the new mechanism (e.g., :<BOOL> arguments |
| 551 | | can be specified as lisp booleans and :<BOOL> results are returned |
| 552 | | as lisp boolean values, and an argument value of NIL is coerced to |
| 553 | | a null pointer if the corresponding argument type is :ID. |
| 554 | | |
| 555 | | Some ObjC methods accept variable numbers of arguments; the |
| 556 | | foreign types of non-required arguments are determined by the |
| 557 | | lisp types of those arguments (e.g., integers are passed as |
| 558 | | integers, floats as floats, pointers as pointers, record types |
| 559 | | by reference.) |
| 560 | | |
| 561 | | Some examples: |
| | 553 | package triggers an interface database lookup of Objc methods |
| | 554 | with the corresponding message name. If any such information |
| | 555 | is found, a special type of dispatching function is created |
| | 556 | and initialized and the weird-looking symbol is given that |
| | 557 | dispatching function as its function definition. |
| | 558 | |
| | 559 | The dispatching function knows how to call declared ObjC methods defined on |
| | 560 | the message. In many cases, all methods have the same foreign type |
| | 561 | signature, and the dispatching function merely passes any arguments |
| | 562 | that it receives to a function that does an ObjC message send with |
| | 563 | the indicated foreign argument and return types. In other cases, |
| | 564 | where different ObjC messages have different type signatures, the |
| | 565 | dispatching function tries to choose a function that handles the |
| | 566 | right type signature based on the class of the dispatching function's |
| | 567 | first argument. |
| | 568 | |
| | 569 | If new information about ObjC methods is introduced (e.g., by |
| | 570 | using additional interface files or as ObjC methods are defined |
| | 571 | from lisp), the dispatch function is reinitialized to recognize |
| | 572 | newly-introduced foreign type signatures. |
| | 573 | |
| | 574 | The argument and result coercion that the bridge has tradionally |
| | 575 | supported is supported by the new mechanism (e.g., :<BOOL> arguments |
| | 576 | can be specified as lisp booleans and :<BOOL> results are returned |
| | 577 | as lisp boolean values, and an argument value of NIL is coerced to |
| | 578 | a null pointer if the corresponding argument type is :ID. |
| | 579 | |
| | 580 | Some ObjC methods accept variable numbers of arguments; the |
| | 581 | foreign types of non-required arguments are determined by the |
| | 582 | lisp types of those arguments (e.g., integers are passed as |
| | 583 | integers, floats as floats, pointers as pointers, record types |
| | 584 | by reference.) |
| | 585 | |
| | 586 | Some examples: |
| 589 | | will return a gcable pointer to a structure that describes that window's |
| 590 | | frame rectangle. (The good news is that there's no need to use SLET |
| 591 | | or special structure-returning message send syntax; the bad news is |
| 592 | | that #_malloc, #_free, and the GC are all involved in the creation |
| 593 | | and eventual destruction of structure-typed return values. Unless |
| 594 | | and until those factors negatively affect performance, the advantages |
| 595 | | seem to outweigh the disadvantages.) |
| | 614 | will return a gcable pointer to a structure that describes that window's |
| | 615 | frame rectangle. (The good news is that there's no need to use SLET |
| | 616 | or special structure-returning message send syntax; the bad news is |
| | 617 | that #_malloc, #_free, and the GC are all involved in the creation |
| | 618 | and eventual destruction of structure-typed return values. Unless |
| | 619 | and until those factors negatively affect performance, the advantages |
| | 620 | seem to outweigh the disadvantages.) |
| 598 | | possible to treat pointers to some foreign types as "instances of |
| 599 | | built-in classes." Specifically, a pointer to an :<NSR>ect is |
| 600 | | recognized as an instance of the built-in class NS:NS-RECT, a |
| 601 | | pointer to an <NSS>ize is treated as an instance of NS:NS-SIZE, |
| 602 | | <NSP>oint is recognized as NS:NS-POINT, and <NSR>ange maps to |
| 603 | | NS:NS-RANGE. (There are a few other more obscure structure |
| 604 | | types that get this treatment, and with a little more work the |
| 605 | | mechanism could be made extensible.) |
| 606 | | |
| 607 | | For each of these built-in classes: |
| 608 | | |
| 609 | | - a PRINT-OBJECT method is defined |
| 610 | | |
| 611 | | - a foreign type name derived from the class name (e.g., :NS-RECT |
| | 623 | possible to treat pointers to some foreign types as "instances of |
| | 624 | built-in classes." Specifically, a pointer to an :<NSR>ect is |
| | 625 | recognized as an instance of the built-in class NS:NS-RECT, a |
| | 626 | pointer to an <NSS>ize is treated as an instance of NS:NS-SIZE, |
| | 627 | <NSP>oint is recognized as NS:NS-POINT, and <NSR>ange maps to |
| | 628 | NS:NS-RANGE. (There are a few other more obscure structure |
| | 629 | types that get this treatment, and with a little more work the |
| | 630 | mechanism could be made extensible.) |
| | 631 | |
| | 632 | For each of these built-in classes: |
| | 633 | |
| | 634 | * a PRINT-OBJECT method is defined |
| | 635 | |
| | 636 | * a foreign type name derived from the class name (e.g., :NS-RECT |