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]