Next: compiler global assign, Previous: compiler sanitise bindings, Up: compiler [Index]
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)
.
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.
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: compiler global assign, Previous: compiler sanitise bindings, Up: compiler [Index]