1.0.11.18: Make fasls LISP-IMPLEMENTATION-VERSION specific
authorJuho Snellman <jsnell@iki.fi>
Fri, 9 Nov 2007 01:10:21 +0000 (01:10 +0000)
committerJuho Snellman <jsnell@iki.fi>
Fri, 9 Nov 2007 01:10:21 +0000 (01:10 +0000)
        * As discussed on sbcl-devel.
        * Reduce the support burden: We get a lot of bug reports that turn
          out to be caused by stale fasls, and even more people probably
          don't report these problems, but just end up thinking that SBCL
          crashes all the time.
        * +FASL-FILE-VERSION+ retained for backwards compability, but should
          only be incremented if the actual fasl format changes.

src/code/early-fasl.lisp
src/code/load.lisp
src/compiler/dump.lisp
version.lisp-expr

index f65a958..5785573 100644 (file)
@@ -76,7 +76,7 @@
 ;;; versions which break binary compatibility. But it certainly should
 ;;; be incremented for release versions which break binary
 ;;; compatibility.
-(def!constant +fasl-file-version+ 76)
+(def!constant +fasl-file-version+ 77)
 ;;; (description of versions before 0.9.0.1 deleted in 0.9.17)
 ;;; 56: (2005-05-22) Something between 0.9.0.1 and 0.9.0.14. My money is
 ;;;     on 0.9.0.6 (MORE CASE CONSISTENCY).
 ;;; 73: (2007-04-13) Changed a hash function
 ;;; 74: (2007-06-05) UNWIND-TO-FRAME-AND-CALL
 ;;; 75: (2007-08-06) FD-STREAM layout changes
-;;; 76: (2007-05-10) MUTEX layout changes
+;;; 76: (2007-10-05) MUTEX layout changes
+;;; 77: (2007-11-08) Essentially obsolete fasl-file-version, fasls are now
+;;;     considered compatible only when the version numbers of the compiling
+;;;     SBCL instance is exactly the same as the one of the loading instance.
+;;;     Further fasl-file-version bumps should only be done for real changes
+;;;     in the fasl format, not for changes in function/macro signatures or
+;;;     lisp data structures.
 
 ;;; the conventional file extension for our fasl files
 (declaim (type simple-string *fasl-file-type*))
index 8b3067d..1a0bcea 100644 (file)
              (invalid-fasl-expected condition)))))
 
 (define-condition invalid-fasl-version (invalid-fasl)
-  ((variant :reader invalid-fasl-variant :initarg :variant)
-   (version :reader invalid-fasl-version :initarg :version))
+  ((version :reader invalid-fasl-version :initarg :version))
   (:report
    (lambda (condition stream)
-     (format stream "~@<~S is in ~A fasl file format version ~W, ~
-                    but this version of SBCL uses format version ~W.~:@>"
+     (format stream "~@<~S is a fasl file compiled with SBCL ~W, and ~
+                      can't be loaded into SBCL ~W.~:@>"
              (invalid-fasl-stream condition)
-             (invalid-fasl-variant condition)
              (invalid-fasl-version condition)
              (invalid-fasl-expected condition)))))
 
 ;;; or NIL if EOF was hit before anything was read. Signal an error if
 ;;; we encounter garbage.
 (defun check-fasl-header (stream)
-
   (let ((byte (read-byte stream nil)))
     (when byte
-
       ;; Read and validate constant string prefix in fasl header.
       (let* ((fhsss *fasl-header-string-start-string*)
              (fhsss-length (length fhsss)))
                    :byte-nr count
                    :byte byte
                    :expected (char-code (schar fhsss count))))))
-
       ;; Read and validate version-specific compatibility stuff.
       (flet ((string-from-stream ()
                (let* ((length (read-unsigned-byte-32-arg))
                  result)))
         ;; Read and validate implementation and version.
         (let* ((implementation (keywordicate (string-from-stream)))
-               ;; FIXME: The logic above to read a keyword from the fasl file
-               ;; could probably be shared with the read-a-keyword fop.
-               (version (read-word-arg)))
-          (flet ((check-version (variant
-                                 possible-implementation
-                                 needed-version)
-                   (when (string= possible-implementation implementation)
-                     (or (= version needed-version)
-                         (error 'invalid-fasl-version
-                                ;; :error :wrong-version
-                                :stream stream
-                                :variant variant
-                                :version version
-                                :expected needed-version)))))
-            (or (check-version "native code"
-                               +backend-fasl-file-implementation+
-                               +fasl-file-version+)
-                (error 'invalid-fasl-implementation
-                       :stream stream
-                       :implementation implementation
-                       :expected +backend-fasl-file-implementation+))))
+               (fasl-version (read-word-arg))
+               (sbcl-version (if (<= fasl-version 76)
+                                 "1.0.11.18"
+                                 (string-from-stream)))
+               (expected-version (sb!xc:lisp-implementation-version))
+               (expected-implementation +backend-fasl-file-implementation+))
+          (cond ((string/= expected-implementation implementation)
+                 (error 'invalid-fasl-implementation
+                        :stream stream
+                        :implementation implementation
+                        :expected expected-implementation))
+                ((string/= expected-version sbcl-version)
+                 (restart-case
+                     (error 'invalid-fasl-version
+                            :stream stream
+                            :version sbcl-version
+                            :expected expected-version)
+                   (continue ()
+                     :report "Load the fasl file anyway")))))
         ;; Read and validate *FEATURES* which affect binary compatibility.
         (let ((faff-in-this-file (string-from-stream)))
           (unless (string= faff-in-this-file *features-affecting-fasl-format*)
index bf3527e..4535238 100644 (file)
                        :if-exists :supersede
                        :element-type 'sb!assem:assembly-unit))
          (res (make-fasl-output :stream stream)))
-
     ;; Begin the header with the constant machine-readable (and
     ;; semi-human-readable) string which is used to identify fasl files.
     (fasl-write-string *fasl-header-string-start-string* stream)
-
     ;; The constant string which begins the header is followed by
     ;; arbitrary human-readable text, terminated by a special
     ;; character code.
                   at ~A~%  ~
                   on ~A~%  ~
                   using ~A version ~A~%"
-         where
+                 where
                  (format-universal-time nil (get-universal-time))
                  (machine-instance)
                  (sb!xc:lisp-implementation-type)
                  (sb!xc:lisp-implementation-version))))
      stream)
     (dump-byte +fasl-header-string-stop-char-code+ res)
-
     ;; Finish the header by outputting fasl file implementation,
     ;; version, and key *FEATURES*.
     (flet ((dump-counted-string (string)
                (dump-byte (char-code (aref string i)) res))))
       (dump-counted-string (symbol-name +backend-fasl-file-implementation+))
       (dump-word +fasl-file-version+ res)
+      (dump-counted-string (sb!xc:lisp-implementation-version))
       (dump-counted-string *features-affecting-fasl-format*))
-
     res))
 
 ;;; Close the specified FASL-OUTPUT, aborting the write if ABORT-P.
index 46ffe81..4387ce8 100644 (file)
@@ -17,4 +17,4 @@
 ;;; checkins which aren't released. (And occasionally for internal
 ;;; versions, especially for internal versions off the main CVS
 ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"1.0.11.17"
+"1.0.11.18"