~ chicken-core (chicken-5) 7ab8030ca16177b719a370f3cde40f2a83a0b95d


commit 7ab8030ca16177b719a370f3cde40f2a83a0b95d
Author:     felix <felix@call-with-current-continuation.org>
AuthorDate: Thu Jan 20 04:56:39 2011 -0500
Commit:     felix <felix@call-with-current-continuation.org>
CommitDate: Thu Jan 20 04:56:39 2011 -0500

    -specialize option and scrutinizer changes

diff --git a/batch-driver.scm b/batch-driver.scm
index a9e7f276..87acb498 100644
--- a/batch-driver.scm
+++ b/batch-driver.scm
@@ -91,6 +91,8 @@
 	(a-only (memq 'analyze-only options))
 	(dynamic (memq 'dynamic options))
 	(unbox (memq 'unboxing options))
+	(do-scrutinize (when (memq 'scrutinize options))
+	(do-specialize (when (memq 'specialize options))
 	(dumpnodes #f)
 	(start-time #f)
 	(upap #f)
@@ -185,8 +187,6 @@
       (set! all-import-libraries #t))
     (set! enable-module-registration (not (memq 'no-module-registration options)))
     (when (memq 'lambda-lift options) (set! do-lambda-lifting #t))
-    (when (memq 'scrutinize options)
-      (set! do-scrutinize #t))
     (when (memq 't debugging-chicken) (##sys#start-timer))
     (when (memq 'b debugging-chicken) (set! time-breakdown #t))
     (when (memq 'emit-exports options)
@@ -500,8 +500,8 @@
 	       (print-node "initial node tree" '|T| node0)
 	       (initialize-analysis-database)
 
-	       (when do-scrutinize
-		 ;;;*** hardcoded database file name
+	       (when (or do-scrutinize do-specialize)
+		 ;;;XXX hardcoded database file name
 		 (unless (memq 'ignore-repository options)
 		   (load-type-database "types.db"))
 		 (for-each (cut load-type-database <> #f) (collect-options 'types))
@@ -512,14 +512,14 @@
 		 (end-time "pre-analysis")
 		 (begin-time)
 		 (debugging 'p "performing scrutiny")
-		 (scrutinize node0 db)
+		 (scrutinize node0 db do-scrutinize do-specialize)
 		 (end-time "scrutiny")
 		 (set! first-analysis #t) )
 
 	       (when do-lambda-lifting
 		 (begin-time)
-		 (unless do-scrutinize	; no need to do analysis if already done above
-		   (set! first-analysis #f)
+		 (unless do-scrutinize ; no need to do analysis if already done
+		   (set! first-analysis #f) ; (and not specialized)
 		   (set! db (analyze 'lift node0))
 		   (print-db "analysis" '|0| db 0)
 		   (end-time "pre-analysis (lambda-lift)"))
diff --git a/c-platform.scm b/c-platform.scm
index c1074bef..1a3e9273 100644
--- a/c-platform.scm
+++ b/c-platform.scm
@@ -85,7 +85,7 @@
     profile inline keep-shadowed-macros ignore-repository
     fixnum-arithmetic disable-interrupts optimize-leaf-routines
     lambda-lift compile-syntax tag-pointers accumulate-profile
-    disable-stack-overflow-checks raw 
+    disable-stack-overflow-checks raw specialize
     emit-external-prototypes-first release local inline-global
     analyze-only dynamic scrutinize no-argc-checks no-procedure-checks
     no-procedure-checks-for-toplevel-bindings module
diff --git a/compiler-namespace.scm b/compiler-namespace.scm
index d4fa6b56..679a62c8 100644
--- a/compiler-namespace.scm
+++ b/compiler-namespace.scm
@@ -98,7 +98,6 @@
  display-line-number-database
  display-real-name-table
  do-lambda-lifting
- do-scrutinize
  dump-defined-globals
  dump-global-refs
  dump-nodes
diff --git a/compiler.scm b/compiler.scm
index a7d08eb5..41d6736c 100644
--- a/compiler.scm
+++ b/compiler.scm
@@ -333,7 +333,6 @@
 (define local-definitions #f)
 (define inline-locally #f)
 (define inline-output-file #f)
-(define do-scrutinize #f)
 (define enable-inline-files #f)
 (define compiler-syntax-enabled #t)
 (define unchecked-specialized-arithmetic #f)
@@ -1464,9 +1463,11 @@
        ((type)
 	(for-each
 	 (lambda (spec)
-	   (cond ((and (list? spec) (symbol? (car spec)) (= 2 (length spec)))
+	   (cond ((and (list? spec) (symbol? (car spec)) (>= 2 (length spec)))
 		  (##sys#put! (car spec) '##core#type (cadr spec))
-		  (##sys#put! (car spec) '##core#declared-type #t))
+		  (##sys#put! (car spec) '##core#declared-type #t)
+		  (when (pair? (cddr spec))
+		    (##sys#put! (car spec) '##core#specializations (cddr spec))))
 		 (else
 		  (warning "illegal `type' declaration item" spec))))
 	 (globalize-all (cdr spec))))
diff --git a/csc.scm b/csc.scm
index e097523d..bc840c79 100644
--- a/csc.scm
+++ b/csc.scm
@@ -138,7 +138,7 @@
     -no-symbol-escape -no-parentheses-synonyms -r5rs-syntax
     -no-argc-checks -no-bound-checks -no-procedure-checks -no-compiler-syntax
     -emit-all-import-libraries -setup-mode -unboxing -no-elevation -no-module-registration
-    -no-procedure-checks-for-usual-bindings -module
+    -no-procedure-checks-for-usual-bindings -module -specialize
     -no-procedure-checks-for-toplevel-bindings))
 
 (define-constant complex-options
@@ -370,6 +370,7 @@ Usage: #{csc} FILENAME | OPTION ...
     -inline-limit LIMIT            set inlining threshold
     -inline-global                 enable cross-module inlining
     -unboxing                      use unboxed temporaries if possible
+    -specialize                    perform type-based specialization of primitive calls
     -n -emit-inline-file FILENAME  generate file with globally inlinable
                                     procedures (implies -inline -local)
     -consult-inline-file FILENAME  explicitly load inline file
diff --git a/scrutinizer.scm b/scrutinizer.scm
index 0c2d77ba..87baa8f2 100755
--- a/scrutinizer.scm
+++ b/scrutinizer.scm
@@ -24,7 +24,9 @@
 ; POSSIBILITY OF SUCH DAMAGE.
 
 
-(declare (unit scrutinizer))
+(declare
+  (unit scrutinizer)
+  (hide match-specialization specialize-node!))
 
 
 (include "compiler-namespace")
@@ -59,11 +61,20 @@
 ;
 ;   ##core#type           ->  <typespec>
 ;   ##core#declared-type  ->  <bool>
+;   ##core#specializations -> (SPECIALIZATION ...)
+;
+; specialization specifiers:
+;
+;   SPECIALIZATION = ((VAL ... [#!rest VAL]) TEMPLATE)
+;   TEMPLATE = INTEGER | SYMBOL | STRING
+;            | (quote CONSTANT)
+;            | (TEMPLATE . TEMPLATE)
+
 
 (define-constant +fragment-max-length+ 5)
 (define-constant +fragment-max-depth+ 3)
 
-(define (scrutinize node db)
+(define (scrutinize node db complain specialize)
   (define (constant-result lit)
     (cond ((string? lit) 'string)
 	  ((symbol? lit) 'symbol)
@@ -394,8 +405,9 @@
 			   what n (multiples n)))
 		 (first tv))))))
   (define (report loc desc)
-    (warning
-     (conc (location-name loc) desc)))
+    (when complain
+      (warning
+       (conc (location-name loc) desc))))
   (define (location-name loc)
     (define (lname loc1)
       (if loc1
@@ -423,7 +435,7 @@
      (with-output-to-string
        (lambda ()
 	 (pp (fragment x))))))
-  (define (call-result args e loc x params)
+  (define (call-result node args e loc params)
     (define (pname)
       (sprintf "~ain procedure call to `~s', " 
 	  (if (and (pair? params) (pair? (cdr params)))
@@ -432,7 +444,7 @@
 		    (sprintf "~a: " n)
 		    ""))
 	      "")
-	(fragment x)))
+	(fragment (first (node-subexpressions node)))))
     (d "call-result: ~a (~a)" args loc)
     (let* ((ptype (car args))
 	   (nargs (length (cdr args)))
@@ -446,7 +458,7 @@
 	  (pname) 
 	  xptype
 	  ptype)))
-      (let-values (((atypes values-rest) (procedure-argument-types ptype (length (cdr args)))))
+      (let-values (((atypes values-rest) (procedure-argument-types ptype nargs)))
 	(d "  argument-types: ~a (~a)" atypes values-rest)
 	(unless (= (length atypes) nargs)
 	  (let ((alen (length atypes)))
@@ -468,6 +480,15 @@
 	      (pname) i (car atypes) (car args)))))
 	(let ((r (procedure-result-types ptype values-rest (cdr args))))
 	  (d  "  result-types: ~a" r)
+	  (when specialize
+	    ;;XXX we should check whether this is a standard- or extended bindng
+	    (and-let* ((pn (procedure-name ptype))
+		       (specs (##sys#get pn '##core#specializations)))
+	      (for-each
+	       (lambda (spec)
+		 (when (match-specialization (car spec) (cdr args) match)
+		   (specialize-node! node (cadr spec))))
+	       specs)))
 	  r))))
   (define (procedure-type? t)
     (or (eq? 'procedure t)
@@ -475,6 +496,11 @@
 	     (or (eq? 'procedure (car t))
 		 (and (eq? 'or (car t))
 		      (every procedure-type? (cdr t)))))))
+  (define (procedure-name t)
+    (and (pair? t)
+	 (eq? 'procedure (car t))
+	 (or (string? (cadr t)) (symbol? (cadr t)))
+	 (->string (cadr t))))
   (define (procedure-argument-types t n)
     (cond ((or (memq t '(* procedure)) 
 	       (not-pair? t)
@@ -620,7 +646,7 @@
 				      f)
 				     (walk n e loc #f #f) loc))
 				  subs (iota (length subs)))))
-		  (call-result args e loc (first subs) params)))
+		  (call-result n args e loc params)))
 	       ((##core#switch ##core#cond)
 		(bomb "unexpected node class: ~a" class))
 	       (else
@@ -638,11 +664,32 @@
      (lambda (e)
        (let* ((name (car e))
 	      (old (##sys#get name '##core#type))
-	      (new (cadr e)))
+	      (new (cadr e))
+	      (specs (and (pair? (cddr e)) (cddr e))))
 	 (when (and old (not (equal? old new)))
 	   (##sys#notice
 	    (sprintf
 		"type-definition `~a' for toplevel binding `~a' conflicts with previously loaded type `~a'"
 		name new old)))
-	 (##sys#put! name '##core#type new)))
+	 (##sys#put! name '##core#type new)
+	 (when specs
+	   (##sys#put! name '##core#specializations specs))))
      (read-file dbfile))))
+
+(define (match-specialization typelist atypes match)
+  (let loop ((tl typelist) (atypes atypes))
+    (cond ((null? tl) (null? atypes))
+	  ((null? atypes) #f)
+	  ((eq? (car tl) '#!rest)
+	   (every (cute match (cadr tl) <>) atypes))
+	  ((match (car tl) (car atypes)) (loop (cdr tl) (cdr atypes)))
+	  (else #f))))
+
+(define (specialize-node! node template)
+  (let ((args (cdr (node-subexpressions node))))
+    (define (subst x)
+      (cond ((fixnum? x) (list-ref args x))
+	    ((not (pair? x)) x)
+	    ((eq? 'quote (car x)) x)
+	    (else (cons (subst (car x)) (subst (cdr x))))))
+    (copy-node! (build-node-graph (subst template)) node)))
diff --git a/support.scm b/support.scm
index 4c84cd99..34cf3400 100644
--- a/support.scm
+++ b/support.scm
@@ -1212,144 +1212,6 @@
 	    [else (loop (sub1 i))] ) ) ) )
 
 
-;;; Print version/usage information:
-
-(define (print-version #!optional b)
-  (when b (print* +banner+))
-  (print (chicken-version #t)) )
-
-(define (print-usage)
-  (print-version)
-  (newline)
-  (display #<<EOF
-Usage: chicken FILENAME OPTION ...
-
-  `chicken' is the CHICKEN compiler.
-  
-  FILENAME should be a complete source file name with extension, or "-" for
-  standard input. OPTION may be one of the following:
-
-  General options:
-
-    -help                        display this text and exit
-    -version                     display compiler version and exit
-    -release                     print release number and exit
-    -verbose                     display information on compilation progress
-
-  File and pathname options:
-
-    -output-file FILENAME        specifies output-filename, default is 'out.c'
-    -include-path PATHNAME       specifies alternative path for included files
-    -to-stdout                   write compiled file to stdout instead of file
-
-  Language options:
-
-    -feature SYMBOL              register feature identifier
-    -no-feature SYMBOL           disable built-in feature identifier
-
-  Syntax related options:
-
-    -case-insensitive            don't preserve case of read symbols
-    -keyword-style STYLE         allow alternative keyword syntax
-                                  (prefix, suffix or none)
-    -no-parentheses-synonyms     disables list delimiter synonyms
-    -no-symbol-escape            disables support for escaped symbols
-    -r5rs-syntax                 disables the Chicken extensions to
-                                  R5RS syntax
-    -compile-syntax              macros are made available at run-time
-    -emit-import-library MODULE  write compile-time module information into
-                                  separate file
-    -emit-all-import-libraries   emit import-libraries for all defined modules
-    -no-module-registration      do not generate module registration code
-    -no-compiler-syntax          disable expansion of compiler-macros
-    -module                      wrap compiled code into implicit module
-
-  Translation options:
-
-    -explicit-use                do not use units 'library' and 'eval' by
-                                  default
-    -check-syntax                stop compilation after macro-expansion
-    -analyze-only                stop compilation after first analysis pass
-
-  Debugging options:
-
-    -no-warnings                 disable warnings
-    -debug-level NUMBER          set level of available debugging information
-    -no-trace                    disable tracing information
-    -profile                     executable emits profiling information 
-    -profile-name FILENAME       name of the generated profile information file
-    -accumulate-profile          executable emits profiling information in
-                                  append mode
-    -no-lambda-info              omit additional procedure-information
-    -scrutinize                  perform local flow analysis for static checks
-    -picky                       perform more static checks (implies -scrutinize)
-    -types FILENAME              load additional type database
-
-  Optimization options:
-
-    -optimize-level NUMBER       enable certain sets of optimization options
-    -optimize-leaf-routines      enable leaf routine optimization
-    -lambda-lift                 enable lambda-lifting
-    -no-usual-integrations       standard procedures may be redefined
-    -unsafe                      disable all safety checks
-    -local                       assume globals are only modified in current
-                                  file
-    -block                       enable block-compilation
-    -disable-interrupts          disable interrupts in compiled code
-    -fixnum-arithmetic           assume all numbers are fixnums
-    -benchmark-mode              equivalent to 'block -optimize-level 4
-                                  -debug-level 0 -fixnum-arithmetic -lambda-lift
-                                  -inline -disable-interrupts'
-    -disable-stack-overflow-checks  disables detection of stack-overflows
-    -inline                      enable inlining
-    -inline-limit LIMIT          set inlining threshold
-    -inline-global               enable cross-module inlining
-    -unboxing                    use unboxed temporaries if possible
-    -emit-inline-file FILENAME   generate file with globally inlinable
-                                  procedures (implies -inline -local)
-    -consult-inline-file FILENAME  explicitly load inline file
-    -no-argc-checks              disable argument count checks
-    -no-bound-checks             disable bound variable checks
-    -no-procedure-checks         disable procedure call checks
-    -no-procedure-checks-for-usual-bindings
-                                 disable procedure call checks only for usual
-                                  bindings
-    -no-procedure-checks-for-toplevel-bindings
-                                   disable procedure call checks for toplevel
-                                    bindings
-
-  Configuration options:
-
-    -unit NAME                   compile file as a library unit
-    -uses NAME                   declare library unit as used.
-    -heap-size NUMBER            specifies heap-size of compiled executable
-    -heap-initial-size NUMBER    specifies heap-size at startup time
-    -heap-growth PERCENTAGE      specifies growth-rate of expanding heap
-    -heap-shrinkage PERCENTAGE   specifies shrink-rate of contracting heap
-    -nursery NUMBER  -stack-size NUMBER
-                                 specifies nursery size of compiled executable
-    -extend FILENAME             load file before compilation commences
-    -prelude EXPRESSION          add expression to front of source file
-    -postlude EXPRESSION         add expression to end of source file
-    -prologue FILENAME           include file before main source file
-    -epilogue FILENAME           include file after main source file
-    -dynamic                     compile as dynamically loadable code
-    -require-extension NAME      require and import extension NAME
-
-  Obscure options:
-
-    -debug MODES                 display debugging output for the given modes
-    -raw                         do not generate implicit init- and exit code                           
-    -emit-external-prototypes-first
-                                 emit prototypes for callbacks before foreign
-                                  declarations
-    -ignore-repository           do not refer to repository for extensions
-    -setup-mode                  prefer the current directory when locating extensions
-
-EOF
-) )
-
-
 ;;; Special block-variable literal type:
 
 (define-record-type block-variable-literal 
@@ -1563,3 +1425,142 @@ EOF
 	  id '##core#db
 	  (append (or (##sys#get id '##core#db) '()) (list (cdr e))) )))
      (read-file dbfile))))
+
+
+;;; Print version/usage information:
+
+(define (print-version #!optional b)
+  (when b (print* +banner+))
+  (print (chicken-version #t)) )
+
+(define (print-usage)
+  (print-version)
+  (newline)
+  (display #<<EOF
+Usage: chicken FILENAME OPTION ...
+
+  `chicken' is the CHICKEN compiler.
+  
+  FILENAME should be a complete source file name with extension, or "-" for
+  standard input. OPTION may be one of the following:
+
+  General options:
+
+    -help                        display this text and exit
+    -version                     display compiler version and exit
+    -release                     print release number and exit
+    -verbose                     display information on compilation progress
+
+  File and pathname options:
+
+    -output-file FILENAME        specifies output-filename, default is 'out.c'
+    -include-path PATHNAME       specifies alternative path for included files
+    -to-stdout                   write compiled file to stdout instead of file
+
+  Language options:
+
+    -feature SYMBOL              register feature identifier
+    -no-feature SYMBOL           disable built-in feature identifier
+
+  Syntax related options:
+
+    -case-insensitive            don't preserve case of read symbols
+    -keyword-style STYLE         allow alternative keyword syntax
+                                  (prefix, suffix or none)
+    -no-parentheses-synonyms     disables list delimiter synonyms
+    -no-symbol-escape            disables support for escaped symbols
+    -r5rs-syntax                 disables the Chicken extensions to
+                                  R5RS syntax
+    -compile-syntax              macros are made available at run-time
+    -emit-import-library MODULE  write compile-time module information into
+                                  separate file
+    -emit-all-import-libraries   emit import-libraries for all defined modules
+    -no-module-registration      do not generate module registration code
+    -no-compiler-syntax          disable expansion of compiler-macros
+    -module                      wrap compiled code into implicit module
+
+  Translation options:
+
+    -explicit-use                do not use units 'library' and 'eval' by
+                                  default
+    -check-syntax                stop compilation after macro-expansion
+    -analyze-only                stop compilation after first analysis pass
+
+  Debugging options:
+
+    -no-warnings                 disable warnings
+    -debug-level NUMBER          set level of available debugging information
+    -no-trace                    disable tracing information
+    -profile                     executable emits profiling information 
+    -profile-name FILENAME       name of the generated profile information file
+    -accumulate-profile          executable emits profiling information in
+                                  append mode
+    -no-lambda-info              omit additional procedure-information
+    -scrutinize                  perform local flow analysis for static checks
+    -picky                       perform more static checks (implies -scrutinize)
+    -types FILENAME              load additional type database
+
+  Optimization options:
+
+    -optimize-level NUMBER       enable certain sets of optimization options
+    -optimize-leaf-routines      enable leaf routine optimization
+    -lambda-lift                 enable lambda-lifting
+    -no-usual-integrations       standard procedures may be redefined
+    -unsafe                      disable all safety checks
+    -local                       assume globals are only modified in current
+                                  file
+    -block                       enable block-compilation
+    -disable-interrupts          disable interrupts in compiled code
+    -fixnum-arithmetic           assume all numbers are fixnums
+    -benchmark-mode              equivalent to 'block -optimize-level 4
+                                  -debug-level 0 -fixnum-arithmetic -lambda-lift
+                                  -inline -disable-interrupts'
+    -disable-stack-overflow-checks  disables detection of stack-overflows
+    -inline                      enable inlining
+    -inline-limit LIMIT          set inlining threshold
+    -inline-global               enable cross-module inlining
+    -specialize                  perform type-based specialization of primitive calls
+    -unboxing                    use unboxed temporaries if possible
+    -emit-inline-file FILENAME   generate file with globally inlinable
+                                  procedures (implies -inline -local)
+    -consult-inline-file FILENAME  explicitly load inline file
+    -no-argc-checks              disable argument count checks
+    -no-bound-checks             disable bound variable checks
+    -no-procedure-checks         disable procedure call checks
+    -no-procedure-checks-for-usual-bindings
+                                 disable procedure call checks only for usual
+                                  bindings
+    -no-procedure-checks-for-toplevel-bindings
+                                   disable procedure call checks for toplevel
+                                    bindings
+
+  Configuration options:
+
+    -unit NAME                   compile file as a library unit
+    -uses NAME                   declare library unit as used.
+    -heap-size NUMBER            specifies heap-size of compiled executable
+    -heap-initial-size NUMBER    specifies heap-size at startup time
+    -heap-growth PERCENTAGE      specifies growth-rate of expanding heap
+    -heap-shrinkage PERCENTAGE   specifies shrink-rate of contracting heap
+    -nursery NUMBER  -stack-size NUMBER
+                                 specifies nursery size of compiled executable
+    -extend FILENAME             load file before compilation commences
+    -prelude EXPRESSION          add expression to front of source file
+    -postlude EXPRESSION         add expression to end of source file
+    -prologue FILENAME           include file before main source file
+    -epilogue FILENAME           include file after main source file
+    -dynamic                     compile as dynamically loadable code
+    -require-extension NAME      require and import extension NAME
+
+  Obscure options:
+
+    -debug MODES                 display debugging output for the given modes
+    -raw                         do not generate implicit init- and exit code                           
+    -emit-external-prototypes-first
+                                 emit prototypes for callbacks before foreign
+                                  declarations
+    -ignore-repository           do not refer to repository for extensions
+    -setup-mode                  prefer the current directory when locating extensions
+
+EOF
+) )
Trap