hunting bug 138...
...Poking around in the bug 138 test case, I found that the
failure is occurring for a LAMBDA which represents
the inline expansion of LAYOUT-INHERITS. It seems
correct for :INLINE LAMBDAs not to be in
COMPONENT-LAMBDAS, so it looks as though the bug is
in the AVER, not the code it's trying to protect,
so I added a new :INLINE case to the check logic.
Alas, that only converted bug 138a into bug 138b.
...added some assertions and comments hunting for 138b
redid DUMP-CODE-OBJECT loop for clarity as LOOP not DO
"SB-INT:&MORE processor".
138:
- a cross-compiler bug in sbcl-0.pre7.107
+ a pair of cross-compiler bugs in sbcl-0.pre7.107
- $ cat > /tmp/bug139.lisp << EOF
+138a:
+ $ cat > /tmp/bug138.lisp << EOF
(in-package "SB!KERNEL")
(defun f-c-l (name parent-types)
(let* ((cpl (mapcar (lambda (x)
EOF
$ sbcl --core output/after-xc.core
...
- * (target-compile-file "/tmp/bug139.lisp")
+ * (target-compile-file "/tmp/bug138.lisp")
...
internal error, failed AVER:
"(COMMON-LISP:MEMBER SB!C::FUN (SB!C::COMPONENT-LAMBDAS SB!C:COMPONENT))"
related weirdness: Using #'(LAMBDA (X) ...) instead of (LAMBDA (X) ...)
makes the assertion failure go away.
+138b:
+ Even when you relax the AVER that fails in 138a, there's another
+ problem cross-compiling the same code:
+ internal error, failed AVER:
+ "(COMMON-LISP:ZEROP
+ (COMMON-LISP:HASH-TABLE-COUNT
+ (SB!FASL::FASL-OUTPUT-PATCH-TABLE SB!FASL:FASL-OUTPUT)))"
+
+ The same problem appears in the simpler test case
+ (in-package "SB!KERNEL")
+ (defun f-c-l ()
+ (let ((cpl (foo (lambda (x)
+ (condition-class-cpl x))))
+ (new-inherits (layout-inherits cond-layout)))
+ (layout-inherits olayout)))
+
+ Changing CONDITION-CLASS-CPL or (either of the calls to) LAYOUT-INHERITS
+ to arbitrary nonmagic not-defined-yet just-do-a-full-call functions makes
+ the problem go away. Also, even in this simpler test case which fails
+ on a very different AVER, the 138a weirdness about s/(lambda/#'(lambda/
+ making the problem go away is preserved.
+
+ I still haven't found any way to make this happen in the ordinary
+ (not cross-) SBCL compiler, nor in CMU CL.
+
+138c:
+ In sbcl-0.pre7.111 I added an assertion upstream, in IR2-CONVERT-CLOSURE,
+ which fails for the test case above but doesn't keep the system
+ from cross-compiling itself or passing its tests.
+
139:
In sbcl-0.pre7.107, (DIRECTORY "*.*") is broken, as reported by
Nathan Froyd sbcl-devel 2001-12-28.
** finished s/FUNCTION/FUN/
** s/VARIABLE/VAR/
** perhaps s/DEF-FROB/DEF/ or s/DEF-FROB/DEFINE/
+* Perhaps rename "cold" stuff (e.g. SB-COLD and src/cold/) to "boot".
* global style systematization:
** s/#'(lambda/(lambda/
* pending patches and bug reports that go in (or else get handled
* patches postponed until after 0.7.0:
** Christophe Rhodes "rough patch to fix bug 106" 2001-10-28
** Alexey Dejneka "bug 111" 2001-12-30
-* building with CLISP (or explaining why not)
+* building with CLISP (or explaining why not). This will likely involve
+ a rearrangement of the build system so that it never renames
+ the output from COMPILE-FILE, because CLISP's COMPILE-FILE
+ outputs two (!) files and as far as I can tell LOAD uses both
+ of them. Since I have other motivations for this rearrangement
+ besides CLISPiosyncrasies, I'm reasonably motivated to do it.
* urgent EVAL/EVAL-WHEN/%COMPILE/DEFUN/DEFSTRUCT cleanup:
** fixed bug 137
* faster bootstrapping (both make.sh and slam.sh)
;; for e.g. SPECIFIER-TYPE, needed by primtype.lisp
("src/code/early-type")
- ;; FIXME: Classic CMU CL had SAFETY 2 DEBUG 2 set around the compilation
- ;; of "code/class". Why?
+ ;; FIXME: Classic CMU CL had (OPTIMIZE (SAFETY 2) (DEBUG 2) declared
+ ;; around the compilation of "code/class". Why?
("src/code/class")
;; The definition of CONDITION-CLASS depends on SLOT-CLASS, defined
(declare (notinline sb!xc:find-class))
(find-class 'condition)))
#'(lambda (cond stream)
- (format stream "Condition ~S was signalled." (type-of cond))))
+ (format stream "Condition ~S was signalled." (type-of cond))))
(eval-when (:compile-toplevel :load-toplevel :execute)
(reverse
(reduce #'append
(mapcar #'(lambda (x)
- (condition-class-cpl
- (sb!xc:find-class x)))
+ (condition-class-cpl
+ (sb!xc:find-class x)))
parent-types)))))
(cond-layout (info :type :compiler-layout 'condition))
(olayout (info :type :compiler-layout name))
(dolist (reader (condition-slot-readers slot))
(setf (fdefinition reader)
#'(lambda (condition)
- (condition-reader-function condition name))))
+ (condition-reader-function condition name))))
(dolist (writer (condition-slot-writers slot))
(setf (fdefinition writer)
#'(lambda (new-value condition)
- (condition-writer-function condition new-value name))))))
+ (condition-writer-function condition new-value name))))))
;; Compute effective slots and set up the class and hairy slots
;; (subsets of the effective slots.)
(setq report
(if (stringp arg)
`#'(lambda (condition stream)
- (declare (ignore condition))
- (write-string ,arg stream))
+ (declare (ignore condition))
+ (write-string ,arg stream))
`#'(lambda (condition stream)
- (funcall #',arg condition stream))))))
+ (funcall #',arg condition stream))))))
(:default-initargs
(do ((initargs (rest option) (cddr initargs)))
((endp initargs))
(make-normal-tn *fixnum-primitive-type*)))
-;;; This function is called by the Entry-Analyze phase, allowing
-;;; VM-dependent initialization of the IR2-Component structure. We
-;;; push placeholder entries in the Constants to leave room for
+;;; This function is called by the ENTRY-ANALYZE phase, allowing
+;;; VM-dependent initialization of the IR2-COMPONENT structure. We
+;;; push placeholder entries in the CONSTANTS to leave room for
;;; additional noise in the code object header.
(!def-vm-support-routine select-component-format (component)
(declare (type component component))
;; an alist (PACKAGE . OFFSET) of the table offsets for each package
;; we have currently located.
(packages () :type list)
- ;; a table mapping from the Entry-Info structures for dumped XEPs to
+ ;; a table mapping from the ENTRY-INFO structures for dumped XEPs to
;; the table offsets of the corresponding code pointers
(entry-table (make-hash-table :test 'eq) :type hash-table)
;; a table holding back-patching info for forward references to XEPs.
- ;; The key is the Entry-Info structure for the XEP, and the value is
+ ;; The key is the ENTRY-INFO structure for the XEP, and the value is
;; a list of conses (<code-handle> . <offset>), where <code-handle>
;; is the offset in the table of the code object needing to be
;; patched, and <offset> is the offset that must be patched.
;; far as I know no modern CMU CL does either -- WHN
;; 2001-10-05). So might we be able to get rid of trace tables?
- ;; Dump the constants, noting any :entries that have to be fixed up.
- (do ((i sb!vm:code-constants-offset (1+ i)))
- ((>= i header-length))
+ ;; Dump the constants, noting any :ENTRY constants that have to
+ ;; be patched.
+ (loop for i from sb!vm:code-constants-offset below header-length do
(let ((entry (aref constants i)))
(etypecase entry
(constant
(handle (gethash info
(fasl-output-entry-table
fasl-output))))
+ (declare (type sb!c::entry-info info))
(cond
(handle
(dump-push handle fasl-output))
(t
+
+ ;; REMOVEME after fixing bug 138b.
+ #|
+ (unless (member info (sb!c::ir2-component-entries 2comp))
+ (format t "~&i=~S~%" i)
+ (error "bogus FASL-OUTPUT-PATCH-TABLE value ~S" info))
+ |#
+
(patches (cons info i))
(dump-fop 'fop-misc-trap fasl-output)))))
(:load-time-value
(dump-fixups fixups fasl-output)
(dump-fop 'fop-sanctify-for-execution fasl-output)
+
(let ((handle (dump-pop fasl-output)))
(dolist (patch (patches))
(push (cons handle (cdr patch))
(setf (leaf-info fun) (make-entry-info)))))
(compute-entry-info fun info)
(push info (ir2-component-entries 2comp))))))
-
(select-component-format component)
(values))
(note-function entry res object))))
-;;; Dump a component to core. We pass in the assembler fixups, code vector
-;;; and node info.
+;;; Dump a component to core. We pass in the assembler fixups, code
+;;; vector and node info.
(defun make-core-component (component segment length trace-table fixups object)
(declare (type component component)
(type sb!assem:segment segment)
(values))
;;; Convert a call to a local function. If the function has already
-;;; been let converted, then throw FUN to LOCAL-CALL-LOSSAGE. This
+;;; been LET converted, then throw FUN to LOCAL-CALL-LOSSAGE. This
;;; should only happen when we are converting inline expansions for
;;; local functions during optimization.
(defun ir1-convert-local-combination (start cont form fun)
;;; Emit code to load a function object representing LEAF into RES.
;;; This gets interesting when the referenced function is a closure:
-;;; we must make the closure and move the closed over values into it.
+;;; we must make the closure and move the closed-over values into it.
;;;
;;; LEAF is either a :TOPLEVEL-XEP functional or the XEP lambda for
;;; the called function, since local call analysis converts all
-;;; closure references. If a TL-XEP, we know it is not a closure.
+;;; closure references. If a :TOPLEVEL-XEP, we know it is not a closure.
;;;
;;; If a closed-over LAMBDA-VAR has no refs (is deleted), then we
;;; don't initialize that slot. This can happen with closures over
(declare (type ref node) (type ir2-block block)
(type functional leaf) (type tn res))
(unless (leaf-info leaf)
- (setf (leaf-info leaf) (make-entry-info)))
+ (setf (leaf-info leaf)
+ (make-entry-info :name (functional-debug-name leaf))))
(let ((entry (make-load-time-constant-tn :entry leaf))
(closure (etypecase leaf
(clambda
+
+ ;; Check for some weirdness which came up in bug
+ ;; 138, 2002-01-02.
+ ;;
+ ;; The MAKE-LOAD-TIME-CONSTANT-TN call above puts
+ ;; an :ENTRY record into the
+ ;; IR2-COMPONENT-CONSTANTS table. The
+ ;; dump-a-COMPONENT code
+ ;; * treats every HANDLEless :ENTRY record into a
+ ;; patch, and
+ ;; * expects every patch to correspond to an
+ ;; IR2-COMPONENT-ENTRIES record.
+ ;; The IR2-COMPONENT-ENTRIES records are set by
+ ;; ENTRY-ANALYZE walking over COMPONENT-LAMBDAS.
+ ;; Bug 138b arose because there was a HANDLEless
+ ;; :ENTRY record which didn't correspond to an
+ ;; IR2-COMPONENT-ENTRIES record. That problem is
+ ;; hard to debug when it's caught at dump time, so
+ ;; this assertion tries to catch it here.
+ (aver (member leaf
+ (component-lambdas (lambda-component leaf))))
+
(physenv-closure (get-lambda-physenv leaf)))
(functional
(aver (eq (functional-kind leaf) :toplevel-xep))
nil))))
+
(cond (closure
(let ((this-env (node-physenv node)))
(vop make-closure node block entry (length closure) res)
;;;
;;; Note that there is a lot of action going on behind the scenes
;;; here, triggered by reference deletion. In particular, the
-;;; COMPONENT-LAMBDAS are being hacked to remove newly deleted and let
+;;; COMPONENT-LAMBDAS are being hacked to remove newly deleted and LET
;;; converted LAMBDAs, so it is important that the LAMBDA is added to
;;; the COMPONENT-LAMBDAS when it is. Also, the COMPONENT-NEW-FUNS may
;;; contain all sorts of drivel, since it is not updated when we
;; FUN becomes part of COMPONENT-LAMBDAS now.
(aver (not (member fun (component-lambdas component))))
(push fun (component-lambdas component)))
+ ((eql (lambda-inlinep fun) :inline)
+ ;; FUNs marked :INLINE are sometimes in
+ ;; COMPONENT-LAMBDAS and sometimes not. I (WHN
+ ;; 2002-01-01) haven't figured this one out yet,
+ ;; so don't assert anything.
+ ;;
+ ;; (One possibility: LAMBDAs to represent the
+ ;; inline expansions of things which are defined
+ ;; elsewhere might not be in COMPONENT-LAMBDAS,
+ ;; which LAMBDAs to represent the inline
+ ;; expansions of local functions might in
+ ;; COMPONENT-LAMBDAS?)
+ (values))
(t ; FUN's old.
;; FUN should be in COMPONENT-LAMBDAS already.
(aver (member fun (component-lambdas component)))))
;;; Return a load-time constant TN with the specified KIND and INFO.
;;; If the desired CONSTANTS entry already exists, then reuse it,
-;;; otherwise allocate a anew load-time constant slot.
+;;; otherwise allocate a new load-time constant slot.
(defun make-load-time-constant-tn (kind info)
(declare (type keyword kind))
(let* ((component (component-info *component-being-compiled*))
(list (make-stack-pointer-tn)
(make-normal-tn *fixnum-primitive-type*)))
-;;; This function is called by the Entry-Analyze phase, allowing
+;;; This function is called by the ENTRY-ANALYZE phase, allowing
;;; VM-dependent initialization of the IR2-COMPONENT structure. We
-;;; push placeholder entries in the Constants to leave room for
+;;; push placeholder entries in the CONSTANTS to leave room for
;;; additional noise in the code object header.
-;;;
-;;; For the x86 the first constant is a pointer to a list of fixups,
-;;; or NIL if the code object has none.
(!def-vm-support-routine select-component-format (component)
(declare (type component component))
+ ;; The 1+ here is because for the x86 the first constant is a
+ ;; pointer to a list of fixups, or NIL if the code object has none.
+ ;; (If I understand correctly, the fixups are needed at GC copy
+ ;; time because the X86 code isn't relocatable.)
+ ;;
+ ;; KLUDGE: It'd be cleaner to have the fixups entry be a named
+ ;; element of the CODE (aka component) primitive object. However,
+ ;; it's currently a large, tricky, error-prone chore to change
+ ;; the layout of any primitive object, so for the foreseeable future
+ ;; we'll just live with this ugliness. -- WHN 2002-01-02
(dotimes (i (1+ code-constants-offset))
(vector-push-extend nil
(ir2-component-constants (component-info component))))
;;; for internal versions, especially for internal versions off the
;;; main CVS branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.pre7.110"
+"0.pre7.111"