aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2019-09-03 21:53:36 -0700
committerPaul Eggert2019-09-03 22:46:11 -0700
commit9117a667908064a0b4ae6ec6c8f3674d95ad6225 (patch)
tree0506b8ef8525347bb7c9c810d55bf4fa85237d66 /src
parentd20655669bd6f94cdd9fb2472668e92a069c0cf2 (diff)
downloademacs-9117a667908064a0b4ae6ec6c8f3674d95ad6225.tar.gz
emacs-9117a667908064a0b4ae6ec6c8f3674d95ad6225.zip
Avoid macros in pdumper.c when it’s easy
Problem with DUMP_SET_REFERRER mentioned by Pip Cet at end of: https://lists.gnu.org/archive/html/emacs-devel/2019-07/msg00548.html * src/pdumper.c (DANGEROUS, EMACS_RELOC_TYPE_BITS) (EMACS_RELOC_LENGTH_BITS, DUMP_RELOC_TYPE_BITS) (DUMP_RELOC_ALIGNMENT_BITS, DUMP_RELOC_OFFSET_BITS) (DUMP_RELOCATION_ALIGNMENT, DUMP_ALIGNMENT) (WEIGHT_NONE, WEIGHT_NORMAL, WEIGHT_STRONG) (PDUMPER_MAX_OBJECT_SIZE): Now a constant, not a macro. (divide_round_up): Now a function, not a macro DIVIDE_ROUND_UP. All uses changed. (enum link_weight_enum, WEIGHT_NONE_VALUE) (WEIGHT_NORMAL_VALUE, WEIGHT_STRONG_VALUE): Remove. (struct link_weight): Just use an int. (dump_set_referrer): New function, replacing DUMP_SET_REFERRER macro with a different API. All uses changed. (dump_clear_referrer): Rename from DUMP_CLEAR_REFERRER. All uses changed. (DEFINE_FROMLISP_FUNC, DEFINE_TOLISP_FUNC): Remove. (intmax_t_from_lisp, intmax_t_to_lisp, dump_off_from_lisp) (dump_off_to_lisp): Define without using macros, (dump_off_from_lisp): Add an eassert range check. (DUMP_FIELD_COPY): Simplify.
Diffstat (limited to 'src')
-rw-r--r--src/pdumper.c196
1 files changed, 98 insertions, 98 deletions
diff --git a/src/pdumper.c b/src/pdumper.c
index f9c31d125a4..306a70396e0 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -105,8 +105,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
105# define VM_SUPPORTED 0 105# define VM_SUPPORTED 0
106#endif 106#endif
107 107
108#define DANGEROUS 0
109
110/* PDUMPER_CHECK_REHASHING being true causes the portable dumper to 108/* PDUMPER_CHECK_REHASHING being true causes the portable dumper to
111 check, for each hash table it dumps, that the hash table means the 109 check, for each hash table it dumps, that the hash table means the
112 same thing after rehashing. */ 110 same thing after rehashing. */
@@ -129,7 +127,11 @@ verify (sizeof (ptrdiff_t) <= sizeof (Lisp_Object));
129verify (sizeof (ptrdiff_t) <= sizeof (EMACS_INT)); 127verify (sizeof (ptrdiff_t) <= sizeof (EMACS_INT));
130verify (CHAR_BIT == 8); 128verify (CHAR_BIT == 8);
131 129
132#define DIVIDE_ROUND_UP(x, y) (((x) + (y) - 1) / (y)) 130static size_t
131divide_round_up (size_t x, size_t y)
132{
133 return (x + y - 1) / y;
134}
133 135
134static const char dump_magic[16] = { 136static const char dump_magic[16] = {
135 'D', 'U', 'M', 'P', 'E', 'D', 137 'D', 'U', 'M', 'P', 'E', 'D',
@@ -235,9 +237,12 @@ enum emacs_reloc_type
235 RELOC_EMACS_EMACS_LV, 237 RELOC_EMACS_EMACS_LV,
236 }; 238 };
237 239
238#define EMACS_RELOC_TYPE_BITS 3 240enum
239#define EMACS_RELOC_LENGTH_BITS \ 241 {
240 (sizeof (dump_off) * CHAR_BIT - EMACS_RELOC_TYPE_BITS) 242 EMACS_RELOC_TYPE_BITS = 3,
243 EMACS_RELOC_LENGTH_BITS = (sizeof (dump_off) * CHAR_BIT
244 - EMACS_RELOC_TYPE_BITS)
245 };
241 246
242struct emacs_reloc 247struct emacs_reloc
243{ 248{
@@ -274,19 +279,22 @@ struct dump_table_locator
274 dump_off nr_entries; 279 dump_off nr_entries;
275}; 280};
276 281
277#define DUMP_RELOC_TYPE_BITS 5 282enum
278verify (RELOC_DUMP_TO_EMACS_LV + 8 < (1 << DUMP_RELOC_TYPE_BITS)); 283 {
284 DUMP_RELOC_TYPE_BITS = 5,
285 DUMP_RELOC_ALIGNMENT_BITS = 2,
286
287 /* Minimum alignment required by dump file format. */
288 DUMP_RELOCATION_ALIGNMENT = 1 << DUMP_RELOC_ALIGNMENT_BITS,
279 289
280#define DUMP_RELOC_ALIGNMENT_BITS 2 290 /* The alignment granularity (in bytes) for objects we store in the
281#define DUMP_RELOC_OFFSET_BITS \ 291 dump. Always suitable for heap objects; may be more aligned. */
282 (sizeof (dump_off) * CHAR_BIT - DUMP_RELOC_TYPE_BITS) 292 DUMP_ALIGNMENT = max (GCALIGNMENT, DUMP_RELOCATION_ALIGNMENT),
283 293
284/* Minimum alignment required by dump file format. */ 294 DUMP_RELOC_OFFSET_BITS = sizeof (dump_off) * CHAR_BIT - DUMP_RELOC_TYPE_BITS
285#define DUMP_RELOCATION_ALIGNMENT (1<<DUMP_RELOC_ALIGNMENT_BITS) 295 };
286 296
287/* The alignment granularity (in bytes) for objects we store in the 297verify (RELOC_DUMP_TO_EMACS_LV + 8 < (1 << DUMP_RELOC_TYPE_BITS));
288 dump. Always suitable for heap objects; may be more aligned. */
289#define DUMP_ALIGNMENT (max (GCALIGNMENT, DUMP_RELOCATION_ALIGNMENT))
290verify (DUMP_ALIGNMENT >= GCALIGNMENT); 298verify (DUMP_ALIGNMENT >= GCALIGNMENT);
291 299
292struct dump_reloc 300struct dump_reloc
@@ -572,23 +580,17 @@ enum dump_object_special_offset
572 }; 580 };
573 581
574/* Weights for score scores for object non-locality. */ 582/* Weights for score scores for object non-locality. */
575enum link_weight_enum
576 {
577 WEIGHT_NONE_VALUE = 0,
578 WEIGHT_NORMAL_VALUE = 1000,
579 WEIGHT_STRONG_VALUE = 1200,
580 };
581 583
582struct link_weight 584struct link_weight
583{ 585{
584 /* Wrapped in a struct to break unwanted implicit conversion. */ 586 /* Wrapped in a struct to break unwanted implicit conversion. */
585 enum link_weight_enum value; 587 int value;
586}; 588};
587 589
588#define LINK_WEIGHT_LITERAL(x) ((struct link_weight){.value=(x)}) 590static struct link_weight const
589#define WEIGHT_NONE LINK_WEIGHT_LITERAL (WEIGHT_NONE_VALUE) 591 WEIGHT_NONE = { .value = 0 },
590#define WEIGHT_NORMAL LINK_WEIGHT_LITERAL (WEIGHT_NORMAL_VALUE) 592 WEIGHT_NORMAL = { .value = 1000 },
591#define WEIGHT_STRONG LINK_WEIGHT_LITERAL (WEIGHT_STRONG_VALUE) 593 WEIGHT_STRONG = { .value = 1200 };
592 594
593 595
594/* Dump file creation */ 596/* Dump file creation */
@@ -628,35 +630,27 @@ dump_set_have_current_referrer (struct dump_context *ctx, bool have)
628#endif 630#endif
629} 631}
630 632
631/* Remember the reason objects are enqueued. 633/* Return true if if objects should be enqueued in CTX to refer to an
634 object that the caller should store into CTX->current_referrer.
632 635
633 Until DUMP_CLEAR_REFERRER is called, any objects enqueued are being 636 Until dump_clear_referrer is called, any objects enqueued are being
634 enqueued because OBJECT refers to them. It is not legal to enqueue 637 enqueued because the object refers to them. It is not valid to
635 objects without a referer set. We check this constraint 638 enqueue objects without a referrer set. We check this constraint
636 at runtime. 639 at runtime.
637 640
638 It is illegal to call DUMP_SET_REFERRER twice without an 641 It is invalid to call dump_set_referrer twice without an
639 intervening call to DUMP_CLEAR_REFERRER. 642 intervening call to dump_clear_referrer. */
640 643static bool
641 Define as a macro so we can avoid evaluating OBJECT 644dump_set_referrer (struct dump_context *ctx)
642 if we dont want referrer tracking. */ 645{
643#define DUMP_SET_REFERRER(ctx, object) \ 646 eassert (!ctx->have_current_referrer);
644 do \ 647 dump_set_have_current_referrer (ctx, true);
645 { \ 648 return dump_tracking_referrers_p (ctx);
646 struct dump_context *_ctx = (ctx); \ 649}
647 eassert (!_ctx->have_current_referrer); \ 650
648 dump_set_have_current_referrer (_ctx, true); \ 651/* Unset the referrer that dump_set_referrer prepared for. */
649 if (dump_tracking_referrers_p (_ctx)) \
650 ctx->current_referrer = (object); \
651 } \
652 while (0)
653
654/* Unset the referer that DUMP_SET_REFERRER set.
655
656 Named with upper-case letters for symmetry with
657 DUMP_SET_REFERRER. */
658static void 652static void
659DUMP_CLEAR_REFERRER (struct dump_context *ctx) 653dump_clear_referrer (struct dump_context *ctx)
660{ 654{
661 eassert (ctx->have_current_referrer); 655 eassert (ctx->have_current_referrer);
662 dump_set_have_current_referrer (ctx, false); 656 dump_set_have_current_referrer (ctx, false);
@@ -732,34 +726,36 @@ dump_object_self_representing_p (Lisp_Object object)
732 return FIXNUMP (object) || dump_builtin_symbol_p (object); 726 return FIXNUMP (object) || dump_builtin_symbol_p (object);
733} 727}
734 728
735#define DEFINE_FROMLISP_FUNC(fn, type) \ 729static intmax_t
736 static type \ 730intmax_t_from_lisp (Lisp_Object value)
737 fn (Lisp_Object value) \ 731{
738 { \ 732 intmax_t n;
739 ALLOW_IMPLICIT_CONVERSION; \ 733 bool ok = integer_to_intmax (value, &n);
740 if (FIXNUMP (value)) \ 734 eassert (ok);
741 return XFIXNUM (value); \ 735 return n;
742 eassert (BIGNUMP (value)); \ 736}
743 type result; \
744 if (TYPE_SIGNED (type)) \
745 result = bignum_to_intmax (value); \
746 else \
747 result = bignum_to_uintmax (value); \
748 DISALLOW_IMPLICIT_CONVERSION; \
749 return result; \
750 }
751 737
752#define DEFINE_TOLISP_FUNC(fn, type) \ 738static Lisp_Object
753 static Lisp_Object \ 739intmax_t_to_lisp (intmax_t value)
754 fn (type value) \ 740{
755 { \ 741 return INT_TO_INTEGER (value);
756 return INT_TO_INTEGER (value); \ 742}
757 } 743
744static dump_off
745dump_off_from_lisp (Lisp_Object value)
746{
747 intmax_t n = intmax_t_from_lisp (value);
748 eassert (DUMP_OFF_MIN <= n && n <= DUMP_OFF_MAX);
749 ALLOW_IMPLICIT_CONVERSION;
750 return n;
751 DISALLOW_IMPLICIT_CONVERSION;
752}
758 753
759DEFINE_FROMLISP_FUNC (intmax_t_from_lisp, intmax_t) 754static Lisp_Object
760DEFINE_TOLISP_FUNC (intmax_t_to_lisp, intmax_t) 755dump_off_to_lisp (dump_off value)
761DEFINE_FROMLISP_FUNC (dump_off_from_lisp, dump_off) 756{
762DEFINE_TOLISP_FUNC (dump_off_to_lisp, dump_off) 757 return INT_TO_INTEGER (value);
758}
763 759
764static void 760static void
765dump_write (struct dump_context *ctx, const void *buf, dump_off nbyte) 761dump_write (struct dump_context *ctx, const void *buf, dump_off nbyte)
@@ -1731,9 +1727,10 @@ dump_root_visitor (Lisp_Object const *root_ptr, enum gc_root_type type,
1731 eassert (dump_builtin_symbol_p (value)); 1727 eassert (dump_builtin_symbol_p (value));
1732 /* Remember to dump the object itself later along with all the 1728 /* Remember to dump the object itself later along with all the
1733 rest of the copied-to-Emacs objects. */ 1729 rest of the copied-to-Emacs objects. */
1734 DUMP_SET_REFERRER (ctx, build_string ("built-in symbol list")); 1730 if (dump_set_referrer (ctx))
1731 ctx->current_referrer = build_string ("built-in symbol list");
1735 dump_enqueue_object (ctx, value, WEIGHT_NONE); 1732 dump_enqueue_object (ctx, value, WEIGHT_NONE);
1736 DUMP_CLEAR_REFERRER (ctx); 1733 dump_clear_referrer (ctx);
1737 } 1734 }
1738 else 1735 else
1739 { 1736 {
@@ -1743,9 +1740,11 @@ dump_root_visitor (Lisp_Object const *root_ptr, enum gc_root_type type,
1743 ctx->staticpro_table); 1740 ctx->staticpro_table);
1744 if (root_ptr != &Vinternal_interpreter_environment) 1741 if (root_ptr != &Vinternal_interpreter_environment)
1745 { 1742 {
1746 DUMP_SET_REFERRER (ctx, dump_ptr_referrer ("emacs root", root_ptr)); 1743 if (dump_set_referrer (ctx))
1744 ctx->current_referrer
1745 = dump_ptr_referrer ("emacs root", root_ptr);
1747 dump_emacs_reloc_to_lv (ctx, root_ptr, *root_ptr); 1746 dump_emacs_reloc_to_lv (ctx, root_ptr, *root_ptr);
1748 DUMP_CLEAR_REFERRER (ctx); 1747 dump_clear_referrer (ctx);
1749 } 1748 }
1750 } 1749 }
1751} 1750}
@@ -1759,7 +1758,7 @@ dump_roots (struct dump_context *ctx)
1759 visit_static_gc_roots (visitor); 1758 visit_static_gc_roots (visitor);
1760} 1759}
1761 1760
1762#define PDUMPER_MAX_OBJECT_SIZE 2048 1761enum { PDUMPER_MAX_OBJECT_SIZE = 2048 };
1763 1762
1764static dump_off 1763static dump_off
1765field_relpos (const void *in_start, const void *in_field) 1764field_relpos (const void *in_start, const void *in_field)
@@ -1788,11 +1787,7 @@ cpyptr (void *out, const void *in)
1788 1787
1789/* Convenience macro for regular assignment. */ 1788/* Convenience macro for regular assignment. */
1790#define DUMP_FIELD_COPY(out, in, name) \ 1789#define DUMP_FIELD_COPY(out, in, name) \
1791 do \ 1790 ((out)->name = (in)->name)
1792 { \
1793 (out)->name = (in)->name; \
1794 } \
1795 while (0)
1796 1791
1797static void 1792static void
1798dump_field_lv_or_rawptr (struct dump_context *ctx, 1793dump_field_lv_or_rawptr (struct dump_context *ctx,
@@ -1848,6 +1843,7 @@ dump_field_lv_or_rawptr (struct dump_context *ctx,
1848 intptr_t out_value; 1843 intptr_t out_value;
1849 dump_off out_field_offset = ctx->obj_offset + relpos; 1844 dump_off out_field_offset = ctx->obj_offset + relpos;
1850 dump_off target_offset = dump_recall_object (ctx, value); 1845 dump_off target_offset = dump_recall_object (ctx, value);
1846 enum { DANGEROUS = false };
1851 if (DANGEROUS 1847 if (DANGEROUS
1852 && target_offset > 0 && dump_object_emacs_ptr (value) == NULL) 1848 && target_offset > 0 && dump_object_emacs_ptr (value) == NULL)
1853 { 1849 {
@@ -2408,7 +2404,8 @@ dump_pre_dump_symbol (struct dump_context *ctx, struct Lisp_Symbol *symbol)
2408{ 2404{
2409 Lisp_Object symbol_lv = make_lisp_symbol (symbol); 2405 Lisp_Object symbol_lv = make_lisp_symbol (symbol);
2410 eassert (!dump_recall_symbol_aux (ctx, symbol_lv)); 2406 eassert (!dump_recall_symbol_aux (ctx, symbol_lv));
2411 DUMP_SET_REFERRER (ctx, symbol_lv); 2407 if (dump_set_referrer (ctx))
2408 ctx->current_referrer = symbol_lv;
2412 switch (symbol->u.s.redirect) 2409 switch (symbol->u.s.redirect)
2413 { 2410 {
2414 case SYMBOL_LOCALIZED: 2411 case SYMBOL_LOCALIZED:
@@ -2422,7 +2419,7 @@ dump_pre_dump_symbol (struct dump_context *ctx, struct Lisp_Symbol *symbol)
2422 default: 2419 default:
2423 break; 2420 break;
2424 } 2421 }
2425 DUMP_CLEAR_REFERRER (ctx); 2422 dump_clear_referrer (ctx);
2426} 2423}
2427 2424
2428static dump_off 2425static dump_off
@@ -2443,13 +2440,14 @@ dump_symbol (struct dump_context *ctx,
2443 { 2440 {
2444 eassert (offset == DUMP_OBJECT_ON_NORMAL_QUEUE 2441 eassert (offset == DUMP_OBJECT_ON_NORMAL_QUEUE
2445 || offset == DUMP_OBJECT_NOT_SEEN); 2442 || offset == DUMP_OBJECT_NOT_SEEN);
2446 DUMP_CLEAR_REFERRER (ctx); 2443 dump_clear_referrer (ctx);
2447 struct dump_flags old_flags = ctx->flags; 2444 struct dump_flags old_flags = ctx->flags;
2448 ctx->flags.dump_object_contents = false; 2445 ctx->flags.dump_object_contents = false;
2449 ctx->flags.defer_symbols = false; 2446 ctx->flags.defer_symbols = false;
2450 dump_object (ctx, object); 2447 dump_object (ctx, object);
2451 ctx->flags = old_flags; 2448 ctx->flags = old_flags;
2452 DUMP_SET_REFERRER (ctx, object); 2449 if (dump_set_referrer (ctx))
2450 ctx->current_referrer = object;
2453 2451
2454 offset = DUMP_OBJECT_ON_SYMBOL_QUEUE; 2452 offset = DUMP_OBJECT_ON_SYMBOL_QUEUE;
2455 dump_remember_object (ctx, object, offset); 2453 dump_remember_object (ctx, object, offset);
@@ -3118,7 +3116,8 @@ dump_object (struct dump_context *ctx, Lisp_Object object)
3118 } 3116 }
3119 3117
3120 /* Object needs to be dumped. */ 3118 /* Object needs to be dumped. */
3121 DUMP_SET_REFERRER (ctx, object); 3119 if (dump_set_referrer (ctx))
3120 ctx->current_referrer = object;
3122 switch (XTYPE (object)) 3121 switch (XTYPE (object))
3123 { 3122 {
3124 case Lisp_String: 3123 case Lisp_String:
@@ -3142,7 +3141,7 @@ dump_object (struct dump_context *ctx, Lisp_Object object)
3142 default: 3141 default:
3143 emacs_abort (); 3142 emacs_abort ();
3144 } 3143 }
3145 DUMP_CLEAR_REFERRER (ctx); 3144 dump_clear_referrer (ctx);
3146 3145
3147 /* offset can be < 0 if we've deferred an object. */ 3146 /* offset can be < 0 if we've deferred an object. */
3148 if (ctx->flags.dump_object_contents && offset > DUMP_OBJECT_NOT_SEEN) 3147 if (ctx->flags.dump_object_contents && offset > DUMP_OBJECT_NOT_SEEN)
@@ -3507,9 +3506,10 @@ dump_drain_user_remembered_data_hot (struct dump_context *ctx)
3507 read_ptr_raw_and_lv (mem, type, &value, &lv); 3506 read_ptr_raw_and_lv (mem, type, &value, &lv);
3508 if (value != NULL) 3507 if (value != NULL)
3509 { 3508 {
3510 DUMP_SET_REFERRER (ctx, dump_ptr_referrer ("user data", mem)); 3509 if (dump_set_referrer (ctx))
3510 ctx->current_referrer = dump_ptr_referrer ("user data", mem);
3511 dump_enqueue_object (ctx, lv, WEIGHT_NONE); 3511 dump_enqueue_object (ctx, lv, WEIGHT_NONE);
3512 DUMP_CLEAR_REFERRER (ctx); 3512 dump_clear_referrer (ctx);
3513 } 3513 }
3514 } 3514 }
3515 } 3515 }
@@ -4877,7 +4877,7 @@ dump_bitset_init (struct dump_bitset *bitset, size_t number_bits)
4877{ 4877{
4878 int xword_size = sizeof (bitset->bits[0]); 4878 int xword_size = sizeof (bitset->bits[0]);
4879 int bits_per_word = xword_size * CHAR_BIT; 4879 int bits_per_word = xword_size * CHAR_BIT;
4880 ptrdiff_t words_needed = DIVIDE_ROUND_UP (number_bits, bits_per_word); 4880 ptrdiff_t words_needed = divide_round_up (number_bits, bits_per_word);
4881 bitset->number_words = words_needed; 4881 bitset->number_words = words_needed;
4882 bitset->bits = calloc (words_needed, xword_size); 4882 bitset->bits = calloc (words_needed, xword_size);
4883 return bitset->bits != NULL; 4883 return bitset->bits != NULL;
@@ -5420,7 +5420,7 @@ pdumper_load (const char *dump_filename)
5420 5420
5421 err = PDUMPER_LOAD_ERROR; 5421 err = PDUMPER_LOAD_ERROR;
5422 mark_bits_needed = 5422 mark_bits_needed =
5423 DIVIDE_ROUND_UP (header->discardable_start, DUMP_ALIGNMENT); 5423 divide_round_up (header->discardable_start, DUMP_ALIGNMENT);
5424 if (!dump_bitset_init (&mark_bits, mark_bits_needed)) 5424 if (!dump_bitset_init (&mark_bits, mark_bits_needed))
5425 goto out; 5425 goto out;
5426 5426