![](https://secure.gravatar.com/avatar/1acb146697fe261dc4e0c1c04f7508ec.jpg?s=120&d=mm&r=g)
I got curious about how I might generate better code for JSS. The JSS reader macro generates a lambda, so the typical pattern one sees is: (#"matches" 'integer ".*a" ) -> ((LAMBDA (#:|#"matches"-first| &REST #:|#"matches"-rest|) (JSS:INVOKE-RESTARGS "matches" #:|#"matches"-first| #:|#"matches"-rest| NIL)) 'INTEGER ".*a") (yes I know this will generate an error at runtime) Right now the compiled code for one such call goes through 3 functions: (JSTATIC "matches" #<java class java.lang.Integer {3BBD30F}> ".*a") (APPLY #<JSTATIC {41D16045}> "matches" #<java class java.lang.Integer {3BBD30F}> (".*a")) (INVOKE-RESTARGS "matches" INTEGER (".*a") NIL) Really we only need: (JSTATIC "matches" #<java class java.lang.Integer {3BBD30F}> ".*a") and we know enough at compile time to generate that form. If only I could figure out where the right hook would be. The only place I could figure to do this is in precompile-function-call [1] With a hook in place, i define the hook as [2] After checking if the function call is one of the JSS ones, the hook transforms ((lambda(a b ) (jss::invoke-restargs-experimental method a b raw?) c d) to (jss::invoke-restargs-experimental method c '(d) raw? t) jss::invoke-restargs-experimental is macro that does the transformation I want. [3] The question is: Is there a more elegant way to do this, or a hook already built that I could use instead of redefining precompile-function-call If not, would it be reasonable to add a hook in the ABCL source so I don't need to patch it to do the optimization. Thanks, Alan [1] (defun precompile-function-call (form) (let ((op (car form))) (when (and (consp op) (eq (%car op) 'LAMBDA)) (return-from precompile-function-call I added this line --- (or (jss-fix-precompile op (mapcar #'precompile1 (cdr form))) --- (cons (precompile-lambda op) (mapcar #'precompile1 (cdr form)))))) (when (or (not *in-jvm-compile*) (notinline-p op)) (return-from precompile-function-call (precompile-cons form))) (when (source-transform op) (let ((new-form (expand-source-transform form))) (when (neq new-form form) (return-from precompile-function-call (precompile1 new-form))))) (when *enable-inline-expansion* (let ((expansion (inline-expansion op))) (when expansion (let ((explain *explain*)) (when (and explain (memq :calls explain)) (format t "; inlining call to ~S~%" op))) (return-from precompile-function-call (precompile1 (expand-inline form expansion)))))) (cons op (mapcar #'precompile1 (cdr form))))) [2] (defun jss-fix-precompile (op args) "Check if this is one of mine, and do the rewrite, otherwise pass" (ignore-errors (let ((body (cddr op))) (if (and (= (length body) 1) (consp (car body)) (eq (caar body) 'jss::invoke-restargs-experimental)) (precompile-function-call `(jss::invoke-restargs-experimental ,(second (car body)) ,(car args) ,(cdr args) ,(fifth (car body)) t)) nil)))) [3] (defmacro invoke-restargs-experimental (&whole form method object args &optional (raw? nil) (precompile nil)) "If I'm precompiling then I can do the transformation. If not I revert to the original method" (if precompile (if (and (consp object) (eq (car object) 'quote)) (let ((object (eval object))) (let* ((object-as-class-name (if (symbolp object) (maybe-resolve-class-against-imports object) )) (object-as-class (if object-as-class-name (find-java-class object-as-class-name)))) (cl-user::print-db object object-as-class-name object-as-class) (if raw? `(jstatic-raw ,method ,object-as-class ,@args) `(jstatic ,method ,object-as-class ,@args)))) (if raw? `(if (symbolp ,object) (jstatic-raw ,method (find-java-class ,object) ,@args) (jcall-raw ,method ,object ,@args)) `(if (symbolp ,object) (jstatic ,method (find-java-class ,object) ,@args) (jcall ,method ,object ,@args)))) `(invoke-restargs ,method ,object ,args ,raw?)))