SBCL
1. SBCL
ID: a7f9b428-9323-492f-aaa5-94669bfbc55b–
1.1. Extensions
1.1.1. ed functions
ID: 11329fdb-2923-4ccf-953c-037e78433b1a CREATED: <2025-03-03 Mon 14:53>
- State "NOTE" from
Although SBCL does not provide a resident editor, the ed function can be customized to hook into user-provided editing mechanisms as follows: Function: ed [cl] &optional x Starts the editor (on a file or a function if named). Functions from the list *ed-functions* are called in order with x as an argument until one of them returns non-NIL; these functions are responsible for signalling a file-error to indicate failure to perform an operation on the file system. Variable: *ed-functions* [sb-ext] See function documentation for ed.
1.1.2. Concurrency
ID: e99f0d2a-546a-479e-9014-3acdbcccd5ab CREATED: <2025-03-06 Thu 14:14>
(defvar *buffer-queue* (make-waitqueue)) (defvar *buffer-lock* (make-mutex :name "buffer lock")) (defvar *buffer* (list nil)) (defun reader () (with-mutex (*buffer-lock*) (loop (condition-wait *buffer-queue* *buffer-lock*) (loop (unless *buffer* (return)) (let ((head (car *buffer*))) (setf *buffer* (cdr *buffer*)) (format t "reader ~A woke, read ~A~%" *current-thread* head)))))) (defun writer () (loop (sleep (random 5)) (with-mutex (*buffer-lock*) (let ((el (intern (string (code-char (+ (char-code #\A) (random 26))))))) (setf *buffer* (cons el *buffer*))) (condition-notify *buffer-queue*)))) (make-thread #'writer) (make-thread #'reader) (make-thread #'reader)
#<THREAD tid=0 RUNNING {100C873E73}>
(defvar *data* nil) (defvar *queue* (make-waitqueue)) (defvar *lock* (make-mutex)) ;; Consumer (defun pop-data (&optional timeout) (with-mutex (*lock*) (loop until *data* do (or (condition-wait *queue* *lock* :timeout timeout) ;; Lock not held, must unwind without touching *data*. (return-from pop-data nil))) (pop *data*))) ;; Producer (defun push-data (data) (with-mutex (*lock*) (push data *data*) (condition-notify *queue*)))
PUSH-DATA
- Barriers
ID: dc91fb4a-adee-44ec-9bd8-cbfa10db8dca CREATED: <2025-03-06 Thu 14:19>
These are based on the Linux kernel barrier design, which is in turn based on the Alpha CPU memory model. They are presently implemented for x86, x86-64, PPC, ARM64, and RISC-V systems, and behave as compiler barriers on all other CPUs.
In addition to explicit use of the sb-thread:barrier macro, the following functions and macros also serve as :memory barriers:
- sb-ext:atomic-decf, sb-ext:atomic-incf, sb-ext:atomic-push, and sb-ext:atomic-pop.
- sb-ext:compare-and-swap.
- sb-thread:grab-mutex, sb-thread:release-mutex, sb-thread:with-mutex and sb-thread:with-recursive-lock.
- sb-thread:signal-semaphore, sb-thread:try-semaphore and sb-thread:wait-on-semaphore.
- sb-thread:condition-wait, sb-thread:condition-notify and sb-thread:condition-broadcast.
- Timers
ID: 6ff7096f-a666-4103-8f32-1dc62c04cb35 CREATED: <2025-03-06 Thu 14:19>
– - sb-thread
ID: 7bf0993f-6212-4635-a071-bf2e7d9ba7f9 CREATED: <2025-03-06 Thu 14:06>
->(make-thread (lambda () (write-line "Hello, world")))
#<THREAD tid=0 RUNNING {100933AD93}>
- Atomics
ID: bb27d9c3-513a-4ac6-8780-580c09257040 CREATED: <2025-03-06 Thu 14:11>
–
1.1.3. global vars
ID: c33d77c8-188c-4ba0-90ff-f49fac6468c2 CREATED: <2025-04-28 Mon 18:11>
(describe 'sb-ext:defglobal)
SB-EXT:DEFGLOBAL [symbol] DEFGLOBAL names a macro: Lambda-list: (NAME VALUE &OPTIONAL (DOC NIL)) Documentation: Defines NAME as a global variable that is always bound. VALUE is evaluated and assigned to NAME both at compile- and load-time, but only if NAME is not already bound. Global variables share their values between all threads, and cannot be locally bound, declared special, defined as constants, and neither bound nor defined as symbol macros. See also the declarations SB-EXT:GLOBAL and SB-EXT:ALWAYS-BOUND. Source file: SYS:SRC;CODE;MACROS.LISP
(describe 'sb-ext:define-load-time-global)
SB-EXT:DEFINE-LOAD-TIME-GLOBAL [symbol] DEFINE-LOAD-TIME-GLOBAL names a macro: Lambda-list: (NAME VALUE &OPTIONAL (DOC NIL)) Documentation: Defines NAME as a global variable that is always bound. VALUE is evaluated and assigned to NAME at load-time, but only if NAME is not already bound. Attempts to read NAME at compile-time will signal an UNBOUND-VARIABLE error unless it has otherwise been assigned a value. See also DEFGLOBAL which assigns the VALUE at compile-time too. Source file: SYS:SRC;CODE;MACROS.LISP
1.2. Internals
ID: 9aac997a-5d9c-43dd-b2ca-8b8b02d9f2dd
An exploration of SBCL internals - simonsafar.com – guicho271828/sbcl-wiki – Starting to hack on SBCL - Paul Khuong: some Lisp
–- DFO
- Data Flow Optimization?
- (no term)
-
TN is, i think, a 'Temporary Name', i.e. an abstract register inside VMR(IR2 represenation, i.e. VOPs). Names bound to VOP arguments, results, temporary variables, etc are TNs. Specific registers could also be used as TNs, those are suffixed with -tn, for ex. RAX-TN, FLOAT[0-15]-TN etc.
- TN
- Temporary Name
- SB
- storage base
- SC
- storage class
- TLAB
- Thread-Local Allocation Buffer
- (no term)
sfunction
;;; Similar to FUNCTION, but the result type is "exactly" specified: ;;; if it is an object type, then the function returns exactly one ;;; value, if it is a short form of VALUES, then this short form ;;; specifies the exact number of values. (def!type sfunction (args &optional result) (let ((result (cond ((eq result '*) '*) ((or (atom result) (not (eq (car result) 'values))) `(values ,result &optional)) ((intersection (cdr result) lambda-list-keywords) result) (t `(values ,@(cdr result) &optional))))) `(function ,args ,result)))
- msan
Memory Sanitizer
;; from 'llvm/projects/compiler-rt/lib/msan/msan.h': ;; "#define MEM_TO_SHADOW(mem) (((uptr)(mem)) ^ 0x500000000000ULL)" #+linux ; shadow space differs by OS (defconstant sb-vm::msan-mem-to-shadow-xor-const #x500000000000)
- (no term)
backend
;;;; VM support routines which backends need to implement ;;; from vm.lisp ;;; immediate-constant-sc ;;; location-print-name ;;; convert-conditional-move-p ;;; boxed-immediate-sc-p ;;; from c-call.lisp ;;; make-call-out-tns ;;; from call.lisp ;;; make-return-pc-passing-location ;;; make-old-fp-passing-location ;;; make-old-fp-save-location ;;; make-return-pc-save-location ;;; make-arg-count-location ;;; from nlx.lisp ;;; make-nlx-entry-arg-start-location ;;; from pred.lisp ;;; convert-conditional-move-p ;;; from support.lisp ;;; generate-call-sequence ;;; generate-return-sequence ;;; for use with scheduler ;;; emit-nop ;;; location-number
- (no term)
XSET
;;;; XSET ;;;; ;;;; A somewhat efficient set implementation that can store arbitrary ;;;; objects. For small sets the data is stored in a list, but when ;;;; the amount of elements grows beyond +XSET-LIST-SIZE-LIMIT+, we ;;;; switch to a hash-table instead. ;;;; ;;;; ALLOC-XSET allocates an empty XSET. ADD-TO-XSET adds an element ;;;; to an XSET: it should be used only on freshly allocated XSETs. ;;;; ;;;; XSET-EMPTY-P, XSET-INTERSECTION, XSET-SUBSET-P, and XSET-MEMBER-P ;;;; do the obvious things. MAP-XSET maps over the element, but ;;;; requires a function as the first argument -- not a function ;;;; designator. ;;;; ;;;; Note: XSET always uses EQL as the equivalence test
- IDF
- Identical Code Folding (similar to what might be done by a C linker)
1.2.1. FREEZE-TYPE
ID: 9aa17e32-5677-4ff1-9e85-6df91557cea1 CREATED: <2025-05-27 Tue 22:04>
From CMUCL:
The extensions:freeze-type declaration is a CMUCL extension that enables more efficient compilation of user-defined types by asserting that the definition is not going to change. This declaration may only be used globally (with declaim or proclaim). Currently freeze-type only affects structure type testing done by typep, typecase, etc. Here is an example:
(declaim (freeze-type foo bar))
This asserts that the types foo and bar and their subtypes are not going to change. This allows more efficient type testing, since the compiler can open-code a test for all possible subtypes, rather than having to examine the type hierarchy at run-time.
1.2.2. CTYPE
ID: ed7c8a7c-0b0f-42f5-9e68-b2528ff26af9 CREATED: <2025-05-26 Mon 21:47>
referred to globally as the internal name for Lisp types, and in SB-C as IR1 types.
compiler/ctype.lisp
;;;; FIXME: This is a poor name for this file, since CTYPE is the name ;;;; of the type used internally to represent Lisp types. It'd ;;;; probably be good to rename this file to "call-type.lisp" or ;;;; "ir1-type.lisp" or something.
type-class.lisp
;;;; This file contains the definition of the CTYPE (Compiler TYPE) ;;;; structure, as well as the TYPE-CLASS structure which is a metaobject ;;;; that factors out commonality amongst the subtypes of CTYPE. ;;;; Together they form a sort of mini object system with slightly ;;;; odd dispatching rules. The TYPE-CLASS is a vtable, essentially. ;;;; Various macros related to manipulating those things are here too. ;; ... ;;; the base class for the internal representation of types ;;; Each CTYPE instance (all subtypes thereof) has a random opaque hash value. ;;; Hashes are mixed together to form a lookup key in the memoization wrappers ;;; for most operations on CTYPES. This works because CTYPEs are immutable. ;;; No more than N-FIXNUM-BITS for 32-bit machines are used, even for 64-bit words. ;;; It's easiest this way. It could be host-fixnum-sized for the host, and then ;;; target-fixnum-sized for the target, but that's not easy to do with DEF!STRUCT. ;;; (In fact I think it's probably infeasible but I'm not certain of it) ;;; You could always make it SB-XC:FIXNUM at the risk of forcing the host to ;;; deal in bignums. Why cause it undue slowness when we don't need so many bits? ;;; NOTE: we _do_ use the sign bit, leaving us 25 pseudorandom bits, but ;;; the 3 bits of least significance are NOT pseudorandom, so it's best ;;; not to use them directly in the hash index. (defconstant ctype-hash-size 30) ; all significant bits, for the slot type specifier (defconstant ctype-PRNG-nbits 25) ; from pseudorandom number generator (defconstant ctype-contains-unknown #b001) (defconstant ctype-contains-hairy #b010) ; any hairy type, including UNKNOWN (defconstant ctype-contains-class #b100) ; standard-class (defconstant +ctype-flag-mask+ #b111) (defconstant +ctype-hash-mask+ (logandc2 (1- (ash 1 ctype-PRNG-nbits)) #b111)) (defstruct (ctype (:conc-name type-) (:constructor nil) (:copier nil) #-sb-xc-host (:pure t)) ;; bits 0..24: pseudorandom hash ;; bits 25..29: 5 bits for type-class index (%bits (missing-arg) :type (signed-byte #.ctype-hash-size) :read-only t))
1.2.3. DEFTRANSFORM
ID: 4f3868b5-131e-4d3d-9833-bbe00d0d6cde CREATED: <2025-05-26 Mon 20:30>
- so: define-compiler-macro vs deftransform/defknown
- compiler-macro/notes at master · Bike/compiler-macro
- basically, compiler-macros don't quite give us enough info to make
useful source2source transformations
- possible to use sb-cltl2 envs to retrieve type info, but even then we don't get to take full advantange of the compiler (type propagation isn't automatic, etc)
- deftransform is used for more complex transformations with direct access to the compiler (operates on IR1)
(sb-c:defknown wat (T T) *) (sb-c:deftransform wat ((x y) (string string) *) `(string-wat x y)) (defun wat (x y) (if (and (numberp x) (numberp y)) (+ x y) (concatenate 'string x y))) (defun string-wat (x y) (declare (optimize (speed 3) (safety 0)) (string x y)) (concatenate 'string x y "watpow")) (let ((a (concatenate 'string "bo" "b")) (b (concatenate 'string "dole"))) (wat a b))
bobdolewatpow
1.2.4. Low Tags
CREATED: <2025-01-17 Fri 15:50> ID: fd50e430-8a51-406a-96bd-ae6a1cf73bdd
Tags for the main low-level types are stored in the low n (usually three) bits to identify the type of a machine word. Certain constraints apply: ,* EVEN-FIXNUM-LOWTAG and ODD-FIXNUM-LOWTAG must be 0 and 4: code which shifts left two places to convert raw integers to tagged fixnums is ubiquitous. ,* LIST-POINTER-LOWTAG + N-WORD-BYTES = OTHER-POINTER-LOWTAG: NIL is both a cons and a symbol (at the same address) and depends on this. See the definition of SYMBOL in objdef.lisp ,* OTHER-IMMEDIATE-0-LOWTAG are spaced 4 apart: various code wants to iterate through these. (This is not true on PPC64) (These are just the ones we know about as of sbcl-0.7.1.22. There might easily be more, since these values have stayed highly constrained for more than a decade, an inviting target for inventive abstraction-phobic maintainers.:-)
Another way to look at lowtags is that there is no one lowtag length. On 32-bit platforms, fixnums and other-immediates have a lowtag length of two bits, and pointers have a lowtag length of three bits. On 64-bit platforms, fixnums and pointers gain an extra bit, and six "pad" lowtags waste the extra encoding space so obtained.
x00 – fixnum x10 – other-immediate 001 – instance-pointer 011 – list-pointer 101 – fun-pointer 111 – other-pointer
If you change the tag layout, check the various functions in src/runtime/runtime.h to see if they need to be updated, along with print_obj() in src/runtime/print.c, possibly 'late-objdef.lisp' and possibly the code in src/code/room.
#define SBCL_GENESIS_CONSTANTS #define FIXNUM_TAG_MASK 1 /* 0x1 */ #define N_FIXNUM_TAG_BITS 1 /* 0x1 */ #define N_LOWTAG_BITS 4 /* 0x4 */ #define N_WIDETAG_BITS 8 /* 0x8 */ #define N_WORD_BYTES 8 /* 0x8 */ #define LOWTAG_MASK 15 /* 0xF */ #define N_WORD_BITS 64 /* 0x40 */ #define WIDETAG_MASK 255 /* 0xFF */ #define SHORT_HEADER_MAX_WORDS 32767 /* 0x7FFF */ #define EVEN_FIXNUM_LOWTAG 0 /* 0x0 */ #define OTHER_IMMEDIATE_0_LOWTAG 1 /* 0x1 */ #define PAD0_LOWTAG 2 /* 0x2 */ #define INSTANCE_POINTER_LOWTAG 3 /* 0x3 */ #define PAD1_LOWTAG 4 /* 0x4 */ #define OTHER_IMMEDIATE_1_LOWTAG 5 /* 0x5 */ #define PAD2_LOWTAG 6 /* 0x6 */ #define LIST_POINTER_LOWTAG 7 /* 0x7 */ #define ODD_FIXNUM_LOWTAG 8 /* 0x8 */ #define OTHER_IMMEDIATE_2_LOWTAG 9 /* 0x9 */ #define PAD3_LOWTAG 10 /* 0xA */ #define FUN_POINTER_LOWTAG 11 /* 0xB */ #define PAD4_LOWTAG 12 /* 0xC */ #define OTHER_IMMEDIATE_3_LOWTAG 13 /* 0xD */ #define PAD5_LOWTAG 14 /* 0xE */ #define OTHER_POINTER_LOWTAG 15 /* 0xF */
1.2.5. Bindings
ID: a4d05da6-b90d-4a9f-8237-67a10c8c4588 CREATED: <2025-02-09 Sun 14:21>–
1.2.6. Symbols of Interest
ID: a8ee911d-6d19-452b-b03a-249a446c1b20 CREATED: <2025-01-17 Fri 19:11>
sb-sys:*runtime-dlhandle* sb-fasl:+fasl-file-version+ sb-fasl:+backend-fasl-file-implementation+ sb-debug:print-backtrace sb-debug:map-backtrace sb-pretty:pprint-dispatch-table sb-lockless: sb-ext:simd-pack sb-walker:define-walker-template sb-walker:macroexpand-all sb-walker:walk-form sb-kernel:empty-type sb-kernel:*eval-calls* sb-kernel:*gc-pin-code-pages* sb-kernel:*restart-clusters* sb-kernel:*save-lisp-clobbered-globals* sb-kernel:*top-level-form-p* sb-kernel:*universal-fun-type* sb-kernel:*universal-type* sb-kernel:*wild-type* sb-kernel:+simd-pack-element-types+ (sb-vm:memory-usage) (sb-vm:boxed-context-register) (sb-vm:c-find-heap->arena) (sb-vm:copy-number-to-heap) (sb-vm:dump-arena-objects) (sb-vm:fixnumize) (sb-vm:rewind-arena) (sb-vm:show-heap->arena) (sb-vm:with/without-arena) (sb-cltl2:{augment-environment,compiler-let,define-declaration,parse-macro}) (sb-cltl2:{declaration-information, variable-information, function-information}) sb-di: sb-assem: sb-md5: sb-regalloc: sb-disassem:
1.2.7. Core Format
ID: db473315-0c74-40cb-ab07-9259b2113043 CREATED: <2025-02-24 Mon 21:36>
sbcl/src/runtime/coreparse.c at master · sbcl/sbcl · GitHub sbcl/src/runtime/core.h at master · sbcl/sbcl · GitHub
1.2.8. Arenas
ID: 70679001-871e-40c6-a660-d766e355e871 CREATED: <2025-06-02 Mon 21:53>
sbcl/doc/internals-notes/arena-allocation.txt -> Arena Allocator
–It is possible for multiple threads to share one arena, or for threads to each get their own arena, or potentially even to have more than one arena controlled by a thread. The constraint is that in order to release all memory used by an arena without incurring a stop-the-world event there must be no heap-to-arena pointer reachable in a graph trace, supposing that the about-to-be-released memory is not a root. An arena has to be released in total, though in theory it could be possible to provide a partial release feature as well. It thus becomes possible to discard large portions of the reachability graph under user control.
Pending items
===========
,* Some of the waste that comes from switching between arena and heap can be avoided by adding more state to the thread structure.
,* Background thread pools in particular are a problem. In one such implementation, a thread which requests work to be performed by a worker in a pool sends as part of the work request an identifier of the arena in use by the requester. The worker will switch to that same arena. The implication is that worker threads will constantly be switching their arena, which as per above, is inefficient.
1.2.9. DEFINE-VOP
ID: f9bcac71-99b9-4375-9c23-8b650d21d86c CREATED: <2025-02-28 Fri 19:08>
SBCL: the ultimate assembly code breadboard - Paul Khuong: some Lisp – How to define new intrinsics in SBCL - Paul Khuong: some Lisp – 001-sbcl-vops.txt
–Virtual Operations
;;; Define the symbol NAME to be a Virtual OPeration in the compiler. ;;; If specified, INHERITS is the name of a VOP that we default ;;; unspecified information from. Each SPEC is a list beginning with a ;;; keyword indicating the interpretation of the other forms in the ;;; SPEC: ;;; ;;; :ARGS {(Name {Key Value}*)}* ;;; :RESULTS {(Name {Key Value}*)}* ;;; The Args and Results are specifications of the operand TNs passed ;;; to the VOP. If there is an inherited VOP, any unspecified options ;;; are defaulted from the inherited argument (or result) of the same ;;; name. The following operand options are defined: ;;; ;;; :SCs (SC*) ;;; :SCs specifies good SCs for this operand. Other SCs will ;;; be penalized according to move costs. A load TN will be ;;; allocated if necessary, guaranteeing that the operand is ;;; always one of the specified SCs. ;;; ;;; :LOAD-TN Load-Name ;;; Load-Name is bound to the load TN allocated for this ;;; operand, or to NIL if no load TN was allocated. ;;; ;;; :LOAD-IF EXPRESSION ;;; Controls whether automatic operand loading is done. ;;; EXPRESSION is evaluated with the fixed operand TNs bound. ;;; If EXPRESSION is true, then loading is done and the variable ;;; is bound to the load TN in the generator body. Otherwise, ;;; loading is not done, and the variable is bound to the actual ;;; operand. ;;; ;;; :MORE T-or-NIL ;;; If specified, NAME is bound to the TN-REF for the first ;;; argument or result following the fixed arguments or results. ;;; A :MORE operand must appear last, and cannot be targeted or ;;; restricted. ;;; ;;; :TARGET Operand ;;; This operand is targeted to the named operand, indicating a ;;; desire to pack in the same location. Not legal for results. ;;; ;;; :FROM Time-Spec ;;; :TO Time-Spec ;;; Specify the beginning or end of the operand's lifetime. ;;; :FROM can only be used with results, and :TO only with ;;; arguments. The default for the N'th argument/result is ;;; (:ARGUMENT N)/(:RESULT N). These options are necessary ;;; primarily when operands are read or written out of order. ;;; ;;; :CONDITIONAL [Condition-descriptor+] ;;; This is used in place of :RESULTS with conditional branch VOPs. ;;; There are no result values: the result is a transfer of control. ;;; The target label is passed as the first :INFO arg. The second ;;; :INFO arg is true if the sense of the test should be negated. ;;; A side effect is to set the PREDICATE attribute for functions ;;; in the :TRANSLATE option. ;;; ;;; If some condition descriptors are provided, this is a flag-setting ;;; VOP. Descriptors are interpreted in an architecture-dependent ;;; manner. See the BRANCH-IF VOP in $ARCH/pred.lisp. ;;; ;;; :TEMPORARY ({Key Value}*) Name* ;;; Allocate a temporary TN for each Name, binding that variable to ;;; the TN within the body of the generators. In addition to :TARGET ;;; (which is is the same as for operands), the following options are ;;; defined: ;;; ;;; :SC SC-Name ;;; :OFFSET SB-Offset ;;; Force the temporary to be allocated in the specified SC ;;; with the specified offset. Offset is evaluated at ;;; macroexpand time. If Offset is omitted, the register ;;; allocator chooses a free location in SC. If both SC and ;;; Offset are omitted, then the temporary is packed according ;;; to its primitive type. ;;; ;;; :FROM Time-Spec ;;; :TO Time-Spec ;;; Similar to the argument/result option, this specifies the ;;; start and end of the temporaries' lives. The defaults are ;;; :LOAD and :SAVE, i.e. the duration of the VOP. The other ;;; intervening phases are :ARGUMENT, :EVAL and :RESULT. ;;; Non-zero sub-phases can be specified by a list, e.g. by ;;; default the second argument's life ends at (:ARGUMENT 1). ;;; ;;; :GENERATOR Cost Form* ;;; Specifies the translation into assembly code. Cost is the ;;; estimated cost of the code emitted by this generator. The body ;;; is arbitrary Lisp code that emits the assembly language ;;; translation of the VOP. An ASSEMBLE form is wrapped around ;;; the body, so code may be emitted by using the local INST macro. ;;; During the evaluation of the body, the names of the operands ;;; and temporaries are bound to the actual TNs. ;;; ;;; :INFO Name* ;;; Define some magic arguments that are passed directly to the code ;;; generator. The corresponding trailing arguments to VOP or ;;; %PRIMITIVE are stored in the VOP structure. Within the body ;;; of the generators, the named variables are bound to these ;;; values. Except in the case of :CONDITIONAL VOPs, :INFO arguments ;;; cannot be specified for VOPS that are the direct translation ;;; for a function (specified by :TRANSLATE). ;;; ;;; :IGNORE Name* ;;; Causes the named variables to be declared IGNORE in the ;;; generator body. ;;; ;;; :VARIANT Thing* ;;; :VARIANT-VARS Name* ;;; These options provide a way to parameterize families of VOPs ;;; that differ only trivially. :VARIANT makes the specified ;;; evaluated Things be the "variant" associated with this VOP. ;;; :VARIANT-VARS causes the named variables to be bound to the ;;; corresponding Things within the body of the generator. ;;; ;;; :VARIANT-COST Cost ;;; Specifies the cost of this VOP, overriding the cost of any ;;; inherited generator. ;;; ;;; :NOTE {String | NIL} ;;; A short noun-like phrase describing what this VOP "does", i.e. ;;; the implementation strategy. If supplied, efficiency notes will ;;; be generated when type uncertainty prevents :TRANSLATE from ;;; working. NIL inhibits any efficiency note. ;;; ;;; :ARG-TYPES {* | PType | (:OR PType*) | (:CONSTANT Type)}* ;;; :RESULT-TYPES {* | PType | (:OR PType*)}* ;;; Specify the template type restrictions used for automatic ;;; translation. If there is a :MORE operand, the last type is the ;;; more type. :CONSTANT specifies that the argument must be a ;;; compile-time constant of the specified Lisp type. The constant ;;; values of :CONSTANT arguments are passed as additional :INFO ;;; arguments rather than as :ARGS. ;;; ;;; :TRANSLATE Name* ;;; This option causes the VOP template to be entered as an IR2 ;;; translation for the named functions. ;;; ;;; :POLICY {:SMALL | :SMALL-SAFE | :FAST | :SAFE | :FAST-SAFE} ;;; Specifies the policy under which this VOP is the best translation. ;;; ;;; :GUARD Form ;;; Specifies a Form that is evaluated in the global environment. ;;; If form returns NIL, then emission of this VOP is prohibited ;;; even when all other restrictions are met. ;;; As an additional possibility, if Form is a lambda expression, ;;; then it is funcalled with the node under consideration. ;;; ;;; :VOP-VAR Name ;;; :NODE-VAR Name ;;; In the generator, bind the specified variable to the VOP or ;;; the Node that generated this VOP. ;;; ;;; :SAVE-P {NIL | T | :COMPUTE-ONLY | :FORCE-TO-STACK} ;;; Indicates how a VOP wants live registers saved. ;;; ;;; :MOVE-ARGS {NIL | :FULL-CALL | :LOCAL-CALL | :KNOWN-RETURN} ;;; Indicates if and how the more args should be moved into a ;;; different frame. (defmacro define-vop ((&optional name inherits) &body specs) (%define-vop name inherits specs t))
1.2.10. Aliens ffi
ID: 93e1ed13-dc82-4a9b-8b9e-f60f06b01a4f CREATED: <2025-02-28 Fri 19:09>
Lazy Alien Resolution - SBCL Internals – Callbacks - SBCL Internals – Linkage-table - SBCL Internals
–1.2.11. SB-ASSEM asm
ID: 86674fe2-4105-4246-9682-f6e3fb84f7de CREATED: <2025-03-08 Sat 20:24>->
- sb-assem, sb-vm, sb-c
gen-label
(describe (sb-assem:gen-label "this is a label comment"))
#<SB-ASSEM:LABEL {1012471C13}> [structure-object] Slots with :INSTANCE allocation: INDEX = 0 POSN = NIL COMMENT = "this is a label comment" USEDP = NIL
- sb-assem:make-segment
- emit, assemble
1.2.12. Compiler comp
ID: 624cbc9a-9797-4889-a8b5-8440b04d9c01 CREATED: <2025-02-28 Fri 19:14>
CMUCL User's Manual: Advanced Compiler Use and Efficiency Hints
–- derive-function-types
ID: 76c64438-4db7-4318-8701-241d4f253782 CREATED: <2025-03-23 Sun 15:05>
DERIVE-FUNCTION-TYPES names a special variable: Value: NIL Documentation: Should the compiler assume that function types will never change, so that it can use type information inferred from current definitions to optimize code which uses those definitions? Setting this true gives non-ANSI, early-CMU-CL behavior. It can be useful for improving the efficiency of stable code.
- Inlining
;;; An INLINEP value describes how a function is called. The values ;;; have these meanings: ;;; NIL No declaration seen: do whatever you feel like, but don't ;;; dump an inline expansion. ;;; NOTINLINE NOTINLINE declaration seen: always do full function call. ;;; INLINE INLINE declaration seen: save expansion, expanding to it ;;; if policy favors. ;;; MAYBE-INLINE ;;; Retain expansion, but only use it opportunistically. ;;; MAYBE-INLINE is quite different from INLINE. As explained ;;; by APD on #lisp 2005-11-26: "MAYBE-INLINE lambda is ;;; instantiated once per component, INLINE - for all ;;; references (even under #'without FUNCALL)." (deftype inlinep () '(member inline maybe-inline notinline nil))
1.2.13. SB-KERNEL
ID: 31cebf6f-e67c-4289-a75e-ad012b4bbe5d CREATED: <2025-04-27 Sun 16:01>
WITH-ARRAY-DATA This checks to see whether the array is simple and the start and end are in bounds. If so, it proceeds with those values. Otherwise, it calls %WITH-ARRAY-DATA. Note that %WITH-ARRAY-DATA may be further optimized. Given any ARRAY, bind DATA-VAR to the array's data vector and START-VAR and END-VAR to the start and end of the designated portion of the data vector. SVALUE and EVALUE are any start and end specified to the original operation, and are factored into the bindings of START-VAR and END-VAR. OFFSET-VAR is the cumulative offset of all displacements encountered, and does not include SVALUE. When FORCE-INLINE is set, the underlying %WITH-ARRAY-DATA form is forced to be inline, overriding the ordinary judgment of the %WITH-ARRAY-DATA DEFTRANSFORMs. Ordinarily the DEFTRANSFORMs are fairly picky about their arguments, figuring that if you haven't bothered to get all your ducks in a row, you probably don't care that much about speed anyway! But in some cases it makes sense to do type testing inside %WITH-ARRAY-DATA instead of outside, and the DEFTRANSFORM can't tell that that's going on, so it can make sense to use FORCE-INLINE option in that case.
1.3. Tree Shaker
ID: 6beca36e-6264-4741-9180-66e81bf58c49 CREATED: <2025-01-26 Sun 00:54>>>
With the complexity involved in SBCL image dumps it becomes a hard problem to design an effective tree-shaker.
- sbcl/tests/treeshake.pure.lisp
- Shake tree harder · sbcl/sbcl@f9b92e4
sb-impl::shake-packages
1.4. Contribs
ID: c33a5587-daab-4e61-a0df-fc6856b00f70 CREATED: <2025-02-11 Tue 20:55>>>
1.4.1. sb-bsd-sockets
ID: 0c2908c2-69d0-4866-b225-3d7eec026b76 CREATED: <2025-02-11 Tue 20:55>
(defvar *protocols* `((:tcp ,sockint::ipproto_tcp "tcp" "TCP") (:udp ,sockint::ipproto_udp "udp" "UDP") (:ip ,sockint::ipproto_ip "ip" "IP") (:ipv6 ,sockint::ipproto_ipv6 "ipv6" "IPV6") (:icmp ,sockint::ipproto_icmp "icmp" "ICMP") (:igmp ,sockint::ipproto_igmp "igmp" "IGMP") (:raw ,sockint::ipproto_raw "raw" "RAW")))
1.4.2. sb-cltl2
ID: d2269803-9084-4845-8860-047c37da36c7 CREATED: <2025-04-23 Wed 15:21>
Deals with environments, closures, etc.
- It seems that the
sb-kernel:closure
type applies to the result ofsb-cltl2:enclose
- test withsb-kernel:closurep
.