X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Fmain.lisp;h=1c42b5840b45c2bbd519fd114479de03815d717a;hb=a160917364f85b38dc0826a5e3dcef87e3c4c62c;hp=57ec2ee951cc388d24119db29176a06e40efba18;hpb=b1cd84e0503ff29d72a860ea1709c87f721412ed;p=sbcl.git diff --git a/src/compiler/main.lisp b/src/compiler/main.lisp index 57ec2ee..1c42b58 100644 --- a/src/compiler/main.lisp +++ b/src/compiler/main.lisp @@ -176,7 +176,7 @@ (*compiler-note-count* 0) (*undefined-warnings* nil) (*in-compilation-unit* t)) - (sb!thread:with-recursive-lock (*big-compiler-lock*) + (with-world-lock () (handler-bind ((parse-unknown-type (lambda (c) (note-undefined-reference @@ -387,10 +387,12 @@ (defun ir1-phases (component) (declare (type component component)) (aver-live-component component) - (let ((*constraint-number* 0) + (let ((*constraint-universe* (make-array 64 ; arbitrary, but don't + ;make this 0. + :fill-pointer 0 :adjustable t)) (loop-count 1) (*delayed-ir1-transforms* nil)) - (declare (special *constraint-number* *delayed-ir1-transforms*)) + (declare (special *constraint-universe* *delayed-ir1-transforms*)) (loop (ir1-optimize-until-done component) (when (or (component-new-functionals component) @@ -457,6 +459,8 @@ (maybe-mumble "copy ") (copy-propagate component)) + (ir2-optimize component) + (select-representations component) (when *check-consistency* @@ -720,10 +724,15 @@ ;;; A FILE-INFO structure holds all the source information for a ;;; given file. -(def!struct (file-info (:copier nil)) +(def!struct (file-info + (:copier nil) + #-no-ansi-print-object + (:print-object (lambda (s stream) + (print-unreadable-object (s stream :type t) + (princ (file-info-name s) stream))))) ;; If a file, the truename of the corresponding source file. If from ;; a Lisp form, :LISP. If from a stream, :STREAM. - (name (missing-arg) :type (or pathname (member :lisp :stream))) + (name (missing-arg) :type (or pathname (eql :lisp))) ;; the external format that we'll call OPEN with, if NAME is a file. (external-format nil) ;; the defaulted, but not necessarily absolute file name (i.e. prior @@ -751,34 +760,44 @@ (print-unreadable-object (s stream :type t)))) (:copier nil)) ;; the UT that compilation started at - (start-time (get-universal-time) :type unsigned-byte) + (start-time (get-internal-real-time) :type unsigned-byte) ;; the FILE-INFO structure for this compilation (file-info nil :type (or file-info null)) ;; the stream that we are using to read the FILE-INFO, or NIL if ;; no stream has been opened yet - (stream nil :type (or stream null))) + (stream nil :type (or stream null)) + ;; if the current compilation is recursive (e.g., due to EVAL-WHEN + ;; processing at compile-time), the invoking compilation's + ;; source-info. + (parent nil :type (or source-info null))) ;;; Given a pathname, return a SOURCE-INFO structure. (defun make-file-source-info (file external-format) - (let ((file-info (make-file-info :name (truename file) - :untruename (merge-pathnames file) - :external-format external-format - :write-date (file-write-date file)))) - - (make-source-info :file-info file-info))) + (make-source-info + :file-info (make-file-info :name (truename file) + :untruename (merge-pathnames file) + :external-format external-format + :write-date (file-write-date file)))) ;;; Return a SOURCE-INFO to describe the incremental compilation of FORM. -(defun make-lisp-source-info (form) - (make-source-info :start-time (get-universal-time) - :file-info (make-file-info :name :lisp - :forms (vector form) - :positions '#(0)))) - -;;; Return a SOURCE-INFO which will read from STREAM. -(defun make-stream-source-info (stream) - (let ((file-info (make-file-info :name :stream))) - (make-source-info :file-info file-info - :stream stream))) +(defun make-lisp-source-info (form &key parent) + (make-source-info + :file-info (make-file-info :name :lisp + :forms (vector form) + :positions '#(0)) + :parent parent)) + +;;; Walk up the SOURCE-INFO list until we either reach a SOURCE-INFO +;;; with no parent (e.g., from a REPL evaluation) or until we reach a +;;; SOURCE-INFO whose FILE-INFO denotes a file. +(defun get-toplevelish-file-info (&optional (source-info *source-info*)) + (if source-info + (do* ((sinfo source-info (source-info-parent sinfo)) + (finfo (source-info-file-info sinfo) + (source-info-file-info sinfo))) + ((or (not (source-info-p (source-info-parent sinfo))) + (pathnamep (file-info-name finfo))) + finfo)))) ;;; Return a form read from STREAM; or for EOF use the trick, ;;; popularized by Kent Pitman, of returning STREAM itself. If an @@ -835,24 +854,37 @@ (setf (source-info-stream info) nil) (values)) +;;; Loop over FORMS retrieved from INFO. Used by COMPILE-FILE and +;;; LOAD when loading from a FILE-STREAM associated with a source +;;; file. +(defmacro do-forms-from-info (((form &rest keys) info) + &body body) + (aver (symbolp form)) + (once-only ((info info)) + `(let ((*source-info* ,info)) + (loop (destructuring-bind (,form &key ,@keys &allow-other-keys) + (let* ((file-info (source-info-file-info ,info)) + (stream (get-source-stream ,info)) + (pos (file-position stream)) + (form (read-for-compile-file stream pos))) + (if (eq form stream) ; i.e., if EOF + (return) + (let* ((forms (file-info-forms file-info)) + (current-idx (+ (fill-pointer forms) + (file-info-source-root + file-info)))) + (vector-push-extend form forms) + (vector-push-extend pos (file-info-positions + file-info)) + (list form :current-index current-idx)))) + ,@body))))) + ;;; Read and compile the source file. (defun sub-sub-compile-file (info) - (let* ((file-info (source-info-file-info info)) - (stream (get-source-stream info))) - (loop - (let* ((pos (file-position stream)) - (form (read-for-compile-file stream pos))) - (if (eq form stream) ; i.e., if EOF - (return) - (let* ((forms (file-info-forms file-info)) - (current-idx (+ (fill-pointer forms) - (file-info-source-root file-info)))) - (vector-push-extend form forms) - (vector-push-extend pos (file-info-positions file-info)) - (find-source-paths form current-idx) - (process-toplevel-form form - `(original-source-start 0 ,current-idx) - nil))))))) + (do-forms-from-info ((form current-index) info) + (find-source-paths form current-index) + (process-toplevel-form + form `(original-source-start 0 ,current-index) nil))) ;;; Return the INDEX'th source form read from INFO and the position ;;; where it was read. @@ -870,19 +902,21 @@ ;;; *TOPLEVEL-LAMBDAS* instead. (defun convert-and-maybe-compile (form path) (declare (list path)) - (if (fopcompilable-p form) - (let ((*fopcompile-label-counter* 0)) - (fopcompile form path nil)) - (let* ((*top-level-form-noted* (note-top-level-form form t)) - (*lexenv* (make-lexenv - :policy *policy* - :handled-conditions *handled-conditions* - :disabled-package-locks *disabled-package-locks*)) - (tll (ir1-toplevel form path nil))) - (if (eq *block-compile* t) - (push tll *toplevel-lambdas*) - (compile-toplevel (list tll) nil)) - nil))) + (let ((*top-level-form-noted* (note-top-level-form form t))) + ;; Don't bother to compile simple objects that just sit there. + (when (and form (or (symbolp form) (consp form))) + (if (fopcompilable-p form) + (let ((*fopcompile-label-counter* 0)) + (fopcompile form path nil)) + (let ((*lexenv* (make-lexenv + :policy *policy* + :handled-conditions *handled-conditions* + :disabled-package-locks *disabled-package-locks*)) + (tll (ir1-toplevel form path nil))) + (if (eq *block-compile* t) + (push tll *toplevel-lambdas*) + (compile-toplevel (list tll) nil)) + nil))))) ;;; Macroexpand FORM in the current environment with an error handler. ;;; We only expand one level, so that we retain all the intervening @@ -971,7 +1005,7 @@ (maybe-frob (optional-dispatch-main-entry f))) result)))) -(defun make-functional-from-toplevel-lambda (definition +(defun make-functional-from-toplevel-lambda (lambda-expression &key name (path @@ -981,17 +1015,15 @@ (missing-arg))) (let* ((*current-path* path) (component (make-empty-component)) - (*current-component* component)) - (setf (component-name component) - (debug-name 'initial-component name)) - (setf (component-kind component) :initial) + (*current-component* component) + (debug-name-tail (or name (name-lambdalike lambda-expression))) + (source-name (or name '.anonymous.))) + (setf (component-name component) (debug-name 'initial-component debug-name-tail) + (component-kind component) :initial) (let* ((locall-fun (let ((*allow-instrumenting* t)) (funcall #'ir1-convert-lambdalike - definition - :source-name name))) - (debug-name (debug-name 'tl-xep - (or name - (functional-%source-name locall-fun)))) + lambda-expression + :source-name source-name))) ;; Convert the XEP using the policy of the real ;; function. Otherwise the wrong policy will be used for ;; deciding whether to type-check the parameters of the @@ -1000,8 +1032,9 @@ (*lexenv* (make-lexenv :policy (lexenv-policy (functional-lexenv locall-fun)))) (fun (ir1-convert-lambda (make-xep-lambda-expression locall-fun) - :source-name (or name '.anonymous.) - :debug-name debug-name))) + :source-name source-name + :debug-name (debug-name 'tl-xep debug-name-tail) + :system-lambda t))) (when name (assert-global-function-definition-type name locall-fun)) (setf (functional-entry-fun fun) locall-fun @@ -1496,7 +1529,6 @@ (*disabled-package-locks* *disabled-package-locks*) (*lexenv* (make-null-lexenv)) (*block-compile* *block-compile-arg*) - (*source-info* info) (*toplevel-lambdas* ()) (*fun-names-in-this-file* ()) (*allow-instrumenting* nil) @@ -1576,10 +1608,13 @@ ((try-with-type pathname "lisp" nil)) ((try-with-type pathname "lisp" t)))))) -(defun elapsed-time-to-string (tsec) - (multiple-value-bind (tmin sec) (truncate tsec 60) - (multiple-value-bind (thr min) (truncate tmin 60) - (format nil "~D:~2,'0D:~2,'0D" thr min sec)))) +(defun elapsed-time-to-string (internal-time-delta) + (multiple-value-bind (tsec remainder) + (truncate internal-time-delta internal-time-units-per-second) + (let ((ms (truncate remainder (/ internal-time-units-per-second 1000)))) + (multiple-value-bind (tmin sec) (truncate tsec 60) + (multiple-value-bind (thr min) (truncate tmin 60) + (format nil "~D:~2,'0D:~2,'0D.~3,'0D" thr min sec ms)))))) ;;; Print some junk at the beginning and end of compilation. (defun print-compile-start-note (source-info) @@ -1600,7 +1635,7 @@ (compiler-mumble "~&; compilation ~:[aborted after~;finished in~] ~A~&" won (elapsed-time-to-string - (- (get-universal-time) + (- (get-internal-real-time) (source-info-start-time source-info)))) (values)) @@ -1666,7 +1701,7 @@ SPEED and COMPILATION-SPEED optimization values, and the |# (let* ((fasl-output nil) (output-file-name nil) - (abort-p nil) + (abort-p t) (warnings-p nil) (failure-p t) ; T in case error keeps this from being set later (input-pathname (verify-source-file input-file)) @@ -1812,7 +1847,7 @@ SPEED and COMPILATION-SPEED optimization values, and the (defvar *constants-being-created* nil) (defvar *constants-created-since-last-init* nil) ;;; FIXME: Shouldn't these^ variables be unbound outside LET forms? -(defun emit-make-load-form (constant) +(defun emit-make-load-form (constant &optional (name nil namep)) (aver (fasl-output-p *compile-object*)) (unless (or (fasl-constant-already-dumped-p constant *compile-object*) ;; KLUDGE: This special hack is because I was too lazy @@ -1828,10 +1863,14 @@ SPEED and COMPILATION-SPEED optimization values, and the (throw constant t)) (throw 'pending-init circular-ref))) (multiple-value-bind (creation-form init-form) - (handler-case - (sb!xc:make-load-form constant (make-null-lexenv)) - (error (condition) - (compiler-error condition))) + (if namep + ;; If the constant is a reference to a named constant, we can + ;; just use SYMBOL-VALUE during LOAD. + (values `(symbol-value ',name) nil) + (handler-case + (sb!xc:make-load-form constant (make-null-lexenv)) + (error (condition) + (compiler-error condition)))) (case creation-form (:sb-just-dump-it-normally (fasl-validate-structure constant *compile-object*)