~ chicken-core (chicken-5) 4bb4631943d477324ebf2570fc295c4cbfe752d1
commit 4bb4631943d477324ebf2570fc295c4cbfe752d1 Author: Peter Bex <peter@more-magic.net> AuthorDate: Thu Nov 21 17:06:26 2019 +0100 Commit: Evan Hanson <evhan@foldling.org> CommitDate: Sun Nov 24 15:39:07 2019 +1300 Add new ##core#rest-length form which speeds up case-lambda A case-lambda form will simply expand into something like (lambda rest (case (length rest) ((0) zero-arg-case) ((1) one-arg-case) ...)) The length call is the only thing that is "special", as can be verified with a simple test case like this: (define foo (case-lambda ((x) (+ x 1)) ((x y) (* x y)))) (print (foo 1)) (print (foo 2 3)) Signed-off-by: Evan Hanson <evhan@foldling.org> diff --git a/NEWS b/NEWS index dde34053..477ffa40 100644 --- a/NEWS +++ b/NEWS @@ -38,7 +38,7 @@ - Inline files no longer refer to unexported foreign stub functions (fixes #1440, thanks to "megane"). - In some cases, rest argument lists do not need to be reified, which - should make using optional arguments faster (#1623). + should make using optional arguments and case-lambda faster (#1623). - Module system - Trying to export a foreign variable, define-inlined procedure or diff --git a/c-backend.scm b/c-backend.scm index 2af59829..ef8c12b1 100644 --- a/c-backend.scm +++ b/c-backend.scm @@ -199,6 +199,15 @@ (gen "C_rest_nullp(c," (+ depth n) ")") (gen "C_mk_bool(C_unfix(C_i_length(t" (sub1 n) ")) >= " depth ")")))) + ((##core#rest-length) + (let* ((n (lambda-literal-argument-count ll)) + (depth (second params)) + (have-av? (not (or (lambda-literal-customizable ll) + (lambda-literal-direct ll))))) + (if have-av? + (gen "C_fix(c - " (+ depth n) ")") + (gen "C_u_i_length(t" (sub1 n) ")")))) + ((##core#unbox) (gen "((C_word*)") (expr (car subs) i) diff --git a/core.scm b/core.scm index baeacb67..4623122b 100644 --- a/core.scm +++ b/core.scm @@ -180,7 +180,8 @@ ; [##core#switch {<count>} <exp> <const1> <body1> ... <defaultbody>] ; [##core#rest-car {restvar depth [<debug-info>]}] ; [##core#rest-cdr {restvar depth [<debug-info>]}] -; [##core#rest-null? {restvar depth [<debug-info>]} <restvar>] +; [##core#rest-null? {restvar depth [<debug-info>]}] +; [##core#rest-length {restvar depth [<debug-info>]}] ; [##core#cond <exp> <exp> <exp>] ; [##core#provide <id>] ; [##core#recurse {<tail-flag>} <exp1> ...] @@ -2634,7 +2635,7 @@ (make-node '##core#unbox '() (list val)) val) ) ) - ((##core#rest-cdr ##core#rest-car ##core#rest-null?) + ((##core#rest-cdr ##core#rest-car ##core#rest-null? ##core#rest-length) (let* ((rest-var (first params)) (val (ref-var n here closure))) (unless (eq? val n) @@ -2665,6 +2666,11 @@ (list "C_i_greater_or_equal_p") (list (qnode (second params)) (make-node '##core#inline (list "C_i_length") (list (varnode rest-var))))) here closure)) + ((and (eq? class '##core#rest-length) + (test here 'customizable)) + (transform (make-node '##core#inline + (list "C_i_length") + (list (varnode rest-var) (second params))) here closure)) (else val)) ) ) ((if ##core#call ##core#inline ##core#inline_allocate ##core#callunit diff --git a/optimizer.scm b/optimizer.scm index b14b72f3..384557af 100644 --- a/optimizer.scm +++ b/optimizer.scm @@ -200,6 +200,7 @@ ((member native '("C_i_car" "C_u_i_car")) '##core#rest-car) ((member native '("C_i_cdr" "C_u_i_cdr")) '##core#rest-cdr) ((member native '("C_i_nullp")) '##core#rest-null?) + ((member native '("C_i_length" "C_u_i_length")) '##core#rest-length) (else #f))) (arg (first (node-subexpressions node))) ((eq? '##core#variable (node-class arg)))Trap