Add a simple pass to infer pure functions not explicitly declared as
such. Use this information only during compilation (speed 3) to
optimize out function calls whe possible.
* lisp/emacs-lisp/comp.el (comp-c-func-name): Add FIRST argument
to ignore the compiler context and return the first name.
* lisp/emacs-lisp/disass.el (disassemble-internal): Update the
`comp-c-func-name' call.
Lambda-lists must stay in the same relocation class of the object
referenced by code to respect uninterned symbols.
* lisp/emacs-lisp/comp.el (comp-prepare-args-for-top-level): Break
the original function in a generic specializing for
dynamic/lexical functions. When allocating the lambda-list for
dynamic functions do that in the default relocation class.
(comp-emit-for-top-level): Make use of the new
`comp-prepare-args-for-top-level'.
(comp-emit-lambda-for-top-level): Likewise.
* lisp/emacs-lisp/comp.el (comp-func): New slot 'pure'.
(comp-spill-decl-spec): New function.
(comp-spill-speed): Rework to use the later.
(comp-spill-lap-function, comp-intern-func-in-ctxt): Spill pure
decl value.
(comp-function-optimizable-p): Check in the compiler env too if
pure.
* src/comp.c (COMP_SPEED): Rename.
(comp_t): Add 'func_speed' field.
(emit_mvar_lval, compile_function): Update for per function speed.
(Fcomp__compile_ctxt_to_file): COMP_SPEED renamed.
* lisp/emacs-lisp/comp.el (comp-speed): Doc update.
(comp-func): New 'speed' slot.
(comp-spill-speed): New function.
(comp-spill-lap-function, comp-intern-func-in-ctxt): Fill 'speed'
slot.
(comp-spill-lap-function): Gate -1 speed functions for native
compilation and emit bytecode instead.
(comp-spill-lap): Close over `byte-to-native-plist-environment'.
(comp-latch-make-fill): Update for per function speed.
(comp-limplify-top-level): Fill speed.
(comp-propagate1, comp-call-optim-form-call, comp-call-optim)
(comp-dead-code, comp-tco, comp-remove-type-hints): Update for per
function speed.
Add an initial implementation to support dynamic scope. Arg
parsing/binding it's done using the existing code in use for
bytecode (no ad-hoc code is synthetized for that).
* src/lisp.h (struct Lisp_Subr): Add lambda_list field.
(SUBR_NATIVE_COMPILED_DYNP): New inliner.
* src/alloc.c (mark_object): Update for Add lambda_list field.
* src/eval.c (eval_sub, Ffuncall, funcall_lambda): Handle native
compiled dynamic scope
* src/comp.c (declare_lex_function): Rename from declare_function
and rework.
(declare_function): New function.
(make_subr): Handle daynamic scope
* src/pdumper.c (dump_subr): Update for lambda_list field.
* lisp/emacs-lisp/comp.el (comp-func): Remove args slot.
(comp-func-l, comp-func-d): New classes deriving from `comp-func'.
(comp-spill-lap-function): Rework.
(comp-prepare-args-for-top-level): New function.
(comp-emit-for-top-level, comp-emit-lambda-for-top-level): Make
use of `comp-prepare-args-for-top-level'.
(comp-limplify-top-level): Use `comp-func-l'.
(comp-limplify-function): Emit arg prologue only for dynamic
scoped functions.
(comp-call-optim-form-call): Use `comp-func-l'.
(comp-call-optim, comp-tco): Do not optimize dynamic scoped code.
Define a new kind of basic block 'latch' to close over loops. Its
purpose is for now to emit calls to `comp-maybe-gc-or-quit' but in
future will be usefull for the loop optimizer to exploit unboxes.
* lisp/emacs-lisp/comp.el (comp-block): New base class.
(comp-block-lap): New class for LAP derived basic blocks.
(comp-latch): New class.
(comp-bb-maybe-add, comp-make-curr-block, comp-emit-handler)
(comp-emit-switch, comp-emit-switch, comp-limplify-top-level)
(comp-addr-to-bb-name, comp-limplify-block)
(comp-limplify-function): Update logic for new bb objects
arrangment.
(comp-latch-make-fill): New function.
(comp-emit-uncond-jump, comp-emit-cond-jump): Update to emit
latches.
(comp-new-block-sym): Add a postfix paramenter.
As function folding can generate 'setimm' insns handle them in the
`comp-propagate-insn'.
* lisp/emacs-lisp/comp.el (comp-propagate-insn): Handle 'setimm'
insn.
* lisp/emacs-lisp/comp.el (comp-symbol-values-optimizable): New
defconst.
(comp-function-call-maybe-remove): New logic to to remove
unnecessary `symbol-value' calls.
Do not perform trampoline optimization at speed 3 on function if their
name is not unique inside the compilation unit. Note that the
function can still be redefined in any other way therefore this is a
mitigation.
* lisp/emacs-lisp/comp.el (comp-func-unique-in-cu-p): New
predicate.
(comp-call-optim-form-call): Perform trampoline optimization
for named functions only if they are unique within the current
compilation unit.
Is cleaner to have the function c-name as first argument of
'direct-call' 'direct-callref'. This is preparatory to anonymous
lambdas optimization.
* lisp/emacs-lisp/comp.el (comp-propagate-insn): Use c-name when
gathering the comp-func definition for direct calls.
(comp-call-optim-form-call): Add put c-name as first argument of
direct-call direct-callref when optimizing.
* src/comp.c (emit_call): Update logic for having c-name as
first arg of direct calls.
(emit_call_ref): Rename 'subr_sym' into 'func'.
* lisp/emacs-lisp/comp.el (comp-loop-insn-in-block): New macro.
(comp-call-optim-func, comp-dead-assignments-func)
(comp-remove-type-hints-func): Use `comp-loop-insn-in-block'.
Given SSA prop overwrite mvar type slot we clean-up the compiler type
hints as last.
* lisp/emacs-lisp/comp.el (comp-passes): Add comp-remove-type-hints.
(comp-remove-type-hints-func): Code move.
(comp-dead-code): Do not call `comp-remove-type-hints-func'.
(comp-remove-type-hints): Add as new pass.
When closing emacs will inspect all directories from which it loaded
native compilation units. If it finds a ".eln.old" file it will try to
delete it, if it fails that means that another Emacs instance is using it.
When compiling a file we rename the file that was in the output path
in case it has been loaded into another Emacs instance.
When deleting a package we move any ".eln" or ".eln.old" files in the
package folder that we can't delete to `package-user-dir`. Emacs will
check that directory when closing and delete them.
* lisp/emacs-lisp/comp.el (comp--replace-output-file): Function called
from C code to finish the compilation process. It performs renaming of
the old file if necessary.
* lisp/emacs-lisp/package.el (package--delete-directory): Function to
delete a package directory. It moves native compilation units that it
can't delete to `package-user-dir'.
* src/alloc.c (cleanup_vector): Call dispose_comp_unit().
(garbage_collect): Call finish_delayed_disposal_of_comp_units().
* src/comp.c: Restore the signal mask using unwind-protect. Store
loaded native compilation units in a hash table for disposal on
close. Store filenames of native compilation units GC'd in a linked
list to finish their disposal when the GC is over.
(clean_comp_unit_directory): Delete all *.eln.old files in a
directory.
(clean_package_user_dir_of_old_comp_units): Delete all *.eln.old files
in `package-user-dir'.
(dispose_all_remaining_comp_units): Dispose of native compilation
units that are still loaded.
(dispose_comp_unit): Close handle and cleanup directory or arrange for
later cleanup if DELAY is true.
(finish_delayed_disposal_of_comp_units): Dispose of native compilation
units that were GC'd.
(register_native_comp_unit): Register native compilation unit for
disposal when Emacs closes.
* src/comp.h: Introduce cfile member in Lisp_Native_Comp_Unit.
Add declarations of functions that: clean directories of unused native
compilation units, handle disposal of native compilation units.
* src/emacs.c (kill-emacs): Dispose all remaining compilation units
right right before calling exit().
* src/eval.c (internal_condition_case_3, internal_condition_case_4):
Add functions.
* src/lisp.h (internal_condition_case_3, internal_condition_case_4):
Add functions.
* src/pdumper.c (dump_do_dump_relocation): Set cfile to a copy of the
Lisp string specifying the file path.
* lisp/emacs-lisp/comp.el (comp-effective-async-max-jobs): Use
NUMBER_OF_PROCESSORS environment variable if system is Windows NT,
"nproc" if it is in PATH or a default of 1.
* lisp/emacs-lisp/comp.el (comp-run-async-workers): Pass the
compilation commands through a temporary file that is loaded by the
child process. This is also done all other operating systems, even
those that support long command lines. It should not be a problem
since libgccjit uses temporary files too.
* lisp/emacs-lisp/comp.el (comp-num-cpus): New special variable.
(comp-effective-async-max-jobs): Make use of `comp-num-cpus'.
(comp-call-optim-form-call): Remove unnecessary parameter.
(comp-call-optim-func): Reflect `comp-call-optim-form-call'
parameter removal.
* lisp/emacs-lisp/comp.el (comp-never-optimize-functions):
Blacklist all primitives advised by evil-mode from trampoline
optimization.
(comp-call-optim-form-call): Prevent trampoline optimization for
recursive calls at speed 2 to respect elisp original semantic.
* lisp/emacs-lisp/comp.el (comp-lex-byte-func-p): New subst.
(comp-intern-func-in-ctxt): Do not crash if we still encounter a
non lexical scoped lambda.
* src/pdumper.c (dump_do_dump_relocation): While fixing up lambda
relocation verify placeholder coherency.
* src/comp.c (syms_of_comp): Define symbol 'lambda-fixup'.
* lisp/emacs-lisp/comp.el (comp-finalize-container): Leave a
lambda-fixup as placeholder in the relocation as a sanity check.
* lisp/emacs-lisp/comp.el (comp-spill-lap-function): Move code
from to comp-intern-func-in-ctxt.
(comp-intern-func-in-ctxt): New function, this guard
in case byte-to-native-lambda-byte-func is nil.
* lisp/emacs-lisp/comp.el (comp-spill-lap-function): Make use of
byte-to-native-lambdas-h and update for 'byte-to-native-func-def'.
(comp-spill-lap-function): Rework logic to retrive LAP using
'byte-to-native-lambdas-h'.
(comp-emit-for-top-level): Update for 'byte-to-native-function'.
* lisp/emacs-lisp/bytecomp.el: Add commentary on new spill LAP
mechanism.
(byte-to-native-lambda, byte-to-native-func-def): New structures.
(byte-to-native-top-level): Indent.
(byte-to-native-lambdas-h): Update doc.
(byte-compile-lapcode): Add a 'byte-to-native-lambda' instance
into byte-to-native-lambdas-h instead of just LAP.
(byte-compile-file-form-defmumble): Store into
'byte-to-native-func-def' only the byte compiled function, the LAP
will be retrived through 'byte-to-native-lambdas-h'.
(byte-compile-lambda): Return the byte compiled function.
* lisp/emacs-lisp/comp.el (comp-deferred-compilation-black-list):
New customize.
(native-compile-async): Make use of
'comp-deferred-compilation-black-list'.
* lisp/emacs-lisp/comp.el (comp-bootstrap-black-list): New customize.
(batch-native-compile): Rework to make use of
'comp-bootstrap-black-list'.
(batch-byte-native-compile-for-bootstrap): Add assertion to make
logic assumption explicit.
* lisp/emacs-lisp/comp.el (comp-spill-lap-function): No need anymore
to have `byte-native-compiling' bound to free-func.
(comp-spill-lap-function): Make use of `byte-to-native-lap-h' and
clean-up.
(comp-spill-lap-function): Likewise.
* lisp/emacs-lisp/bytecomp.el (byte-to-native-function): Add lap slot.
(byte-to-native-lap): Rename into byte-to-native-lap-h.
(byte-compile-lapcode): Spill lap after having int assembled and
store it into `byte-to-native-lap-h'.
(byte-compile-not-top-level): Remove.
(byte-compile-file-form-defmumble): Fill directly lap slot.
(byte-compile-lambda): Remove `byte-compile-not-top-level'.
(byte-compile-out-toplevel): Restore original code.
(byte-compile-form): Remove `byte-compile-not-top-level'.
(byte-compile-function-form): Likewise.
(byte-compile-flush-pending): No need anymore to set
`byte-compile-current-form' so restore orignal code.