diff options
| author | Vibhav Pant | 2020-08-21 14:04:35 +0530 |
|---|---|---|
| committer | Vibhav Pant | 2020-08-21 14:04:35 +0530 |
| commit | f0f8d7b82492e741950c363a03b886965c91b1b0 (patch) | |
| tree | 19b716830b1ebabc0d7d75949c4e6800c0f104ad /src/comp.c | |
| parent | 9e64a087c4d167e7ec1c4e22bea3e6af53b563de (diff) | |
| parent | c818c29771d3cb51875643b2f6c894073e429dd2 (diff) | |
| download | emacs-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.c | 150 |
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 | ||
| 640 | static Lisp_Object | ||
| 641 | comp_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 | ||
| 639 | void | 652 | void |
| @@ -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. */ | ||
| 3865 | static Lisp_Object loadsearch_re_list; | ||
| 3866 | |||
| 3867 | DEFUN ("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. | ||
| 3870 | If 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 | |||
| 3855 | DEFUN ("comp--init-ctxt", Fcomp__init_ctxt, Scomp__init_ctxt, | 3929 | DEFUN ("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 | ||
| 4123 | DEFUN ("comp-libgccjit-version", Fcomp_libgccjit_version, | 4197 | DEFUN ("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'. */ | ||
| 4580 | void | ||
| 4581 | fixup_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 | |||
| 4500 | typedef char *(*comp_lit_str_func) (void); | 4599 | typedef 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 |
| 4972 | being loaded. | ||
| 4973 | |||
| 4974 | Once compilation happened each function definition is updated to the | ||
| 4975 | native 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 | |||
| 5133 | If a directory is non absolute is assumed to be relative to | ||
| 5134 | `invocation-directory'. | ||
| 5135 | The 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); |