diff options
| author | AndreaCorallo | 2020-02-25 22:35:02 +0000 |
|---|---|---|
| committer | Andrea Corallo | 2020-02-26 10:40:29 +0000 |
| commit | 94dcb69256a0daea2c51540217c3abdc2fd50552 (patch) | |
| tree | 12fd007e8e632f411a7db59f7548969cc8109351 /src | |
| parent | f0daf1292ccfd6f07b8ded28e29f01919c43022e (diff) | |
| download | emacs-94dcb69256a0daea2c51540217c3abdc2fd50552.tar.gz emacs-94dcb69256a0daea2c51540217c3abdc2fd50552.zip | |
Add ephemeral relocation data class
Add a new class of relocated objects that is in use just during load
process. This in order to avoid having to maintain them in the heap
and traverse them at every GC.
Diffstat (limited to 'src')
| -rw-r--r-- | src/comp.c | 78 |
1 files changed, 62 insertions, 16 deletions
diff --git a/src/comp.c b/src/comp.c index 2f24b10bba0..b6de0ece36a 100644 --- a/src/comp.c +++ b/src/comp.c | |||
| @@ -40,11 +40,13 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 40 | #define PURE_RELOC_SYM "pure_reloc" | 40 | #define PURE_RELOC_SYM "pure_reloc" |
| 41 | #define DATA_RELOC_SYM "d_reloc" | 41 | #define DATA_RELOC_SYM "d_reloc" |
| 42 | #define DATA_RELOC_IMPURE_SYM "d_reloc_imp" | 42 | #define DATA_RELOC_IMPURE_SYM "d_reloc_imp" |
| 43 | #define DATA_RELOC_EPHEMERAL_SYM "d_reloc_eph" | ||
| 43 | #define FUNC_LINK_TABLE_SYM "freloc_link_table" | 44 | #define FUNC_LINK_TABLE_SYM "freloc_link_table" |
| 44 | #define LINK_TABLE_HASH_SYM "freloc_hash" | 45 | #define LINK_TABLE_HASH_SYM "freloc_hash" |
| 45 | #define COMP_UNIT_SYM "comp_unit" | 46 | #define COMP_UNIT_SYM "comp_unit" |
| 46 | #define TEXT_DATA_RELOC_SYM "text_data_reloc" | 47 | #define TEXT_DATA_RELOC_SYM "text_data_reloc" |
| 47 | #define TEXT_DATA_RELOC_IMPURE_SYM "text_data_reloc_imp" | 48 | #define TEXT_DATA_RELOC_IMPURE_SYM "text_data_reloc_imp" |
| 49 | #define TEXT_DATA_RELOC_EPHEMERAL_SYM "text_data_reloc_eph" | ||
| 48 | 50 | ||
| 49 | #define SPEED XFIXNUM (Fsymbol_value (Qcomp_speed)) | 51 | #define SPEED XFIXNUM (Fsymbol_value (Qcomp_speed)) |
| 50 | #define COMP_DEBUG XFIXNUM (Fsymbol_value (Qcomp_debug)) | 52 | #define COMP_DEBUG XFIXNUM (Fsymbol_value (Qcomp_debug)) |
| @@ -178,6 +180,8 @@ typedef struct { | |||
| 178 | gcc_jit_rvalue *data_relocs; | 180 | gcc_jit_rvalue *data_relocs; |
| 179 | /* Same as before but can't go in pure space. */ | 181 | /* Same as before but can't go in pure space. */ |
| 180 | gcc_jit_rvalue *data_relocs_impure; | 182 | gcc_jit_rvalue *data_relocs_impure; |
| 183 | /* Same as before but content does not survive load phase. */ | ||
| 184 | gcc_jit_rvalue *data_relocs_ephemeral; | ||
| 181 | /* Synthesized struct holding func relocs. */ | 185 | /* Synthesized struct holding func relocs. */ |
| 182 | gcc_jit_lvalue *func_relocs; | 186 | gcc_jit_lvalue *func_relocs; |
| 183 | } comp_t; | 187 | } comp_t; |
| @@ -382,6 +386,20 @@ register_emitter (Lisp_Object key, void *func) | |||
| 382 | Fputhash (key, value, comp.emitter_dispatcher); | 386 | Fputhash (key, value, comp.emitter_dispatcher); |
| 383 | } | 387 | } |
| 384 | 388 | ||
| 389 | static gcc_jit_rvalue * | ||
| 390 | alloc_class_to_reloc (Lisp_Object alloc_class) | ||
| 391 | { | ||
| 392 | if (alloc_class == Qd_base) | ||
| 393 | return comp.data_relocs; | ||
| 394 | else if (alloc_class == Qd_impure) | ||
| 395 | return comp.data_relocs_impure; | ||
| 396 | else if (alloc_class == Qd_ephemeral) | ||
| 397 | return comp.data_relocs_ephemeral; | ||
| 398 | xsignal (Qnative_ice, | ||
| 399 | build_string ("inconsistent allocation class")); | ||
| 400 | assume (false); | ||
| 401 | } | ||
| 402 | |||
| 385 | static void | 403 | static void |
| 386 | emit_comment (const char *str) | 404 | emit_comment (const char *str) |
| 387 | { | 405 | { |
| @@ -893,7 +911,7 @@ emit_make_fixnum (gcc_jit_rvalue *obj) | |||
| 893 | } | 911 | } |
| 894 | 912 | ||
| 895 | static gcc_jit_rvalue * | 913 | static gcc_jit_rvalue * |
| 896 | emit_const_lisp_obj (Lisp_Object obj, Lisp_Object impure) | 914 | emit_const_lisp_obj (Lisp_Object obj, Lisp_Object alloc_class) |
| 897 | { | 915 | { |
| 898 | emit_comment (format_string ("const lisp obj: %s", | 916 | emit_comment (format_string ("const lisp obj: %s", |
| 899 | SSDATA (Fprin1_to_string (obj, Qnil)))); | 917 | SSDATA (Fprin1_to_string (obj, Qnil)))); |
| @@ -904,8 +922,7 @@ emit_const_lisp_obj (Lisp_Object obj, Lisp_Object impure) | |||
| 904 | comp.void_ptr_type, | 922 | comp.void_ptr_type, |
| 905 | NULL)); | 923 | NULL)); |
| 906 | 924 | ||
| 907 | Lisp_Object container = impure ? CALL1I (comp-ctxt-d-impure, Vcomp_ctxt) | 925 | Lisp_Object container = CALL1I (comp-alloc-class-to-container, alloc_class); |
| 908 | : CALL1I (comp-ctxt-d-base, Vcomp_ctxt); | ||
| 909 | Lisp_Object reloc_idx = | 926 | Lisp_Object reloc_idx = |
| 910 | Fgethash (obj, CALL1I (comp-data-container-idx, container), Qnil); | 927 | Fgethash (obj, CALL1I (comp-data-container-idx, container), Qnil); |
| 911 | eassert (!NILP (reloc_idx)); | 928 | eassert (!NILP (reloc_idx)); |
| @@ -917,8 +934,7 @@ emit_const_lisp_obj (Lisp_Object obj, Lisp_Object impure) | |||
| 917 | gcc_jit_lvalue_as_rvalue ( | 934 | gcc_jit_lvalue_as_rvalue ( |
| 918 | gcc_jit_context_new_array_access (comp.ctxt, | 935 | gcc_jit_context_new_array_access (comp.ctxt, |
| 919 | NULL, | 936 | NULL, |
| 920 | impure ? comp.data_relocs_impure | 937 | alloc_class_to_reloc (alloc_class), |
| 921 | : comp.data_relocs, | ||
| 922 | reloc_n)); | 938 | reloc_n)); |
| 923 | } | 939 | } |
| 924 | 940 | ||
| @@ -926,7 +942,7 @@ static gcc_jit_rvalue * | |||
| 926 | emit_NILP (gcc_jit_rvalue *x) | 942 | emit_NILP (gcc_jit_rvalue *x) |
| 927 | { | 943 | { |
| 928 | emit_comment ("NILP"); | 944 | emit_comment ("NILP"); |
| 929 | return emit_EQ (x, emit_const_lisp_obj (Qnil, Qnil)); | 945 | return emit_EQ (x, emit_const_lisp_obj (Qnil, Qd_base)); |
| 930 | } | 946 | } |
| 931 | 947 | ||
| 932 | static gcc_jit_rvalue * | 948 | static gcc_jit_rvalue * |
| @@ -1029,7 +1045,7 @@ emit_CHECK_CONS (gcc_jit_rvalue *x) | |||
| 1029 | 1045 | ||
| 1030 | gcc_jit_rvalue *args[] = | 1046 | gcc_jit_rvalue *args[] = |
| 1031 | { emit_CONSP (x), | 1047 | { emit_CONSP (x), |
| 1032 | emit_const_lisp_obj (Qconsp, Qnil), | 1048 | emit_const_lisp_obj (Qconsp, Qd_base), |
| 1033 | x }; | 1049 | x }; |
| 1034 | 1050 | ||
| 1035 | gcc_jit_block_add_eval ( | 1051 | gcc_jit_block_add_eval ( |
| @@ -1140,7 +1156,8 @@ emit_mvar_val (Lisp_Object mvar) | |||
| 1140 | return emit_cast (comp.lisp_obj_type, word); | 1156 | return emit_cast (comp.lisp_obj_type, word); |
| 1141 | } | 1157 | } |
| 1142 | /* Other const objects are fetched from the reloc array. */ | 1158 | /* Other const objects are fetched from the reloc array. */ |
| 1143 | return emit_const_lisp_obj (constant, CALL1I (comp-mvar-impure, mvar)); | 1159 | return emit_const_lisp_obj (constant, |
| 1160 | CALL1I (comp-mvar-alloc-class, mvar)); | ||
| 1144 | } | 1161 | } |
| 1145 | 1162 | ||
| 1146 | return gcc_jit_lvalue_as_rvalue (emit_mvar_access (mvar)); | 1163 | return gcc_jit_lvalue_as_rvalue (emit_mvar_access (mvar)); |
| @@ -1175,7 +1192,7 @@ emit_set_internal (Lisp_Object args) | |||
| 1175 | gcc_jit_rvalue *gcc_args[4]; | 1192 | gcc_jit_rvalue *gcc_args[4]; |
| 1176 | FOR_EACH_TAIL (args) | 1193 | FOR_EACH_TAIL (args) |
| 1177 | gcc_args[i++] = emit_mvar_val (XCAR (args)); | 1194 | gcc_args[i++] = emit_mvar_val (XCAR (args)); |
| 1178 | gcc_args[2] = emit_const_lisp_obj (Qnil, Qnil); | 1195 | gcc_args[2] = emit_const_lisp_obj (Qnil, Qd_base); |
| 1179 | gcc_args[3] = gcc_jit_context_new_rvalue_from_int (comp.ctxt, | 1196 | gcc_args[3] = gcc_jit_context_new_rvalue_from_int (comp.ctxt, |
| 1180 | comp.int_type, | 1197 | comp.int_type, |
| 1181 | SET_INTERNAL_SET); | 1198 | SET_INTERNAL_SET); |
| @@ -1563,7 +1580,9 @@ emit_limple_insn (Lisp_Object insn) | |||
| 1563 | gcc_jit_lvalue_as_rvalue ( | 1580 | gcc_jit_lvalue_as_rvalue ( |
| 1564 | gcc_jit_context_new_array_access (comp.ctxt, | 1581 | gcc_jit_context_new_array_access (comp.ctxt, |
| 1565 | NULL, | 1582 | NULL, |
| 1566 | comp.data_relocs, | 1583 | alloc_class_to_reloc ( |
| 1584 | CALL1I (comp-mvar-alloc-class, | ||
| 1585 | arg[0])), | ||
| 1567 | reloc_n))); | 1586 | reloc_n))); |
| 1568 | } | 1587 | } |
| 1569 | else if (EQ (op, Qcomment)) | 1588 | else if (EQ (op, Qcomment)) |
| @@ -1825,6 +1844,10 @@ declare_imported_data (void) | |||
| 1825 | declare_imported_data_relocs (CALL1I (comp-ctxt-d-impure, Vcomp_ctxt), | 1844 | declare_imported_data_relocs (CALL1I (comp-ctxt-d-impure, Vcomp_ctxt), |
| 1826 | DATA_RELOC_IMPURE_SYM, | 1845 | DATA_RELOC_IMPURE_SYM, |
| 1827 | TEXT_DATA_RELOC_IMPURE_SYM); | 1846 | TEXT_DATA_RELOC_IMPURE_SYM); |
| 1847 | comp.data_relocs_ephemeral = | ||
| 1848 | declare_imported_data_relocs (CALL1I (comp-ctxt-d-ephemeral, Vcomp_ctxt), | ||
| 1849 | DATA_RELOC_EPHEMERAL_SYM, | ||
| 1850 | TEXT_DATA_RELOC_EPHEMERAL_SYM); | ||
| 1828 | } | 1851 | } |
| 1829 | 1852 | ||
| 1830 | /* | 1853 | /* |
| @@ -2417,11 +2440,11 @@ define_CAR_CDR (void) | |||
| 2417 | comp.block = is_nil_b; | 2440 | comp.block = is_nil_b; |
| 2418 | gcc_jit_block_end_with_return (comp.block, | 2441 | gcc_jit_block_end_with_return (comp.block, |
| 2419 | NULL, | 2442 | NULL, |
| 2420 | emit_const_lisp_obj (Qnil, Qnil)); | 2443 | emit_const_lisp_obj (Qnil, Qd_base)); |
| 2421 | 2444 | ||
| 2422 | comp.block = not_nil_b; | 2445 | comp.block = not_nil_b; |
| 2423 | gcc_jit_rvalue *wrong_type_args[] = | 2446 | gcc_jit_rvalue *wrong_type_args[] = |
| 2424 | { emit_const_lisp_obj (Qlistp, Qnil), c }; | 2447 | { emit_const_lisp_obj (Qlistp, Qd_base), c }; |
| 2425 | 2448 | ||
| 2426 | gcc_jit_block_add_eval (comp.block, | 2449 | gcc_jit_block_add_eval (comp.block, |
| 2427 | NULL, | 2450 | NULL, |
| @@ -2430,7 +2453,7 @@ define_CAR_CDR (void) | |||
| 2430 | false)); | 2453 | false)); |
| 2431 | gcc_jit_block_end_with_return (comp.block, | 2454 | gcc_jit_block_end_with_return (comp.block, |
| 2432 | NULL, | 2455 | NULL, |
| 2433 | emit_const_lisp_obj (Qnil, Qnil)); | 2456 | emit_const_lisp_obj (Qnil, Qd_base)); |
| 2434 | } | 2457 | } |
| 2435 | comp.car = func[0]; | 2458 | comp.car = func[0]; |
| 2436 | comp.cdr = func[1]; | 2459 | comp.cdr = func[1]; |
| @@ -2810,13 +2833,12 @@ define_bool_to_lisp_obj (void) | |||
| 2810 | comp.block = ret_t_block; | 2833 | comp.block = ret_t_block; |
| 2811 | gcc_jit_block_end_with_return (ret_t_block, | 2834 | gcc_jit_block_end_with_return (ret_t_block, |
| 2812 | NULL, | 2835 | NULL, |
| 2813 | emit_const_lisp_obj (Qt, Qnil)); | 2836 | emit_const_lisp_obj (Qt, Qd_base)); |
| 2814 | 2837 | ||
| 2815 | comp.block = ret_nil_block; | 2838 | comp.block = ret_nil_block; |
| 2816 | gcc_jit_block_end_with_return (ret_nil_block, | 2839 | gcc_jit_block_end_with_return (ret_nil_block, |
| 2817 | NULL, | 2840 | NULL, |
| 2818 | emit_const_lisp_obj (Qnil, Qnil)); | 2841 | emit_const_lisp_obj (Qnil, Qd_base)); |
| 2819 | |||
| 2820 | } | 2842 | } |
| 2821 | 2843 | ||
| 2822 | /* Declare a function being compiled and add it to comp.exported_funcs_h. */ | 2844 | /* Declare a function being compiled and add it to comp.exported_funcs_h. */ |
| @@ -3358,12 +3380,25 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump) | |||
| 3358 | EMACS_INT ***pure_reloc = dynlib_sym (handle, PURE_RELOC_SYM); | 3380 | EMACS_INT ***pure_reloc = dynlib_sym (handle, PURE_RELOC_SYM); |
| 3359 | Lisp_Object *data_relocs = dynlib_sym (handle, DATA_RELOC_SYM); | 3381 | Lisp_Object *data_relocs = dynlib_sym (handle, DATA_RELOC_SYM); |
| 3360 | Lisp_Object *data_imp_relocs = dynlib_sym (handle, DATA_RELOC_IMPURE_SYM); | 3382 | Lisp_Object *data_imp_relocs = dynlib_sym (handle, DATA_RELOC_IMPURE_SYM); |
| 3383 | Lisp_Object *data_eph_relocs = | ||
| 3384 | dynlib_sym (handle, DATA_RELOC_EPHEMERAL_SYM); | ||
| 3361 | void **freloc_link_table = dynlib_sym (handle, FUNC_LINK_TABLE_SYM); | 3385 | void **freloc_link_table = dynlib_sym (handle, FUNC_LINK_TABLE_SYM); |
| 3386 | Lisp_Object volatile data_ephemeral_vec; | ||
| 3387 | |||
| 3388 | /* Note: data_ephemeral_vec is not GC protected except than by | ||
| 3389 | this function frame. After this functions will be | ||
| 3390 | deactivated GC will be free to collect it, but it MUST | ||
| 3391 | survive till 'top_level_run' has finished his job. We store | ||
| 3392 | into the ephemeral allocation class only objects that we know | ||
| 3393 | are necessary exclusively during the first load. Once these | ||
| 3394 | are collected we don't have to maintain them in the heap | ||
| 3395 | forever. */ | ||
| 3362 | 3396 | ||
| 3363 | if (!(current_thread_reloc | 3397 | if (!(current_thread_reloc |
| 3364 | && pure_reloc | 3398 | && pure_reloc |
| 3365 | && data_relocs | 3399 | && data_relocs |
| 3366 | && data_imp_relocs | 3400 | && data_imp_relocs |
| 3401 | && data_eph_relocs | ||
| 3367 | && freloc_link_table | 3402 | && freloc_link_table |
| 3368 | && top_level_run) | 3403 | && top_level_run) |
| 3369 | || NILP (Fstring_equal (load_static_obj (comp_u, LINK_TABLE_HASH_SYM), | 3404 | || NILP (Fstring_equal (load_static_obj (comp_u, LINK_TABLE_HASH_SYM), |
| @@ -3382,6 +3417,12 @@ load_comp_unit (struct Lisp_Native_Comp_Unit *comp_u, bool loading_dump) | |||
| 3382 | comp_u->data_vec = load_static_obj (comp_u, TEXT_DATA_RELOC_SYM); | 3417 | comp_u->data_vec = load_static_obj (comp_u, TEXT_DATA_RELOC_SYM); |
| 3383 | comp_u->data_impure_vec = | 3418 | comp_u->data_impure_vec = |
| 3384 | load_static_obj (comp_u, TEXT_DATA_RELOC_IMPURE_SYM); | 3419 | load_static_obj (comp_u, TEXT_DATA_RELOC_IMPURE_SYM); |
| 3420 | data_ephemeral_vec = | ||
| 3421 | load_static_obj (comp_u, TEXT_DATA_RELOC_EPHEMERAL_SYM); | ||
| 3422 | |||
| 3423 | EMACS_INT d_vec_len = XFIXNUM (Flength (data_ephemeral_vec)); | ||
| 3424 | for (EMACS_INT i = 0; i < d_vec_len; i++) | ||
| 3425 | data_eph_relocs[i] = AREF (data_ephemeral_vec, i); | ||
| 3385 | 3426 | ||
| 3386 | if (!NILP (Vpurify_flag)) | 3427 | if (!NILP (Vpurify_flag)) |
| 3387 | /* Non impure can be copied into pure space. */ | 3428 | /* Non impure can be copied into pure space. */ |
| @@ -3512,6 +3553,11 @@ syms_of_comp (void) | |||
| 3512 | DEFSYM (Qnumberp, "numberp"); | 3553 | DEFSYM (Qnumberp, "numberp"); |
| 3513 | DEFSYM (Qintegerp, "integerp"); | 3554 | DEFSYM (Qintegerp, "integerp"); |
| 3514 | 3555 | ||
| 3556 | /* Allocation classes. */ | ||
| 3557 | DEFSYM (Qd_base, "d-base"); | ||
| 3558 | DEFSYM (Qd_impure, "d-impure"); | ||
| 3559 | DEFSYM (Qd_ephemeral, "d-ephemeral"); | ||
| 3560 | |||
| 3515 | /* Others. */ | 3561 | /* Others. */ |
| 3516 | DEFSYM (Qfixnum, "fixnum"); | 3562 | DEFSYM (Qfixnum, "fixnum"); |
| 3517 | DEFSYM (Qscratch, "scratch"); | 3563 | DEFSYM (Qscratch, "scratch"); |