aboutsummaryrefslogtreecommitdiffstats
path: root/src/comp.c
diff options
context:
space:
mode:
authorVibhav Pant2020-08-21 14:04:35 +0530
committerVibhav Pant2020-08-21 14:04:35 +0530
commitf0f8d7b82492e741950c363a03b886965c91b1b0 (patch)
tree19b716830b1ebabc0d7d75949c4e6800c0f104ad /src/comp.c
parent9e64a087c4d167e7ec1c4e22bea3e6af53b563de (diff)
parentc818c29771d3cb51875643b2f6c894073e429dd2 (diff)
downloademacs-feature/native-comp-macos-fixes.tar.gz
emacs-feature/native-comp-macos-fixes.zip
Merge branch 'feature/native-comp' into feature/native-comp-macos-fixesfeature/native-comp-macos-fixes
Diffstat (limited to 'src/comp.c')
-rw-r--r--src/comp.c150
1 files changed, 137 insertions, 13 deletions
diff --git a/src/comp.c b/src/comp.c
index 704bd4b6b35..ff73245b8de 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -29,6 +29,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
29#include <stdio.h> 29#include <stdio.h>
30#include <signal.h> 30#include <signal.h>
31#include <libgccjit.h> 31#include <libgccjit.h>
32#include <epaths.h>
32 33
33#include "puresize.h" 34#include "puresize.h"
34#include "window.h" 35#include "window.h"
@@ -393,6 +394,8 @@ load_gccjit_if_necessary (bool mandatory)
393} 394}
394 395
395 396
397#define ELN_FILENAME_HASH_LEN 64
398
396/* C symbols emitted for the load relocation mechanism. */ 399/* C symbols emitted for the load relocation mechanism. */
397#define CURRENT_THREAD_RELOC_SYM "current_thread_reloc" 400#define CURRENT_THREAD_RELOC_SYM "current_thread_reloc"
398#define PURE_RELOC_SYM "pure_reloc" 401#define PURE_RELOC_SYM "pure_reloc"
@@ -634,6 +637,16 @@ format_string (const char *format, ...)
634 return scratch_area; 637 return scratch_area;
635} 638}
636 639
640static Lisp_Object
641comp_hash_string (Lisp_Object string)
642{
643 Lisp_Object digest = make_uninit_string (SHA512_DIGEST_SIZE * 2);
644 sha512_buffer (SSDATA (string), SCHARS (string), SSDATA (digest));
645 hexbuf_digest (SSDATA (digest), SDATA (digest), SHA512_DIGEST_SIZE);
646
647 return digest;
648}
649
637/* Produce a key hashing Vcomp_subr_list. */ 650/* Produce a key hashing Vcomp_subr_list. */
638 651
639void 652void
@@ -641,10 +654,7 @@ hash_native_abi (void)
641{ 654{
642 Lisp_Object string = Fmapconcat (intern_c_string ("subr-name"), 655 Lisp_Object string = Fmapconcat (intern_c_string ("subr-name"),
643 Vcomp_subr_list, build_string (" ")); 656 Vcomp_subr_list, build_string (" "));
644 Lisp_Object digest = make_uninit_string (SHA512_DIGEST_SIZE * 2); 657 Lisp_Object digest = comp_hash_string (string);
645
646 sha512_buffer (SSDATA (string), SCHARS (string), SSDATA (digest));
647 hexbuf_digest (SSDATA (digest), SDATA (digest), SHA512_DIGEST_SIZE);
648 658
649 /* Check runs once. */ 659 /* Check runs once. */
650 eassert (NILP (Vcomp_abi_hash)); 660 eassert (NILP (Vcomp_abi_hash));
@@ -652,8 +662,7 @@ hash_native_abi (void)
652 /* If 10 characters are usually sufficient for git I guess 16 are 662 /* If 10 characters are usually sufficient for git I guess 16 are
653 fine for us here. */ 663 fine for us here. */
654 Vcomp_native_path_postfix = 664 Vcomp_native_path_postfix =
655 concat3 (make_string ("eln-", 4), 665 concat2 (Vsystem_configuration,
656 Vsystem_configuration,
657 concat2 (make_string ("-", 1), 666 concat2 (make_string ("-", 1),
658 Fsubstring_no_properties (Vcomp_abi_hash, 667 Fsubstring_no_properties (Vcomp_abi_hash,
659 make_fixnum (0), 668 make_fixnum (0),
@@ -3852,6 +3861,71 @@ compile_function (Lisp_Object func)
3852/* Entry points exposed to lisp. */ 3861/* Entry points exposed to lisp. */
3853/**********************************/ 3862/**********************************/
3854 3863
3864/* In use by Fcomp_el_to_eln_filename. */
3865static Lisp_Object loadsearch_re_list;
3866
3867DEFUN ("comp-el-to-eln-filename", Fcomp_el_to_eln_filename,
3868 Scomp_el_to_eln_filename, 1, 2, 0,
3869 doc: /* Given a source file return the corresponding .eln true filename.
3870If BASE-DIR is nil use the first entry in `comp-eln-load-path'. */)
3871 (Lisp_Object filename, Lisp_Object base_dir)
3872{
3873 CHECK_STRING (filename);
3874
3875 if (suffix_p (filename, ".gz"))
3876 filename = Fsubstring (filename, Qnil, make_fixnum (-3));
3877 filename = Fexpand_file_name (filename, Qnil);
3878
3879 /* We create eln filenames with an hash in order to look-up these
3880 starting from the source filename, IOW have a relation
3881 /absolute/path/filename.el -> eln-cache/filename-hash.eln.
3882
3883 As installing .eln files compiled during the build changes their
3884 absolute path we need an hashing mechanism that is not sensitive
3885 to that. For this we replace if match PATH_DUMPLOADSEARCH or
3886 PATH_LOADSEARCH with '//' before generating the hash.
3887
3888 Another approach would be to hash using the source file content
3889 but this may have a measurable performance impact. */
3890
3891 if (NILP (loadsearch_re_list))
3892 {
3893 Lisp_Object loadsearch_list =
3894 Fcons (build_string (PATH_DUMPLOADSEARCH),
3895 Fcons (build_string (PATH_LOADSEARCH), Qnil));
3896 FOR_EACH_TAIL (loadsearch_list)
3897 loadsearch_re_list =
3898 Fcons (Fregexp_quote (XCAR (loadsearch_list)), loadsearch_re_list);
3899 }
3900 Lisp_Object loadsearch_res = loadsearch_re_list;
3901 FOR_EACH_TAIL (loadsearch_res)
3902 {
3903 Lisp_Object match_idx =
3904 Fstring_match (XCAR (loadsearch_res), filename, Qnil);
3905 if (EQ (match_idx, make_fixnum (0)))
3906 {
3907 filename =
3908 Freplace_match (build_string ("//"), Qt, Qt, filename, Qnil);
3909 break;
3910 }
3911 }
3912
3913 Lisp_Object hash = Fsubstring (comp_hash_string (filename), Qnil,
3914 make_fixnum (ELN_FILENAME_HASH_LEN));
3915 filename = concat2 (Ffile_name_nondirectory (Fsubstring (filename, Qnil,
3916 make_fixnum (-3))),
3917 build_string ("-"));
3918 filename = concat3 (filename, hash, build_string (NATIVE_ELISP_SUFFIX));
3919 if (NILP (base_dir))
3920 base_dir = XCAR (Vcomp_eln_load_path);
3921
3922 if (!file_name_absolute_p (SSDATA (base_dir)))
3923 base_dir = Fexpand_file_name (base_dir, Vinvocation_directory);
3924
3925 return Fexpand_file_name (filename,
3926 concat2 (base_dir, Vcomp_native_path_postfix));
3927}
3928
3855DEFUN ("comp--init-ctxt", Fcomp__init_ctxt, Scomp__init_ctxt, 3929DEFUN ("comp--init-ctxt", Fcomp__init_ctxt, Scomp__init_ctxt,
3856 0, 0, 0, 3930 0, 0, 0,
3857 doc: /* Initialize the native compiler context. Return t on success. */) 3931 doc: /* Initialize the native compiler context. Return t on success. */)
@@ -4039,11 +4113,12 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file,
4039 Scomp__compile_ctxt_to_file, 4113 Scomp__compile_ctxt_to_file,
4040 1, 1, 0, 4114 1, 1, 0,
4041 doc: /* Compile as native code the current context to file. */) 4115 doc: /* Compile as native code the current context to file. */)
4042 (Lisp_Object base_name) 4116 (Lisp_Object file_name)
4043{ 4117{
4044 load_gccjit_if_necessary (true); 4118 load_gccjit_if_necessary (true);
4045 4119
4046 CHECK_STRING (base_name); 4120 CHECK_STRING (file_name);
4121 Lisp_Object base_name = Fsubstring (file_name, Qnil, make_fixnum (-4));
4047 4122
4048 gcc_jit_context_set_int_option (comp.ctxt, 4123 gcc_jit_context_set_int_option (comp.ctxt,
4049 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL, 4124 GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL,
@@ -4105,19 +4180,18 @@ DEFUN ("comp--compile-ctxt-to-file", Fcomp__compile_ctxt_to_file,
4105 4180
4106 AUTO_STRING (dot_so, NATIVE_ELISP_SUFFIX); 4181 AUTO_STRING (dot_so, NATIVE_ELISP_SUFFIX);
4107 4182
4108 Lisp_Object out_file = CALLN (Fconcat, base_name, dot_so);
4109 Lisp_Object tmp_file = 4183 Lisp_Object tmp_file =
4110 Fmake_temp_file_internal (base_name, Qnil, dot_so, Qnil); 4184 Fmake_temp_file_internal (base_name, Qnil, dot_so, Qnil);
4111 gcc_jit_context_compile_to_file (comp.ctxt, 4185 gcc_jit_context_compile_to_file (comp.ctxt,
4112 GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY, 4186 GCC_JIT_OUTPUT_KIND_DYNAMIC_LIBRARY,
4113 SSDATA (tmp_file)); 4187 SSDATA (tmp_file));
4114 4188
4115 CALL2I (comp--replace-output-file, out_file, tmp_file); 4189 CALL2I (comp--replace-output-file, file_name, tmp_file);
4116 4190
4117 if (!noninteractive) 4191 if (!noninteractive)
4118 unbind_to (count, Qnil); 4192 unbind_to (count, Qnil);
4119 4193
4120 return out_file; 4194 return file_name;
4121} 4195}
4122 4196
4123DEFUN ("comp-libgccjit-version", Fcomp_libgccjit_version, 4197DEFUN ("comp-libgccjit-version", Fcomp_libgccjit_version,
@@ -4462,7 +4536,11 @@ maybe_defer_native_compilation (Lisp_Object function_name,
4462 concat2 (CALL1I (file-name-sans-extension, Vload_true_file_name), 4536 concat2 (CALL1I (file-name-sans-extension, Vload_true_file_name),
4463 build_pure_c_string (".el")); 4537 build_pure_c_string (".el"));
4464 if (NILP (Ffile_exists_p (src))) 4538 if (NILP (Ffile_exists_p (src)))
4465 return; 4539 {
4540 src = concat2 (src, build_pure_c_string (".gz"));
4541 if (NILP (Ffile_exists_p (src)))
4542 return;
4543 }
4466 4544
4467 /* This is to have deferred compilaiton able to compile comp 4545 /* This is to have deferred compilaiton able to compile comp
4468 dependecies breaking circularity. */ 4546 dependecies breaking circularity. */
@@ -4497,6 +4575,27 @@ maybe_defer_native_compilation (Lisp_Object function_name,
4497/* Functions used to load eln files. */ 4575/* Functions used to load eln files. */
4498/**************************************/ 4576/**************************************/
4499 4577
4578/* Fixup the system eln-cache dir. This is the last entry in
4579 `comp-eln-load-path'. */
4580void
4581fixup_eln_load_path (Lisp_Object directory)
4582{
4583 Lisp_Object last_cell = Qnil;
4584 Lisp_Object tmp = Vcomp_eln_load_path;
4585 FOR_EACH_TAIL (tmp)
4586 if (CONSP (tmp))
4587 last_cell = tmp;
4588
4589 Lisp_Object eln_cache_sys =
4590 Ffile_name_directory (concat2 (Vinvocation_directory,
4591 directory));
4592 /* One directory up... */
4593 eln_cache_sys =
4594 Ffile_name_directory (Fsubstring (eln_cache_sys, Qnil,
4595 make_fixnum (-1)));
4596 Fsetcar (last_cell, eln_cache_sys);
4597}
4598
4500typedef char *(*comp_lit_str_func) (void); 4599typedef char *(*comp_lit_str_func) (void);
4501 4600
4502/* Deserialize read and return static object. */ 4601/* Deserialize read and return static object. */
@@ -4869,7 +4968,13 @@ syms_of_comp (void)
4869#ifdef HAVE_NATIVE_COMP 4968#ifdef HAVE_NATIVE_COMP
4870 /* Compiler control customizes. */ 4969 /* Compiler control customizes. */
4871 DEFVAR_BOOL ("comp-deferred-compilation", comp_deferred_compilation, 4970 DEFVAR_BOOL ("comp-deferred-compilation", comp_deferred_compilation,
4872 doc: /* If t compile asyncronously every .elc file loaded. */); 4971 doc: /* If non-nil compile asyncronously all .elc files
4972being loaded.
4973
4974Once compilation happened each function definition is updated to the
4975native compiled one. */);
4976 comp_deferred_compilation = true;
4977
4873 DEFSYM (Qcomp_speed, "comp-speed"); 4978 DEFSYM (Qcomp_speed, "comp-speed");
4874 DEFSYM (Qcomp_debug, "comp-debug"); 4979 DEFSYM (Qcomp_debug, "comp-debug");
4875 4980
@@ -4971,6 +5076,7 @@ syms_of_comp (void)
4971 build_pure_c_string ("eln file inconsistent with current runtime " 5076 build_pure_c_string ("eln file inconsistent with current runtime "
4972 "configuration, please recompile")); 5077 "configuration, please recompile"));
4973 5078
5079 defsubr (&Scomp_el_to_eln_filename);
4974 defsubr (&Scomp__init_ctxt); 5080 defsubr (&Scomp__init_ctxt);
4975 defsubr (&Scomp__release_ctxt); 5081 defsubr (&Scomp__release_ctxt);
4976 defsubr (&Scomp__compile_ctxt_to_file); 5082 defsubr (&Scomp__compile_ctxt_to_file);
@@ -4989,6 +5095,8 @@ syms_of_comp (void)
4989 comp.emitter_dispatcher = Qnil; 5095 comp.emitter_dispatcher = Qnil;
4990 staticpro (&delayed_sources); 5096 staticpro (&delayed_sources);
4991 delayed_sources = Qnil; 5097 delayed_sources = Qnil;
5098 staticpro (&loadsearch_re_list);
5099 loadsearch_re_list = Qnil;
4992 5100
4993#ifdef WINDOWSNT 5101#ifdef WINDOWSNT
4994 staticpro (&all_loaded_comp_units_h); 5102 staticpro (&all_loaded_comp_units_h);
@@ -5015,6 +5123,22 @@ syms_of_comp (void)
5015 internal use during */); 5123 internal use during */);
5016 Vcomp_deferred_pending_h = CALLN (Fmake_hash_table, QCtest, Qeq); 5124 Vcomp_deferred_pending_h = CALLN (Fmake_hash_table, QCtest, Qeq);
5017 5125
5126 DEFVAR_LISP ("comp-eln-to-el-h", Vcomp_eln_to_el_h,
5127 doc: /* Hash table eln-filename -> el-filename. */);
5128 Vcomp_eln_to_el_h = CALLN (Fmake_hash_table, QCtest, Qequal);
5129
5130 DEFVAR_LISP ("comp-eln-load-path", Vcomp_eln_load_path,
5131 doc: /* List of eln cache directories.
5132
5133If a directory is non absolute is assumed to be relative to
5134`invocation-directory'.
5135The last directory of this list is assumed to be the system one. */);
5136
5137 /* Temporary value in use for boostrap. We can't do better as
5138 `invocation-directory' is still unset, will be fixed up during
5139 dump reload. */
5140 Vcomp_eln_load_path = Fcons (build_string ("../eln-cache/"), Qnil);
5141
5018#endif /* #ifdef HAVE_NATIVE_COMP */ 5142#endif /* #ifdef HAVE_NATIVE_COMP */
5019 5143
5020 defsubr (&Snative_comp_available_p); 5144 defsubr (&Snative_comp_available_p);