The deftype expansion functions now take two parameters, the type
argument and an environment. More precisely, for an atomic type 'x the
type argument for the expansion function is given by '(x) while for a
non-atomic type '(x y z) it is given by '(x y z). This also fixes the
value of &whole parameters in deftype lambda lists. The new behaviour
is consistent with SBCL and CCL.
Fixes#750
This commit replaces capturing whole LEX with an explicit vector of closed
variables. We introduce a set of additional opcodes that deal with closed
entities. Locals are referred as lcl and closed variables as lex.
When we were compiling bytecodes with LABELS, the function SET-CLOSURE-ENV
exhibited infinite recursion by adding the record as FLET. C.f test "cmp.0100".
Constant arguments for the dimensions were not handled correctly. The
valid-array-index function was lost in a refactor some time ago.
Moreover, we need to check all of the conditions on the
dimensions (limits on rank, dimension and total size) using an AND
statement instead of checking only the first condition using OR.
Simply call mkdir and ignore EEXIST errors to prevent race conditions
when two processes try to create a directory at the same time. Also
avoids a redundant syscall since by not calling si::file-kind, so this
should be slightly faster.
These are badly optimized by C compilers (even single use static
functions are not inlined by both gcc and clang), so instead of
generating a separate variadic entrypoint just generate one single
entrypoint with C compatible signature.
The presence of setjmp calls in function bodies means that some
function arguments have to be volatile. However, this doesn't apply to
variadic entrypoints which never include setjmp calls. Thus,
set *volatile* to be empty before writing out the header.
Only applies for COMPILE calls where the name of a setf function
definition will not be equal under the EQ test to the name of the same
function at a later call. Thus, we have to use EQUAL to find those
names in the vv array.
For C compatible variadic dispatch, the compiler now generates two
entrypoints for variadic functions. An entrypoint with specialized
signature that is used for direct C calls from the same file and an
entrypoint with generic signature that implements the variadic to
variadic dispatch, i.e. checking the number of arguments and then
calling the specialized entrypoint.
This approach is faster than using the wrapper functions in
variadic_dispatch_table. The reasons are threefold: we save a call to
ecl_process_env(), we don't need a call through a function pointer but
instead use a direct call to the specialized entrypoint and we emit
better code to deal with required arguments since the number of those
are known.
Moreover, for functions with optional arguments the new approach is
less stack hungry since we can allocate an array of size smaller than
ECL_C_ARGUMENTS_LIMIT to store the arguments.
We now generate entrypoints for both fixed and variable number of
arguments. The entrypoint with fixed number of arguments is used for
direct C calls from the same file while the one with variable number
of arguments for indirect calls from other files or via funcall.
This approach is faster than using the wrapper functions in
fixed_dispatch_table as we did previously for two reasons. First, it
does not require a call to ecl_process_env() and second, it can use a
direct jump to the fixed entrypoint once the number of arguments have
been checked instead of an indirect call through a function pointer.
The previous function call sequence for ordinary global functions
looked as follows.
1. check whether the function is defined, i.e. whether
symbol->symbol.gfdef is not NULL
2. set the_env->function to symbol->symbol.gfdef
3. call the function pointer symbol->symbol.gfdef->cfun.entry
This commit implements a performance optimization that enables us to
skip the first step. The basic idea is to replace symbol->symbol.gfdef
with a closure that signals an undefined-function condition.
However, straightforwardly implementing this would have the
disadvantage that it would consume a larger amount of memory for each
symbol without a function definition. To get around this, we reorder
the fields of the ecl_symbol struct such that the symbol can serve as
the function object itself, introducing an entry point that is only
used for undefined functions.
Benchmarking shows an improvement of about 10% in thight loops
compared to the old method.
This prevents further optimizations down the line. By processing
`(function ,fname) with C1EXPR we treat the function as having been
referenced via a function object. Among other things this will prevent
the function from being a lexical closure as the compiler doesn't know
that this function object is unused.
c1form-movable-p uses c1form-pure-p
The predicate opencoded the exact body of the latter.
c1form-unmodified-p does not explicitly check for global-var-p
The function VAR-CHANGED-IN-FORM-LIST takes care of special and global
variables, so there is no need for an explicit check. When the variable is
global and no form has sp-change, then it is still unmodified.
c2expr, t2expr, t3function all uses the macro now. That yields gives better
introspection environment and more regular handling.
Additionally bind a new variable *CURRENT-C1FORM*.
loc-type -> loc-lisp-type (mirrors loc-host-type)
precise-loc-type -> precise-loc-lisp-type (consistency)
Introduce a new WT element in the table FRAME++, with this we don't need to
consider raw strings as locations.
LOC-LISP-TYPE and LOC-HOST-TYPE has tighter checks for types that bark on
unknown location types. When the location is a symbol, we check against all
known atomic locations (cons checks are more lax at the moment).
COERCE-LOCS optional parameters were used only by produce-inline-loc. All other
uses were much simpler, so we've spinned a separate function and removed
optionality of arguments in coerce-locs.
Previously inlined args were not treated as locations (they were CONS, and later
INLINED-ARG). This commit makes inlined args VV instances with an appropriate
type assigned. Thanks to that we may use location operations directly on
arguments.
SI:STRUCTURE-REF, SI:STRUCTURE-SET, SI:INSTANCE-REF, SI:CALL-GLOBAL were all
removed or merged with other operators.
SI:CALL-GLOBAL was incorporated recently to FCALL. In upcoming commits we will
sort this out in a more regular way (by introducing an FCALL-ARG destination).
cmp: check that the type of init-forms for optional and keyword arguments matches their proclaimed types
See merge request embeddable-common-lisp/ecl!316
Eliminate dead branches in IF/AND/OR forms if the type of the object
returned by the test form is known to be null or non-null. Get rid of
unnecessary tests in AND/OR forms if we know that a clause cannot
short-circuit the evaluation. Replace NOT forms by T or NIL constants
if we know that the argument is null or non-null.
Make the types more precise to improve type propagation. We will fall
back to using object-type as appropriate in later stages of the
compilation.
Also return a new copy for each invocation instead of the same *c1nil*
and *c1t* since we may later set the type of the c1form (e.g. in
enforce-types). This can happen for invalid code which can permanently
set the type of *c1nil* to NIL, leading to miscompilations later on
for unrelated valid code.
Fix errors in handling values types for (and) and (or) (all forms but
the last form return only the primary value). Also be more precise if
branches are not taken or the evaluation is known to short circuit.