Next: , Previous: , Up: compiler   [Index]


17.16 Optimisation for direct jumps

Let’s consider the following code in which the lambda sexp has not been integrated at the call site:

(let ((f (lambda (x) x)))
  (f 123))

by inspecting this code we can verify at compile–time that that f references a clambda and the application form has the correct number of operands; Vicare offers a technique to implement a “full closure object application” (f 123) as a faster “direct jump call” to the clambda clause with the correct number of operands. Another example, when the clambda has multiple clauses:

(let ((f (case-lambda
           ((x)   x)
           ((x y) (list x y)))))
  (f 1 2))

by inspecting this code we can verify at compile–time that f references a clambda and that it is called with 2 arguments: there is technique that allows to implement the application (f 1 2) as a direct jump to the clause with 2 arguments.

The following bindings are exported by the library (vicare compiler).

Function: pass-optimize-for-direct-jumps input

Perform code optimisation traversing the whole hierarchy in input, which must be a struct instance representing recordised code, and building a new hierarchy of optimised, recordised code; return the new hierarchy.

Transform funcall structs into jmpcall structs whenever in the application form:

(funcall ?operator ?operand ...)

the operator is a binding reference known to reference a clambda struct.

Upon entering this transformation: all the clambda structs must appear in the input as right–hand side initialisation expressions of fix structs; all the bind structs must have a non–clambda struct as right–hand side initialisation expression.

Examples

Let’s see some example in which we have disable function integration in application forms. The standard code:

(let ((f (case-lambda
           ((a)   1)
           ((a b) 2))))
  (list (f 1) (f 1 2)))

is transformed into:

(fix ((f_0 (case-lambda
             ((a_0)     (constant 1))
             ((a_1 b_0) (constant 2)))))
  (funcall (primref list)
    (jmpcall asmlabel:f:clambda:case-1
             f_0 (constant 1))
    (jmpcall asmlabel:f:clambda:case-2
             f_0 (constant 1) (constant 2))))

where asmlabel:f:clambda:case-1 is a placeholder for the address of the machine code entry point of the first case of the clambda bound to f_0 (the one with 1 argument); asmlabel:f:clambda:case-2 represents the machine code entry point of the second case.

The following core language code defines a recursive function:

(letrec ((f (case-lambda
              (()  (f '1))
              ((a) a))))
  ((primitive list) (f) (f '2)))

and it is transformed into:

(fix ((f_0 (case-lambda
             (()
              (jmpcall asmlabel:f:clambda:case-1
                       f_0 (constant 1)))
             ((a_0)
              a_0))))
  (funcall (primref list)
    (jmpcall asmlabel:f:clambda:case-0
             f_0)
    (jmpcall asmlabel:f:clambda:case-1
             f_0 (constant 2))))

where we see the recursive function call is also optimised as direct jump.


Next: , Previous: , Up: compiler   [Index]