aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/comp.c213
-rw-r--r--src/comp.h10
-rw-r--r--src/data.c20
-rw-r--r--src/pdumper.c1
4 files changed, 219 insertions, 25 deletions
diff --git a/src/comp.c b/src/comp.c
index ac45eb72cfc..4227a502693 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -480,10 +480,12 @@ load_gccjit_if_necessary (bool mandatory)
480#define DATA_RELOC_EPHEMERAL_SYM "d_reloc_eph" 480#define DATA_RELOC_EPHEMERAL_SYM "d_reloc_eph"
481 481
482#define FUNC_LINK_TABLE_SYM "freloc_link_table" 482#define FUNC_LINK_TABLE_SYM "freloc_link_table"
483#define LOCAL_FUNC_LINK_TABLE_SYM "local_freloc_link_table"
483#define LINK_TABLE_HASH_SYM "freloc_hash" 484#define LINK_TABLE_HASH_SYM "freloc_hash"
484#define COMP_UNIT_SYM "comp_unit" 485#define COMP_UNIT_SYM "comp_unit"
485#define TEXT_DATA_RELOC_SYM "text_data_reloc" 486#define TEXT_DATA_RELOC_SYM "text_data_reloc"
486#define TEXT_DATA_RELOC_EPHEMERAL_SYM "text_data_reloc_eph" 487#define TEXT_DATA_RELOC_EPHEMERAL_SYM "text_data_reloc_eph"
488#define TEXT_LOCAL_FUNC_C_NAMES_SYM "text_local_func_c_names"
487 489
488#define TEXT_OPTIM_QLY_SYM "text_optim_qly" 490#define TEXT_OPTIM_QLY_SYM "text_optim_qly"
489#define TEXT_FDOC_SYM "text_data_fdoc" 491#define TEXT_FDOC_SYM "text_data_fdoc"
@@ -650,6 +652,10 @@ typedef struct {
650 gcc_jit_type *func_relocs_ptr_type; 652 gcc_jit_type *func_relocs_ptr_type;
651 /* Pointer to this structure local to each function. */ 653 /* Pointer to this structure local to each function. */
652 gcc_jit_lvalue *func_relocs_local; 654 gcc_jit_lvalue *func_relocs_local;
655 /* Per compilation unit redirection table for local named functions. */
656 gcc_jit_lvalue *local_func_relocs;
657 gcc_jit_lvalue *local_func_relocs_local;
658 Lisp_Object local_func_reloc_idx_h; /* c-name -> relocation index. */
653 gcc_jit_function *memcpy; 659 gcc_jit_function *memcpy;
654 Lisp_Object d_default_idx; 660 Lisp_Object d_default_idx;
655 Lisp_Object d_ephemeral_idx; 661 Lisp_Object d_ephemeral_idx;
@@ -947,6 +953,9 @@ emit_comment (const char *str)
947 str); 953 str);
948} 954}
949 955
956static gcc_jit_rvalue *emit_coerce (gcc_jit_type *new_type,
957 gcc_jit_rvalue *obj);
958
950/* 959/*
951 Declare an imported function. 960 Declare an imported function.
952 When nargs is MANY (ptrdiff_t nargs, Lisp_Object *args) signature is assumed. 961 When nargs is MANY (ptrdiff_t nargs, Lisp_Object *args) signature is assumed.
@@ -1013,18 +1022,55 @@ static gcc_jit_rvalue *
1013emit_call (Lisp_Object func, gcc_jit_type *ret_type, ptrdiff_t nargs, 1022emit_call (Lisp_Object func, gcc_jit_type *ret_type, ptrdiff_t nargs,
1014 gcc_jit_rvalue **args, bool direct) 1023 gcc_jit_rvalue **args, bool direct)
1015{ 1024{
1016 Lisp_Object gcc_func =
1017 Fgethash (func,
1018 direct ? comp.exported_funcs_h : comp.imported_funcs_h,
1019 Qnil);
1020
1021 if (NILP (gcc_func))
1022 xsignal2 (Qnative_ice,
1023 build_string ("missing function declaration"),
1024 func);
1025
1026 if (direct) 1025 if (direct)
1027 { 1026 {
1027 Lisp_Object local_idx = Qnil;
1028 if (comp.func_speed == 2)
1029 local_idx = Fgethash (func, comp.local_func_reloc_idx_h, Qnil);
1030 if (!NILP (local_idx))
1031 {
1032 USE_SAFE_ALLOCA;
1033 gcc_jit_type **types;
1034 SAFE_NALLOCA (types, 1, nargs);
1035 for (ptrdiff_t i = 0; i < nargs; ++i)
1036 types[i] = gcc_jit_rvalue_get_type (args[i]);
1037
1038 gcc_jit_type *f_ptr_type =
1039 gcc_jit_type_get_const (
1040 gcc_jit_context_new_function_ptr_type (comp.ctxt,
1041 NULL,
1042 ret_type,
1043 nargs,
1044 types,
1045 0));
1046 gcc_jit_lvalue *f_ptr =
1047 gcc_jit_context_new_array_access (
1048 comp.ctxt,
1049 NULL,
1050 gcc_jit_lvalue_as_rvalue (comp.local_func_relocs_local
1051 ? comp.local_func_relocs_local
1052 : comp.local_func_relocs),
1053 gcc_jit_context_new_rvalue_from_int (comp.ctxt,
1054 comp.ptrdiff_type,
1055 XFIXNUM (local_idx)));
1056 gcc_jit_rvalue *res =
1057 gcc_jit_context_new_call_through_ptr (
1058 comp.ctxt,
1059 NULL,
1060 emit_coerce (f_ptr_type, gcc_jit_lvalue_as_rvalue (f_ptr)),
1061 nargs,
1062 args);
1063 SAFE_FREE ();
1064 emit_comment (format_string ("direct call via local reloc to: %s",
1065 SSDATA (func)));
1066 return res;
1067 }
1068
1069 Lisp_Object gcc_func = Fgethash (func, comp.exported_funcs_h, Qnil);
1070 if (NILP (gcc_func))
1071 xsignal2 (Qnative_ice,
1072 build_string ("missing function declaration"),
1073 func);
1028 emit_comment (format_string ("direct call to: %s", 1074 emit_comment (format_string ("direct call to: %s",
1029 SSDATA (func))); 1075 SSDATA (func)));
1030 return gcc_jit_context_new_call (comp.ctxt, 1076 return gcc_jit_context_new_call (comp.ctxt,
@@ -1035,6 +1081,11 @@ emit_call (Lisp_Object func, gcc_jit_type *ret_type, ptrdiff_t nargs,
1035 } 1081 }
1036 else 1082 else
1037 { 1083 {
1084 Lisp_Object gcc_func = Fgethash (func, comp.imported_funcs_h, Qnil);
1085 if (NILP (gcc_func))
1086 xsignal2 (Qnative_ice,
1087 build_string ("missing function declaration"),
1088 func);
1038 /* Inline functions so far don't have a local variable for 1089 /* Inline functions so far don't have a local variable for
1039 function reloc table so we fall back to the global one. Even 1090 function reloc table so we fall back to the global one. Even
1040 if this is not aesthetic calling into C from open-code is 1091 if this is not aesthetic calling into C from open-code is
@@ -2981,6 +3032,14 @@ emit_ctxt_code (void)
2981 emit_static_object (TEXT_FDOC_SYM, 3032 emit_static_object (TEXT_FDOC_SYM,
2982 CALLNI (comp-ctxt-function-docs, Vcomp_ctxt)); 3033 CALLNI (comp-ctxt-function-docs, Vcomp_ctxt));
2983 3034
3035 Lisp_Object local_func_c_names
3036 = CALLNI (comp--cu-local-func-c-name-v, Vcomp_ctxt);
3037 emit_static_object (TEXT_LOCAL_FUNC_C_NAMES_SYM, local_func_c_names);
3038 CHECK_VECTOR (local_func_c_names);
3039 for (EMACS_INT i = 0; i < ASIZE (local_func_c_names); ++i)
3040 Fputhash (AREF (local_func_c_names, i), make_fixnum (i),
3041 comp.local_func_reloc_idx_h);
3042
2984 comp.current_thread_ref = 3043 comp.current_thread_ref =
2985 gcc_jit_lvalue_as_rvalue ( 3044 gcc_jit_lvalue_as_rvalue (
2986 gcc_jit_context_new_global ( 3045 gcc_jit_context_new_global (
@@ -2999,6 +3058,13 @@ emit_ctxt_code (void)
2999 comp.bool_ptr_type, 3058 comp.bool_ptr_type,
3000 F_SYMBOLS_WITH_POS_ENABLED_RELOC_SYM)); 3059 F_SYMBOLS_WITH_POS_ENABLED_RELOC_SYM));
3001 3060
3061 comp.local_func_relocs =
3062 gcc_jit_context_new_global (comp.ctxt,
3063 NULL,
3064 GCC_JIT_GLOBAL_EXPORTED,
3065 gcc_jit_type_get_pointer (comp.void_ptr_type),
3066 LOCAL_FUNC_LINK_TABLE_SYM);
3067
3002 gcc_jit_context_new_global ( 3068 gcc_jit_context_new_global (
3003 comp.ctxt, 3069 comp.ctxt,
3004 NULL, 3070 NULL,
@@ -4186,6 +4252,11 @@ compile_function (Lisp_Object func)
4186 NULL, 4252 NULL,
4187 comp.func_relocs_ptr_type, 4253 comp.func_relocs_ptr_type,
4188 "freloc"); 4254 "freloc");
4255 comp.local_func_relocs_local =
4256 gcc_jit_function_new_local (comp.func,
4257 NULL,
4258 gcc_jit_type_get_pointer (comp.void_ptr_type),
4259 "local_freloc");
4189 4260
4190 SAFE_NALLOCA (comp.frame, 1, comp.frame_size); 4261 SAFE_NALLOCA (comp.frame, 1, comp.frame_size);
4191 if (comp.func_has_non_local || !comp.func_speed) 4262 if (comp.func_has_non_local || !comp.func_speed)
@@ -4242,6 +4313,10 @@ compile_function (Lisp_Object func)
4242 NULL, 4313 NULL,
4243 comp.func_relocs_local, 4314 comp.func_relocs_local,
4244 gcc_jit_lvalue_as_rvalue (comp.func_relocs)); 4315 gcc_jit_lvalue_as_rvalue (comp.func_relocs));
4316 gcc_jit_block_add_assignment (retrieve_block (Qentry),
4317 NULL,
4318 comp.local_func_relocs_local,
4319 gcc_jit_lvalue_as_rvalue (comp.local_func_relocs));
4245 4320
4246 4321
4247 DOHASH (ht, block_name, block) 4322 DOHASH (ht, block_name, block)
@@ -4617,8 +4692,9 @@ Return t on success. */)
4617 /* 4692 /*
4618 Always reinitialize this cause old function definitions are garbage 4693 Always reinitialize this cause old function definitions are garbage
4619 collected by libgccjit when the ctxt is released. 4694 collected by libgccjit when the ctxt is released.
4620 */ 4695 */
4621 comp.imported_funcs_h = Fmake_hash_table (0, NULL); 4696 comp.imported_funcs_h = Fmake_hash_table (0, NULL);
4697 comp.local_func_reloc_idx_h = CALLN (Fmake_hash_table, QCtest, Qequal);
4622 4698
4623 define_memcpy (); 4699 define_memcpy ();
4624 4700
@@ -4774,6 +4850,7 @@ DEFUN ("comp--compile-ctxt-to-file0", Fcomp__compile_ctxt_to_file0,
4774 Lisp_Object ebase_name = ENCODE_FILE (base_name); 4850 Lisp_Object ebase_name = ENCODE_FILE (base_name);
4775 4851
4776 comp.func_relocs_local = NULL; 4852 comp.func_relocs_local = NULL;
4853 comp.local_func_relocs_local = NULL;
4777 4854
4778#ifdef WINDOWSNT 4855#ifdef WINDOWSNT
4779 ebase_name = ansi_encode_filename (ebase_name); 4856 ebase_name = ansi_encode_filename (ebase_name);
@@ -5266,22 +5343,47 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump,
5266 dynlib_sym (handle, F_SYMBOLS_WITH_POS_ENABLED_RELOC_SYM); 5343 dynlib_sym (handle, F_SYMBOLS_WITH_POS_ENABLED_RELOC_SYM);
5267 Lisp_Object *data_relocs = comp_u->data_relocs; 5344 Lisp_Object *data_relocs = comp_u->data_relocs;
5268 void **freloc_link_table = dynlib_sym (handle, FUNC_LINK_TABLE_SYM); 5345 void **freloc_link_table = dynlib_sym (handle, FUNC_LINK_TABLE_SYM);
5346 void ***local_freloc_link_table
5347 = dynlib_sym (handle, LOCAL_FUNC_LINK_TABLE_SYM);
5348 Lisp_Object local_func_c_names =
5349 load_static_obj (comp_u, TEXT_LOCAL_FUNC_C_NAMES_SYM);
5269 5350
5270 if (!(current_thread_reloc 5351 if (!(current_thread_reloc
5271 && f_symbols_with_pos_enabled_reloc 5352 && f_symbols_with_pos_enabled_reloc
5272 && data_relocs 5353 && data_relocs
5273 && data_eph_relocs 5354 && data_eph_relocs
5274 && freloc_link_table 5355 && freloc_link_table
5356 && local_freloc_link_table
5275 && top_level_run) 5357 && top_level_run)
5276 || NILP (Fstring_equal (load_static_obj (comp_u, LINK_TABLE_HASH_SYM), 5358 || NILP (Fstring_equal (load_static_obj (comp_u, LINK_TABLE_HASH_SYM),
5277 Vcomp_abi_hash))) 5359 Vcomp_abi_hash)))
5278 xsignal1 (Qnative_lisp_file_inconsistent, comp_u->file); 5360 xsignal1 (Qnative_lisp_file_inconsistent, comp_u->file);
5361 if (!VECTORP (local_func_c_names))
5362 xsignal2 (Qnative_lisp_file_inconsistent, comp_u->file,
5363 build_string ("missing local function relocation vector"));
5279 5364
5280 *current_thread_reloc = &current_thread; 5365 *current_thread_reloc = &current_thread;
5281 *f_symbols_with_pos_enabled_reloc = &symbols_with_pos_enabled; 5366 *f_symbols_with_pos_enabled_reloc = &symbols_with_pos_enabled;
5282 5367
5283 /* Imported functions. */ 5368 /* Imported functions. */
5284 *freloc_link_table = freloc.link_table; 5369 *freloc_link_table = freloc.link_table;
5370 ptrdiff_t n_local_frelocs = ASIZE (local_func_c_names);
5371 comp_u->local_func_relocs =
5372 n_local_frelocs
5373 ? xnmalloc (n_local_frelocs, sizeof (*comp_u->local_func_relocs))
5374 : NULL;
5375 *local_freloc_link_table = comp_u->local_func_relocs;
5376 for (ptrdiff_t i = 0; i < n_local_frelocs; ++i)
5377 {
5378 Lisp_Object c_name = AREF (local_func_c_names, i);
5379 if (!STRINGP (c_name))
5380 xsignal2 (Qnative_lisp_file_inconsistent, comp_u->file,
5381 build_string ("invalid local function relocation name"));
5382 void *func = dynlib_sym (handle, SSDATA (c_name));
5383 if (!func)
5384 xsignal2 (Qnative_lisp_file_inconsistent, comp_u->file, c_name);
5385 comp_u->local_func_relocs[i] = func;
5386 }
5285 5387
5286 /* Imported data. */ 5388 /* Imported data. */
5287 if (!loading_dump) 5389 if (!loading_dump)
@@ -5351,6 +5453,8 @@ unload_comp_unit (struct Lisp_Native_Comp_Unit *cu)
5351 if (EQ (this_cu, *saved_cu)) 5453 if (EQ (this_cu, *saved_cu))
5352 *saved_cu = Qnil; 5454 *saved_cu = Qnil;
5353 dynlib_close (cu->handle); 5455 dynlib_close (cu->handle);
5456 xfree (cu->local_func_relocs);
5457 cu->local_func_relocs = NULL;
5354} 5458}
5355 5459
5356Lisp_Object 5460Lisp_Object
@@ -5370,6 +5474,70 @@ native_function_doc (Lisp_Object function)
5370 return make_fixnum (doc); 5474 return make_fixnum (doc);
5371} 5475}
5372 5476
5477static ptrdiff_t
5478find_comp_unit_local_func_reloc_idx (struct Lisp_Native_Comp_Unit *cu,
5479 const char *c_name)
5480{
5481 Lisp_Object names = load_static_obj (cu, TEXT_LOCAL_FUNC_C_NAMES_SYM);
5482 if (!VECTORP (names))
5483 xsignal2 (Qnative_lisp_file_inconsistent, cu->file,
5484 build_string ("missing local function relocation vector"));
5485
5486 Lisp_Object target = build_string (c_name);
5487 ptrdiff_t len = ASIZE (names);
5488 for (ptrdiff_t i = 0; i < len; ++i)
5489 if (!NILP (Fstring_equal (AREF (names, i), target)))
5490 return i;
5491
5492 return -1;
5493}
5494
5495bool
5496native_comp_local_function_p (Lisp_Object function)
5497{
5498 if (!NATIVE_COMP_FUNCTIONP (function))
5499 return false;
5500
5501 struct Lisp_Native_Comp_Unit *cu =
5502 XNATIVE_COMP_UNIT (Fsubr_native_comp_unit (function));
5503
5504 return (cu->local_func_relocs
5505 && find_comp_unit_local_func_reloc_idx (
5506 cu, XSUBR (function)->native_c_name) >= 0);
5507}
5508
5509DEFUN ("comp--install-local-function-trampoline",
5510 Fcomp__install_local_function_trampoline,
5511 Scomp__install_local_function_trampoline, 2, 2, 0,
5512 doc: /* Install TRAMPOLINE for speed-2 local native-compiled FUNCTION. */)
5513 (Lisp_Object function, Lisp_Object trampoline)
5514{
5515 CHECK_SUBR (function);
5516 CHECK_SUBR (trampoline);
5517 CHECK_TYPE (NATIVE_COMP_FUNCTIONP (function), Qnative_comp_function,
5518 function);
5519
5520 if (will_dump_p ())
5521 signal_error ("Trying to advice unexpected native function before dumping",
5522 function);
5523
5524 struct Lisp_Native_Comp_Unit *cu =
5525 XNATIVE_COMP_UNIT (Fsubr_native_comp_unit (function));
5526 if (!cu->local_func_relocs)
5527 signal_error ("Trying to install trampoline for unloaded compilation unit",
5528 function);
5529
5530 ptrdiff_t idx = find_comp_unit_local_func_reloc_idx (
5531 cu, XSUBR (function)->native_c_name);
5532 if (idx < 0)
5533 signal_error ("Trying to install trampoline for non existent local native function",
5534 function);
5535
5536 cu->local_func_relocs[idx] = XSUBR (trampoline)->function.a0;
5537 Fputhash (trampoline, Qt, cu->lambda_gc_guard_h);
5538 return Qt;
5539}
5540
5373static Lisp_Object 5541static Lisp_Object
5374make_subr (Lisp_Object symbol_name, Lisp_Object minarg, Lisp_Object maxarg, 5542make_subr (Lisp_Object symbol_name, Lisp_Object minarg, Lisp_Object maxarg,
5375 Lisp_Object c_name, Lisp_Object type, Lisp_Object doc_idx, 5543 Lisp_Object c_name, Lisp_Object type, Lisp_Object doc_idx,
@@ -5697,6 +5865,7 @@ natively compiled one. */);
5697 defsubr (&Scomp_native_driver_options_effective_p); 5865 defsubr (&Scomp_native_driver_options_effective_p);
5698 defsubr (&Scomp_native_compiler_options_effective_p); 5866 defsubr (&Scomp_native_compiler_options_effective_p);
5699 defsubr (&Scomp__install_trampoline); 5867 defsubr (&Scomp__install_trampoline);
5868 defsubr (&Scomp__install_local_function_trampoline);
5700 defsubr (&Scomp__init_ctxt); 5869 defsubr (&Scomp__init_ctxt);
5701 defsubr (&Scomp__release_ctxt); 5870 defsubr (&Scomp__release_ctxt);
5702 defsubr (&Scomp__compile_ctxt_to_file0); 5871 defsubr (&Scomp__compile_ctxt_to_file0);
@@ -5710,6 +5879,8 @@ natively compiled one. */);
5710 comp.exported_funcs_h = Qnil; 5879 comp.exported_funcs_h = Qnil;
5711 staticpro (&comp.imported_funcs_h); 5880 staticpro (&comp.imported_funcs_h);
5712 comp.imported_funcs_h = Qnil; 5881 comp.imported_funcs_h = Qnil;
5882 staticpro (&comp.local_func_reloc_idx_h);
5883 comp.local_func_reloc_idx_h = Qnil;
5713 staticpro (&comp.func_blocks_h); 5884 staticpro (&comp.func_blocks_h);
5714 staticpro (&comp.emitter_dispatcher); 5885 staticpro (&comp.emitter_dispatcher);
5715 comp.emitter_dispatcher = Qnil; 5886 comp.emitter_dispatcher = Qnil;
@@ -5759,14 +5930,15 @@ Emacs. */);
5759 5930
5760 DEFVAR_LISP ("native-comp-enable-subr-trampolines", 5931 DEFVAR_LISP ("native-comp-enable-subr-trampolines",
5761 Vnative_comp_enable_subr_trampolines, 5932 Vnative_comp_enable_subr_trampolines,
5762 doc: /* If non-nil, enable generation of trampolines for calling primitives. 5933 doc: /* If non-nil, enable generation of trampolines for optimized calls.
5763Trampolines are needed so that Emacs respects redefinition or advice of 5934Trampolines are needed so that Emacs respects redefinition or advice of
5764primitive functions when they are called from native-compiled Lisp code 5935primitive functions, and redefinition of named native-compiled
5765at `native-comp-speed' of 2. 5936functions inside the same compilation unit, when these calls are
5937optimized by native compilation at speed 2.
5766 5938
5767By default, the value is t, and when Emacs sees a redefined or advised 5939By default, the value is t, and when Emacs sees a redefined or advised
5768primitive called from native-compiled Lisp, it generates a trampoline 5940optimized function called from native-compiled Lisp, it generates a
5769for it on-the-fly. 5941trampoline for it on-the-fly.
5770 5942
5771If the value is a file name (a string), it specifies the directory in 5943If the value is a file name (a string), it specifies the directory in
5772which to deposit the generated trampolines, overriding the directories 5944which to deposit the generated trampolines, overriding the directories
@@ -5775,12 +5947,9 @@ in `native-comp-eln-load-path'.
5775When this variable is nil, generation of trampolines is disabled. 5947When this variable is nil, generation of trampolines is disabled.
5776 5948
5777Disabling the generation of trampolines, when a trampoline for a redefined 5949Disabling the generation of trampolines, when a trampoline for a redefined
5778or advised primitive is not already available from previous compilations, 5950or advised optimized function is not already available, means that such
5779means that such redefinition or advice will not have effect when calling 5951redefinition or advice will not have effect when calling that function
5780primitives from native-compiled Lisp code. That is, calls to primitives 5952from native-compiled Lisp code. */);
5781without existing trampolines from native-compiled Lisp will behave as if
5782the primitive was called directly from C, and will ignore its redefinition
5783and advice. */);
5784 5953
5785 DEFVAR_LISP ("comp-installed-trampolines-h", Vcomp_installed_trampolines_h, 5954 DEFVAR_LISP ("comp-installed-trampolines-h", Vcomp_installed_trampolines_h,
5786 doc: /* Hash table subr-name -> installed trampoline. 5955 doc: /* Hash table subr-name -> installed trampoline.
diff --git a/src/comp.h b/src/comp.h
index 16f2aab7b9a..5b4fec9d132 100644
--- a/src/comp.h
+++ b/src/comp.h
@@ -44,6 +44,7 @@ struct Lisp_Native_Comp_Unit
44 Lisp_Object data_vec; 44 Lisp_Object data_vec;
45 /* STUFFS WE DO NOT DUMP!! */ 45 /* STUFFS WE DO NOT DUMP!! */
46 Lisp_Object *data_relocs; 46 Lisp_Object *data_relocs;
47 void **local_func_relocs;
47 bool loaded_once; 48 bool loaded_once;
48 bool load_ongoing; 49 bool load_ongoing;
49 dynlib_handle_ptr handle; 50 dynlib_handle_ptr handle;
@@ -75,6 +76,8 @@ extern Lisp_Object load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u,
75 76
76extern void unload_comp_unit (struct Lisp_Native_Comp_Unit *); 77extern void unload_comp_unit (struct Lisp_Native_Comp_Unit *);
77 78
79extern bool native_comp_local_function_p (Lisp_Object function);
80
78extern Lisp_Object native_function_doc (Lisp_Object function); 81extern Lisp_Object native_function_doc (Lisp_Object function);
79 82
80extern void syms_of_comp (void); 83extern void syms_of_comp (void);
@@ -97,6 +100,13 @@ static inline
97void unload_comp_unit (struct Lisp_Native_Comp_Unit *cu) 100void unload_comp_unit (struct Lisp_Native_Comp_Unit *cu)
98{} 101{}
99 102
103static inline bool
104native_comp_local_function_p (Lisp_Object function)
105{
106 (void) function;
107 return false;
108}
109
100extern void syms_of_comp (void); 110extern void syms_of_comp (void);
101 111
102INLINE_HEADER_END 112INLINE_HEADER_END
diff --git a/src/data.c b/src/data.c
index 4973d577c1c..2360033bb6b 100644
--- a/src/data.c
+++ b/src/data.c
@@ -912,10 +912,24 @@ signal a `cyclic-function-indirection' error. */)
912 register Lisp_Object function = XSYMBOL (symbol)->u.s.function; 912 register Lisp_Object function = XSYMBOL (symbol)->u.s.function;
913 913
914 if (!NILP (Vnative_comp_enable_subr_trampolines) 914 if (!NILP (Vnative_comp_enable_subr_trampolines)
915 && SUBRP (function)
916 && !NATIVE_COMP_FUNCTIONP (function)
917 && !EQ (definition, Fsymbol_function (symbol))) 915 && !EQ (definition, Fsymbol_function (symbol)))
918 calln (Qcomp_subr_trampoline_install, symbol); 916 {
917 if (SUBRP (function) && !NATIVE_COMP_FUNCTIONP (function))
918 calln (Qcomp_subr_trampoline_install, symbol);
919 else if (NATIVE_COMP_FUNCTIONP (function))
920 {
921 if (!EQ (symbol, intern_c_string ("--anonymous-lambda"))
922 && native_comp_local_function_p (function)
923 && !(NATIVE_COMP_FUNCTIONP (definition)
924 && EQ (Fsubr_native_comp_unit (function),
925 Fsubr_native_comp_unit (definition))))
926 {
927 calln (intern_c_string ("require"), intern_c_string ("comp-run"));
928 calln (intern_c_string ("comp-local-function-trampoline-install"),
929 symbol, function);
930 }
931 }
932 }
919#endif 933#endif
920 934
921 set_symbol_function (symbol, definition); 935 set_symbol_function (symbol, definition);
diff --git a/src/pdumper.c b/src/pdumper.c
index c21af24d9f1..7108aa64788 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2960,6 +2960,7 @@ dump_native_comp_unit (struct dump_context *ctx,
2960 START_DUMP_PVEC (ctx, &comp_u->header, struct Lisp_Native_Comp_Unit, out); 2960 START_DUMP_PVEC (ctx, &comp_u->header, struct Lisp_Native_Comp_Unit, out);
2961 dump_pseudovector_lisp_fields (ctx, &out->header, &comp_u->header); 2961 dump_pseudovector_lisp_fields (ctx, &out->header, &comp_u->header);
2962 out->handle = NULL; 2962 out->handle = NULL;
2963 out->local_func_relocs = NULL;
2963 2964
2964 dump_off comp_u_off = finish_dump_pvec (ctx, &out->header); 2965 dump_off comp_u_off = finish_dump_pvec (ctx, &out->header);
2965 if (ctx->flags.dump_object_contents) 2966 if (ctx->flags.dump_object_contents)