Speed up array word size calculation.
[sbcl.git] / src / code / target-load.lisp
blobf7f3b078ec7e5319d0f0bf9ac8f6dfd65d479a75
1 ;;;; that part of the loader is only needed on the target system
2 ;;;; (which is basically synonymous with "that part of the loader
3 ;;;; which is not needed by GENESIS")
5 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; more information.
7 ;;;;
8 ;;;; This software is derived from the CMU CL system, which was
9 ;;;; written at Carnegie Mellon University and released into the
10 ;;;; public domain. The software is in the public domain and is
11 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
12 ;;;; files for more information.
14 (in-package "SB!FASL")
16 (defvar *load-source-default-type* "lisp"
17 #!+sb-doc
18 "The source file types which LOAD looks for by default.")
20 (declaim (type (or pathname null) *load-truename* *load-pathname*))
21 (defvar *load-truename* nil
22 #!+sb-doc
23 "the TRUENAME of the file that LOAD is currently loading")
24 (defvar *load-pathname* nil
25 #!+sb-doc
26 "the defaulted pathname that LOAD is currently loading")
28 ;;;; LOAD-AS-SOURCE
30 ;;; Load a text stream. (Note that load-as-fasl is in another file.)
31 ;; We'd like, when entering the debugger as a result of an EVAL error,
32 ;; that the condition be annotated with the stream position.
33 ;; One way to do it is catch all conditions and encapsulate them in
34 ;; something new such as a LOADER-EVAL-ERROR and re-signal.
35 ;; The printer for the encapsulated condition has the data it needs to
36 ;; show the original condition and the line/col. That would unfortunately
37 ;; interfere with handlers that were bound around LOAD, since they would
38 ;; only receive the encapsulated condition, and not be able to test for
39 ;; things they're interested in, such as which redefinition warnings to ignore.
40 ;; Instead, printing a herald for any SERIOUS-CONDITION approximates
41 ;; the desired behavior closely enough without printing something for warnings.
42 ;; TODO: It would be supremely cool if, for toplevel PROGN, we could
43 ;; indicate the position of the specific subform that failed
44 (defun load-as-source (stream &key verbose print (context "loading"))
45 (maybe-announce-load stream verbose)
46 (let* ((pathname (ignore-errors (translate-logical-pathname stream)))
47 (native (when pathname (native-namestring pathname))))
48 (with-simple-restart (abort "Abort ~A file ~S." context native)
49 (labels ((condition-herald (c)
50 (declare (ignore c)) ; propagates up
51 (when (form-tracking-stream-p stream)
52 (let* ((startpos
53 (form-tracking-stream-form-start-char-pos stream))
54 (point (line/col-from-charpos stream startpos)))
55 (format *error-output* "~&While evaluating the form ~
56 starting at line ~D, column ~D~% of ~S:"
57 (car point) (cdr point)
58 (or pathname stream)))))
59 (eval-form (form index)
60 (with-simple-restart (continue "Ignore error and continue ~A file ~S."
61 context native)
62 (loop
63 (handler-bind ((serious-condition #'condition-herald))
64 (with-simple-restart (retry "Retry EVAL of current toplevel form.")
65 (if print
66 (let ((results (multiple-value-list (eval-tlf form index))))
67 (load-fresh-line)
68 (format t "~{~S~^, ~}~%" results))
69 (eval-tlf form index)))
70 (return))))))
71 (if pathname
72 (let* ((info (sb!c::make-file-source-info
73 pathname (stream-external-format stream)))
74 (sb!c::*source-info* info))
75 (setf (sb!c::source-info-stream info) stream)
76 (sb!c::do-forms-from-info ((form current-index) info
77 'sb!c::input-error-in-load)
78 (sb!c::with-source-paths
79 (sb!c::find-source-paths form current-index)
80 (eval-form form current-index))))
81 (let ((sb!c::*source-info* nil))
82 (do ((form (read stream nil *eof-object*)
83 (read stream nil *eof-object*)))
84 ((eq form *eof-object*))
85 (sb!c::with-source-paths
86 (eval-form form nil))))))))
89 ;;;; LOAD itself
91 (define-condition fasl-header-missing (invalid-fasl)
92 ((fhsss :reader invalid-fasl-fhsss :initarg :fhsss))
93 (:report
94 (lambda (condition stream)
95 (format stream "~@<File ~S has a fasl file type, but no fasl header:~%~
96 Expected ~S, but got ~S.~:@>"
97 (invalid-fasl-stream condition)
98 (invalid-fasl-expected condition)
99 (invalid-fasl-fhsss condition)))))
102 ;;; The following comment preceded the pre 1.0.12.36 definition of
103 ;;; LOAD; it may no longer be accurate:
105 ;; FIXME: Daniel Barlow's ilsb.tar ILISP-for-SBCL patches contain an
106 ;; implementation of "DEFUN SOURCE-FILE" which claims, in a comment,
107 ;; that CMU CL does not correctly record source file information when
108 ;; LOADing a non-compiled file. Check whether this bug exists in SBCL
109 ;; and fix it if so.
111 (defun load (pathspec &key (verbose *load-verbose*) (print *load-print*)
112 (if-does-not-exist t) (external-format :default))
113 #!+sb-doc
114 "Load the file given by FILESPEC into the Lisp environment, returning
115 T on success."
116 (flet ((load-stream (stream faslp)
117 (when (and (fd-stream-p stream)
118 (eq (sb!impl::fd-stream-fd-type stream) :directory))
119 (error 'simple-file-error
120 :pathname (pathname stream)
121 :format-control
122 "Can't LOAD a directory: ~s."
123 :format-arguments (list (pathname stream))))
124 (let* (;; Bindings required by ANSI.
125 (*readtable* *readtable*)
126 (*package* (sane-package))
127 ;; FIXME: we should probably document the circumstances
128 ;; where *LOAD-PATHNAME* and *LOAD-TRUENAME* aren't
129 ;; pathnames during LOAD. ANSI makes no exceptions here.
130 (*load-pathname* (handler-case (pathname stream)
131 ;; FIXME: it should probably be a type
132 ;; error to try to get a pathname for a
133 ;; stream that doesn't have one, but I
134 ;; don't know if we guarantee that.
135 (error () nil)))
136 (*load-truename* (when *load-pathname*
137 (handler-case (truename stream)
138 (file-error () nil))))
139 ;; Bindings used internally.
140 (*load-depth* (1+ *load-depth*))
141 ;; KLUDGE: I can't find in the ANSI spec where it says
142 ;; that DECLAIM/PROCLAIM of optimization policy should
143 ;; have file scope. CMU CL did this, and it seems
144 ;; reasonable, but it might not be right; after all,
145 ;; things like (PROCLAIM '(TYPE ..)) don't have file
146 ;; scope, and I can't find anything under PROCLAIM or
147 ;; COMPILE-FILE or LOAD or OPTIMIZE which justifies this
148 ;; behavior. Hmm. -- WHN 2001-04-06
149 (sb!c::*policy* sb!c::*policy*))
150 (return-from load
151 (if faslp
152 (prog1 (load-as-fasl stream verbose print)
153 ;; Try to ameliorate immobile heap fragmentation
154 ;; in case somehow nontoplevel code is garbage.
155 #!+immobile-code (gc))
156 (sb!c:with-compiler-error-resignalling
157 (load-as-source stream :verbose verbose
158 :print print)))))))
159 ;; Case 1: stream.
160 (when (streamp pathspec)
161 (return-from load (load-stream pathspec (fasl-header-p pathspec))))
162 (let ((pathname (pathname pathspec)))
163 ;; Case 2: Open as binary, try to process as a fasl.
164 (with-open-stream
165 (stream (or (open pathspec :element-type '(unsigned-byte 8)
166 :if-does-not-exist nil)
167 (when (null (pathname-type pathspec))
168 (let ((defaulted-pathname
169 (probe-load-defaults pathspec)))
170 (if defaulted-pathname
171 (progn (setq pathname defaulted-pathname)
172 (open pathname
173 :if-does-not-exist
174 (if if-does-not-exist :error nil)
175 :element-type '(unsigned-byte 8))))))
176 (if if-does-not-exist
177 (error 'simple-file-error
178 :pathname pathspec
179 :format-control
180 "~@<Couldn't load ~S: file does not exist.~@:>"
181 :format-arguments (list pathspec)))))
182 (unless stream
183 (return-from load nil))
184 (let* ((real (probe-file stream))
185 (should-be-fasl-p
186 (and real (string-equal (pathname-type real) *fasl-file-type*))))
187 ;; Don't allow empty .fasls, and assume other empty files
188 ;; are source files.
189 (when (and (or should-be-fasl-p (not (eql 0 (file-length stream))))
190 (fasl-header-p stream :errorp should-be-fasl-p))
191 (return-from load (load-stream stream t)))))
192 ;; Case 3: Open using the given external format, process as source.
193 (with-open-file (stream pathname :external-format external-format
194 :class 'form-tracking-stream)
195 (load-stream stream nil)))))
197 ;; This implements the defaulting SBCL seems to have inherited from
198 ;; CMU. This routine does not try to perform any loading; all it does
199 ;; is return the pathname (not the truename) of a file to be loaded,
200 ;; or NIL if no such file can be found. This routine is supposed to
201 ;; signal an error if a fasl's timestamp is older than its source
202 ;; file, but we protect against errors in PROBE-FILE, because any of
203 ;; the ways that we might fail to find a defaulted file are reasons
204 ;; not to load it, but not worth exposing to the user who didn't
205 ;; expicitly ask us to load a file with a made-up name (e.g., the
206 ;; defaulted filename might exceed filename length limits).
207 (defun probe-load-defaults (pathname)
208 (destructuring-bind (defaulted-source-pathname
209 defaulted-source-truename
210 defaulted-fasl-pathname
211 defaulted-fasl-truename)
212 (loop for type in (list *load-source-default-type*
213 *fasl-file-type*)
214 as probe-pathname = (make-pathname :type type
215 :defaults pathname)
216 collect probe-pathname
217 collect (handler-case (probe-file probe-pathname)
218 (file-error () nil)))
219 (cond ((and defaulted-fasl-truename
220 defaulted-source-truename
221 (> (file-write-date defaulted-source-truename)
222 (file-write-date defaulted-fasl-truename)))
223 (restart-case
224 (error "The object file ~A is~@
225 older than the presumed source:~% ~A."
226 defaulted-fasl-truename
227 defaulted-source-truename)
228 (source () :report "load source file"
229 defaulted-source-pathname)
230 (object () :report "load object file"
231 defaulted-fasl-pathname)))
232 (defaulted-fasl-truename defaulted-fasl-pathname)
233 (defaulted-source-truename defaulted-source-pathname))))
235 ;;; Load a code object. BOX-NUM objects are popped off the stack for
236 ;;; the boxed storage section, then CODE-LENGTH bytes of code are read in.
237 (defun load-code (nfuns box-num code-length stack ptr fasl-input)
238 (declare (fixnum box-num code-length))
239 (declare (simple-vector stack) (type index ptr))
240 (let* ((debug-info-index (+ ptr box-num))
241 (toplevel-p (svref stack (1+ debug-info-index)))
242 (code (sb!c:allocate-code-object #!+immobile-code (not toplevel-p)
243 box-num code-length)))
244 (declare (ignorable toplevel-p))
245 (setf (%code-debug-info code) (svref stack debug-info-index))
246 (loop for i of-type index from sb!vm:code-constants-offset
247 for j of-type index from ptr below debug-info-index
248 do (setf (code-header-ref code i) (svref stack j)))
249 (without-gcing
250 ;; FIXME: can this be WITH-PINNED-OBJECTS? Probably.
251 ;; We must pin the range of bytes containing instructions,
252 ;; but we also must prevent scavenging the code object until
253 ;; the embedded simple-funs have been installed,
254 ;; otherwise GC could assert that the word referenced by
255 ;; a fun offset does not have the right widetag.
256 ;; This is achieved by not writing the 'nfuns' value
257 ;; until after the loop which stores the offsets.
258 (read-n-bytes (%fasl-input-stream fasl-input)
259 (code-instructions code) 0 code-length)
260 (loop for i from (1- nfuns) downto 0
261 do (sb!c::new-simple-fun code i (read-varint-arg fasl-input)
262 nfuns)))
263 code))
265 ;;;; linkage fixups
267 ;;; how we learn about assembler routines at startup
268 (defvar *!initial-assembler-routines*)
270 (defun !loader-cold-init ()
271 (/show0 "/!loader-cold-init")
272 (dolist (routine *!initial-assembler-routines*)
273 (setf (gethash (car routine) *assembler-routines*) (cdr routine))))