--- /dev/null
+;;;; needed-early, or at least meaningful-early, stuff for FASL files
+
+;;;; This software is part of the SBCL system. See the README file for
+;;;; more information.
+;;;;
+;;;; This software is derived from the CMU CL system, which was
+;;;; written at Carnegie Mellon University and released into the
+;;;; public domain. The software is in the public domain and is
+;;;; provided with absolutely no warranty. See the COPYING and CREDITS
+;;;; files for more information.
+
+(in-package "SB!FASL")
+\f
+;;;; various constants and essentially-constants
+
+;;; a string which appears at the start of a fasl file header
+;;;
+;;; This value is used to identify fasl files. Even though this is not
+;;; declared as a constant (because ANSI Common Lisp has no facility
+;;; for declaring values which are constant under EQUAL but not EQL),
+;;; obviously you shouldn't mess with it lightly. If you do set a new
+;;; value for some reason, keep these things in mind:
+;;; * To avoid confusion with the similar but incompatible CMU CL
+;;; fasl file format, the value should not be "FASL FILE", which
+;;; is what CMU CL used for the same purpose.
+;;; * Since its presence at the head of a file is used by LOAD to
+;;; decide whether a file is to be fasloaded or just loaded
+;;; ordinarily (as source), the value should be something which
+;;; can't legally appear at the head of a Lisp source file.
+;;; * The value should not contain any line-terminating characters,
+;;; because they're hard to express portably and because the LOAD
+;;; code might reasonably use READ-LINE to get the value to compare
+;;; against.
+(defparameter *fasl-header-string-start-string* "# FASL")
+
+;;; the code for a character which terminates a fasl file header
+(defconstant +fasl-header-string-stop-char-code+ 255)
+
+;;; This value should be incremented when the system changes in such
+;;; a way that it will no longer work reliably with old fasl files.
- (defconstant +fasl-file-version+ 13)
++(defconstant +fasl-file-version+ 14)
+;;; 2 = sbcl-0.6.4 uses COMPILE-OR-LOAD-DEFGENERIC.
+;;; 3 = sbcl-0.6.6 uses private symbol, not :EMPTY, for empty HASH-TABLE slot.
+;;; 4 = sbcl-0.6.7 uses HAIRY-DATA-VECTOR-REF and HAIRY-DATA-VECTOR-SET
+;;; when array headers or data element type uncertainty exist, and
+;;; uses DATA-VECTOR-REF and DATA-VECTOR-SET only for VOPs. (Thus,
+;;; full calls to DATA-VECTOR-REF and DATA-VECTOR-SET from older
+;;; fasl files would fail, because there are no DEFUNs for these
+;;; operations any more.)
+;;; 5 = sbcl-0.6.8 has rearranged static symbols.
+;;; 6 = sbcl-0.6.9, got rid of non-ANSI %DEFCONSTANT/%%DEFCONSTANT stuff
+;;; and deleted a slot from DEBUG-SOURCE structure.
+;;; 7 = around sbcl-0.6.9.8, merged SB-CONDITIONS package into SB-KERNEL
+;;; 8 = sbcl-0.6.10.4 revived Gray stream support, changing stream layouts.
+;;; 9 = deleted obsolete CONS-UNIQUE-TAG bytecode in sbcl-0.6.11.8
+;;; (somewhere in here also changes to AND and OR CTYPE layouts)
+;;; 10 = new layout for CONDITION in sbcl-0.6.11.38
+;;; 11 = (a) new helper functions for MAKE-LOAD-FORM (HASH-TABLE) in
+;;; sbcl-0.6.12.11
+;;; (b) new address space constants for OpenBSD in 0.6.12.17
+;;; (doesn't need separate version from (a) because the
+;;; OpenBSD port was broken from sometime before 0.6.12.11
+;;; until the address space was changed)
+;;; 12 = sbcl-0.6.12.22 added new SB-FASL package
- ;;; 13 = sbcl-0.6.12.x removed some elements from *STATIC-SYMBOLS*
++;;; 13 = sbcl-0.6.12.28 removed some elements from *STATIC-SYMBOLS*
++;;; 14 = sbcl-0.6.12.29 removed more elements from *STATIC-SYMBOLS*
+
+;;; the conventional file extension for fasl files on this
+;;; architecture, e.g. "x86f"
+(declaim (type (or simple-string null) *backend-fasl-file-type*))
+(defvar *backend-fasl-file-type* nil)
+
+;;; This is a sort of pun that we inherited from CMU CL. For ordinary,
+;;; non-byte-coded fasl files, the "implementation" is basically the
+;;; CPU. For byte-coded fasl files, the "implementation" is whether
+;;; the data are stored big-endianly or little-endianly.
+(defun backend-byte-fasl-file-implementation ()
+ *backend-byte-order*)
+\f
+;;; information about below-Lisp-level linkage
+;;;
+;;; Note:
+;;; Assembler routines are named by full Lisp symbols: they
+;;; have packages and that sort of native Lisp stuff associated
+;;; with them. We can compare them with EQ.
+;;; Foreign symbols are named by Lisp strings: the Lisp package
+;;; system doesn't extend out to symbols in languages like C.
+;;; We want to use EQUAL to compare them.
+;;; *STATIC-FOREIGN-SYMBOLS* are static as opposed to "dynamic" (not
+;;; as opposed to "extern"). The table contains symbols known at
+;;; the time that the program was built, but not symbols defined
+;;; in object files which have been loaded dynamically since then.
+(declaim (type hash-table *assembler-routines* *static-foreign-symbols*))
+(defvar *assembler-routines* (make-hash-table :test 'eq))
+(defvar *static-foreign-symbols* (make-hash-table :test 'equal))
+\f
+;;;; the FOP database
+
+(declaim (simple-vector *fop-names* *fop-functions*))
+
+;;; a vector indexed by a FaslOP that yields the FOP's name
+(defvar *fop-names* (make-array 256 :initial-element nil))
+
+;;; a vector indexed by a FaslOP that yields a function of 0 arguments
+;;; which will perform the operation
+(defvar *fop-functions*
+ (make-array 256
+ :initial-element (lambda ()
+ (error "corrupt fasl file: losing FOP"))))
+\f
+;;;; other miscellaneous loading-related stuff
+
+\f
+;;;; variables
+
+(defvar *load-depth* 0
+ #!+sb-doc
+ "the current number of recursive LOADs")
+(declaim (type index *load-depth*))
+
+;;; the FASL file we're reading from
+(defvar *fasl-input-stream*)
+(declaim (type lisp-stream *fasl-input-stream*))
+
+(defvar *load-print* nil
+ #!+sb-doc
+ "the default for the :PRINT argument to LOAD")
+(defvar *load-verbose* nil
+ ;; Note that CMU CL's default for this was T, and ANSI says it's
+ ;; implementation-dependent. We choose NIL on the theory that it's
+ ;; a nicer default behavior for Unix programs.
+ #!+sb-doc
+ "the default for the :VERBOSE argument to LOAD")
+
+(defvar *load-code-verbose* nil)
+
;;;; provided with absolutely no warranty. See the COPYING and CREDITS
;;;; files for more information.
-(in-package "SB!IMPL")
+(in-package "SB!FASL")
;;; a magic number used to identify our core files
(defconstant core-magic
\f
;;;; representation of spaces in the core
+;;; If there is more than one dynamic space in memory (i.e., if a
+;;; copying GC is in use), then only the active dynamic space gets
+;;; dumped to core.
(defvar *dynamic*)
(defconstant dynamic-space-id 1)
(gspace-name gspace)
"unknown"))))))))
-(defun allocate-descriptor (gspace length lowtag)
- #!+sb-doc
- "Return a descriptor for a block of LENGTH bytes out of GSPACE. The free
- word index is boosted as necessary, and if additional memory is needed, we
- grow the GSPACE. The descriptor returned is a pointer of type LOWTAG."
+;;; Return a descriptor for a block of LENGTH bytes out of GSPACE. The
+;;; free word index is boosted as necessary, and if additional memory
+;;; is needed, we grow the GSPACE. The descriptor returned is a
+;;; pointer of type LOWTAG.
+(defun allocate-cold-descriptor (gspace length lowtag)
(let* ((bytes (round-up length (ash 1 sb!vm:lowtag-bits)))
(old-free-word-index (gspace-free-word-index gspace))
(new-free-word-index (+ old-free-word-index
#!+sb-doc
"Allocate LENGTH words in GSPACE and return a new descriptor of type LOWTAG
pointing to them."
- (allocate-descriptor gspace (ash length sb!vm:word-shift) lowtag))
+ (allocate-cold-descriptor gspace (ash length sb!vm:word-shift) lowtag))
(defun allocate-unboxed-object (gspace element-bits length type)
#!+sb-doc
"Allocate LENGTH units of ELEMENT-BITS bits plus a header word in GSPACE and
return an ``other-pointer'' descriptor to them. Initialize the header word
with the resultant length and TYPE."
(let* ((bytes (/ (* element-bits length) sb!vm:byte-bits))
- (des (allocate-descriptor gspace
- (+ bytes sb!vm:word-bytes)
- sb!vm:other-pointer-type)))
+ (des (allocate-cold-descriptor gspace
+ (+ bytes sb!vm:word-bytes)
+ sb!vm:other-pointer-type)))
(write-memory des
(make-other-immediate-descriptor (ash bytes
(- sb!vm:word-shift))
;; FIXME: Here and in ALLOCATE-UNBOXED-OBJECT, BYTES is calculated using
;; #'/ instead of #'CEILING, which seems wrong.
(let* ((bytes (/ (* element-bits length) sb!vm:byte-bits))
- (des (allocate-descriptor gspace (+ bytes (* 2 sb!vm:word-bytes))
- sb!vm:other-pointer-type)))
+ (des (allocate-cold-descriptor gspace
+ (+ bytes (* 2 sb!vm:word-bytes))
+ sb!vm:other-pointer-type)))
(write-memory des (make-other-immediate-descriptor 0 type))
(write-wordindexed des
sb!vm:vector-length-slot
;; the function values for these things?? I.e. why do we need this
;; section at all? Is it because all the FDEFINITION stuff gets in
;; the way of reading function values and is too hairy to rely on at
-- ;; cold boot? FIXME: 5/6 of these are in *STATIC-SYMBOLS* in
++ ;; cold boot? FIXME: Most of these are in *STATIC-SYMBOLS* in
;; parms.lisp, but %HANDLE-FUNCTION-END-BREAKPOINT is not. Why?
;; Explain.
(macrolet ((frob (symbol)
`(cold-set ',symbol
(cold-fdefinition-object (cold-intern ',symbol)))))
-- (frob !cold-init)
- (frob sb!impl::maybe-gc)
+ (frob maybe-gc)
(frob internal-error)
(frob sb!di::handle-breakpoint)
-- (frob sb!di::handle-function-end-breakpoint)
- (frob fdefinition-object))
- (frob sb!impl::fdefinition-object))
++ (frob sb!di::handle-function-end-breakpoint))
(cold-set '*current-catch-block* (make-fixnum-descriptor 0))
(cold-set '*current-unwind-protect-block* (make-fixnum-descriptor 0))
(cold-set '*free-interrupt-context-index* (make-fixnum-descriptor 0))
- ;; FIXME: *!INITIAL-LAYOUTS* should be exported from SB!KERNEL, or
- ;; perhaps from SB-LD.
- (cold-set 'sb!kernel::*!initial-layouts* (cold-list-all-layouts))
+ (cold-set '*!initial-layouts* (cold-list-all-layouts))
(/show "dumping packages" (mapcar #'car *cold-package-symbols*))
(let ((initial-symbols *nil-descriptor*))
(cold-set 'sb!vm::*fp-constant-lg2* (number-to-core (log 2L0 10L0)))
(cold-set 'sb!vm::*fp-constant-ln2*
(number-to-core
- (log 2L0 2.718281828459045235360287471352662L0))))
- #!+gencgc
- (cold-set 'sb!vm::*SCAVENGE-READ-ONLY-GSPACE* *nil-descriptor*)))
+ (log 2L0 2.718281828459045235360287471352662L0))))))
;;; Make a cold list that can be used as the arg list to MAKE-PACKAGE in order
;;; to make a package that is similar to PKG.
(write-wordindexed fdefn
sb!vm:fdefn-raw-addr-slot
(make-random-descriptor
- (lookup-foreign-symbol "undefined_tramp"))))
+ (cold-foreign-symbol-address-as-integer "undefined_tramp"))))
fdefn))))
(defun cold-fset (cold-name defn)
sb!vm:word-shift))))
(#.sb!vm:closure-header-type
(make-random-descriptor
- (lookup-foreign-symbol "closure_tramp")))))
+ (cold-foreign-symbol-address-as-integer "closure_tramp")))))
fdefn))
(defun initialize-static-fns ()
(defvar *cold-foreign-symbol-table*)
(declaim (type hash-table *cold-foreign-symbol-table*))
-(defun load-foreign-symbol-table (filename)
+;;; Read the sbcl.nm file to find the addresses for foreign-symbols in
+;;; the C runtime.
+(defun load-cold-foreign-symbol-table (filename)
(with-open-file (file filename)
(loop
(let ((line (read-line file nil nil)))
(setf (gethash name *cold-foreign-symbol-table*) value))))))
(values)))
-;;; FIXME: the relation between #'lookup-foreign-symbol and
-;;; #'lookup-maybe-prefix-foreign-symbol seems more than slightly
-;;; illdefined
-
-(defun lookup-foreign-symbol (name)
- #!+(or alpha x86)
- (let ((prefixes
- #!+linux #(;; FIXME: How many of these are actually
- ;; needed? The first four are taken from rather
- ;; disorganized CMU CL code, which could easily
- ;; have had redundant values in it..
- "_"
- "__"
- "__libc_"
- "ldso_stub__"
- ;; ..and the fifth seems to match most
- ;; actual symbols, at least in RedHat 6.2.
- "")
- #!+freebsd #("" "ldso_stub__")
- #!+openbsd #("_")))
- (or (some (lambda (prefix)
- (gethash (concatenate 'string prefix name)
- *cold-foreign-symbol-table*
- nil))
- prefixes)
- *foreign-symbol-placeholder-value*
- (progn
- (format *error-output* "~&The foreign symbol table is:~%")
- (maphash (lambda (k v)
- (format *error-output* "~&~S = #X~8X~%" k v))
- *cold-foreign-symbol-table*)
- (format *error-output* "~&The prefix table is: ~S~%" prefixes)
- (error "The foreign symbol ~S is undefined." name))))
- #!-(or x86 alpha) (error "non-x86/alpha unsupported in SBCL (but see old CMU CL code)"))
+(defun cold-foreign-symbol-address-as-integer (name)
+ (or (find-foreign-symbol-in-table name *cold-foreign-symbol-table*)
+ *foreign-symbol-placeholder-value*
+ (progn
+ (format *error-output* "~&The foreign symbol table is:~%")
+ (maphash (lambda (k v)
+ (format *error-output* "~&~S = #X~8X~%" k v))
+ *cold-foreign-symbol-table*)
+ (error "The foreign symbol ~S is undefined." name))))
(defvar *cold-assembler-routines*)
offset-within-code-object))
(gspace-byte-address (gspace-byte-address
(descriptor-gspace code-object))))
- (ecase sb!c:*backend-fasl-file-implementation*
- ;; See CMUCL source for other formerly-supported architectures
- ;; (and note that you have to rewrite them to use vector-ref unstead
- ;; of sap-ref)
+ (ecase +backend-fasl-file-implementation+
+ ;; See CMU CL source for other formerly-supported architectures
+ ;; (and note that you have to rewrite them to use VECTOR-REF
+ ;; unstead of SAP-REF).
(:alpha
(ecase kind
(:jmp-hint
(when value
(do-cold-fixup (second fixup) (third fixup) value (fourth fixup))))))
+;;; *COLD-FOREIGN-SYMBOL-TABLE* becomes *!INITIAL-FOREIGN-SYMBOLS* in
+;;; the core. When the core is loaded, !LOADER-COLD-INIT uses this to
+;;; create *STATIC-FOREIGN-SYMBOLS*, which the code in
+;;; target-load.lisp refers to.
(defun linkage-info-to-core ()
(let ((result *nil-descriptor*))
- (maphash #'(lambda (symbol value)
- (cold-push (cold-cons (string-to-core symbol)
- (number-to-core value))
- result))
+ (maphash (lambda (symbol value)
+ (cold-push (cold-cons (string-to-core symbol)
+ (number-to-core value))
+ result))
*cold-foreign-symbol-table*)
(cold-set (cold-intern '*!initial-foreign-symbols*) result))
(let ((result *nil-descriptor*))
\f
;;;; general machinery for cold-loading FASL files
-(defvar *cold-fop-functions* (replace (make-array 256) *fop-functions*)
- #!+sb-doc
- "FOP functions for cold loading")
+;;; FOP functions for cold loading
+(defvar *cold-fop-functions*
+ ;; We start out with a copy of the ordinary *FOP-FUNCTIONS*. The
+ ;; ones which aren't appropriate for cold load will be destructively
+ ;; modified.
+ (copy-seq *fop-functions*))
(defvar *normal-fop-functions*)
\f
;;;; cold fops for loading symbols
-;;; Load a symbol SIZE characters long from *FASL-FILE* and intern
+;;; Load a symbol SIZE characters long from *FASL-INPUT-STREAM* and intern
;;; that symbol in PACKAGE.
(defun cold-load-symbol (size package)
(let ((string (make-string size)))
- (read-string-as-bytes *fasl-file* string)
+ (read-string-as-bytes *fasl-input-stream* string)
(cold-intern (intern string package) package)))
(macrolet ((frob (name pname-len package-len)
(fop-uninterned-small-symbol-save)
(let* ((size (clone-arg))
(name (make-string size)))
- (read-string-as-bytes *fasl-file* name)
+ (read-string-as-bytes *fasl-input-stream* name)
(let ((symbol (allocate-symbol name)))
(push-fop-table symbol))))
\f
(fop-small-string)
(let* ((len (clone-arg))
(string (make-string len)))
- (read-string-as-bytes *fasl-file* string)
+ (read-string-as-bytes *fasl-input-stream* string)
(string-to-core string)))
(clone-cold-fop (fop-vector)
(ceiling (* len sizebits)
sb!vm:byte-bits))))
(read-sequence-or-die (descriptor-bytes result)
- *fasl-file*
+ *fasl-input-stream*
:start start
:end end)
result))
(ash sb!vm:vector-data-offset sb!vm:word-shift)))
(end (+ start (* len sb!vm:word-bytes))))
(read-sequence-or-die (descriptor-bytes result)
- *fasl-file*
+ *fasl-input-stream*
:start start
:end end)
result))
#!+long-float
(define-cold-fop (fop-long-float)
- (ecase sb!c:*backend-fasl-file-implementation*
- (:x86 ; 80 bit long-float format
- (prepare-for-fast-read-byte *fasl-file*
+ (ecase +backend-fasl-file-implementation+
+ (:x86 ; (which has 80-bit long-float format)
+ (prepare-for-fast-read-byte *fasl-input-stream*
(let* ((des (allocate-unboxed-object *dynamic* sb!vm:word-bits
(1- sb!vm:long-float-size)
sb!vm:long-float-type))
;; SBCL.
#+nil
(#.sb!c:sparc-fasl-file-implementation ; 128 bit long-float format
- (prepare-for-fast-read-byte *fasl-file*
+ (prepare-for-fast-read-byte *fasl-input-stream*
(let* ((des (allocate-unboxed-object *dynamic* sb!vm:word-bits
(1- sb!vm:long-float-size)
sb!vm:long-float-type))
#!+long-float
(define-cold-fop (fop-complex-long-float)
- (ecase sb!c:*backend-fasl-file-implementation*
- (:x86 ; 80 bit long-float format
- (prepare-for-fast-read-byte *fasl-file*
+ (ecase +backend-fasl-file-implementation+
+ (:x86 ; (which has 80-bit long-float format)
+ (prepare-for-fast-read-byte *fasl-input-stream*
(let* ((des (allocate-unboxed-object *dynamic* sb!vm:word-bits
(1- sb!vm:complex-long-float-size)
sb!vm:complex-long-float-type))
;; This was supported in CMU CL, but isn't currently supported in SBCL.
#+nil
(#.sb!c:sparc-fasl-file-implementation ; 128 bit long-float format
- (prepare-for-fast-read-byte *fasl-file*
+ (prepare-for-fast-read-byte *fasl-input-stream*
(let* ((des (allocate-unboxed-object *dynamic* sb!vm:word-bits
(1- sb!vm:complex-long-float-size)
sb!vm:complex-long-float-type))
(make-descriptor 0 0 nil counter)))
(defun finalize-load-time-value-noise ()
- (cold-set (cold-intern 'sb!impl::*!load-time-values*)
+ (cold-set (cold-intern '*!load-time-values*)
(allocate-vector-object *dynamic*
sb!vm:word-bits
*load-time-value-counter*
;; Note: we round the number of constants up to ensure
;; that the code vector will be properly aligned.
(round-up raw-header-n-words 2))
- (des (allocate-descriptor
- ;; In the X86 with CGC, code can't be relocated, so
- ;; we have to put it into static space. In all other
- ;; configurations, code can go into dynamic space.
- #!+(and x86 cgc) *static* ; KLUDGE: Why? -- WHN 19990907
- #!-(and x86 cgc) *dynamic*
- (+ (ash header-n-words sb!vm:word-shift) code-size)
- sb!vm:other-pointer-type)))
+ (des (allocate-cold-descriptor *dynamic*
+ (+ (ash header-n-words
+ sb!vm:word-shift)
+ code-size)
+ sb!vm:other-pointer-type)))
(write-memory des
(make-other-immediate-descriptor header-n-words
sb!vm:code-header-type))
(ash header-n-words sb!vm:word-shift)))
(end (+ start code-size)))
(read-sequence-or-die (descriptor-bytes des)
- *fasl-file*
+ *fasl-input-stream*
:start start
:end end)
#!+sb-show
(code-object (pop-stack))
(len (read-arg 1))
(sym (make-string len)))
- (read-string-as-bytes *fasl-file* sym)
+ (read-string-as-bytes *fasl-input-stream* sym)
(let ((offset (read-arg 4))
- (value (lookup-foreign-symbol sym)))
+ (value (cold-foreign-symbol-address-as-integer sym)))
(do-cold-fixup code-object offset value kind))
code-object))
;; Note: we round the number of constants up to ensure that
;; the code vector will be properly aligned.
(round-up sb!vm:code-constants-offset 2))
- (des (allocate-descriptor *read-only*
- (+ (ash header-n-words sb!vm:word-shift)
- length)
- sb!vm:other-pointer-type)))
+ (des (allocate-cold-descriptor *read-only*
+ (+ (ash header-n-words
+ sb!vm:word-shift)
+ length)
+ sb!vm:other-pointer-type)))
(write-memory des
(make-other-immediate-descriptor header-n-words
sb!vm:code-header-type))
(ash header-n-words sb!vm:word-shift)))
(end (+ start length)))
(read-sequence-or-die (descriptor-bytes des)
- *fasl-file*
+ *fasl-input-stream*
:start start
:end end))
des))
;; Read symbol table, if any.
(when symbol-table-file-name
- (load-foreign-symbol-table symbol-table-file-name))
+ (load-cold-foreign-symbol-table symbol-table-file-name))
;; Now that we've successfully read our only input file (by
;; loading the symbol table, if any), it's a good time to ensure
;; Tell the target Lisp how much stuff we've allocated.
(cold-set 'sb!vm:*read-only-space-free-pointer*
- (allocate-descriptor *read-only* 0 sb!vm:even-fixnum-type))
+ (allocate-cold-descriptor *read-only*
+ 0
+ sb!vm:even-fixnum-type))
(cold-set 'sb!vm:*static-space-free-pointer*
- (allocate-descriptor *static* 0 sb!vm:even-fixnum-type))
+ (allocate-cold-descriptor *static*
+ 0
+ sb!vm:even-fixnum-type))
(cold-set 'sb!vm:*initial-dynamic-space-free-pointer*
- (allocate-descriptor *dynamic* 0 sb!vm:even-fixnum-type))
+ (allocate-cold-descriptor *dynamic*
+ 0
+ sb!vm:even-fixnum-type))
(/show "done setting free pointers")
;; Write results to files.