Index: /branches/mb-coverage-merge/compiler/PPC/ppc2.lisp
===================================================================
--- /branches/mb-coverage-merge/compiler/PPC/ppc2.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/compiler/PPC/ppc2.lisp	(revision 8519)
@@ -464,4 +464,6 @@
                    (if (logbitp $fbitnonnullenv (the fixnum (afunc-bits afunc)))
                      (setq bits (+ bits (ash 1 $lfbits-nonnullenv-bit))))
+                   (when (logbitp $fbitccoverage (the fixnum (afunc-bits afunc)))
+                     (setq bits (+ bits (ash 1 $lfbits-code-coverage-bit))))
                    (let* ((function-debugging-info (afunc-lfun-info afunc)))
                      (when (or function-debugging-info lambda-form *ppc2-record-symbols*)
@@ -494,5 +496,7 @@
                             regsave-addr
                             (if (and fname (symbolp fname)) (symbol-name fname)))))
-                   (ppc2-digest-symbols))))
+                   (ppc2-digest-symbols)
+                   (ppc2-digest-code-notes))))
+          (ppc2-reset-code-notes)
           (backend-remove-labels))))
     afunc))
@@ -2140,5 +2144,51 @@
       (when (and vreg val-reg) (<- val-reg))
       (^))))
-                    
+
+(defun ppc2-code-coverage-entry (seg)
+  (let* ((afunc *ppc2-cur-afunc*)
+         (note (getf (afunc-lfun-info afunc) 'function-source-note)))
+    (when note
+      (setf (afunc-bits afunc) (%ilogior (afunc-bits afunc) (ash 1 $fbitccoverage)))
+      (with-ppc-local-vinsn-macros (seg)
+        (! vpush-register ppc::arg_x)
+        (! misc-ref-c-node ppc::arg_x ppc::nfn (1+ (backend-immediate-index note)))
+        (! misc-set-c-node ppc::rzero ppc::arg_x 1)
+        (! vpop-register ppc::arg_x)))))
+
+(defppc2 ppc2-with-code-note with-code-note (seg vreg xfer note form &aux val)
+  (when *record-pc-mapping*
+    (append-dll-node (setf (code-note-start-pc note) (make-vinsn-label nil)) seg))
+  (when *compile-code-coverage*
+    (with-ppc-local-vinsn-macros (seg)
+      (ppc2-store-immediate seg note ($ ppc::arg_x))
+      (! misc-set-c-node ($ ppc::rzero) ($ ppc::arg_x) 1)))
+  (setq val (ppc2-form seg vreg xfer form))
+  (when *record-pc-mapping*
+    (append-dll-node (setf (code-note-end-pc note) (make-vinsn-label nil)) seg))
+  val)
+
+(defun ppc2-digest-code-notes ()
+  (when *record-pc-mapping*
+    (flet ((address (label)
+             (when (typep label 'vinsn-label)
+               (let ((lap-label (or (vinsn-label-info label)
+                                    (compiler-bug "Missing source note label: ~s" label))))
+                 (lap-label-address lap-label)))))
+      (labels ((rec (note)
+                 (when note
+                   (setf (code-note-start-pc note) (address (code-note-start-pc note)))
+                   (setf (code-note-end-pc note) (address (code-note-end-pc note)))
+                   (dolist (subnote (code-note-subform-notes note)) (rec subnote)))))
+        (rec (getf (afunc-lfun-info *ppc2-cur-afunc*) 'function-source-note))))))
+
+(defun ppc2-reset-code-notes ()
+  (when *record-pc-mapping*
+    (flet ((clear (label) (if (typep label 'vinsn-label) nil label)))
+      (labels ((rec (note)
+                 (when note
+                   (setf (code-note-start-pc note) (clear (code-note-start-pc note)))
+                   (setf (code-note-end-pc note) (clear (code-note-end-pc note)))
+                   (dolist (subnote (code-note-subform-notes note)) (rec subnote)))))
+        (rec (getf (afunc-lfun-info *ppc2-cur-afunc*) 'function-source-note))))))
 
 (defun ppc2-vset (seg vreg xfer type-keyword vector index value safe)
@@ -5064,6 +5114,6 @@
     (if (%vinsn-label-p v)
       (let* ((id (vinsn-label-id v)))
-        (if (typep id 'fixnum)
-          (when (or t (vinsn-label-refs v))
+        (if (or (typep id 'fixnum) (null id))
+          (when (or t (vinsn-label-refs v) (null id))
             (setf (vinsn-label-info v) (emit-lap-label v)))
           (ppc2-expand-note id)))
@@ -5260,4 +5310,9 @@
           (ppc2-allocate-global-registers *ppc2-fcells* *ppc2-vcells* (afunc-all-vars afunc) no-regs))
         (@ (backend-get-next-label)) ; generic self-reference label, should be label #1
+	(when keys ;; Ensure keyvect is the first immediate
+	  (backend-immediate-index (%cadr (%cdddr keys))))
+        (when *compile-code-coverage*
+          (ppc2-code-coverage-entry seg))
+
         (unless next-method-p
           (setq method-var nil))
@@ -9059,4 +9114,14 @@
                              (list nil (list arg))))))))
 
+(defun show-function-constants (f)
+  (cond ((typep f 'function)
+	 (do* ((i 0 j)
+	       (n (uvsize f))
+	       (j 1 (1+ j)))
+	      ((= j n))
+	   (format t "~&~d: ~s" i (uvref f j))))
+	(t (report-bad-arg f 'function))))
+
+	
 ;------
 
Index: /branches/mb-coverage-merge/compiler/X86/x86-disassemble.lisp
===================================================================
--- /branches/mb-coverage-merge/compiler/X86/x86-disassemble.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/compiler/X86/x86-disassemble.lisp	(revision 8519)
@@ -2726,5 +2726,5 @@
          (entry (x86-ds-entry-point ds)))
     (let* ((pc (- addr entry)))
-      (let* ((source-note (getf (%lfun-info function) 'function-source-note))
+      (let* ((source-note (source-note-from-%lfun-info (%lfun-info function)))
              (source-info (find-source-at-pc function pc))
              (text (if (and source-info
@@ -2732,5 +2732,5 @@
                             (plusp (cdr (getf source-info :source-text-range))))
                        (string-sans-most-whitespace
-                        (subseq (%fast-uncompact (getf source-note :%text))
+                        (subseq (source-note-text source-note)
                                 (car (getf source-info :source-text-range))
                                 (cdr (getf source-info :source-text-range)))
Index: /branches/mb-coverage-merge/compiler/X86/x862.lisp
===================================================================
--- /branches/mb-coverage-merge/compiler/X86/x862.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/compiler/X86/x862.lisp	(revision 8519)
@@ -574,6 +574,8 @@
                          (x86-lap-directive frag-list :quad 1)))
                  
-                     (if (logbitp $fbitnonnullenv (the fixnum (afunc-bits afunc)))
+                     (when (logbitp $fbitnonnullenv (the fixnum (afunc-bits afunc)))
                        (setq bits (+ bits (ash 1 $lfbits-nonnullenv-bit))))
+                     (when (logbitp $fbitccoverage (the fixnum (afunc-bits afunc)))
+                       (setq bits (+ bits (ash 1 $lfbits-code-coverage-bit))))
                      (unless (afunc-parent afunc)
                        (x862-fixup-fwd-refs afunc))
@@ -629,7 +631,9 @@
                                (cross-create-x86-function fname frag-list *x862-constant-alist* bits debug-info))
                              #-x86-target
-                             (cross-create-x86-function fname frag-list *x862-constant-alist* bits debug-info)))))))
-          (backend-remove-labels))))
-    afunc))
+                             (cross-create-x86-function fname frag-list *x862-constant-alist* bits debug-info))
+                       (x862-digest-code-notes))))))))
+      (x862-reset-code-notes)
+      (backend-remove-labels)))
+    afunc)
     
 (defun x862-make-stack (size &optional (subtype target::subtag-s16-vector))
@@ -2369,5 +2373,58 @@
       (^))))
           
-          
+(defun x862-code-coverage-entry (seg)
+ (let* ((afunc *x862-cur-afunc*)
+	(note (getf (afunc-lfun-info afunc) 'function-source-note)))
+   (when note
+     (setf (afunc-bits afunc) (%ilogior (afunc-bits afunc) (ash 1 $fbitccoverage)))
+     (with-x86-local-vinsn-macros (seg)
+       (let* ((ccreg ($ x8664::arg_x))
+	      (valreg ($ x8664::arg_z)))
+	 (! vpush-register ccreg)
+	 (! vpush-register valreg)
+	 (! ref-constant ccreg (x86-immediate-label note))
+	 (! load-t valreg)
+	 (! misc-set-c-node valreg ccreg 1)
+	 (! vpop-register valreg)
+	 (! vpop-register ccreg))))))
+
+(defx862 x862-with-code-note with-code-note (seg vreg xfer note form &aux val)
+  (when *record-pc-mapping*
+    (append-dll-node (setf (code-note-start-pc note) (make-vinsn-label nil)) seg))
+  (when *compile-code-coverage*
+    (with-x86-local-vinsn-macros (seg)
+      (x862-store-immediate seg note x8664::arg_x)
+      (! load-t x8664::arg_y)
+      (! misc-set-c-node x8664::arg_y x8664::arg_x 1)))
+  (setq val (x862-form seg vreg xfer form))
+  (when *record-pc-mapping*
+    (append-dll-node (setf (code-note-end-pc note) (make-vinsn-label nil)) seg))
+  val)
+
+
+(defun x862-digest-code-notes ()
+  (when *record-pc-mapping*
+    (flet ((address (label)
+             (when (typep label 'vinsn-label)
+               (let ((lap-label (or (vinsn-label-info label)
+                                    (compiler-bug "Missing source note label: ~s" label))))
+		 (x86-lap-label-address lap-label)))))
+      (labels ((rec (note)
+                 (when note
+                   (setf (code-note-start-pc note) (address (code-note-start-pc note)))
+                   (setf (code-note-end-pc note) (address (code-note-end-pc note)))
+                   (dolist (subnote (code-note-subform-notes note)) (rec subnote)))))
+        (rec (getf (afunc-lfun-info *x862-cur-afunc*) 'function-source-note))))))
+
+(defun x862-reset-code-notes ()
+  (when *record-pc-mapping*
+    (flet ((clear (label) (if (typep label 'vinsn-label) nil label)))
+      (labels ((rec (note)
+                 (when note
+                   (setf (code-note-start-pc note) (clear (code-note-start-pc note)))
+                   (setf (code-note-end-pc note) (clear (code-note-end-pc note)))
+                   (dolist (subnote (code-note-subform-notes note)) (rec subnote)))))
+        (rec (getf (afunc-lfun-info *x862-cur-afunc*) 'function-source-note))))))
+
 
 (defun x862-vset (seg vreg xfer type-keyword vector index value safe)
@@ -5325,6 +5382,6 @@
       (if (%vinsn-label-p v)
         (let* ((id (vinsn-label-id v)))
-          (if (typep id 'fixnum)
-            (when (or t (vinsn-label-refs v))
+          (if (or (typep id 'fixnum) (null id))
+            (when (or t (vinsn-label-refs v) (null id))
               (setf (vinsn-label-info v) (emit-x86-lap-label frag-list v)))
             (x862-expand-note frag-list id)))
@@ -5596,4 +5653,9 @@
         (! establish-fn)
         (@ (backend-get-next-label)) ; self-call label
+	(when keys ;; Ensure keyvect is the first immediate
+	  (x86-immediate-label (%cadr (%cdddr keys))))
+        (when *compile-code-coverage*
+	  (x862-code-coverage-entry seg))
+
         (unless next-method-p
           (setq method-var nil))
@@ -5644,5 +5706,4 @@
                     (unless (= nprev 0)
                       (x862-lri seg x8664::imm0 (ash nprev *x862-target-fixnum-shift*)))
-                    (x86-immediate-label keyvect)
                     (if (= 0 nprev)
                       (! simple-keywords)
Index: /branches/mb-coverage-merge/compiler/lambda-list.lisp
===================================================================
--- /branches/mb-coverage-merge/compiler/lambda-list.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/compiler/lambda-list.lisp	(revision 8519)
@@ -20,4 +20,7 @@
 
 ;;; Compiler functions needed elsewhere
+
+(defun function-source-note (fn)
+  (getf (%lfun-info (require-type fn 'function)) 'function-source-note))
 
 (defun %lfun-info-index (fn)
Index: /branches/mb-coverage-merge/compiler/nx-basic.lisp
===================================================================
--- /branches/mb-coverage-merge/compiler/nx-basic.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/compiler/nx-basic.lisp	(revision 8519)
@@ -489,3 +489,3 @@
       (cdr (assq name (defenv.structrefs defenv))))))
 
-; end
+;end
Index: /branches/mb-coverage-merge/compiler/nx.lisp
===================================================================
--- /branches/mb-coverage-merge/compiler/nx.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/compiler/nx.lisp	(revision 8519)
@@ -141,4 +141,61 @@
 
 (defparameter *load-time-eval-token* nil)
+(defparameter *nx-source-note-map* nil)
+
+(defun note-contained-in-p (note parent)
+  (loop for n = note then (code-note-source n) while (code-note-p n) thereis (eq n parent)))
+
+(defun nx-find-code-note (form parent-source)
+  ;; Try to find a source note for this form.  The act of matching up a source note with
+  ;; forms that might come from macroexpansion is heuristic at best.  In general, err in
+  ;; favor of not matching, because that leads to fewer false positives in code coverage
+  ;; reporting.  But still, try hard to match things up best we can.  The main problem is
+  ;; with atoms, which the source recording stuff doesn't track properly.
+  #| -- This doesn't work, period, it leads to too many false positives.  The problem
+    -- is that even if we have just one instance of the form in the parent source,
+    -- there might be many generated occurences that do NOT correspond to the one
+    -- in the source, and the form can be one of those, leading to false positives on the
+    -- source version.
+  (when parent-source
+    (let ((note (gethash form *nx-source-note-map*)))
+      (cond ((consp note)
+             ;; This form (typically an atom) has multiple source locations.
+             ;; At least try to distinguish occurences in different outer forms.  This allows
+             ;; reasonable code coverage reporting for "(if (test) t (other))", although it
+             ;; doesn't work for cases like "(if foo foo (other))".
+             (loop with found = nil
+               for n in note
+               ;; I tried allowing parent-source to be an indirect ancestor, but that would
+               ;; catch unrelated references in outer forms.
+               when (eq (code-note-source n) parent-source)
+               do (if found (return nil) (setq found n))
+               finally (return found)))
+            ((not (null note))
+             (when (note-contained-in-p note parent-source)
+               ;; As an aside, here's a fun code coverage issue:  What if the same source
+               ;; form (i.e. single source location) gets used multiple times. e.g.
+               ;; (macrolet ((dup (x) `(progn (foo ,x) (bar ,x)))) (dup (something))).
+               ;; We could arrange to have separate records for each instance, but as of right
+               ;; now no existing or contemplated UI has a means of showing the distinction,
+               ;; so don't bother.
+               note))
+            (t nil))))
+  |#
+  (when (and parent-source
+             (or (consp form) (vectorp form) (pathnamep form)))
+    (let ((note (gethash form *nx-source-note-map*)))
+      (unless (listp note)
+        note))))
+
+(defun nx-ensure-code-note (form original parent-note)
+  ;; Try to find a source note for this form; if can't, just make a new record for it.
+  (let* ((parent-source (loop for n = parent-note then (code-note-source n)
+                          when (or (null n) (source-note-p n)) return n))
+         (note (or (and original (nx-find-code-note original parent-source))
+                   (nx-find-code-note form parent-source)
+                   (make-code-note :form (or original form) :source parent-note))))
+    (when (and parent-note (neq note parent-note))
+      (push note (code-note-subform-notes parent-note)))
+    note))
 
 (eval-when (:compile-toplevel)
@@ -147,6 +204,5 @@
 (defparameter *nx-discard-xref-info-hook* nil)
 
-(defun compile-named-function
-    (definition &key name env keep-lambda keep-symbols policy load-time-eval-token target)
+(defun compile-named-function (definition &key name env function-note keep-lambda keep-symbols policy load-time-eval-token target source-notes)
   (when (and name *nx-discard-xref-info-hook*)
     (funcall *nx-discard-xref-info-hook* name))
@@ -154,6 +210,7 @@
    definition
    (let ((*load-time-eval-token* load-time-eval-token)
-         (env (new-lexical-environment env))
-         (*definition-source-note* (and *form-source-note-map* (gethash definition *form-source-note-map*))))
+         (*nx-source-note-map* source-notes)
+         (*definition-source-note* (and *form-source-note-map* (gethash definition *form-source-note-map*)))
+         (env (new-lexical-environment env)))
      (setf (lexenv.variables env) 'barrier)
        (let* ((*target-backend* (or (if target (find-backend target)) *host-backend*))
@@ -165,5 +222,6 @@
                       env 
                       (or policy *default-compiler-policy*)
-                      *load-time-eval-token*)))
+                      *load-time-eval-token*
+                      function-note)))
          (if (afunc-lfun afunc)
              afunc
@@ -212,16 +270,2 @@
             (defenv.functions definition-env)))
     name))
-
-(defun fcomp-named-function (def name env)
-  (let* ((env (new-lexical-environment env)))
-    (multiple-value-bind (lfun warnings)
-                         (compile-named-function def
-                                                 :name name
-                                                 :env env
-                                                 :keep-lambda *fasl-save-definitions*
-                                                 :keep-symbols *fasl-save-local-symbols*
-                                                 :policy *default-file-compilation-policy*
-                                                 :load-time-eval-token cfasl-load-time-eval-sym
-                                                 :target *fasl-target*)
-      (fcomp-signal-or-defer-warnings warnings env)
-      lfun)))
Index: /branches/mb-coverage-merge/compiler/nx0.lisp
===================================================================
--- /branches/mb-coverage-merge/compiler/nx0.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/compiler/nx0.lisp	(revision 8519)
@@ -55,5 +55,5 @@
 (defvar *nx1-fcells* nil)
 
-(defvar *nx1-operators* (make-hash-table :size 160 :test #'eq))
+(defvar *nx1-operators* (make-hash-table :size 300 :test #'eq))
 
                                          
@@ -78,4 +78,6 @@
 (defvar *nx-operators* ())
 (defvar *nx-warnings* nil)
+(defvar *nx-current-code-note* nil)
+
 
 (defvar *nx1-compiler-special-forms* nil "Real special forms")
@@ -91,5 +93,6 @@
 (defvar *cross-compiling* nil "bootstrapping")
 
-
+(defvar *compile-code-coverage* nil "True to instrument for code coverage")
+(defvar *record-pc-mapping* nil "True to record pc -> source mapping")
 
 (defparameter *nx-operator-result-types*
@@ -1270,5 +1273,6 @@
                                  parent-env
                                  (policy *default-compiler-policy*)
-                                 load-time-eval-token)
+                                 load-time-eval-token
+                                 code-note)
   (if q
      (setf (afunc-parent p) q))
@@ -1303,5 +1307,5 @@
                          (parse-body (%cddr lambda-form) *nx-lexical-environment* t)
       (setf (afunc-lambdaform p) lambda-form)
-      (setf (afunc-acode p) (nx1-lambda (%cadr lambda-form) body decls))
+      (setf (afunc-acode p) (nx1-lambda (%cadr lambda-form) body decls code-note))
       (nx1-transitively-punt-bindings *nx-punted-vars*)
       (setf (afunc-blocks p) *nx-blocks*)
@@ -1324,13 +1328,14 @@
        (consp (setq form (%cdr form)))       
        (eq (caar form) '&method)))
-         
-
-
-
-
-
-(defun nx1-lambda (ll body decls &aux (l ll) methvar)
-  (let ((old-env *nx-lexical-environment*)
-        (*nx-bound-vars* *nx-bound-vars*))
+
+
+(defun nx1-lambda (ll body decls &optional code-note &aux (l ll) methvar)
+  (when code-note
+    (setf (afunc-lfun-info *nx-current-function*)
+          (list* 'function-source-note code-note (afunc-lfun-info *nx-current-function*))))
+  (let* ((old-env *nx-lexical-environment*)
+         (*nx-bound-vars* *nx-bound-vars*)
+         (*nx-current-code-note* (and (or *compile-code-coverage* *record-pc-mapping*) code-note)))
+
     (with-nx-declarations (pending)
       (let* ((*nx-parsing-lambda-decls* t))
@@ -1342,5 +1347,5 @@
               (nx-error "invalid lambda-list  - ~s" l)))
           (return-from nx1-lambda
-                       (list
+                       (make-acode
                         (%nx1-operator lambda-list)
                         (list (cons '&lap bits))
@@ -1390,5 +1395,5 @@
          body
          *nx-new-p2decls*)))))
-  
+
 (defun nx-parse-simple-lambda-list (pending ll &aux
 					      req
@@ -1579,8 +1584,4 @@
   "The stream we're reading code to be compiled from.")
 
-(defvar *compile-file-original-truename* nil)
-
-(defvar *compile-file-original-buffer-offset* nil)
-
 (defun substream (stream start end)
   "like subseq, but on streams that support file-position. Leaves stream positioned where it was
@@ -1608,4 +1609,7 @@
 
 (defun %fast-compact (string)
+  ;; mb: bootstrap
+  (when (typep string '(array (unsigned-byte 8)))
+    (return-from %fast-compact string))
   (let ((vec (make-array (length string) :element-type '(unsigned-byte 8))))
     (loop
@@ -1630,33 +1634,4 @@
        *fcomp-stream*
        (eq *fcomp-stream* stream)))
-
-(defstruct (source-note (:constructor %make-source-note))
-  file-name
-  start
-  end
-  %text
-  form
-  children)
-
-(defun make-source-note (&key stream start end %text form children)
-  (when (record-source-location-on-stream-p stream)
-    (%make-source-note :file-name (or *compile-file-original-truename*
-                                      (truename stream))
-                       :start (+ start (or *compile-file-original-buffer-offset* 0))
-                       :end (+ end (or *compile-file-original-buffer-offset* 0))
-                       :%text %text
-                       :form form
-                       :children children)))
-
-;;; we don't actually store source-note structs in the fasl since that runs into problems dumping
-;;; the struct.
-
-(defun source-note-for-%lfun-info (note &key (start t) (end t) (text t) (form t) (children t) (file-name t))
-  (append (when start (list :start (source-note-start note)))
-          (when end   (list :end  (source-note-end   note)))
-          (when text  (list :%text (%fast-compact (source-note-%text  note))))
-          (when form  (list :form (source-note-form  note)))
-          (when children (list :children (source-note-children note)))
-          (when file-name (list :file-name (source-note-file-name note)))))
 
 (defvar *form-source-note-map* nil
@@ -1742,7 +1717,21 @@
 
 (defun nx1-typed-form (original env)
-  (nx1-transformed-form (nx-transform original env) env))
-
-(defun nx1-transformed-form (form &optional (env *nx-lexical-environment*))
+  (nx1-transformed-form (nx-transform original env) env original))
+
+(defun nx1-transformed-form (form env &optional original)
+  (if *nx-current-code-note*
+    ;; It is possible for the form to be a source form when the original is not: macros
+    ;; often insert wrappings, e.g. (when (foo) (bar)) becomes (IF (foo) (PROGN (bar))),
+    ;; and (PROGN (bar)) transforms into (bar), which is a source form.
+    (let* ((new-note (nx-ensure-code-note form original *nx-current-code-note*))
+           (*nx-current-code-note* new-note))
+      (unless new-note
+        (compiler-bug "No source note for ~s -> ~s" original form))
+      (make-acode (%nx1-operator with-code-note)
+		  new-note
+                  (nx1-transformed-form-aux form env)))
+    (nx1-transformed-form-aux form env)))
+
+(defun nx1-transformed-form-aux (form env)
   (flet ((main ()
            (if (consp form)
@@ -2186,8 +2175,11 @@
 
 (defun nx-transform (form &optional (environment *nx-lexical-environment*))
-  (let* ((startform form) sym transforms lexdefs changed enabled macro-function compiler-macro)
+  (let* (sym transforms lexdefs changed enabled macro-function compiler-macro source)
+    (when (or (null *nx-source-note-map*) (gethash form *nx-source-note-map*))
+      (setq source t))
     (tagbody
        (go START)
      LOOP
+       (unless source (setq source (gethash form *nx-source-note-map*)))
        (setq changed t)
        (when (and (consp form) 
@@ -2199,6 +2191,5 @@
 	 (multiple-value-bind (newform win) (nx-transform-symbol form environment)
 	   (unless win (go DONE))
-	   (setq form newform
-                 changed (or changed win))
+	   (setq form newform)
 	   (go LOOP)))
        (when (atom form) (go DONE))
@@ -2209,8 +2200,9 @@
            (if (constantp thing)
              (progn
-               (setq form thing form thing)
+               (setq form thing)
                (go LOOP))
              (multiple-value-bind (newform win) (nx-transform thing environment)
                (when win
+                 (unless source (setq source (gethash newform *nx-source-note-map*)))
                  (setq changed t)
                  (if (and (self-evaluating-p newform)
@@ -2233,9 +2225,14 @@
 	   (when (and enabled (functionp (fboundp sym)))
 	     (multiple-value-setq (form win) (nx-transform-arglist form environment))
-	     (if win (setq changed t)))))
+	     (when win
+               (unless source (setq source (gethash form *nx-source-note-map*)))
+               (setq changed t)))))
        (when (and enabled
 		  (not (nx-declared-notinline-p sym environment)))
 	 (multiple-value-bind (value folded) (nx-constant-fold form environment)
-	   (when folded (setq form value changed t)  (unless (and (consp form) (eq (car form) sym)) (go START))))
+	   (when folded
+             (setq form value changed t)
+             (unless source (setq source (gethash form *nx-source-note-map*)))
+             (unless (and (consp form) (eq (car form) sym)) (go START))))
 	 (when compiler-macro
 	   (multiple-value-bind (newform win) (compiler-macroexpand-1 form environment)
@@ -2254,5 +2251,6 @@
 				      (and #-bccl (boundp '%structure-refs%)
 					   (gethash sym %structure-refs%))))
-	     (setq form (defstruct-ref-transform transforms (%cdr form)) changed T)
+	     (setq form (defstruct-ref-transform transforms (%cdr form)) changed t)
+             (unless source (setq source (gethash form *nx-source-note-map*)))
 	     (go START))
 	   (when (setq transforms (assq sym *nx-synonyms*))
@@ -2264,8 +2262,10 @@
 	 (nx-record-xref-info :macro-calls (function-name macro-function))
 	 (setq form (macroexpand-1 form environment) changed t)
+         (unless source (setq source (gethash form *nx-source-note-map*)))
 	 (go START))
      DONE)
-    (when (and changed *compiler-record-source*)
-      (record-form-source-equivalent startform form))
+    (when (and source (neq source t) (not (gethash form *nx-source-note-map*)))
+      ;; Neither the initial nor final form has source, but somewhere in the middle we encountered one.
+      (setf (gethash form *nx-source-note-map*) source))
     (values form changed)))
 
Index: /branches/mb-coverage-merge/compiler/nx1.lisp
===================================================================
--- /branches/mb-coverage-merge/compiler/nx1.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/compiler/nx1.lisp	(revision 8519)
@@ -29,13 +29,14 @@
       (setq typespec '*)
       (setq typespec (nx-target-type (type-specifier ctype)))))
-  (let* ((*nx-form-type* typespec)
-         (transformed (nx-transform form env)))
-    (if (and (consp transformed)
-             (eq (car transformed) 'the))
-        (setq transformed form))
+  (let* ((*nx-form-type* typespec))
     (make-acode
      (%nx1-operator typed-form)
      typespec
-     (nx1-transformed-form transformed env))))
+     (nx1-transformed-form (let ((transformed (nx-transform form env)))
+                             (if (and (consp transformed)
+                                      (eq (car transformed) 'the))
+                               form
+                               transformed))
+                           env form))))
 
 (defnx1 nx1-struct-ref struct-ref (&whole whole structure offset)
Index: /branches/mb-coverage-merge/compiler/nxenv.lisp
===================================================================
--- /branches/mb-coverage-merge/compiler/nxenv.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/compiler/nxenv.lisp	(revision 8519)
@@ -28,4 +28,6 @@
 #+ppc-target (require "PPCENV")
 #+x8664-target (require "X8664ENV")
+
+#-BOOTSTRAPPED (unless (boundp '$lfbits-info-bit) (set '$lfbits-info-bit 2))
 
 (defconstant $afunc-size 
@@ -409,5 +411,6 @@
      (general-aref2 .  #.(logior operator-acode-subforms-mask operator-assignment-free-mask operator-single-valued-mask))
      (%single-float .  #.(logior operator-acode-subforms-mask operator-assignment-free-mask operator-single-valued-mask))
-     (%double-float . #. #.(logior operator-acode-subforms-mask operator-assignment-free-mask operator-single-valued-mask)))))
+     (%double-float . #. #.(logior operator-acode-subforms-mask operator-assignment-free-mask operator-single-valued-mask))
+     (with-code-note . #.(logior operator-assignment-free-mask)))))
 
 (defmacro %nx1-operator (sym)
@@ -470,4 +473,5 @@
 (defconstant $fbitruntimedef 8)
 (defconstant $fbitnonnullenv 9)
+(defconstant $fbitccoverage 10)
 
 (defconstant $eaclosedbit 24)
Index: /branches/mb-coverage-merge/compiler/optimizers.lisp
===================================================================
--- /branches/mb-coverage-merge/compiler/optimizers.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/compiler/optimizers.lisp	(revision 8519)
@@ -544,13 +544,11 @@
 (define-compiler-macro if (&whole call test true &optional false &environment env)
   (multiple-value-bind (test test-win) (nx-transform test env)
-    (multiple-value-bind (true true-win) (nx-transform true env)
-      (multiple-value-bind (false false-win) (nx-transform false env)
-        (if (or (quoted-form-p test) (self-evaluating-p test))
-          (if (eval test) 
-            true
-            false)
-          (if (or test-win true-win false-win)
-            `(if ,test ,true ,false)
-            call))))))
+    (if (or (quoted-form-p test) (self-evaluating-p test))
+      (if (eval test) 
+        true
+        false)
+      (if test-win
+        `(if ,test ,@(cddr call))
+        call))))
 
 (define-compiler-macro %ilsr (&whole call &environment env shift value)
Index: /branches/mb-coverage-merge/level-0/nfasload.lisp
===================================================================
--- /branches/mb-coverage-merge/level-0/nfasload.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/level-0/nfasload.lisp	(revision 8519)
@@ -687,4 +687,17 @@
   (provide (%fasl-expr s)))    
 
+
+;;; files compiled with code coverage do this
+;; list of lfuns and (source-fn-name . vector-of-lfuns), the latter put there by fasloading.
+(defvar *code-covered-functions* nil)
+
+(defun register-code-covered-functions (functions)
+  (let ((a (assoc (pathname *loading-file-source-file*)
+                  *code-covered-functions*
+                  :test #'equalp)))
+    (when (null a)
+      (push (setq a (list nil nil)) *code-covered-functions*))
+    (setf (car a) *loading-file-source-file* (cdr a) functions)
+    nil))
 
 ;;; The loader itself
Index: /branches/mb-coverage-merge/level-1/l1-aprims.lisp
===================================================================
--- /branches/mb-coverage-merge/level-1/l1-aprims.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/level-1/l1-aprims.lisp	(revision 8519)
@@ -964,5 +964,5 @@
              (and (not (logbitp $lfbits-gfn-bit bits))
                   (not (logbitp $lfbits-cm-bit bits))))
-         (nth-immediate lfun 1))))
+	 (nth-immediate lfun 1))))
 
 
Index: /branches/mb-coverage-merge/level-1/l1-boot-2.lisp
===================================================================
--- /branches/mb-coverage-merge/level-1/l1-boot-2.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/level-1/l1-boot-2.lisp	(revision 8519)
@@ -267,4 +267,5 @@
       (bin-load-provide "DESCRIBE" "describe")
       (bin-load-provide "SOURCE-FILES" "source-files")
+      (bin-load-provide "COVER" "cover")
       (bin-load-provide "MCL-COMPAT" "mcl-compat")
       (require "LOOP")
Index: /branches/mb-coverage-merge/level-1/l1-init.lisp
===================================================================
--- /branches/mb-coverage-merge/level-1/l1-init.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/level-1/l1-init.lisp	(revision 8519)
@@ -260,4 +260,5 @@
 (defparameter *save-definitions* t)
 (defparameter *save-local-symbols* t)
+(defparameter *save-source-locations* nil)
 
 (defvar *modules* nil
Index: /branches/mb-coverage-merge/level-1/l1-reader.lisp
===================================================================
--- /branches/mb-coverage-merge/level-1/l1-reader.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/level-1/l1-reader.lisp	(revision 8519)
@@ -2476,47 +2476,42 @@
   (let* ((readtable *readtable*)
          (attrtab (rdtab.ttab readtable))
-         (attr (%character-attribute firstchar attrtab)))
+         (attr (%character-attribute firstchar attrtab))
+         (start-pos (file-position stream)))
     (declare (fixnum attr))
-    (if (= attr $cht_ill)
+    (if (eql attr $cht_ill)
         (signal-reader-error stream "Illegal character ~S." firstchar))
-    (with-read-source-tracking (stream start end)
-      (let* ((vals (multiple-value-list 
-                       (if (not (logbitp $cht_macbit attr))
-                           (%parse-token stream firstchar dot-ok)
-                           (let* ((def (cdr (assq firstchar (rdtab.alist readtable)))))
-                             (cond ((null def))
-                                   ((atom def)
-                                    (funcall def stream firstchar))
-                                   #+no ; include if %initial-readtable% broken (see above)
-                                   ((and (consp (car def))
-                                         (eq (caar def) 'function))
-                                    (funcall (cadar def) stream firstchar))
-                                   ((functionp (car def))
-                                    (funcall (car def) stream firstchar))
-                                   (t (error "Bogus default dispatch fn: ~S" (car def)) nil)))))))
-        (declare (dynamic-extent vals)
-                 (list vals))
-        (if (null vals)
-            (values nil nil nil)            
-            (destructuring-bind (form &optional nested-source-notes)
-                vals
-              (values form
-                      t
-                      (when (and (not (eql t nested-source-notes))
-                                 (consp form)
-                                 (record-source-location-on-stream-p stream))
-                        ;; mb 2008-02-07: sometime the nested-source-notes end with t, don't know
-                        ;; why. don't really care here.
-                        (make-source-note :stream stream
-                                          :start (1- start)
-                                          :end end
-                                          :form (car vals)
-                                          :children (if nested-source-notes
-                                                      (let ((last (last nested-source-notes)))
-                                                        (when (atom (cdr last))
-                                                          ;; dotted list.
-                                                          (setf (cdr last) (list (cdr last))))
-                                                        nested-source-notes)
-                                                      '()))))))))))
+    (let* ((vals (multiple-value-list 
+                  (if (not (logbitp $cht_macbit attr))
+                    (%parse-token stream firstchar dot-ok)
+                    (let* ((def (cdr (assq firstchar (rdtab.alist readtable)))))
+                      (cond ((null def))
+                            ((atom def)
+                             (funcall def stream firstchar))
+                            #+no ; include if %initial-readtable% broken (see above)
+                            ((and (consp (car def))
+                                  (eq (caar def) 'function))
+                             (funcall (cadar def) stream firstchar))
+                            ((functionp (car def))
+                             (funcall (car def) stream firstchar))
+                            (t (error "Bogus default dispatch fn: ~S" (car def)) nil))))))
+           (end-pos (and start-pos (file-position stream))))
+      (declare (dynamic-extent vals)
+               (list vals))
+      (if (null vals)
+        (values nil nil)
+        (destructuring-bind (form &optional nested-source-notes)
+                            vals
+          ;; Can't really trust random reader macros to return source notes...
+          (unless (and (consp nested-source-notes)
+                       (source-note-p (car nested-source-notes)))
+            (setq nested-source-notes nil))
+          (values form
+                  t
+                  (and start-pos
+                       (make-source-note :form form
+                                         :stream stream
+                                         :start-pos (1- start-pos)
+                                         :end-pos end-pos
+                                         :subform-notes nested-source-notes))))))))
 
 #|
@@ -2545,6 +2540,5 @@
          (head (cons nil nil))
          (tail head)
-         (source-note-list-head (cons nil nil))
-         (source-note-list-tail source-note-list-head))
+         (source-note-list nil))
     (declare (dynamic-extent dot-ok head)
              (list head tail))
@@ -2552,29 +2546,29 @@
     (multiple-value-bind (firstform firstform-p firstform-source-note)
         (%read-list-expression stream dot-ok termch)
+      (when firstform-source-note
+        (push firstform-source-note source-note-list))
       (when firstform-p
         (if (and dot-ok (eq firstform dot-ok))       ; just read a dot
             (signal-reader-error stream "Dot context error."))
-        (rplacd source-note-list-tail (setq source-note-list-tail (cons firstform-source-note nil)))
         (rplacd tail (setq tail (cons firstform nil)))
         (loop
           (multiple-value-bind (nextform nextform-p nextform-source-note)
               (%read-list-expression stream dot-ok termch)
+            (when nextform-source-note
+              (push nextform-source-note source-note-list))
             (if (not nextform-p) (return))
             (if (and dot-ok (eq nextform dot-ok))    ; just read a dot
                 (if (multiple-value-bind (lastform lastform-p lastform-source-note)
                         (%read-list-expression stream nil termch)
+                      (when lastform-source-note
+                        (push lastform-source-note source-note-list))
                       (and lastform-p
                            (progn (rplacd tail lastform)
-                                  (rplacd source-note-list-tail lastform-source-note)
                                   (not (nth-value 1 (%read-list-expression stream nil termch))))))
                     (return)
                     (signal-reader-error stream "Dot context error."))
                 (progn
-                  (rplacd source-note-list-tail (setq source-note-list-tail (cons nextform-source-note nil)))
                   (rplacd tail (setq tail (cons nextform nil)))))))))
-    
-    (if (record-source-location-on-stream-p stream)
-        (values (cdr head) (cdr source-note-list-head))
-        (values (cdr head)))))
+    (values (cdr head) source-note-list)))
 
 #|
@@ -2886,5 +2880,5 @@
   (setq stream (input-stream-arg stream))
   (if recursive-p
-    (%read-form stream 0 nil)
+    (%read-form stream (if eof-error-p 0) nil)
     (let ((%read-objects% nil) (%keep-whitespace% nil))
       (%read-form stream (if eof-error-p 0) eof-value))))
@@ -2952,13 +2946,13 @@
         (let* ((ch (%next-non-whitespace-char-and-attr stream)))
           (if (null ch)
-              (if arg 
-                  (error 'end-of-file :stream stream)
-                  (return eof-val))
-              (multiple-value-bind (form form-p source-note)
-                  (%parse-expression stream ch nil)
-                (when form-p
-                  (return
-                    (values (if *read-suppress* nil form)
-                            source-note)))))))))
+            (if arg 
+              (error 'end-of-file :stream stream)
+              (return eof-val))
+            (multiple-value-bind (form form-p source-note)
+                (%parse-expression stream ch nil)
+              (when form-p
+                (return
+                 (values (if *read-suppress* nil form)
+                         source-note)))))))))
 
 ;;;Until load backquote...
@@ -2989,5 +2983,158 @@
 
 
-
-
-
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defstruct (code-note (:constructor %make-code-note))
+  ;; Code coverage state.  This MUST be the first slot - see nx2-code-coverage.
+  code-coverage
+  ;; The actual form - useful during debugging, perhaps remove later.
+  form
+  ;; For the outermost source form, a string (the text of the form).
+  ;; For an inner source form, the source-note of the outer source form.
+  ;; For a random code form (no file info, generated by macros or other source
+  ;; transform), code-note of parent form
+  source
+  ;; PC information generated by compiler.  For source notes not stored in
+  ;; an lfun, it could contain intermediate results during compilation.
+  start-pc
+  end-pc
+  ;; Notes for code-generating subforms of this form
+  subform-notes)
+
+(defstruct (source-note (:include code-note)
+			(:constructor %make-source-note))
+  ;; The source location: file name, and start/end offsets within the file
+  file-name
+  start-pos
+  end-pos)
+
+;;; we don't actually store source-note structs in the fasl since that runs into problems dumping
+;;; the struct.
+(defun source-note-for-%lfun-info (note &key (start t) (end t) (text t) (form t) (children t) (file-name t))
+  (append (when start (list :start (source-note-start note)))
+          (when end   (list :end  (source-note-end   note)))
+          (when text  (list :%text (%fast-compact (source-note-%text  note))))
+          (when form  (list :form (source-note-form  note)))
+          (when children (list :children (source-note-children note)))
+          (when file-name (list :file-name (source-note-file-name note)))))
+
+(defun source-note-from-%lfun-info (lfun-info)
+  (let ((note-plist (getf lfun-info 'function-source-note)))
+    (%make-source-note :file-name (getf note-plist :file-name)
+                       :start-pos (getf note-plist :start)
+                       :end-pos (getf note-plist :end)
+                       :text (%fast-uncompact (getf note-plist :%text)))))
+
+
+(defmethod make-load-form ((note code-note) &optional env)
+  (make-load-form-saving-slots note :environment env))
+
+(defmethod print-object ((note code-note) stream)
+  (print-unreadable-object (note stream :type t :identity t)
+    (let ((text (and (source-note-p note) (ignore-errors (source-note-text note)))))
+      (when (and (null text) (code-note-form note))
+        (setq text (ignore-errors
+                    (let ((*print-circle* t))
+                      (format nil "~s" (code-note-form note))))))
+      (when (> (length text) 20)
+        (let ((end (position #\Newline text :start 20)))
+          (when (or end (> (length text) 120))
+            (setq text (concatenate 'string
+                                    (subseq text 0 (min (or end (length text)) 120))
+                                    "...")))))
+      (format stream "[~s]~:[~; for ~:*~a~] (~s subforms)"
+              (code-note-code-coverage note)
+              text
+              (length (code-note-subform-notes note))))))
+
+(defun source-note-length (note)
+  (- (source-note-end-pos note) (source-note-start-pos note)))
+
+(defun source-note-text (note)
+  (multiple-value-bind (string offset) (source-note-string-and-offset note)
+    (when string
+      (subseq string offset (+ offset (source-note-length note))))))
+
+(defun source-note-string-and-offset (note)
+  "Returns a string and offset where the text of note's form starts"
+  (when (source-note-p note)
+    (let ((source (source-note-source note)))
+      (cond ((stringp source)
+             (assert (<= (source-note-length note) (length source)))
+             (values source 0))
+            ((source-note-p source)
+             (let ((start (source-note-start-pos note))
+                   (parent-start (source-note-start-pos source)))
+               (assert (<= parent-start start
+                           (source-note-end-pos note) (source-note-end-pos source)))
+               (multiple-value-bind (parent-string parent-offset)
+                                    (source-note-string-and-offset source)
+                 (values parent-string (+ parent-offset (- start parent-start))))))))))
+
+(defvar *recording-source-streams* ())
+
+(defun read-recording-source (stream &key eofval file-name start-offset map)
+  "Read a top-level form, perhaps recording source location.
+If MAP is NIL, just reads a form as if by READ.
+If MAP is non-NIL, returns a second value of a source-note describing the form.
+In addition, if MAP is a hash table, it gets filled with source-note's for all
+non-atomic nested forms."
+  (typecase map
+    (null (values (read-internal stream nil eofval nil) nil))
+    (hash-table
+     (let* ((recording (list stream map file-name (or start-offset 0)))
+            (*recording-source-streams* (cons recording *recording-source-streams*)))
+       (declare (dynamic-extent recording *recording-source-streams*))
+       (multiple-value-bind (form source-note) (read-internal stream nil eofval nil)
+         (when (and source-note (not (eq form eofval)))
+           (assert (null (source-note-source source-note)))
+           (let ((text (make-string (source-note-length source-note)))
+                 (pos (file-position stream)))
+             (file-position stream (- (source-note-start-pos source-note) start-offset))
+             (read-sequence text stream)
+             (file-position stream pos)
+             (setf (source-note-source source-note) text)))
+         (values form source-note))))
+    (t (let* ((start (file-position stream))
+              (form (read-internal stream nil eofval nil)))
+         (values form (and (neq form eofval)
+                           (%make-source-note :form form
+                                              :file-name file-name
+                                              :start-pos (+ (or start-offset 0) start)
+                                              :end-pos (+ (or start-offset 0) (file-position stream)))))))))
+
+(defun make-source-note (&key form stream start-pos end-pos subform-notes)
+  (let ((recording (assoc stream *recording-source-streams*)))
+    (when (and recording (not *read-suppress*))
+      (destructuring-bind (map file-name stream-offset) (cdr recording)
+        (let* ((prev (gethash form map))
+               (note (%make-source-note :form form
+                                        :file-name file-name
+                                        :start-pos (+ stream-offset start-pos)
+                                        :end-pos (+ stream-offset end-pos))))
+          (setf (gethash form map)
+                (cond ((null prev) note)
+                      ((consp prev) (cons note prev))
+                      (t (list note prev))))
+          (loop for sub in subform-notes as subnote = (require-type sub 'source-note)
+            do (when (source-note-source subnote) (error "Subnote ~s already owned?" subnote))
+            do (setf (source-note-source subnote) note))
+          note)))))
+
+(defun make-code-note (&key form source)
+  (declare (ignorable form))
+  ;; A note for a form generated by macroexpansion
+  (let* ((source (and source (require-type source 'code-note)))
+         (note (%make-code-note
+                ;; Unfortunately, recording the macroexpanded form is problematic, since they
+                ;; can have references to non-dumpable forms, see e.g. loop.
+                ;; Could print it and record the string instead.
+                ;; :form form
+                :source source)))
+    #+debug
+    (when form
+      (setf (code-note-form note)
+            (with-output-to-string (s) (let ((*print-string-length* 80)) (prin1 form s)))))
+    note))
+
+; end
Index: /branches/mb-coverage-merge/lib/backquote.lisp
===================================================================
--- /branches/mb-coverage-merge/lib/backquote.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/lib/backquote.lisp	(revision 8519)
@@ -369,5 +369,5 @@
                   (let ((*backquote-stack* (list* |`,| |`,.| |`,@| *backquote-stack*)))
                     (read stream t nil t)))))
-    (if *backquote-expand* (macroexpand-1 form) form))))
+    (if *backquote-expand* (values (macroexpand-1 form)) form))))
 
 (set-macro-character 
Index: /branches/mb-coverage-merge/lib/compile-ccl.lisp
===================================================================
--- /branches/mb-coverage-merge/lib/compile-ccl.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/lib/compile-ccl.lisp	(revision 8519)
@@ -194,4 +194,5 @@
 	edit-callers
         describe
+        cover
 	asdf
 	defsystem
Index: /branches/mb-coverage-merge/lib/db-io.lisp
===================================================================
--- /branches/mb-coverage-merge/lib/db-io.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/lib/db-io.lisp	(revision 8519)
@@ -986,17 +986,19 @@
 (defun %read-symbol-preserving-case (stream package)
   (let* ((case (readtable-case *readtable*))
-         query error sym source
-         (*package* package))
-    (unwind-protect
-         (progn
-           (setf (readtable-case *readtable*) :preserve)
-           (when (eq #\? (peek-char t stream nil nil))
-             (setq query t)
-             (read-char stream))
-           (multiple-value-setq (sym source error)
-             (handler-case
-                 (read-internal stream nil t nil)
-               (error (condition) (values nil nil condition)))))
-      (setf (readtable-case *readtable*) case))
+         (query nil)
+	 (error nil)
+	 (sym nil)
+         (source nil))
+    (let* ((*package* package))
+      (unwind-protect
+	   (progn
+	     (setf (readtable-case *readtable*) :preserve)
+             (when (eq #\? (peek-char t stream nil nil))
+               (setq query t)
+               (read-char stream))
+	     (multiple-value-setq (sym source error)
+	       (handler-case (read-internal stream nil t nil)
+		 (error (condition) (values nil nil condition)))))
+	(setf (readtable-case *readtable*) case)))
     (when error
       (error error))
@@ -1015,23 +1017,23 @@
          (etypecase sym
            (symbol
-              (if query
-                  (values (load-os-constant sym query) source)
-                  (progn
-                    (when (eq (symbol-package sym) package)
-                      (unless arg (setq arg 0))
-                      (ecase arg
-                        (0
-                           (unless (and (constant-symbol-p sym)
-                                        (not (eq (%sym-global-value sym)
-                                                 (%unbound-marker-8))))
-                             (load-os-constant sym)))
-                        (1 (makunbound sym) (load-os-constant sym))))
-                    (values sym source))))
+            (if query
+              (values (load-os-constant sym query) source)
+              (progn
+                (when (eq (symbol-package sym) package)
+                  (unless arg (setq arg 0))
+                  (ecase arg
+                    (0
+                     (unless (and (constant-symbol-p sym)
+                                  (not (eq (%sym-global-value sym)
+                                           (%unbound-marker-8))))
+                       (load-os-constant sym)))
+                    (1 (makunbound sym) (load-os-constant sym))))
+                (values sym source))))
            (string
-              (let* ((val 0)
-                     (len (length sym)))
-                (dotimes (i 4 (values val source))
-                  (let* ((ch (if (< i len) (char sym i) #\space)))
-                    (setq val (logior (ash val 8) (char-code ch)))))))))))))
+            (let* ((val 0)
+                   (len (length sym)))
+              (dotimes (i 4 (values val source))
+                (let* ((ch (if (< i len) (char sym i) #\space)))
+                  (setq val (logior (ash val 8) (char-code ch)))))))))))))
 
 (set-dispatch-macro-character #\# #\_
@@ -1046,12 +1048,12 @@
         (unless (and sym (symbolp sym)) (report-bad-arg sym 'symbol))
         (if query
-            (values (load-external-function sym t) source)
-            (let* ((def (if (eql arg 0)
-                            (gethash sym (ftd-external-function-definitions
-                                          *target-ftd*)))))
-              (values (if (and def (eq (macro-function sym) #'%external-call-expander))
-                          sym
-                          (load-external-function sym nil))
-                      source)))))))
+          (values (load-external-function sym t) source)
+          (let* ((def (if (eql arg 0)
+                        (gethash sym (ftd-external-function-definitions
+                                      *target-ftd*)))))
+            (values (if (and def (eq (macro-function sym) #'%external-call-expander))
+                      sym
+                      (load-external-function sym nil))
+                    source)))))))
 
 (set-dispatch-macro-character
Index: /branches/mb-coverage-merge/lib/defstruct-lds.lisp
===================================================================
--- /branches/mb-coverage-merge/lib/defstruct-lds.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/lib/defstruct-lds.lisp	(revision 8519)
@@ -257,5 +257,4 @@
          ,(if (and predicate (null (sd-type sd))) `',predicate)
          ,.(if documentation (list documentation)))
-        (record-source-file ',(sd-name sd) 'structure)
         ,(%defstruct-compile sd refnames)
        ;; Wait until slot accessors are defined, to avoid
Index: /branches/mb-coverage-merge/lib/defstruct.lisp
===================================================================
--- /branches/mb-coverage-merge/lib/defstruct.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/lib/defstruct.lisp	(revision 8519)
@@ -97,4 +97,5 @@
     (set-documentation name 'type doc))  
   (puthash name %defstructs% sd)
+  (record-source-file name 'structure)
   (when (and predicate (null (sd-type sd)))
     (puthash predicate %structure-refs% name))  
Index: /branches/mb-coverage-merge/lib/encapsulate.lisp
===================================================================
--- /branches/mb-coverage-merge/lib/encapsulate.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/lib/encapsulate.lisp	(revision 8519)
@@ -585,12 +585,12 @@
 
 (defmacro with-traces (syms &body body)
-  `(unwind-protect
-        (progn
-          (let ((*trace-output* (make-broadcast-stream)))
-            ;; if you're tracing ccl internals you'll get trace output as it encapsulates the
-            ;; functions so hide all the trace output while eval'ing teh trace form itself.
-            (trace ,@syms))
-          ,@body)
-     (untrace ,@syms)))
+ `(unwind-protect
+       (progn
+         (let ((*trace-output* (make-broadcast-stream)))
+           ;; if you're tracing ccl internals you'll get trace output as it encapsulates the
+           ;; functions so hide all the trace output while eval'ing the trace form itself.
+           (trace ,@syms))
+         ,@body)
+    (untrace ,@syms)))
 
 ;; this week def is the name of an uninterned gensym whose fn-cell is original def
Index: /branches/mb-coverage-merge/lib/nfcomp.lisp
===================================================================
--- /branches/mb-coverage-merge/lib/nfcomp.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/lib/nfcomp.lisp	(revision 8519)
@@ -30,4 +30,12 @@
 (require 'defstruct-macros)
 
+#-BOOTSTRAPPED (unless (fboundp 'read-recording-source)
+                 (defun read-internal (stream &optional eof-error-p eofval recursive-p)
+                   (read stream eof-error-p eofval recursive-p))
+                 (defun read-recording-source (stream &key eofval file-name start-offset map)
+                   (read stream nil eofval nil)))
+#-BOOTSTRAPPED (defvar *save-source-locations* nil)
+#-BOOTSTRAPPED (defvar *record-pc-mapping* nil)
+#-BOOTSTRAPPED (defvar *compile-code-coverage* nil)
 
 (defmacro short-fixnum-p (fixnum)
@@ -60,4 +68,12 @@
   "The TRUENAME of the file currently being compiled, or NIL if not
   compiling.") ; truename ...
+(defvar *compile-file-original-truename* nil
+  "The name to use for recording source locations. Should not be set
+directly, intsead use the :compile-file-original-truename parameter to
+cl:compile-file.")
+(defvar *compile-file-original-buffer-offset* nil
+  "Start offset to use for recording source locations. Should not be
+set directly, instead use the :compile-file-original-buffer-offset
+parameter to cl:compile-file.")
 (defvar *fasl-target* (backend-name *host-backend*))
 (defvar *fasl-backend* *host-backend*)
@@ -100,7 +116,40 @@
                      *.fasl-pathname*) 
                    pathname))
+(defvar *fasl-save-source-locations*)
+
+(defun compile-file (src &key output-file
+                         (verbose *compile-verbose*)
+                         (print *compile-print*)
+                         load
+                         features
+                         (target *fasl-target* target-p)
+                         (save-local-symbols *fasl-save-local-symbols*)
+                         (save-doc-strings *fasl-save-doc-strings*)
+                         (save-definitions *fasl-save-definitions*)
+                         (save-source-locations *save-source-locations*)
+			 (external-format :default)
+                         force
+                         compile-file-original-truename
+                         (compile-file-original-buffer-offset 0))
+  "Compile INPUT-FILE, producing a corresponding fasl file and returning
+   its filename."
+  (let* ((backend *target-backend*))
+    (when (and target-p (not (setq backend (find-backend target))))
+      (warn "Unknown :TARGET : ~S.  Reverting to ~s ..." target *fasl-target*)
+      (setq target *fasl-target*  backend *target-backend*))
+    (loop
+	(restart-case
+	 (return (%compile-file src output-file verbose print load features
+				save-local-symbols save-doc-strings save-definitions save-source-locations force backend external-format
+                                compile-file-original-truename compile-file-original-buffer-offset))
+	 (retry-compile-file ()
+			     :report (lambda (stream) (format stream "Retry compiling ~s" src))
+			     nil)
+	 (skip-compile-file ()
+			    :report (lambda (stream) (format stream "Skip compiling ~s" src))
+			    (return))))))
 
 (defun %compile-file (src output-file verbose print load features
-                          save-local-symbols save-doc-strings save-definitions force target-backend external-format
+                          save-local-symbols save-doc-strings save-definitions save-source-locations force target-backend external-format
                           compile-file-original-truename compile-file-original-buffer-offset
 			  &aux orig-src)
@@ -135,4 +184,5 @@
              (*fasl-deferred-warnings* nil) ; !!! WITH-COMPILATION-UNIT ...
              (*fasl-save-local-symbols* save-local-symbols)
+             (*fasl-save-source-locations* save-source-locations)
              (*fasl-save-doc-strings* save-doc-strings)
              (*fasl-save-definitions* save-definitions)
@@ -172,35 +222,4 @@
               *fasl-non-style-warnings-signalled-p*))))
 
-(defun compile-file (src &key output-file
-                         (verbose *compile-verbose*)
-                         (print *compile-print*)
-                         load
-                         features
-                         (target *fasl-target* target-p)
-                         (save-local-symbols *fasl-save-local-symbols*)
-                         (save-doc-strings *fasl-save-doc-strings*)
-                         (save-definitions *fasl-save-definitions*)
-			 (external-format :default)
-                         force
-                         compile-file-original-truename
-                         (compile-file-original-buffer-offset 0))
-  "Compile INPUT-FILE, producing a corresponding fasl file and returning
-   its filename."
-  (let* ((backend *target-backend*))
-    (when (and target-p (not (setq backend (find-backend target))))
-      (warn "Unknown :TARGET : ~S.  Reverting to ~s ..." target *fasl-target*)
-      (setq target *fasl-target*  backend *target-backend*))
-    (loop
-	(restart-case
-	 (return (%compile-file src output-file verbose print load features
-				save-local-symbols save-doc-strings save-definitions force backend external-format
-                                compile-file-original-truename compile-file-original-buffer-offset))
-	 (retry-compile-file ()
-			     :report (lambda (stream) (format stream "Retry compiling ~s" src))
-			     nil)
-	 (skip-compile-file ()
-			    :report (lambda (stream) (format stream "Skip compiling ~s" src))
-			    (return))))))
-
 (defvar *fcomp-locked-hash-tables*)
 (defvar *fcomp-load-forms-environment* nil)
@@ -287,4 +306,6 @@
 ;;;;          with read packages.
 
+(defparameter *fasl-eof-forms* nil)
+
 (defparameter cfasl-load-time-eval-sym (make-symbol "LOAD-TIME-EVAL"))
 (%macro-have cfasl-load-time-eval-sym
@@ -318,4 +339,6 @@
 (defvar *fcomp-output-list*)
 (defvar *fcomp-toplevel-forms*)
+(defvar *fcomp-source-note-map* nil) ;; init to nil as might be ref'd outside read loop by load forms
+(defvar *fcomp-covered-functions*)
 (defvar *fcomp-warnings-header*)
 (defvar *fcomp-stream-position* nil)
@@ -392,9 +415,11 @@
            (*fcomp-toplevel-forms* '())
            (*loading-file-source-file* (namestring orig-file)) ; why orig-file???
+           (*fcomp-source-note-map* (and (or *record-pc-mapping* *compile-code-coverage*)
+                                         (make-hash-table)))
+           (*fcomp-covered-functions* nil)
            (eofval (cons nil nil))
            (read-package nil)
-           *form-source-note-map*
-           (*nx1-source-note-map* (make-hash-table)))
-      (declare (special *fcomp-toplevel-forms* *fasl-source-file*))
+           form source-note)
+      (declare (special *fasl-eof-forms* *fcomp-toplevel-forms* *fasl-source-file*))
       ;;This should really be something like `(set-loading-source
       ;;,filename) but then couldn't compile level-1 with this...  ->
@@ -419,18 +444,28 @@
                                 (format *error-output* "~&Read error between positions ~a and ~a in ~a." pos (file-position *fcomp-stream*) filename)
                                 (signal c))))
-                  (multiple-value-bind (-form source-note)
-                      (read-internal *fcomp-stream* nil eofval nil)
-                    (when (eq -form eofval)
-                      (return))
-                    (setf form -form
-                          *form-source-note-map* (make-source-note-form-map
-                                                  (compute-children-text source-note *fcomp-stream* (make-hash-table :test 'eq))))))))            
-            (fcomp-form form env processing-mode)
+		  (when *fcomp-source-note-map*
+		    ;; Hack to keep from sharing inline function source notes...
+		    (clrhash *fcomp-source-note-map*))
+                  (multiple-value-setq (form source-note)
+                    (read-recording-source *fcomp-stream*
+                                           :eofval eofval
+                                           :file-name (or *compile-file-original-truename* *loading-file-source-file*)
+                                           :start-offset (or *compile-file-original-buffer-offset* 0)
+                                           :map (or *fcomp-source-note-map*
+                                                    (and *fasl-save-source-locations* t)))))))
+            (when (eq eofval form) (return))
+            (fcomp-form form env processing-mode source-note)
             (setq *fcomp-previous-position* *fcomp-stream-position*))))
+      (when *fcomp-covered-functions*
+        (let ((v (nreverse (coerce *fcomp-covered-functions* 'vector))))
+          (fcomp-random-toplevel-form `(register-code-covered-functions ',v) env nil)))
+      (while (setq form *fasl-eof-forms*)
+        (setq *fasl-eof-forms* nil)
+        (fcomp-form-list form env processing-mode nil))
       (when old-file
         (fcomp-output-form $fasl-src env (namestring *compile-file-pathname*)))
       (fcomp-compile-toplevel-forms env))))
 
-(defun fcomp-form (form env processing-mode
+(defun fcomp-form (form env processing-mode &optional source-note
                         &aux print-stuff 
                         (load-time (and processing-mode (neq processing-mode :compile-time)))
@@ -471,28 +506,19 @@
                              "  (Compiletime)"
                              "")))))))
-    (fcomp-form-1 form env processing-mode)))
-
-(defun record-form-source-equivalent/list (form list)
-  (dolist (f list)
-    (record-form-source-equivalent form f)))
-
-(defun fcomp-form-1 (form env processing-mode &aux sym body)
+    (fcomp-form-1 form env processing-mode source-note)))
+
+(defun fcomp-form-1 (form env processing-mode &optional source-note &aux sym body)
   (if (consp form) (setq sym (%car form) body (%cdr form)))
   (case sym
     (progn
-      (record-form-source-equivalent/list form body)
-      (fcomp-form-list body env processing-mode))
+      (fcomp-form-list body env processing-mode source-note))
     (eval-when
-      (record-form-source-equivalent/list form body)
-      (fcomp-eval-when body env processing-mode))
+      (fcomp-eval-when body env processing-mode source-note))
     (compiler-let
-      (record-form-source-equivalent/list form body)
-      (fcomp-compiler-let body env processing-mode))
+      (fcomp-compiler-let body env processing-mode source-note))
     (locally
-      (record-form-source-equivalent/list form body)
-      (fcomp-locally body env processing-mode))
+      (fcomp-locally body env processing-mode source-note))
     (macrolet
-      (record-form-source-equivalent/list form body)
-      (fcomp-macrolet body env processing-mode))
+      (fcomp-macrolet body env processing-mode source-note))
     ((%include include) (fcomp-include form env processing-mode))
     (t
@@ -503,21 +529,17 @@
      (cond 
        ((and (non-nil-symbol-p sym)
-             (macro-function sym env)            
+             (macro-function sym env)
              (not (compiler-macro-function sym env))
              (not (eq sym '%defvar-init)) ;  a macro that we want to special-case
-             (multiple-value-bind (new win)
-                 (macroexpand-1 form env)
-               (if win
-                   (progn
-                    (record-form-source-equivalent form new)
-                    (setf form new)))
+             (multiple-value-bind (new win) (macroexpand-1 form env)
+               (when win
+                 (setq form new))
                win))
-        (fcomp-form form env processing-mode))
+        (fcomp-form form env processing-mode source-note))
        ((and (not *fcomp-inside-eval-always*)
              (memq sym *fcomp-eval-always-functions*))
         (let* ((*fcomp-inside-eval-always* t)
                (new `(eval-when (:execute :compile-toplevel :load-toplevel) ,form)))
-          (record-form-source-equivalent form new)
-          (fcomp-form-1 new env processing-mode)))
+          (fcomp-form-1 new env processing-mode source-note)))
        (t
         (when (or (eq processing-mode :compile-time) (eq processing-mode :compile-time-too))
@@ -525,21 +547,20 @@
         (when (and processing-mode (neq processing-mode :compile-time))
           (case sym
-            ((%defconstant) (fcomp-load-%defconstant form env))
-            ((%defparameter) (fcomp-load-%defparameter form env))
-            ((%defvar %defvar-init) (fcomp-load-defvar form env))
-            ((%defun) (fcomp-load-%defun form env))
+            ((%defconstant) (fcomp-load-%defconstant form env source-note))
+            ((%defparameter) (fcomp-load-%defparameter form env source-note))
+            ((%defvar %defvar-init) (fcomp-load-defvar form env source-note))
+            ((%defun) (fcomp-load-%defun form env source-note))
             ((set-package %define-package)
-             (fcomp-random-toplevel-form form env)
+             (fcomp-random-toplevel-form form env source-note)
              (fcomp-compile-toplevel-forms env))
-            ((%macro) (fcomp-load-%macro form env))
-            ;; ((%deftype) (fcomp-load-%deftype form))
-            ;; ((define-setf-method) (fcomp-load-define-setf-method form))
-            (t (fcomp-random-toplevel-form form env)))))))))
-
-(defun fcomp-form-list (forms env processing-mode)
-  (dolist (form forms)
-    (fcomp-form form env processing-mode)))
-
-(defun fcomp-compiler-let (form env processing-mode &aux vars varinits)
+            ((%macro) (fcomp-load-%macro form env source-note))
+            ;; ((%deftype) (fcomp-load-%deftype form source-note))
+            ;; ((define-setf-method) (fcomp-load-define-setf-method form source-note))
+            (t (fcomp-random-toplevel-form form env source-note)))))))))
+
+(defun fcomp-form-list (forms env processing-mode source-note)
+  (dolist (form forms) (fcomp-form form env processing-mode source-note)))
+
+(defun fcomp-compiler-let (form env processing-mode source-note &aux vars varinits)
   (fcomp-compile-toplevel-forms env)
   (dolist (pair (pop form))
@@ -547,15 +568,15 @@
     (push (%compile-time-eval (nx-pair-initform pair) env) varinits))
   (progv (nreverse vars) (nreverse varinits)
-    (fcomp-form-list form env processing-mode)
+    (fcomp-form-list form env processing-mode source-note)
     (fcomp-compile-toplevel-forms env)))
 
-(defun fcomp-locally (body env processing-mode)
+(defun fcomp-locally (body env processing-mode source-note)
   (fcomp-compile-toplevel-forms env)
   (multiple-value-bind (body decls) (parse-body body env)
     (let* ((env (augment-environment env :declare (decl-specs-from-declarations decls))))
-      (fcomp-form-list body env processing-mode)
+      (fcomp-form-list body env processing-mode source-note)
       (fcomp-compile-toplevel-forms env))))
 
-(defun fcomp-macrolet (body env processing-mode)
+(defun fcomp-macrolet (body env processing-mode source-note)
   (fcomp-compile-toplevel-forms env)
   (let ((outer-env (augment-environment env 
@@ -570,8 +591,8 @@
                    outer-env
                    :declare (decl-specs-from-declarations decls))))
-        (fcomp-form-list body env processing-mode)
+        (fcomp-form-list body env processing-mode source-note)
         (fcomp-compile-toplevel-forms env)))))
 
-(defun fcomp-symbol-macrolet (body env processing-mode)
+(defun fcomp-symbol-macrolet (body env processing-mode source-note)
   (fcomp-compile-toplevel-forms env)
   (let* ((outer-env (augment-environment env :symbol-macro (car body))))
@@ -579,8 +600,8 @@
       (let* ((env (augment-environment outer-env 
                                        :declare (decl-specs-from-declarations decls))))
-        (fcomp-form-list body env processing-mode)
+        (fcomp-form-list body env processing-mode source-note)
         (fcomp-compile-toplevel-forms env)))))
-                                                               
-(defun fcomp-eval-when (form env processing-mode &aux (eval-times (pop form)))
+
+(defun fcomp-eval-when (form env processing-mode source-note &aux (eval-times (pop form)))
   (let* ((compile-time-too  (eq processing-mode :compile-time-too))
          (compile-time-only (eq processing-mode :compile-time))
@@ -599,11 +620,11 @@
     (fcomp-compile-toplevel-forms env)        ; always flush the suckers
     (cond (compile-time-only
-           (if at-eval-time (fcomp-form-list form env :compile-time)))
+           (if at-eval-time (fcomp-form-list form env :compile-time source-note)))
           (at-load-time
            (fcomp-form-list form env (if (or at-compile-time (and at-eval-time compile-time-too))
                                        :compile-time-too
-                                       :not-compile-time)))
+                                       :not-compile-time) source-note))
           ((or at-compile-time (and at-eval-time compile-time-too))
-           (fcomp-form-list form env :compile-time))))
+           (fcomp-form-list form env :compile-time source-note))))
   (fcomp-compile-toplevel-forms env))
 
@@ -634,5 +655,5 @@
     symbol))
 
-(defun fcomp-load-%defconstant (form env)
+(defun fcomp-load-%defconstant (form env source-note)
   (destructuring-bind (sym valform &optional doc) (cdr form)
     (unless *fasl-save-doc-strings*
@@ -642,7 +663,7 @@
     (if (and (typep sym 'symbol) (or  (quoted-form-p valform) (self-evaluating-p valform)))
       (fcomp-output-form $fasl-defconstant env sym (eval-constant valform) (eval-constant doc))
-      (fcomp-random-toplevel-form form env))))
-
-(defun fcomp-load-%defparameter (form env)
+      (fcomp-random-toplevel-form form env source-note))))
+
+(defun fcomp-load-%defparameter (form env source-note)
   (destructuring-bind (sym valform &optional doc) (cdr form)
     (unless *fasl-save-doc-strings*
@@ -650,8 +671,8 @@
     (if (quoted-form-p sym)
       (setq sym (%cadr sym)))
-    (let* ((fn (fcomp-function-arg valform env)))
+    (let* ((fn (fcomp-function-arg valform env source-note)))
       (if (and (typep sym 'symbol) (or fn (constantp valform)))
         (fcomp-output-form $fasl-defparameter env sym (or fn (eval-constant valform)) (eval-constant doc))
-        (fcomp-random-toplevel-form form env)))))
+        (fcomp-random-toplevel-form form env source-note)))))
 
 ; Both the simple %DEFVAR and the initial-value case (%DEFVAR-INIT) come here.
@@ -660,5 +681,5 @@
 ; Hairier initforms could be handled by another fasl operator that takes a thunk
 ; and conditionally calls it.
-(defun fcomp-load-defvar (form env)
+(defun fcomp-load-defvar (form env source-note)
   (destructuring-bind (sym &optional (valform nil val-p) doc) (cdr form)
     (unless *fasl-save-doc-strings*
@@ -669,8 +690,8 @@
       (if (and sym-p (not val-p))
         (fcomp-output-form $fasl-defvar env sym)
-        (let* ((fn (if sym-p (fcomp-function-arg valform env))))
+        (let* ((fn (if sym-p (fcomp-function-arg valform env source-note))))
           (if (and sym-p (or fn (constantp valform)))
             (fcomp-output-form $fasl-defvar-init env sym (or fn (eval-constant valform)) (eval-constant doc))
-            (fcomp-random-toplevel-form (macroexpand-1 form env) env)))))))
+            (fcomp-random-toplevel-form (macroexpand-1 form env) env source-note)))))))
       
 (defun define-compile-time-macro (name lambda-expression env)
@@ -747,5 +768,5 @@
          )))))
 
-(defun fcomp-load-%defun (form env)
+(defun fcomp-load-%defun (form env source-note)
   (destructuring-bind (fn &optional doc) (cdr form)
     (unless *fasl-save-doc-strings*
@@ -756,19 +777,19 @@
     (record-form-source-equivalent form fn)
     (if (and (constantp doc)
-             (setq fn (fcomp-function-arg fn env)))
+             (setq fn (fcomp-function-arg fn env source-note)))
       (progn
         (setq doc (eval-constant doc))
         (fcomp-output-form $fasl-defun env fn doc))
-      (fcomp-random-toplevel-form form env))))
-
-(defun fcomp-load-%macro (form env &aux fn doc)
+      (fcomp-random-toplevel-form form env source-note))))
+
+(defun fcomp-load-%macro (form env source-note &aux fn doc)
   (verify-arg-count form 1 2)
   (record-form-source-equivalent form (cadr form))
   (if (and (constantp (setq doc (caddr form)))
-           (setq fn (fcomp-function-arg (cadr form) env)))
+           (setq fn (fcomp-function-arg (cadr form) env source-note)))
     (progn
       (setq doc (eval-constant doc))
       (fcomp-output-form $fasl-macro env fn doc))
-    (fcomp-random-toplevel-form form env)))
+    (fcomp-random-toplevel-form form env source-note)))
 
 (defun define-compile-time-structure (sd refnames predicate env)
@@ -793,5 +814,5 @@
   (nx-transform form env))
 
-(defun fcomp-random-toplevel-form (form env)
+(defun fcomp-random-toplevel-form (form env source-note)
   (unless (constantp form)
     (unless (or (atom form)
@@ -806,5 +827,5 @@
           (record-form-source-equivalent form (first args))
           (multiple-value-bind (arg win) (fcomp-transform (%car args) env)
-            (when (or (setq lfun (fcomp-function-arg arg env))
+            (when (or (setq lfun (fcomp-function-arg arg env source-note))
                       win)
               (when lfun (setq arg `',lfun))
@@ -816,15 +837,12 @@
     (push form *fcomp-toplevel-forms*)))
 
-(defun fcomp-function-arg (expr env)
+(defun fcomp-function-arg (expr env &optional source-note)
   (when (consp expr)
-    (cond
-      ((and (eq (%car expr) 'nfunction)
-            (lambda-expression-p (cadr (%cdr expr))))
-       (record-form-source-equivalent expr (%caddr expr))
-       (fcomp-named-function (%caddr expr) (%cadr expr) env))
-      ((and (eq (%car expr) 'function)
-            (lambda-expression-p (%cadr expr)))
-       (record-form-source-equivalent expr (%cadr expr))
-       (fcomp-named-function (%cadr expr) nil env)))))
+    (cond ((and (eq (%car expr) 'nfunction)
+                (lambda-expression-p (cadr (%cdr expr))))
+           (fcomp-named-function (%caddr expr) (%cadr expr) env source-note))
+          ((and (eq (%car expr) 'function)
+                (lambda-expression-p (car (%cdr expr))))
+           (fcomp-named-function (%cadr expr) nil env source-note)))))
 
 (defun fcomp-compile-toplevel-forms (env)
@@ -866,5 +884,5 @@
 ;;; file.  The result will not be funcalled.  This really shouldn't bother
 ;;; making an lfun, but it's simpler this way...
-(defun fcomp-named-function (def name env)
+(defun fcomp-named-function (def name env &optional source-note)
   (let* ((env (new-lexical-environment env)))
     (multiple-value-bind (lfun warnings)
@@ -872,10 +890,14 @@
                                 :name name
                                 :env env
+                                :function-note source-note
                                 :keep-lambda *fasl-save-definitions*
                                 :keep-symbols *fasl-save-local-symbols*
                                 :policy *default-file-compilation-policy*
+                                :source-notes *fcomp-source-note-map*
                                 :load-time-eval-token cfasl-load-time-eval-sym
                                 :target *fasl-target*)
       (fcomp-signal-or-defer-warnings warnings env)
+      (when (logbitp $lfbits-code-coverage-bit (lfun-bits lfun))
+        (push lfun *fcomp-covered-functions*))
       lfun)))
 
@@ -1114,5 +1136,5 @@
                                              (or
                                               (gethash load-form *make-load-form-hash*)
-                                              (fcomp-named-function `(lambda () ,load-form) nil nil))
+                                              (fcomp-named-function `(lambda () ,load-form) nil nil nil))
                           (when warnings
                             (cerror "Ignore the warnings"
Index: /branches/mb-coverage-merge/library/cover.lisp
===================================================================
--- /branches/mb-coverage-merge/library/cover.lisp	(revision 8519)
+++ /branches/mb-coverage-merge/library/cover.lisp	(revision 8519)
@@ -0,0 +1,365 @@
+;;; Code coverage reporting facility, based on the SBCL's
+;;; sb-cover written by Juho Snellman, and placed under public domain.
+;;; Port to ccl by gz@clozure.com
+
+(in-package :ccl)
+
+(export '(*compile-code-coverage*
+          report-coverage
+          reset-coverage
+          clear-coverage
+          save-coverage-in-file
+          restore-coverage-from-file))
+
+(defconstant $not-executed-style 2)
+(defconstant $totally-covered-style 5)
+(defconstant $partially-covered-style 6)
+
+(defun show-notes (note)
+  (when (functionp note)
+    (setq note (function-source-note note)))
+  (labels ((show (note indent label)
+             (dotimes (i indent) (write-char #\space))
+             (format t "~a ~a~%" label note)
+             (loop with subindent = (+ indent 3)
+               for sub in (code-note-subform-notes note) as i upfrom 1
+               do (show sub subindent (format nil "~a~d." label i)))))
+    (show note 0 "")))
+
+(defun covered-functions-for-file (path)
+  (let* ((true-path (probe-file path))
+         (data (find-if #'(lambda (data)
+                           (and (consp data)
+                                (equalp (probe-file (car data)) true-path)))
+                       *code-covered-functions*)))
+    (cdr data)))
+
+(defun map-covered-functions (fn)
+  (loop for data in *code-covered-functions*
+    do (typecase data
+         (cons ;; (source-file . functions)
+          (map nil fn (cdr data)))
+         (function
+          (funcall fn data)))))
+
+(defun map-coverage-records (fn)
+  (map-covered-functions #'(lambda (function)
+                             (labels ((rec (note)
+                                        (when note
+                                          (map nil #'rec (code-note-subform-notes note))
+                                          (funcall fn note))))
+                               (rec (function-source-note function))))))
+
+(defun clear-coverage ()
+  "Clear all files from the coverage database. The files will be re-entered
+into the database when the FASL files (produced by compiling with
+CCL:*COMPILE-CODE-COVERAGE* set to true) are loaded again into the
+image."
+  (setq *code-covered-functions* nil))
+
+(defun reset-coverage ()
+  "Reset all coverage data back to the `Not executed` state."
+  (map-coverage-records #'(lambda (note)
+                            (setf (code-note-code-coverage note) nil))))
+
+(defun save-coverage ()
+  "Returns an opaque representation of the current code coverage state.
+The only operation that may be done on the state is passing it to
+RESTORE-COVERAGE. The representation is guaranteed to be readably printable.
+A representation that has been printed and read back will work identically
+in RESTORE-COVERAGE."
+  #+sbcl(loop for file being the hash-keys of sb-c::*code-coverage-info*
+	   using (hash-value states)
+	   collect (cons file states))
+  (error "Not implemented yet"))
+
+(defun restore-coverage (coverage-state)
+  "Restore the code coverage data back to an earlier state produced by
+SAVE-COVERAGE."
+  #+sbcl
+  (loop for (file . states) in coverage-state
+        do (let ((image-states (gethash file sb-c::*code-coverage-info*))
+                 (table (make-hash-table :test 'equal)))
+             (when image-states
+               (loop for cons in image-states
+                     do (setf (gethash (car cons) table) cons))
+               (loop for (key . value) in states
+                     do (let ((state (gethash key table)))
+                          (when state
+                            (setf (cdr state) value)))))))
+  coverage-state
+  (error "Not implemented yet"))
+
+(defun save-coverage-in-file (pathname)
+  "Call SAVE-COVERAGE and write the results of that operation into the
+file designated by PATHNAME."
+  (with-open-file (stream pathname
+                          :direction :output
+                          :if-exists :supersede
+                          :if-does-not-exist :create)
+    (with-standard-io-syntax
+      (let ((*package* (find-package :sb-cover)))
+        (write (save-coverage) :stream stream)))
+    (values)))
+
+(defun restore-coverage-from-file (pathname)
+  "READ the contents of the file designated by PATHNAME and pass the
+result to RESTORE-COVERAGE."
+  (with-open-file (stream pathname :direction :input)
+    (with-standard-io-syntax
+      (let ((*package* (find-package :sb-cover)))
+        (restore-coverage (read stream))))
+    (values)))
+
+(defun common-coverage-directory ()
+  (let* ((host :unknown)
+	 (rev-dir ()))
+    (loop for data in *code-covered-functions*
+       when (consp data)
+       do (let ((file (probe-file (car data))))
+	    (when file
+	      (cond ((eq host :unknown)
+		     (setq host (pathname-host file)
+			   rev-dir (reverse (pathname-directory file))))
+		    ((not (equalp host (pathname-host file)))
+		     (return-from common-coverage-directory nil))
+		    (t
+		     (let* ((path (pathname-directory file))
+			    (dir-len (length rev-dir))
+			    (len (length path)))
+		       (if (< len dir-len)
+			 (setq rev-dir (nthcdr (- dir-len len) rev-dir))
+			 (setq path (subseq path 0 dir-len)))
+		       (loop for pp on (reverse path) until (equalp pp rev-dir)
+			  do (pop rev-dir))))))))
+    (unless (eq host :unknown)
+      (make-pathname :host host :directory (reverse rev-dir)))))
+
+
+(defun report-coverage (output-file &key (external-format :default))
+  "Print a code coverage report of all instrumented files into DIRECTORY.
+If DIRECTORY does not exist, it will be created. The main report will be
+printed to the file cover-index.html. The external format of the source
+files can be specified with the EXTERNAL-FORMAT parameter.
+"
+  (let* ((paths)
+         (directory (make-pathname :name nil :type nil :defaults output-file))
+         (coverage-dir (common-coverage-directory)))
+    (ensure-directories-exist directory)
+    (loop for data in *code-covered-functions*
+      as file = (and (consp data)
+                     (or (probe-file (car data))
+                         (progn (warn "Cannot find ~s" (car data)) nil)))
+      do (when file
+           (let* ((src-name (enough-namestring file coverage-dir))
+                  (html-name (substitute #\_ #\: (substitute #\_ #\. (substitute #\_ #\/ src-name)))))
+             (with-open-file (stream (make-pathname :name html-name :type "html" :defaults directory)
+                                     :direction :output
+                                     :if-exists :supersede
+                                     :if-does-not-exist :create)
+               (report-file-coverage file (cdr data) stream external-format))
+             (push (list* src-name html-name (cdr data)) paths))))
+    (setq paths (sort paths #'string< :key #'car))
+    (when (null paths)
+      (error "No code coverage data available"))
+    (let ((index-file (merge-pathnames output-file "index.html")))
+      (with-open-file (stream index-file
+                              :direction :output
+                              :if-exists :supersede
+                              :if-does-not-exist :create)
+        (write-coverage-styles stream)
+        (unless paths
+          (warn "No coverage data found for any file, producing an empty report. Maybe you forgot to (SETQ CCL::*COMPILE-CODE-COVERAGE* T) before compiling?")
+          (format stream "<h3>No code coverage data found.</h3>")
+          (return-from report-coverage))
+        (format stream "<table class='summary'>")
+        (coverage-stats-head-html stream)
+        (loop for prev = nil then source-file
+          for (source-file report-name . functions) in paths
+          for even = nil then (not even)
+          do (when (or (null prev)
+                       (not (equal (pathname-directory (pathname source-file))
+                                   (pathname-directory (pathname prev)))))
+               (format stream "<tr class='subheading'><td colspan='11'>~A</td></tr>~%"
+                       (namestring (make-pathname :name nil :type nil :defaults source-file))))
+          do (coverage-stats-data-html stream source-file functions even report-name))
+        (format stream "</table>"))
+      index-file)))
+
+(defun colorize-function (function styles)
+  (let ((note (function-source-note function)))
+    ;; Change coverage flag to 'full if all subforms are covered.
+    (labels ((rec (note)
+               (when note
+                 (if (code-note-code-coverage note)
+                   (let ((subnotes (code-note-subform-notes note)))
+                     (map nil #'rec subnotes)
+                     (unless (find 'full subnotes :test #'neq
+                                   :key #'code-note-code-coverage)
+                       (setf (code-note-code-coverage note) 'full)))
+                   #+gz
+		   (let ((subnotes (code-note-subform-notes note)))
+		     (unless  (every #'(lambda (subnote)
+					 (null (code-note-code-coverage subnote)))
+				     subnotes)
+		       (warn "~s: Covered internal subnote in ~s" function note)
+		       #+no (map nil #'show-notes subnotes))
+		     (map nil #'rec subnotes))))))
+      (rec note))
+    ;; Now actually change text styles, from outside in.
+    (labels ((rec (note)
+               (let* ((style (case (code-note-code-coverage note)
+                              ((full) $totally-covered-style)
+                              ((nil) $not-executed-style)
+                              (t $partially-covered-style))))
+                 (when (source-note-p note)
+                   (fill styles style
+                         :start (source-note-start-pos note)
+                         :end (source-note-end-pos note)))
+                 (when (or (eq style $partially-covered-style)
+                           ;; If not a source note, descend in case have some subnotes
+                           ;; that can be showna
+                           (not (source-note-p note)))
+                   (map nil #'rec (code-note-subform-notes note))))))
+      (rec note))))
+
+(defun colorize-functions (functions styles)
+  (map nil #'(lambda (function) (colorize-function function styles)) functions))
+
+(defun report-file-coverage (file functions html-stream external-format)
+  "Print a code coverage report of FILE into the stream HTML-STREAM."
+  (format html-stream "<html><head>")
+  (write-coverage-styles html-stream)
+  (format html-stream "</head><body>")
+  (let* ((source (with-open-file (s file :external-format external-format)
+                   (let ((string (make-string (file-length s))))
+                     (read-sequence string s)
+                     string)))
+         (styles (make-array (length source)
+                             :initial-element 0
+                             :element-type '(unsigned-byte 2))))
+    (colorize-functions functions styles)
+    (print-coverage-report html-stream file styles source functions)
+    (format html-stream "</body></html>")))
+
+(defun print-coverage-report (html-stream file styles source functions)
+  (let ((*print-case* :downcase))
+    (format html-stream "<h3>Coverage report: ~a <br />~%</h3>~%" file)
+
+    (format html-stream "<table class='summary'>")
+    (coverage-stats-head-html html-stream)
+    (coverage-stats-data-html html-stream file functions)
+    (format html-stream "</table>")
+
+    (format html-stream "<div class='key'><b>Key</b><br />~%")
+    (format html-stream "<div class='state-~a'>Fully covered - every single instruction executed</div>" $totally-covered-style)
+    (format html-stream "<div class='state-~a'>Partly covered - entered but some subforms not executed</div>" $partially-covered-style)
+    (format html-stream "<div class='state-~a'>Never entered - not a single instruction executed</div>" $not-executed-style)
+    (format html-stream "<p></p><div><code>~%")
+
+    (flet ((line (line)
+             (unless (eql line 0)
+               (format html-stream "</span>"))
+             (incf line)
+             (format html-stream "</code></div></nobr>~%<nobr><div class='source'><div class='line-number'><code>~A</code></div><code>&#160;" line)
+             line))
+      (loop with line = (line 0) with col = 0
+        for last-style = nil then style
+        for char across source
+        for style across styles
+        do (unless (eq style last-style)
+             (when last-style
+               (format html-stream "</span>"))
+             (format html-stream "<span class='state-~a'>" style))
+        do (case char
+             ((#\Newline)
+              (setq style nil)
+              (setq col 0)
+              (setq line (line line)))
+             ((#\Space)
+              (incf col)
+              (write-string "&#160;" html-stream))
+             ((#\Tab)
+              (dotimes (i (- 8 (mod col 8)))
+                (incf col)
+                (write-string "&#160;" html-stream)))
+             (t
+              (incf col)
+              (if (alphanumericp char)
+                (write-char char html-stream)
+                (format html-stream "&#~D;" (char-code char))))))
+      (format html-stream "</code></div>"))))
+
+
+(defun coverage-stats-head-html (html-stream)
+  (format html-stream "<tr class='head-row'><td></td><td class='main-head' colspan='3'>Expressions</td><td class='main-head' colspan='7'>Functions</td></tr>")
+  (format html-stream "<tr class='head-row'>~{<td width='60px'>~A</td>~}</tr>"
+          (list "Source file"
+                "Total" "Covered" "% covered"
+                "Total" "Fully covered" "% fully covered" "Partly covered" "% partly covered" "Not entered" "% not entered")))
+
+(defun coverage-stats-data-html (html-stream source-file functions &optional evenp report-name)
+  (format html-stream "<tr class='~:[odd~;even~]'>" evenp)
+  (if report-name
+    (format html-stream "<td class='text-cell'><a href='~a.html'>~a</a></td>" report-name source-file)
+    (format html-stream "<td class='text-cell'>~a</td>" source-file))
+  (format html-stream "~{<td>~:[-~;~:*~a~]</td><td>~:[-~;~:*~a~]</td><td>~:[-~;~:*~5,1f%~]</td>~}"
+          (count-covered-expressions functions))
+  (destructuring-bind (total . counts) (count-covered-functions functions)
+    (format html-stream "<td>~:[-~;~:*~a~]</td>~{<td>~:[-~;~:*~a~]</td><td>~:[-~;~:*~5,1f%~]</td>~}</tr>"
+            total counts)))
+
+(defun count-covered-functions (functions)
+  (let ((fully 0) (partly 0) (never 0) (total 0))
+    (map nil #'(lambda (function)
+                 (let ((note (function-source-note function)))
+                   (when note
+                     (incf total)
+                     (case (code-note-code-coverage note)
+                       ((full) (incf fully))
+                       ((nil) (incf never))
+                       (t (incf partly))))))
+         functions)
+    (list total
+          fully (* 100.0 (/ fully total))
+          partly (* 100.0 (/ partly total))
+          never (* 100.0 (/ never total)))))
+
+(defun count-covered-expressions (functions)
+  (let ((covered 0) (total 0))
+    (map nil #'(lambda (function)
+                 (labels ((rec (note)
+                            (when note
+                              (incf total)
+                              (when (code-note-code-coverage note)
+                                (incf covered))
+                              (map nil #'rec (code-note-subform-notes note)))))
+                   (rec (function-source-note function))))
+         functions)
+    (list total covered  (* 100.0d0 (/ covered total)))))
+
+
+(defun write-coverage-styles (html-stream)
+  (format html-stream "<style type='text/css'>
+*.state-~a { background-color: #ffaaaa }
+*.state-~a { background-color: #aaffaa }
+*.state-~a { background-color: #44dd44 }
+div.key { margin: 20px; width: 88ex }
+div.source { width: 98ex; background-color: #eeeeee; padding-left: 5px;
+             /* border-style: solid none none none; border-width: 1px;
+             border-color: #dddddd */ }
+
+*.line-number { color: #666666; float: left; width: 6ex; text-align: right; margin-right: 1ex; }
+
+table.summary tr.head-row { background-color: #aaaaff }
+table.summary tr td.text-cell { text-align: left }
+table.summary tr td.main-head { text-align: center }
+table.summary tr td { text-align: right }
+table.summary tr.even { background-color: #eeeeff }
+table.summary tr.subheading { background-color: #aaaaff}
+table.summary tr.subheading td { text-align: left; font-weight: bold; padding-left: 5ex; }
+</style>"
+          $not-executed-style
+          $partially-covered-style
+          $totally-covered-style
+          ))
Index: /branches/mb-coverage-merge/library/lispequ.lisp
===================================================================
--- /branches/mb-coverage-merge/library/lispequ.lisp	(revision 8518)
+++ /branches/mb-coverage-merge/library/lispequ.lisp	(revision 8519)
@@ -141,5 +141,5 @@
 (defconstant $lfbits-info-bit 23)
 (defconstant $lfbits-trampoline-bit 24)
-(defconstant $lfbits-evaluated-bit 25)
+(defconstant $lfbits-code-coverage-bit 25)
 (defconstant $lfbits-cm-bit 26)         ; combined-method
 (defconstant $lfbits-nextmeth-bit 26)   ; or call-next-method with method-bit
