/[cmucl]/src/compiler/life.lisp
ViewVC logotype

Diff of /src/compiler/life.lisp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.11 by ram, Mon Jul 23 14:52:33 1990 UTC revision 1.12 by ram, Thu Aug 16 16:20:35 1990 UTC
# Line 40  Line 40 
40                    new)))                    new)))
41      (setf (tn-current-conflict tn) new)      (setf (tn-current-conflict tn) new)
42    
43      (let ((global-num (tn-number tn)))      (insert-block-global-conflict new block))
44        (do ((prev nil conf)    (undefined-value))
45             (conf (ir2-block-global-tns block)  
46                   (global-conflicts-next conf)))  
47            ((or (null conf)  ;;; INSERT-BLOCK-GLOBAL-CONFLICT  --  Internal
48                 (> (tn-number (global-conflicts-tn conf)) global-num))  ;;;
49             (if prev  ;;;    Do the actual insertion of the conflict New into Block's global
50                 (setf (global-conflicts-next prev) new)  ;;; conflicts.
51                 (setf (ir2-block-global-tns block) new))  ;;;
52             (setf (global-conflicts-next new) conf)))))  (defun insert-block-global-conflict (new block)
53      (let ((global-num (tn-number (global-conflicts-tn new))))
54        (do ((prev nil conf)
55             (conf (ir2-block-global-tns block)
56                   (global-conflicts-next conf)))
57            ((or (null conf)
58                 (> (tn-number (global-conflicts-tn conf)) global-num))
59             (if prev
60                 (setf (global-conflicts-next prev) new)
61                 (setf (ir2-block-global-tns block) new))
62             (setf (global-conflicts-next new) conf))))
63    (undefined-value))    (undefined-value))
64    
65    
# Line 123  Line 133 
133            (let* ((tn (tn-ref-tn ref))            (let* ((tn (tn-ref-tn ref))
134                   (local (tn-local tn))                   (local (tn-local tn))
135                   (kind (tn-kind tn)))                   (kind (tn-kind tn)))
136              (when (eq kind :normal)              (unless (member kind '(:component :environment :constant))
137                (unless (eq local block)                (unless (eq local block)
138                  (when (= ltn-num local-tn-limit)                  (when (= ltn-num local-tn-limit)
139                    (return-from find-local-references vop))                    (return-from find-local-references vop))
# Line 395  Line 405 
405    (undefined-value))    (undefined-value))
406    
407    
408    ;;;; Environment TN stuff:
409    
410    
411    ;;; SETUP-ENVIRONMENT-TN-CONFLICT  --  Internal
412    ;;;
413    ;;;    Add a :LIVE global conflict for TN in 2block if there is none present.
414    ;;; If Debug-P is false (a :ENVIRONMENT TN), then modify any existing conflict
415    ;;; to be :LIVE.
416    ;;;
417    (defun setup-environment-tn-conflict (tn 2block debug-p)
418      (declare (type tn tn) (type ir2-block 2block))
419      (let ((block-num (ir2-block-number 2block)))
420        (do ((conf (tn-current-conflict tn) (global-conflicts-tn-next conf))
421             (prev nil conf))
422            ((or (null conf)
423                 (> (ir2-block-number (global-conflicts-block conf)) block-num))
424             (setf (tn-current-conflict tn) prev)
425             (add-global-conflict :live tn 2block nil))
426          (when (eq (global-conflicts-block conf) 2block)
427            (unless (or debug-p
428                        (eq (global-conflicts-kind conf) :live))
429              (setf (global-conflicts-kind conf) :live)
430              (setf (svref (ir2-block-local-tns 2block)
431                           (global-conflicts-number conf))
432                    nil)
433              (setf (global-conflicts-number conf) nil))
434            (setf (tn-current-conflict tn) conf)
435            (return))))
436      (undefined-value))
437    
438    
439    ;;; SETUP-ENVIRONMENT-TN-CONFLICTS  --  Internal
440    ;;;
441    ;;;    Iterate over all the blocks in Env, setting up :LIVE conflicts for TN.
442    ;;; We make the TN global if it isn't already.  The TN must have at least one
443    ;;; reference.
444    ;;;
445    (defun setup-environment-tn-conflicts (component tn env debug-p)
446      (declare (type component component) (type tn tn) (type environment env))
447      (when (and debug-p (not (tn-global-conflicts tn)))
448        (convert-to-global tn))
449      (setf (tn-current-conflict tn) (tn-global-conflicts tn))
450      (do-blocks-backwards (block component)
451        (when (eq (block-environment block) env)
452          (let* ((2block (block-info block))
453                 (last (do ((b (ir2-block-next 2block) (ir2-block-next b))
454                            (prev 2block b))
455                           ((not (eq (ir2-block-block b) block))
456                            prev))))
457            (do ((b last (ir2-block-prev b)))
458                ((not (eq (ir2-block-block b) block)))
459              (setup-environment-tn-conflict tn b debug-p)))))
460      (undefined-value))
461    
462    
463    ;;; SETUP-ENVIRONMENT-[DEBUG-]LIVE-CONFLICTS  --  Internal
464    ;;;
465    ;;;    Iterate over all the environment TNs, adding always-live conflicts as
466    ;;; appropriate.
467    ;;;
468    (defun setup-environment-live-conflicts (component)
469      (declare (type component component))
470      (dolist (fun (component-lambdas component))
471        (let ((env (lambda-environment fun)))
472          (dolist (tn (ir2-environment-live-tns (environment-info env)))
473            (setup-environment-tn-conflicts component tn env nil))))
474      (undefined-value))
475    ;;;
476    (defun setup-environment-debug-live-conflicts (component)
477      (declare (type component component))
478      (dolist (fun (component-lambdas component))
479        (let ((env (lambda-environment fun)))
480          (dolist (tn (ir2-environment-debug-live-tns (environment-info env)))
481            (setup-environment-tn-conflicts component tn env t))))
482      (undefined-value))
483    
484    
485    ;;; Convert-To-Environment-TN  --  Internal
486    ;;;
487    ;;;    Convert a :NORMAL or :DEBUG-ENVIRONMENT TN to an :ENVIRONMENT TN.  This
488    ;;; requires adding :LIVE conflicts to all blocks in TN-ENV.
489    ;;;
490    (defun convert-to-environment-tn (tn tn-env)
491      (declare (type tn tn) (type environment tn-env))
492      (assert (member (tn-kind tn) '(:normal :debug-environment)))
493      (when (eq (tn-kind tn) :debug-environment)
494        (assert (eq (tn-environment tn) tn-env))
495        (let ((2env (environment-info tn-env)))
496          (setf (ir2-environment-debug-live-tns 2env)
497                (delete tn (ir2-environment-debug-live-tns 2env)))))
498      (setup-environment-tn-conflicts *compile-component* tn tn-env nil)
499      (setf (tn-local tn) nil)
500      (setf (tn-local-number tn) nil)
501      (setf (tn-kind tn) :environment)
502      (setf (tn-environment tn) tn-env)
503      (push tn (ir2-environment-live-tns (environment-info tn-env)))
504      (undefined-value))
505    
506    
507  ;;;; Flow analysis:  ;;;; Flow analysis:
508    
509  ;;; Propagate-Live-TNs  --  Internal  ;;; Propagate-Live-TNs  --  Internal
# Line 494  Line 603 
603    
604  ;;;; Post-pass:  ;;;; Post-pass:
605    
 ;;; Convert-To-Environment-TN  --  Internal  
 ;;;  
 ;;;    Convert a :Normal TN to an :Environment TN.  This requires deleting the  
 ;;; existing conflict info.  
 ;;;  
 (defun convert-to-environment-tn (tn)  
   (declare (type tn tn))  
   (assert (eq (tn-kind tn) :normal))  
   (let ((confs (tn-global-conflicts tn)))  
     (if confs  
         (do ((conf confs (global-conflicts-tn-next conf)))  
             ((null conf))  
           (let ((block (global-conflicts-block conf)))  
             (unless (eq (global-conflicts-kind conf) :live)  
               (let ((ltns (ir2-block-local-tns block))  
                     (num (global-conflicts-number conf)))  
                 (assert (not (eq (svref ltns num) :more)))  
                 (setf (svref ltns num) nil)))  
             (deletef-in global-conflicts-next (ir2-block-global-tns block)  
                         conf)))  
         (setf (svref (ir2-block-local-tns (tn-local tn))  
                      (tn-local-number tn))  
               nil))  
     (setf (tn-local tn) nil)  
     (setf (tn-local-number tn) nil)  
     (setf (tn-global-conflicts tn) nil)  
     (setf (tn-kind tn) :environment)  
     (push tn (ir2-environment-live-tns  
               (environment-info  
                (tn-environment tn)))))  
   (undefined-value))  
   
   
606  ;;; Note-Conflicts  --  Internal  ;;; Note-Conflicts  --  Internal
607  ;;;  ;;;
608  ;;;    Note that TN conflicts with all current live TNs.  Num is TN's LTN  ;;;    Note that TN conflicts with all current live TNs.  Num is TN's LTN
# Line 550  Line 626 
626  ;;;    Compute a bit vector of the TNs live after VOP that aren't results.  ;;;    Compute a bit vector of the TNs live after VOP that aren't results.
627  ;;;  ;;;
628  (defun compute-save-set (vop live-bits)  (defun compute-save-set (vop live-bits)
629    (declare (type vop vop) (type local-tn-bit-vector live-list))    (declare (type vop vop) (type local-tn-bit-vector live-bits))
630    (let ((live (bit-vector-copy live-bits)))    (let ((live (bit-vector-copy live-bits)))
631      (do ((r (vop-results vop) (tn-ref-across r)))      (do ((r (vop-results vop) (tn-ref-across r)))
632          ((null r))          ((null r))
633        (let ((tn (tn-ref-tn r)))        (let ((tn (tn-ref-tn r)))
634          (ecase (tn-kind tn)          (ecase (tn-kind tn)
635            (:normal (setf (sbit live (tn-local-number tn)) 0))            ((:normal :debug-environment)
636               (setf (sbit live (tn-local-number tn)) 0))
637            (:environment :component))))            (:environment :component))))
638      live))      live))
639    
640    
641    ;;; SAVED-AFTER-READ  --  Internal
642    ;;;
643    ;;;    Used to determine whether a :DEBUG-ENVIRONMENT TN should be considered
644    ;;; live at block end.  We return true if a VOP with non-null SAVE-P appears
645    ;;; before the first read of TN (hence is seen first in our backward scan.)
646    ;;;
647    (defun saved-after-read (tn block)
648      (do ((vop (ir2-block-last-vop block) (vop-prev vop)))
649          ((null vop) t)
650        (when (vop-info-save-p (vop-info vop)) (return t))
651        (when (find-in #'tn-ref-across tn (vop-args vop) :key #'tn-ref-tn)
652          (return nil))))
653    
654    
655  ;;; Compute-Initial-Conflicts  --  Internal  ;;; Compute-Initial-Conflicts  --  Internal
656  ;;;  ;;;
657  ;;;    Return as values, a LTN bit-vector and a list (threaded by TN-Next*)  ;;;    Return as values, a LTN bit-vector and a list (threaded by TN-Next*)
# Line 570  Line 661 
661  ;;; end, setting up the TN-Local-Conflicts and TN-Local-Number, and adding the  ;;; end, setting up the TN-Local-Conflicts and TN-Local-Number, and adding the
662  ;;; TN to the live list.  ;;; TN to the live list.
663  ;;;  ;;;
664    ;;; If the block has no successors, or its successor is the component tail,
665    ;;; then all :DEBUG-ENVIRONMENT TNs are always added, regardless of whether
666    ;;; they appeared to be live.  This ensures that these TNs are considered to be
667    ;;; live throughout blocks that read them, but don't have any interesting
668    ;;; successors (such as a return or tail call.)  In this case, we set the
669    ;;; corresponding bit in LIVE-IN as well.
670    ;;;
671  ;;; ### Note: we alias the global-conflicts-conflicts here as the  ;;; ### Note: we alias the global-conflicts-conflicts here as the
672  ;;; tn-local-conflicts.  ;;; tn-local-conflicts.
673  ;;;  ;;;
674  (defun compute-initial-conflicts (block)  (defun compute-initial-conflicts (block)
675    (declare (type ir2-block block))    (declare (type ir2-block block))
676    (let ((live-bits (bit-vector-copy (ir2-block-live-in block)))    (let* ((live-in (ir2-block-live-in block))
677          (live-list nil))           (live-bits (bit-vector-copy live-in))
678             (live-list nil))
679    
680      (do ((conf (ir2-block-global-tns block)      (do ((conf (ir2-block-global-tns block)
681                 (global-conflicts-next conf)))                 (global-conflicts-next conf)))
# Line 592  Line 691 
691              (push-in tn-next* tn live-list))              (push-in tn-next* tn live-list))
692            (setf (tn-local-conflicts tn) bits))))            (setf (tn-local-conflicts tn) bits))))
693    
694        (let* ((1block (ir2-block-block block))
695               (succ (block-succ 1block))
696               (next (ir2-block-next block)))
697          (when (and next
698                     (not (eq (ir2-block-block next) 1block))
699                     (or (null succ)
700                         (eq (first succ)
701                             (component-tail (block-component 1block)))))
702            (do ((conf (ir2-block-global-tns block)
703                       (global-conflicts-next conf)))
704                ((null conf))
705              (let* ((tn (global-conflicts-tn conf))
706                     (num (global-conflicts-number conf)))
707                (when (and num (zerop (sbit live-bits num))
708                           (eq (tn-kind tn) :debug-environment)
709                           (eq (tn-environment tn) (block-environment 1block))
710                           (saved-after-read tn block))
711                  (note-conflicts live-bits live-list tn num)
712                  (setf (sbit live-bits num) 1)
713                  (push-in tn-next* tn live-list)
714                  (setf (sbit live-in num) 1))))))
715    
716      (values live-bits live-list)))      (values live-bits live-list)))
717    
718    
# Line 645  Line 766 
766                    (unless (eq (tn-kind tn) :component)                    (unless (eq (tn-kind tn) :component)
767                      (force-tn-to-stack tn)                      (force-tn-to-stack tn)
768                      (unless (eq (tn-kind tn) :environment)                      (unless (eq (tn-kind tn) :environment)
769                        (convert-to-environment-tn tn))))))))                        (convert-to-environment-tn
770                           tn
771                           (block-environment (ir2-block-block block))))))))))
772    
773          (do ((ref (vop-refs vop) (tn-ref-next-ref ref)))          (do ((ref (vop-refs vop) (tn-ref-next-ref ref)))
774              ((null ref))              ((null ref))
# Line 680  Line 803 
803      (conflict-analyze-1-block block)))      (conflict-analyze-1-block block)))
804    
805    
806    ;;;; Alias TN stuff:
807    
808    ;;; MERGE-ALIAS-BLOCK-CONFLICTS  --  Internal
809    ;;;
810    ;;;    Destructively modify Oconf to include the conflict information in Conf.
811    ;;;
812    (defun merge-alias-block-conflicts (conf oconf)
813      (declare (type global-conflicts conf oconf))
814      (let* ((kind (global-conflicts-kind conf))
815             (num (global-conflicts-number conf))
816             (okind (global-conflicts-kind oconf))
817             (onum (global-conflicts-number oconf))
818             (block (global-conflicts-block oconf))
819             (ltns (ir2-block-local-tns block)))
820        (cond
821         ((eq okind :live))
822         ((eq kind :live)
823          (setf (global-conflicts-kind oconf) :live)
824          (setf (svref ltns onum) nil)
825          (setf (global-conflicts-number oconf) nil))
826         (t
827          (unless (eq kind okind)
828            (setf (global-conflicts-kind oconf) :read))
829          ;;
830          ;; Make original conflict with all the local TNs the alias conflicted
831          ;; with.
832          (bit-ior (global-conflicts-conflicts oconf)
833                   (global-conflicts-conflicts conf)
834                   t)
835          (flet ((frob (x)
836                   (unless (zerop (sbit x num))
837                     (setf (sbit x onum) 1))))
838            ;;
839            ;; Make all the local TNs that conflicted with the alias conflict
840            ;; with the original.
841            (dotimes (i (ir2-block-local-tn-count block))
842              (let ((tn (svref ltns i)))
843                (when (and tn (not (eq tn :more))
844                           (null (tn-global-conflicts tn)))
845                  (frob (tn-local-conflicts tn)))))
846            ;;
847            ;; Same for global TNs...
848            (do ((current (ir2-block-global-tns block)
849                          (global-conflicts-next current)))
850                ((null current))
851              (unless (eq (global-conflicts-kind current) :live)
852                (frob (global-conflicts-conflicts current))))
853            ;;
854            ;; Make the original TN live everywhere that the alias was live.
855            (frob (ir2-block-written block))
856            (frob (ir2-block-live-in block))
857            (frob (ir2-block-live-out block))
858            (do ((vop (ir2-block-start-vop block)
859                      (vop-next vop)))
860                ((null vop))
861              (let ((sset (vop-save-set vop)))
862                (when sset (frob sset)))))))
863        ;;
864        ;; Delete the alias's conflict info.
865        (when num
866          (setf (svref ltns num) nil))
867        (deletef-in global-conflicts-next (ir2-block-global-tns block) conf))
868    
869      (undefined-value))
870    
871    
872    ;;; CHANGE-GLOBAL-CONFLICTS-TN  --  Internal
873    ;;;
874    ;;;    Co-opt Conf to be a conflict for TN.
875    ;;;
876    (defun change-global-conflicts-tn (conf new)
877      (declare (type global-conflicts conf) (type tn new))
878      (setf (global-conflicts-tn conf) new)
879      (let ((ltn-num (global-conflicts-number conf))
880            (block (global-conflicts-block conf)))
881        (deletef-in global-conflicts-next (ir2-block-global-tns block) conf)
882        (setf (global-conflicts-next conf) nil)
883        (insert-block-global-conflict conf block)
884        (when ltn-num
885          (setf (svref (ir2-block-local-tns block) ltn-num) new)))
886      (undefined-value))
887    
888    
889    ;;; ENSURE-GLOBAL-TN  --  Internal
890    ;;;
891    ;;;    Do CONVERT-TO-GLOBAL on TN if it has no global conflicts.  Copy the
892    ;;; local conflicts into the global bit vector.
893    ;;;
894    (defun ensure-global-tn (tn)
895      (declare (type tn tn))
896      (unless (tn-global-conflicts tn)
897        (convert-to-global tn)
898        (bit-ior (global-conflicts-conflicts (tn-global-conflicts tn))
899                 (tn-local-conflicts tn)
900                 t))
901      (undefined-value))
902    
903    
904    ;;; MERGE-ALIAS-CONFLICTS  --  Internal
905    ;;;
906    ;;;    For each :ALIAS TN, destructively merge the conflict info into the
907    ;;; original TN and replace the uses of the alias.
908    ;;;
909    ;;; For any block that uses only the alias TN, just insert that conflict into
910    ;;; the conflicts for the original TN, changing the LTN map to refer to the
911    ;;; original TN.  This gives a result indistinguishable from the what there
912    ;;; would have been if the original TN had always been referenced.  This leaves
913    ;;; no sign that an alias TN was ever involved.
914    ;;;
915    ;;; If a block has references to both the alias and the original TN, then we
916    ;;; call MERGE-ALIAS-BLOCK-CONFLICTS to combine the conflicts into the original
917    ;;; conflict.
918    ;;;
919    (defun merge-alias-conflicts (component)
920      (declare (type component component))
921      (do ((tn (ir2-component-alias-tns (component-info component))
922               (tn-next tn)))
923          ((null tn))
924        (let ((original (tn-save-tn tn)))
925          (ensure-global-tn tn)
926          (ensure-global-tn original)
927          (let ((conf (tn-global-conflicts tn))
928                (oconf (tn-global-conflicts original))
929                (oprev nil))
930            (loop
931              (let* ((block (global-conflicts-block conf))
932                     (num (ir2-block-number block))
933                     (onum (ir2-block-number (global-conflicts-block oconf))))
934    
935                (cond ((< onum num)
936                       (shiftf oprev oconf (global-conflicts-tn-next oconf)))
937                      ((> onum num)
938                       (if oprev
939                           (setf (global-conflicts-tn-next oprev) conf)
940                           (setf (tn-global-conflicts original) conf))
941                       (change-global-conflicts-tn conf original)
942                       (shiftf conf (global-conflicts-tn-next conf) oconf))
943                      (t
944                       (merge-alias-block-conflicts conf oconf)
945                       (shiftf oprev oconf (global-conflicts-tn-next oconf))
946                       (setf conf (global-conflicts-tn-next conf)))))
947              (unless oconf
948                (if oprev
949                    (setf (global-conflicts-tn-next oprev) conf)
950                    (setf (tn-global-conflicts original) conf))
951                (do ((current conf (global-conflicts-tn-next current)))
952                    ((null current))
953                  (change-global-conflicts-tn conf original))
954                (return))
955              (unless conf (return))))
956    
957          (flet ((frob (refs)
958                   (let ((ref refs)
959                         (next nil))
960                     (loop
961                       (unless ref (return))
962                       (setq next (tn-ref-next ref))
963                       (change-tn-ref-tn ref original)
964                       (setq ref next)))))
965            (frob (tn-reads tn))
966            (frob (tn-writes tn)))
967          (setf (tn-global-conflicts tn) nil)))
968    
969      (undefined-value))
970    
971    
972  ;;; Lifetime-Analyze  --  Interface  ;;; Lifetime-Analyze  --  Interface
973  ;;;  ;;;
974  ;;;  ;;;
975  (defun lifetime-analyze (component)  (defun lifetime-analyze (component)
976    (lifetime-pre-pass component)    (lifetime-pre-pass component)
977      (setup-environment-live-conflicts component)
978    (lifetime-flow-analysis component)    (lifetime-flow-analysis component)
979    (lifetime-post-pass component))    (setup-environment-debug-live-conflicts component)
980      (lifetime-post-pass component)
981      (merge-alias-conflicts component))
982    
983    
984  ;;;; Conflict testing:  ;;;; Conflict testing:
# Line 747  Line 1039 
1039              (advance y-num y-conf)))))))              (advance y-num y-conf)))))))
1040    
1041    
 ;;; TNs-Conflict-Environment-Global  --  Interface  
 ;;;  
 ;;;    Return true if any of Y's blocks are in X's environment.  
 ;;;  
 (defun tns-conflict-environment-global (x y)  
   (declare (type tn x y))  
   (let ((env (tn-environment x)))  
     (do ((conf (tn-global-conflicts y) (global-conflicts-tn-next conf)))  
         ((null conf)  
          nil)  
       (when (eq (block-environment  
                  (ir2-block-block (global-conflicts-block conf)))  
                 env)  
         (return t)))))  
   
   
 ;;; TNs-Conflict-Environment-Local  --  Interface  
 ;;;  
 ;;;    Return true if Y's block is in X's environment.  
 ;;;  
 (defun tns-conflict-environment-local (x y)  
   (declare (type tn x y))  
   (eq (block-environment (ir2-block-block (tn-local y)))  
       (tn-environment x)))  
   
   
1042  ;;; TNs-Conflict  --  Interface  ;;; TNs-Conflict  --  Interface
1043  ;;;  ;;;
1044  ;;;    Return true if X and Y are distinct and the lifetimes of X and Y overlap  ;;;    Return true if X and Y are distinct and the lifetimes of X and Y overlap
# Line 783  Line 1049 
1049    (let ((x-kind (tn-kind x))    (let ((x-kind (tn-kind x))
1050          (y-kind (tn-kind y)))          (y-kind (tn-kind y)))
1051      (cond ((eq x y) nil)      (cond ((eq x y) nil)
           ((eq x-kind :environment)  
            (cond ((tn-global-conflicts y)  
                   (tns-conflict-environment-global x y))  
                  ((eq (tn-kind y) :environment)  
                   (eq (tn-environment x) (tn-environment y)))  
                  (t  
                   (tns-conflict-environment-local x y))))  
           ((eq y-kind :environment)  
            (if (tn-global-conflicts x)  
                (tns-conflict-environment-global y x)  
                (tns-conflict-environment-local y x)))  
1052            ((or (eq x-kind :component) (eq y-kind :component)) t)            ((or (eq x-kind :component) (eq y-kind :component)) t)
1053            ((tn-global-conflicts x)            ((tn-global-conflicts x)
1054             (if (tn-global-conflicts y)             (if (tn-global-conflicts y)
# Line 805  Line 1060 
1060             (and (eq (tn-local x) (tn-local y))             (and (eq (tn-local x) (tn-local y))
1061                  (not (zerop (sbit (tn-local-conflicts x)                  (not (zerop (sbit (tn-local-conflicts x)
1062                                    (tn-local-number y)))))))))                                    (tn-local-number y)))))))))
1063    

Legend:
Removed from v.1.11  
changed lines
  Added in v.1.12

  ViewVC Help
Powered by ViewVC 1.1.5