diff options
| author | Po Lu | 2025-03-09 23:02:21 +0800 |
|---|---|---|
| committer | Po Lu | 2025-03-09 23:07:33 +0800 |
| commit | a5f8ce9f1eae29f87fe13adb61bd4e15faa628a2 (patch) | |
| tree | 602dba32bf3efcd7743f0d2df5e73339d98a5b2e /src | |
| parent | 57cef07710d91988b6332ad3ed2f5c4b4b371585 (diff) | |
| download | emacs-a5f8ce9f1eae29f87fe13adb61bd4e15faa628a2.tar.gz emacs-a5f8ce9f1eae29f87fe13adb61bd4e15faa628a2.zip | |
Re-port to 32-bit systems without alignment primitives
* configure.ac (ALIGNOF_INT, ALIGNOF_LONG, ALIGNOF_LONG_LONG):
New variables.
(emacs_cv_alignas_unavailable): Define if alignas and structure
alignment primitives are unavailable. In such an environment,
the MSB tagging scheme must be enabled, as must the GNU malloc.
* msdos/sed2v2.inp: Adjust correspondingly.
* src/alloc.c (union emacs_align_type): Remove types which
contain flexible array members. The address of a field
subsequent to an aggregate with flexible array members cannot
validly be taken.
(mark_memory) [!USE_LSB_TAG && !WIDE_EMACS_INT]: Strip type bits
before scanning memory.
* src/emacs.c (main):
* src/eval.c (Fautoload_do_load):
* src/fns.c (Frequire): Rename a number of illogically named
fields.
* src/lisp.h (ALIGNOF_EMACS_INT): Define to the natural
alignment of EMACS_INT.
(IDEAL_GCALIGNMENT): New macro.
(USE_LSB_TAG): Disable if no alignment specifiers are available,
WIDE_EMACS_INT is undefined, and the natural alignment of
EMACS_INT falls short of LSB tagging's requirements.
(gflags): Rename illogically named fields and don't define them
as bitfields, which runs afoul of certain compiler issues.
(will_dump_p, will_bootstrap_p, will_dump_with_pdumper_p)
(dumped_with_pdumper_p): Adjust accordingly.
* src/pdumper.c (VM_SUPPORTED): Define to 0 when !USE_LSB_TAG.
It is better to read dump files into the heap by hand than to be
supplied with an address that is not representable.
(_dump_object_start_pseudovector): Rename to
dump_object_start_pseudovector, to avoid encroaching on reserved
names.
(START_DUMP_PVEC): Adjust correspondingly.
(dump_mmap_contiguous_vm): Preserve errno around failure
cleanup.
(dump_bitset_bit_set_p): Work around certain compiler issues.
(pdumper_load) [!USE_LSB_TAG]: Reject dump file allocations
that are not representable as Lisp_Objects.
Tested on i386-unknown-solaris2.10, sparc-sun-solaris2.10.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 22 | ||||
| -rw-r--r-- | src/emacs.c | 12 | ||||
| -rw-r--r-- | src/eval.c | 2 | ||||
| -rw-r--r-- | src/fns.c | 2 | ||||
| -rw-r--r-- | src/lisp.h | 34 | ||||
| -rw-r--r-- | src/pdumper.c | 141 |
6 files changed, 130 insertions, 83 deletions
diff --git a/src/alloc.c b/src/alloc.c index 7fa05e54202..c0d68e6c964 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -150,8 +150,6 @@ union emacs_align_type | |||
| 150 | { | 150 | { |
| 151 | struct frame frame; | 151 | struct frame frame; |
| 152 | struct Lisp_Bignum Lisp_Bignum; | 152 | struct Lisp_Bignum Lisp_Bignum; |
| 153 | struct Lisp_Bool_Vector Lisp_Bool_Vector; | ||
| 154 | struct Lisp_Char_Table Lisp_Char_Table; | ||
| 155 | struct Lisp_CondVar Lisp_CondVar; | 153 | struct Lisp_CondVar Lisp_CondVar; |
| 156 | struct Lisp_Finalizer Lisp_Finalizer; | 154 | struct Lisp_Finalizer Lisp_Finalizer; |
| 157 | struct Lisp_Float Lisp_Float; | 155 | struct Lisp_Float Lisp_Float; |
| @@ -160,21 +158,25 @@ union emacs_align_type | |||
| 160 | struct Lisp_Misc_Ptr Lisp_Misc_Ptr; | 158 | struct Lisp_Misc_Ptr Lisp_Misc_Ptr; |
| 161 | struct Lisp_Mutex Lisp_Mutex; | 159 | struct Lisp_Mutex Lisp_Mutex; |
| 162 | struct Lisp_Overlay Lisp_Overlay; | 160 | struct Lisp_Overlay Lisp_Overlay; |
| 163 | struct Lisp_Sub_Char_Table Lisp_Sub_Char_Table; | ||
| 164 | struct Lisp_Subr Lisp_Subr; | 161 | struct Lisp_Subr Lisp_Subr; |
| 165 | struct Lisp_Sqlite Lisp_Sqlite; | 162 | struct Lisp_Sqlite Lisp_Sqlite; |
| 166 | struct Lisp_User_Ptr Lisp_User_Ptr; | 163 | struct Lisp_User_Ptr Lisp_User_Ptr; |
| 167 | struct Lisp_Vector Lisp_Vector; | ||
| 168 | struct terminal terminal; | 164 | struct terminal terminal; |
| 169 | struct thread_state thread_state; | 165 | struct thread_state thread_state; |
| 170 | struct window window; | 166 | struct window window; |
| 171 | 167 | ||
| 172 | /* Omit the following since they would require including process.h | 168 | /* Omit the following since they would require including process.h |
| 173 | etc. In practice their alignments never exceed that of the | 169 | etc, or because they are defined with flexible array members, which |
| 174 | structs already listed. */ | 170 | are rejected by some C99 compilers when this union subsequently |
| 171 | appears in an `alignof' expression. In practice their alignments | ||
| 172 | never exceed that of the structs already listed. */ | ||
| 175 | #if 0 | 173 | #if 0 |
| 174 | struct Lisp_Bool_Vector Lisp_Bool_Vector; | ||
| 175 | struct Lisp_Char_Table Lisp_Char_Table; | ||
| 176 | struct Lisp_Sub_Char_Table Lisp_Sub_Char_Table; | ||
| 176 | struct Lisp_Module_Function Lisp_Module_Function; | 177 | struct Lisp_Module_Function Lisp_Module_Function; |
| 177 | struct Lisp_Process Lisp_Process; | 178 | struct Lisp_Process Lisp_Process; |
| 179 | struct Lisp_Vector Lisp_Vector; | ||
| 178 | struct save_window_data save_window_data; | 180 | struct save_window_data save_window_data; |
| 179 | struct scroll_bar scroll_bar; | 181 | struct scroll_bar scroll_bar; |
| 180 | struct xwidget_view xwidget_view; | 182 | struct xwidget_view xwidget_view; |
| @@ -5167,14 +5169,20 @@ mark_memory (void const *start, void const *end) | |||
| 5167 | for (pp = start; (void const *) pp < end; pp += GC_POINTER_ALIGNMENT) | 5169 | for (pp = start; (void const *) pp < end; pp += GC_POINTER_ALIGNMENT) |
| 5168 | { | 5170 | { |
| 5169 | void *p = *(void *const *) pp; | 5171 | void *p = *(void *const *) pp; |
| 5172 | intptr_t ip; | ||
| 5173 | |||
| 5174 | #if !USE_LSB_TAG && !defined WIDE_EMACS_INT | ||
| 5175 | ip = (intptr_t) p; | ||
| 5176 | mark_maybe_pointer ((void *) (ip & VALMASK), false); | ||
| 5177 | #else /* USE_LSB_TAG || WIDE_EMACS_INT */ | ||
| 5170 | mark_maybe_pointer (p, false); | 5178 | mark_maybe_pointer (p, false); |
| 5179 | #endif /* USE_LSB_TAG || WIDE_EMACS_INT */ | ||
| 5171 | 5180 | ||
| 5172 | /* Unmask any struct Lisp_Symbol pointer that make_lisp_symbol | 5181 | /* Unmask any struct Lisp_Symbol pointer that make_lisp_symbol |
| 5173 | previously disguised by adding the address of 'lispsym'. | 5182 | previously disguised by adding the address of 'lispsym'. |
| 5174 | On a host with 32-bit pointers and 64-bit Lisp_Objects, | 5183 | On a host with 32-bit pointers and 64-bit Lisp_Objects, |
| 5175 | a Lisp_Object might be split into registers saved into | 5184 | a Lisp_Object might be split into registers saved into |
| 5176 | non-adjacent words and P might be the low-order word's value. */ | 5185 | non-adjacent words and P might be the low-order word's value. */ |
| 5177 | intptr_t ip; | ||
| 5178 | ckd_add (&ip, (intptr_t) p, (intptr_t) lispsym); | 5186 | ckd_add (&ip, (intptr_t) p, (intptr_t) lispsym); |
| 5179 | mark_maybe_pointer ((void *) ip, true); | 5187 | mark_maybe_pointer ((void *) ip, true); |
| 5180 | } | 5188 | } |
diff --git a/src/emacs.c b/src/emacs.c index dc7041c2338..6ff7b632c0f 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -1311,13 +1311,11 @@ android_emacs_init (int argc, char **argv, char *dump_file) | |||
| 1311 | if (!initialized && temacs) | 1311 | if (!initialized && temacs) |
| 1312 | { | 1312 | { |
| 1313 | #ifdef HAVE_PDUMPER | 1313 | #ifdef HAVE_PDUMPER |
| 1314 | if (strcmp (temacs, "pdump") == 0 || | 1314 | if (!strcmp (temacs, "pdump") || !strcmp (temacs, "pbootstrap")) |
| 1315 | strcmp (temacs, "pbootstrap") == 0) | 1315 | gflags.will_dump_with_pdumper = true; |
| 1316 | gflags.will_dump_with_pdumper_ = true; | 1316 | if (!strcmp (temacs, "pbootstrap")) |
| 1317 | if (strcmp (temacs, "pbootstrap") == 0) | 1317 | gflags.will_bootstrap = true; |
| 1318 | gflags.will_bootstrap_ = true; | 1318 | gflags.will_dump = will_dump_with_pdumper_p (); |
| 1319 | gflags.will_dump_ = | ||
| 1320 | will_dump_with_pdumper_p (); | ||
| 1321 | if (will_dump_p ()) | 1319 | if (will_dump_p ()) |
| 1322 | dump_mode = temacs; | 1320 | dump_mode = temacs; |
| 1323 | #endif | 1321 | #endif |
diff --git a/src/eval.c b/src/eval.c index a514bb4b8f9..5de723cf3bc 100644 --- a/src/eval.c +++ b/src/eval.c | |||
| @@ -2389,7 +2389,7 @@ it defines a macro. */) | |||
| 2389 | { | 2389 | { |
| 2390 | /* Avoid landing here recursively while outputting the | 2390 | /* Avoid landing here recursively while outputting the |
| 2391 | backtrace from the error. */ | 2391 | backtrace from the error. */ |
| 2392 | gflags.will_dump_ = false; | 2392 | gflags.will_dump = false; |
| 2393 | error ("Attempt to autoload %s while preparing to dump", | 2393 | error ("Attempt to autoload %s while preparing to dump", |
| 2394 | SDATA (SYMBOL_NAME (funname))); | 2394 | SDATA (SYMBOL_NAME (funname))); |
| 2395 | } | 2395 | } |
| @@ -3780,7 +3780,7 @@ FILENAME are suppressed. */) | |||
| 3780 | { | 3780 | { |
| 3781 | /* Avoid landing here recursively while outputting the | 3781 | /* Avoid landing here recursively while outputting the |
| 3782 | backtrace from the error. */ | 3782 | backtrace from the error. */ |
| 3783 | gflags.will_dump_ = false; | 3783 | gflags.will_dump = false; |
| 3784 | error ("(require %s) while preparing to dump", | 3784 | error ("(require %s) while preparing to dump", |
| 3785 | SDATA (SYMBOL_NAME (feature))); | 3785 | SDATA (SYMBOL_NAME (feature))); |
| 3786 | } | 3786 | } |
diff --git a/src/lisp.h b/src/lisp.h index 24e4fe0f84d..22c822ad12f 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -89,18 +89,21 @@ DEFINE_GDB_SYMBOL_END (GCTYPEBITS) | |||
| 89 | typedef int EMACS_INT; | 89 | typedef int EMACS_INT; |
| 90 | typedef unsigned int EMACS_UINT; | 90 | typedef unsigned int EMACS_UINT; |
| 91 | enum { EMACS_INT_WIDTH = INT_WIDTH, EMACS_UINT_WIDTH = UINT_WIDTH }; | 91 | enum { EMACS_INT_WIDTH = INT_WIDTH, EMACS_UINT_WIDTH = UINT_WIDTH }; |
| 92 | # define ALIGNOF_EMACS_INT ALIGNOF_INT | ||
| 92 | # define EMACS_INT_MAX INT_MAX | 93 | # define EMACS_INT_MAX INT_MAX |
| 93 | # define pI "" | 94 | # define pI "" |
| 94 | # elif INTPTR_MAX <= LONG_MAX && !defined WIDE_EMACS_INT | 95 | # elif INTPTR_MAX <= LONG_MAX && !defined WIDE_EMACS_INT |
| 95 | typedef long int EMACS_INT; | 96 | typedef long int EMACS_INT; |
| 96 | typedef unsigned long EMACS_UINT; | 97 | typedef unsigned long EMACS_UINT; |
| 97 | enum { EMACS_INT_WIDTH = LONG_WIDTH, EMACS_UINT_WIDTH = ULONG_WIDTH }; | 98 | enum { EMACS_INT_WIDTH = LONG_WIDTH, EMACS_UINT_WIDTH = ULONG_WIDTH }; |
| 99 | # define ALIGNOF_EMACS_INT ALIGNOF_LONG | ||
| 98 | # define EMACS_INT_MAX LONG_MAX | 100 | # define EMACS_INT_MAX LONG_MAX |
| 99 | # define pI "l" | 101 | # define pI "l" |
| 100 | # elif INTPTR_MAX <= LLONG_MAX | 102 | # elif INTPTR_MAX <= LLONG_MAX |
| 101 | typedef long long int EMACS_INT; | 103 | typedef long long int EMACS_INT; |
| 102 | typedef unsigned long long int EMACS_UINT; | 104 | typedef unsigned long long int EMACS_UINT; |
| 103 | enum { EMACS_INT_WIDTH = LLONG_WIDTH, EMACS_UINT_WIDTH = ULLONG_WIDTH }; | 105 | enum { EMACS_INT_WIDTH = LLONG_WIDTH, EMACS_UINT_WIDTH = ULLONG_WIDTH }; |
| 106 | # define ALIGNOF_EMACS_INT ALIGNOF_LONG_LONG | ||
| 104 | # define EMACS_INT_MAX LLONG_MAX | 107 | # define EMACS_INT_MAX LLONG_MAX |
| 105 | /* MinGW supports %lld only if __USE_MINGW_ANSI_STDIO is non-zero, | 108 | /* MinGW supports %lld only if __USE_MINGW_ANSI_STDIO is non-zero, |
| 106 | which is arranged by config.h, and (for mingw.org) if GCC is 6.0 or | 109 | which is arranged by config.h, and (for mingw.org) if GCC is 6.0 or |
| @@ -237,13 +240,26 @@ DEFINE_GDB_SYMBOL_END (INTTYPEBITS) | |||
| 237 | expression involving VAL_MAX. */ | 240 | expression involving VAL_MAX. */ |
| 238 | #define VAL_MAX (EMACS_INT_MAX >> (GCTYPEBITS - 1)) | 241 | #define VAL_MAX (EMACS_INT_MAX >> (GCTYPEBITS - 1)) |
| 239 | 242 | ||
| 243 | /* The alignment ideally required of objects subject to garbage | ||
| 244 | collection. (In the sense that it would be ideal for such an | ||
| 245 | alignment to be available to enable LSB tagging.) */ | ||
| 246 | #define IDEAL_GCALIGNMENT 8 | ||
| 247 | |||
| 240 | /* Whether the least-significant bits of an EMACS_INT contain the tag. | 248 | /* Whether the least-significant bits of an EMACS_INT contain the tag. |
| 241 | On hosts where pointers-as-ints do not exceed VAL_MAX / 2, USE_LSB_TAG is: | 249 | On hosts where pointers-as-ints do not exceed VAL_MAX / 2, USE_LSB_TAG is: |
| 242 | a. unnecessary, because the top bits of an EMACS_INT are unused, and | 250 | a. unnecessary, because the top bits of an EMACS_INT are unused, and |
| 243 | b. slower, because it typically requires extra masking. | 251 | b. slower, because it typically requires extra masking. |
| 244 | So, USE_LSB_TAG is true only on hosts where it might be useful. */ | 252 | So, USE_LSB_TAG is true only on hosts where it might be useful. */ |
| 245 | DEFINE_GDB_SYMBOL_BEGIN (bool, USE_LSB_TAG) | 253 | DEFINE_GDB_SYMBOL_BEGIN (bool, USE_LSB_TAG) |
| 254 | #if (ALIGNOF_EMACS_INT < IDEAL_GCALIGNMENT && !defined alignas \ | ||
| 255 | && !defined WIDE_EMACS_INT \ | ||
| 256 | && !defined HAVE_STRUCT_ATTRIBUTE_ALIGNED \ | ||
| 257 | && !defined __alignas_is_defined \ | ||
| 258 | && __STDC_VERSION__ < 202311 && __cplusplus < 201103) | ||
| 259 | #define USE_LSB_TAG 0 | ||
| 260 | #else /* EMACS_INT_WIDTH >= GCALIGNMENT || defined alignas ... */ | ||
| 246 | #define USE_LSB_TAG (VAL_MAX / 2 < INTPTR_MAX) | 261 | #define USE_LSB_TAG (VAL_MAX / 2 < INTPTR_MAX) |
| 262 | #endif /* EMACS_INT_WIDTH >= GCALIGNMENT || defined alignas ... */ | ||
| 247 | DEFINE_GDB_SYMBOL_END (USE_LSB_TAG) | 263 | DEFINE_GDB_SYMBOL_END (USE_LSB_TAG) |
| 248 | 264 | ||
| 249 | /* Mask for the value (as opposed to the type bits) of a Lisp object. */ | 265 | /* Mask for the value (as opposed to the type bits) of a Lisp object. */ |
| @@ -262,7 +278,7 @@ DEFINE_GDB_SYMBOL_END (VALMASK) | |||
| 262 | USE_LSB_TAG, 1 otherwise. It must be a literal integer constant, | 278 | USE_LSB_TAG, 1 otherwise. It must be a literal integer constant, |
| 263 | for older versions of GCC (through at least 4.9). */ | 279 | for older versions of GCC (through at least 4.9). */ |
| 264 | #if USE_LSB_TAG | 280 | #if USE_LSB_TAG |
| 265 | # define GCALIGNMENT 8 | 281 | # define GCALIGNMENT IDEAL_GCALIGNMENT |
| 266 | # if GCALIGNMENT != 1 << GCTYPEBITS | 282 | # if GCALIGNMENT != 1 << GCTYPEBITS |
| 267 | # error "GCALIGNMENT and GCTYPEBITS are inconsistent" | 283 | # error "GCALIGNMENT and GCTYPEBITS are inconsistent" |
| 268 | # endif | 284 | # endif |
| @@ -629,15 +645,15 @@ extern bool initialized; | |||
| 629 | extern struct gflags | 645 | extern struct gflags |
| 630 | { | 646 | { |
| 631 | /* True means this Emacs instance was born to dump. */ | 647 | /* True means this Emacs instance was born to dump. */ |
| 632 | bool will_dump_ : 1; | 648 | bool will_dump; |
| 633 | bool will_bootstrap_ : 1; | 649 | bool will_bootstrap; |
| 634 | #ifdef HAVE_PDUMPER | 650 | #ifdef HAVE_PDUMPER |
| 635 | /* Set in an Emacs process that will likely dump with pdumper; all | 651 | /* Set in an Emacs process that will likely dump with pdumper; all |
| 636 | Emacs processes may dump with pdumper, however. */ | 652 | Emacs processes may dump with pdumper, however. */ |
| 637 | bool will_dump_with_pdumper_ : 1; | 653 | bool will_dump_with_pdumper; |
| 638 | /* Set in an Emacs process that has been restored from a portable | 654 | /* Set in an Emacs process that has been restored from a portable |
| 639 | dump. */ | 655 | dump. */ |
| 640 | bool dumped_with_pdumper_ : 1; | 656 | bool dumped_with_pdumper; |
| 641 | #endif | 657 | #endif |
| 642 | } gflags; | 658 | } gflags; |
| 643 | 659 | ||
| @@ -645,7 +661,7 @@ INLINE bool | |||
| 645 | will_dump_p (void) | 661 | will_dump_p (void) |
| 646 | { | 662 | { |
| 647 | #if HAVE_PDUMPER | 663 | #if HAVE_PDUMPER |
| 648 | return gflags.will_dump_; | 664 | return gflags.will_dump; |
| 649 | #else | 665 | #else |
| 650 | return false; | 666 | return false; |
| 651 | #endif | 667 | #endif |
| @@ -655,7 +671,7 @@ INLINE bool | |||
| 655 | will_bootstrap_p (void) | 671 | will_bootstrap_p (void) |
| 656 | { | 672 | { |
| 657 | #if HAVE_PDUMPER | 673 | #if HAVE_PDUMPER |
| 658 | return gflags.will_bootstrap_; | 674 | return gflags.will_bootstrap; |
| 659 | #else | 675 | #else |
| 660 | return false; | 676 | return false; |
| 661 | #endif | 677 | #endif |
| @@ -665,7 +681,7 @@ INLINE bool | |||
| 665 | will_dump_with_pdumper_p (void) | 681 | will_dump_with_pdumper_p (void) |
| 666 | { | 682 | { |
| 667 | #if HAVE_PDUMPER | 683 | #if HAVE_PDUMPER |
| 668 | return gflags.will_dump_with_pdumper_; | 684 | return gflags.will_dump_with_pdumper; |
| 669 | #else | 685 | #else |
| 670 | return false; | 686 | return false; |
| 671 | #endif | 687 | #endif |
| @@ -675,7 +691,7 @@ INLINE bool | |||
| 675 | dumped_with_pdumper_p (void) | 691 | dumped_with_pdumper_p (void) |
| 676 | { | 692 | { |
| 677 | #if HAVE_PDUMPER | 693 | #if HAVE_PDUMPER |
| 678 | return gflags.dumped_with_pdumper_; | 694 | return gflags.dumped_with_pdumper; |
| 679 | #else | 695 | #else |
| 680 | return false; | 696 | return false; |
| 681 | #endif | 697 | #endif |
diff --git a/src/pdumper.c b/src/pdumper.c index 342c37b5e62..8e10e561bcf 100644 --- a/src/pdumper.c +++ b/src/pdumper.c | |||
| @@ -77,7 +77,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 77 | #define VM_POSIX 1 | 77 | #define VM_POSIX 1 |
| 78 | #define VM_MS_WINDOWS 2 | 78 | #define VM_MS_WINDOWS 2 |
| 79 | 79 | ||
| 80 | #if defined (HAVE_MMAP) && defined (MAP_FIXED) | 80 | #if !USE_LSB_TAG |
| 81 | # define VM_SUPPORTED 0 | ||
| 82 | #elif defined (HAVE_MMAP) && defined (MAP_FIXED) | ||
| 81 | # define VM_SUPPORTED VM_POSIX | 83 | # define VM_SUPPORTED VM_POSIX |
| 82 | # if !defined (MAP_POPULATE) && defined (MAP_PREFAULT_READ) | 84 | # if !defined (MAP_POPULATE) && defined (MAP_PREFAULT_READ) |
| 83 | # define MAP_POPULATE MAP_PREFAULT_READ | 85 | # define MAP_POPULATE MAP_PREFAULT_READ |
| @@ -1964,9 +1966,9 @@ dump_field_emacs_ptr (struct dump_context *ctx, | |||
| 1964 | } | 1966 | } |
| 1965 | 1967 | ||
| 1966 | static void | 1968 | static void |
| 1967 | _dump_object_start_pseudovector (struct dump_context *ctx, | 1969 | dump_object_start_pseudovector (struct dump_context *ctx, |
| 1968 | union vectorlike_header *out_hdr, | 1970 | union vectorlike_header *out_hdr, |
| 1969 | const union vectorlike_header *in_hdr) | 1971 | const union vectorlike_header *in_hdr) |
| 1970 | { | 1972 | { |
| 1971 | eassert (in_hdr->size & PSEUDOVECTOR_FLAG); | 1973 | eassert (in_hdr->size & PSEUDOVECTOR_FLAG); |
| 1972 | ptrdiff_t vec_size = vectorlike_nbytes (in_hdr); | 1974 | ptrdiff_t vec_size = vectorlike_nbytes (in_hdr); |
| @@ -1976,9 +1978,9 @@ _dump_object_start_pseudovector (struct dump_context *ctx, | |||
| 1976 | 1978 | ||
| 1977 | /* Need a macro for alloca. */ | 1979 | /* Need a macro for alloca. */ |
| 1978 | #define START_DUMP_PVEC(ctx, hdr, type, out) \ | 1980 | #define START_DUMP_PVEC(ctx, hdr, type, out) \ |
| 1979 | const union vectorlike_header *_in_hdr = (hdr); \ | 1981 | const union vectorlike_header *in_hdr = (hdr); \ |
| 1980 | type *out = alloca (vectorlike_nbytes (_in_hdr)); \ | 1982 | type *out = alloca (vectorlike_nbytes (in_hdr)); \ |
| 1981 | _dump_object_start_pseudovector (ctx, &out->header, _in_hdr) | 1983 | dump_object_start_pseudovector (ctx, &out->header, in_hdr) |
| 1982 | 1984 | ||
| 1983 | static dump_off | 1985 | static dump_off |
| 1984 | finish_dump_pvec (struct dump_context *ctx, | 1986 | finish_dump_pvec (struct dump_context *ctx, |
| @@ -3994,14 +3996,14 @@ dump_do_fixup (struct dump_context *ctx, | |||
| 3994 | Lisp_Object fixup, | 3996 | Lisp_Object fixup, |
| 3995 | Lisp_Object prev_fixup) | 3997 | Lisp_Object prev_fixup) |
| 3996 | { | 3998 | { |
| 3997 | enum dump_fixup_type type = | 3999 | enum dump_fixup_type type |
| 3998 | (enum dump_fixup_type) XFIXNUM (dump_pop (&fixup)); | 4000 | = (enum dump_fixup_type) XFIXNUM (dump_pop (&fixup)); |
| 3999 | dump_off dump_fixup_offset = dump_off_from_lisp (dump_pop (&fixup)); | 4001 | dump_off dump_fixup_offset = dump_off_from_lisp (dump_pop (&fixup)); |
| 4000 | #ifdef ENABLE_CHECKING | 4002 | #ifdef ENABLE_CHECKING |
| 4001 | if (!NILP (prev_fixup)) | 4003 | if (!NILP (prev_fixup)) |
| 4002 | { | 4004 | { |
| 4003 | dump_off prev_dump_fixup_offset = | 4005 | dump_off prev_dump_fixup_offset |
| 4004 | dump_off_from_lisp (XCAR (XCDR (prev_fixup))); | 4006 | = dump_off_from_lisp (XCAR (XCDR (prev_fixup))); |
| 4005 | eassert (dump_fixup_offset - prev_dump_fixup_offset | 4007 | eassert (dump_fixup_offset - prev_dump_fixup_offset |
| 4006 | >= sizeof (void *)); | 4008 | >= sizeof (void *)); |
| 4007 | } | 4009 | } |
| @@ -4618,23 +4620,8 @@ dump_anonymous_allocate_posix (void *base, | |||
| 4618 | } | 4620 | } |
| 4619 | #endif | 4621 | #endif |
| 4620 | 4622 | ||
| 4621 | /* Perform anonymous memory allocation. */ | 4623 | /* Undo the effect of `dump_reserve_address_space'. */ |
| 4622 | static void * | ||
| 4623 | dump_anonymous_allocate (void *base, | ||
| 4624 | const size_t size, | ||
| 4625 | enum dump_memory_protection protection) | ||
| 4626 | { | ||
| 4627 | #if VM_SUPPORTED == VM_POSIX | ||
| 4628 | return dump_anonymous_allocate_posix (base, size, protection); | ||
| 4629 | #elif VM_SUPPORTED == VM_MS_WINDOWS | ||
| 4630 | return dump_anonymous_allocate_w32 (base, size, protection); | ||
| 4631 | #else | ||
| 4632 | errno = ENOSYS; | ||
| 4633 | return NULL; | ||
| 4634 | #endif | ||
| 4635 | } | ||
| 4636 | 4624 | ||
| 4637 | /* Undo the effect of dump_reserve_address_space(). */ | ||
| 4638 | static void | 4625 | static void |
| 4639 | dump_anonymous_release (void *addr, size_t size) | 4626 | dump_anonymous_release (void *addr, size_t size) |
| 4640 | { | 4627 | { |
| @@ -4653,6 +4640,26 @@ dump_anonymous_release (void *addr, size_t size) | |||
| 4653 | #endif | 4640 | #endif |
| 4654 | } | 4641 | } |
| 4655 | 4642 | ||
| 4643 | /* Perform anonymous memory allocation. */ | ||
| 4644 | static void * | ||
| 4645 | dump_anonymous_allocate (void *base, | ||
| 4646 | const size_t size, | ||
| 4647 | enum dump_memory_protection protection) | ||
| 4648 | { | ||
| 4649 | void *val; | ||
| 4650 | |||
| 4651 | #if VM_SUPPORTED == VM_POSIX | ||
| 4652 | val = dump_anonymous_allocate_posix (base, size, protection); | ||
| 4653 | #elif VM_SUPPORTED == VM_MS_WINDOWS | ||
| 4654 | val = dump_anonymous_allocate_w32 (base, size, protection); | ||
| 4655 | #else | ||
| 4656 | errno = ENOSYS; | ||
| 4657 | val = NULL; | ||
| 4658 | #endif | ||
| 4659 | |||
| 4660 | return val; | ||
| 4661 | } | ||
| 4662 | |||
| 4656 | #if VM_SUPPORTED == VM_MS_WINDOWS | 4663 | #if VM_SUPPORTED == VM_MS_WINDOWS |
| 4657 | static void * | 4664 | static void * |
| 4658 | dump_map_file_w32 (void *base, int fd, off_t offset, size_t size, | 4665 | dump_map_file_w32 (void *base, int fd, off_t offset, size_t size, |
| @@ -4824,20 +4831,20 @@ static void | |||
| 4824 | dump_discard_mem (void *mem, size_t size) | 4831 | dump_discard_mem (void *mem, size_t size) |
| 4825 | { | 4832 | { |
| 4826 | #if VM_SUPPORTED == VM_MS_WINDOWS | 4833 | #if VM_SUPPORTED == VM_MS_WINDOWS |
| 4827 | /* Discard COWed pages. */ | 4834 | /* Discard COWed pages. */ |
| 4828 | (void) VirtualFree (mem, size, MEM_DECOMMIT); | 4835 | (void) VirtualFree (mem, size, MEM_DECOMMIT); |
| 4829 | /* Release the commit charge for the mapping. */ | 4836 | /* Release the commit charge for the mapping. */ |
| 4830 | DWORD old_prot; | 4837 | DWORD old_prot; |
| 4831 | (void) VirtualProtect (mem, size, PAGE_NOACCESS, &old_prot); | 4838 | (void) VirtualProtect (mem, size, PAGE_NOACCESS, &old_prot); |
| 4832 | #elif VM_SUPPORTED == VM_POSIX | 4839 | #elif VM_SUPPORTED == VM_POSIX |
| 4833 | # ifdef HAVE_POSIX_MADVISE | 4840 | # ifdef HAVE_POSIX_MADVISE |
| 4834 | /* Discard COWed pages. */ | 4841 | /* Discard COWed pages. */ |
| 4835 | (void) posix_madvise (mem, size, POSIX_MADV_DONTNEED); | 4842 | (void) posix_madvise (mem, size, POSIX_MADV_DONTNEED); |
| 4836 | # elif defined HAVE_MADVISE | 4843 | # elif defined HAVE_MADVISE |
| 4837 | (void) madvise (mem, size, MADV_DONTNEED); | 4844 | (void) madvise (mem, size, MADV_DONTNEED); |
| 4838 | #endif | 4845 | #endif |
| 4839 | /* Release the commit charge for the mapping. */ | 4846 | /* Release the commit charge for the mapping. */ |
| 4840 | (void) mprotect (mem, size, PROT_NONE); | 4847 | (void) mprotect (mem, size, PROT_NONE); |
| 4841 | #endif | 4848 | #endif |
| 4842 | } | 4849 | } |
| 4843 | 4850 | ||
| @@ -4959,21 +4966,23 @@ dump_mmap_release_vm (struct dump_memory_map *map) | |||
| 4959 | static bool | 4966 | static bool |
| 4960 | needs_mmap_retry_p (void) | 4967 | needs_mmap_retry_p (void) |
| 4961 | { | 4968 | { |
| 4962 | #if defined CYGWIN || VM_SUPPORTED == VM_MS_WINDOWS || defined _AIX | 4969 | #if defined CYGWIN || VM_SUPPORTED == VM_MS_WINDOWS \ |
| 4970 | || defined _AIX | ||
| 4963 | return true; | 4971 | return true; |
| 4964 | #else | 4972 | #else /* !CYGWIN && VM_SUPPORTED != VM_MS_WINDOWS && !_AIX */ |
| 4965 | return false; | 4973 | return false; |
| 4966 | #endif | 4974 | #endif /* !CYGWIN && VM_SUPPORTED != VM_MS_WINDOWS && !_AIX */ |
| 4967 | } | 4975 | } |
| 4968 | 4976 | ||
| 4969 | static bool | 4977 | static bool |
| 4970 | dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps, | 4978 | dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps, |
| 4971 | size_t total_size) | 4979 | size_t total_size) |
| 4972 | { | 4980 | { |
| 4981 | int save_errno; | ||
| 4973 | bool ret = false; | 4982 | bool ret = false; |
| 4974 | void *resv = NULL; | 4983 | void *resv = NULL; |
| 4975 | bool retry = false; | 4984 | bool retry = false; |
| 4976 | const bool need_retry = needs_mmap_retry_p (); | 4985 | bool need_retry = needs_mmap_retry_p (); |
| 4977 | 4986 | ||
| 4978 | do | 4987 | do |
| 4979 | { | 4988 | { |
| @@ -4986,11 +4995,10 @@ dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps, | |||
| 4986 | } | 4995 | } |
| 4987 | 4996 | ||
| 4988 | eassert (resv == NULL); | 4997 | eassert (resv == NULL); |
| 4989 | resv = dump_anonymous_allocate (NULL, | 4998 | resv = dump_anonymous_allocate (NULL, total_size, |
| 4990 | total_size, | ||
| 4991 | DUMP_MEMORY_ACCESS_NONE); | 4999 | DUMP_MEMORY_ACCESS_NONE); |
| 4992 | if (!resv) | 5000 | if (!resv) |
| 4993 | goto out; | 5001 | goto out; |
| 4994 | 5002 | ||
| 4995 | char *mem = resv; | 5003 | char *mem = resv; |
| 4996 | 5004 | ||
| @@ -5039,6 +5047,7 @@ dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps, | |||
| 5039 | ret = true; | 5047 | ret = true; |
| 5040 | resv = NULL; | 5048 | resv = NULL; |
| 5041 | out: | 5049 | out: |
| 5050 | save_errno = errno; | ||
| 5042 | if (resv) | 5051 | if (resv) |
| 5043 | dump_anonymous_release (resv, total_size); | 5052 | dump_anonymous_release (resv, total_size); |
| 5044 | if (!ret) | 5053 | if (!ret) |
| @@ -5051,6 +5060,7 @@ dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps, | |||
| 5051 | dump_mmap_release (&maps[i]); | 5060 | dump_mmap_release (&maps[i]); |
| 5052 | } | 5061 | } |
| 5053 | } | 5062 | } |
| 5063 | errno = save_errno; | ||
| 5054 | return ret; | 5064 | return ret; |
| 5055 | } | 5065 | } |
| 5056 | 5066 | ||
| @@ -5058,8 +5068,8 @@ dump_mmap_contiguous_vm (struct dump_memory_map *maps, int nr_maps, | |||
| 5058 | 5068 | ||
| 5059 | Each dump_memory_map structure describes how to fill the | 5069 | Each dump_memory_map structure describes how to fill the |
| 5060 | corresponding range of memory. On input, all members except MAPPING | 5070 | corresponding range of memory. On input, all members except MAPPING |
| 5061 | are valid. On output, MAPPING contains the location of the given | 5071 | are valid. On output, MAPPING contains the location of the given |
| 5062 | chunk of memory. The MAPPING for MAPS[N] is MAPS[N-1].mapping + | 5072 | chunk of memory. The MAPPING for MAPS[N] is MAPS[N-1].mapping + |
| 5063 | MAPS[N-1].size. | 5073 | MAPS[N-1].size. |
| 5064 | 5074 | ||
| 5065 | Each mapping SIZE must be a multiple of the system page size except | 5075 | Each mapping SIZE must be a multiple of the system page size except |
| @@ -5085,8 +5095,10 @@ dump_mmap_contiguous (struct dump_memory_map *maps, int nr_maps) | |||
| 5085 | total_size += maps[i].spec.size; | 5095 | total_size += maps[i].spec.size; |
| 5086 | } | 5096 | } |
| 5087 | 5097 | ||
| 5088 | return (VM_SUPPORTED ? dump_mmap_contiguous_vm : dump_mmap_contiguous_heap) | 5098 | if (VM_SUPPORTED) |
| 5089 | (maps, nr_maps, total_size); | 5099 | return dump_mmap_contiguous_vm (maps, nr_maps, total_size); |
| 5100 | else | ||
| 5101 | return dump_mmap_contiguous_heap (maps, nr_maps, total_size); | ||
| 5090 | } | 5102 | } |
| 5091 | 5103 | ||
| 5092 | typedef uint_fast32_t dump_bitset_word; | 5104 | typedef uint_fast32_t dump_bitset_word; |
| @@ -5129,7 +5141,7 @@ dump_bitset_bit_set_p (const struct dump_bitset *bitset, | |||
| 5129 | { | 5141 | { |
| 5130 | dump_bitset_word bit = 1; | 5142 | dump_bitset_word bit = 1; |
| 5131 | bit <<= bit_number % DUMP_BITSET_WORD_WIDTH; | 5143 | bit <<= bit_number % DUMP_BITSET_WORD_WIDTH; |
| 5132 | return *dump_bitset__bit_slot (bitset, bit_number) & bit; | 5144 | return (*dump_bitset__bit_slot (bitset, bit_number) & bit) != 0; |
| 5133 | } | 5145 | } |
| 5134 | 5146 | ||
| 5135 | static void | 5147 | static void |
| @@ -5548,8 +5560,8 @@ dump_do_dump_relocation (const uintptr_t dump_base, | |||
| 5548 | struct bignum_reload_info reload_info; | 5560 | struct bignum_reload_info reload_info; |
| 5549 | static_assert (sizeof (reload_info) <= sizeof (*bignum_val (bignum))); | 5561 | static_assert (sizeof (reload_info) <= sizeof (*bignum_val (bignum))); |
| 5550 | memcpy (&reload_info, bignum_val (bignum), sizeof (reload_info)); | 5562 | memcpy (&reload_info, bignum_val (bignum), sizeof (reload_info)); |
| 5551 | const mp_limb_t *limbs = | 5563 | const mp_limb_t *limbs = dump_ptr (dump_base, |
| 5552 | dump_ptr (dump_base, reload_info.data_location); | 5564 | reload_info.data_location); |
| 5553 | mpz_roinit_n (bignum->value, limbs, reload_info.nlimbs); | 5565 | mpz_roinit_n (bignum->value, limbs, reload_info.nlimbs); |
| 5554 | break; | 5566 | break; |
| 5555 | } | 5567 | } |
| @@ -5790,15 +5802,29 @@ pdumper_load (const char *dump_filename, char *argv0) | |||
| 5790 | goto out; | 5802 | goto out; |
| 5791 | 5803 | ||
| 5792 | err = PDUMPER_LOAD_ERROR; | 5804 | err = PDUMPER_LOAD_ERROR; |
| 5793 | mark_bits_needed = | 5805 | dump_base = (uintptr_t) sections[DS_HOT].mapping; |
| 5794 | divide_round_up (header->discardable_start, DUMP_ALIGNMENT); | 5806 | |
| 5807 | #if !USE_LSB_TAG | ||
| 5808 | /* The dump may have been mapped at a location that does not admit of | ||
| 5809 | representation as Lisp_Objects. Abort in this case. */ | ||
| 5810 | if ((dump_base + dump_size) & ~VALMASK) | ||
| 5811 | { | ||
| 5812 | fprintf (stderr, | ||
| 5813 | "Failed to load dump file: 0x%p+0x%p & 0x%p != 0\n", | ||
| 5814 | (void *) dump_base, (void *) dump_size, | ||
| 5815 | (void *) (uintptr_t) VALMASK); | ||
| 5816 | goto out; | ||
| 5817 | } | ||
| 5818 | #endif /* !USE_LSB_TAG */ | ||
| 5819 | |||
| 5820 | mark_bits_needed | ||
| 5821 | = divide_round_up (header->discardable_start, DUMP_ALIGNMENT); | ||
| 5795 | if (!dump_bitsets_init (mark_bits, mark_bits_needed)) | 5822 | if (!dump_bitsets_init (mark_bits, mark_bits_needed)) |
| 5796 | goto out; | 5823 | goto out; |
| 5797 | 5824 | ||
| 5798 | /* Point of no return. */ | 5825 | /* Point of no return. */ |
| 5799 | err = PDUMPER_LOAD_SUCCESS; | 5826 | err = PDUMPER_LOAD_SUCCESS; |
| 5800 | dump_base = (uintptr_t) sections[DS_HOT].mapping; | 5827 | gflags.dumped_with_pdumper = true; |
| 5801 | gflags.dumped_with_pdumper_ = true; | ||
| 5802 | dump_private.header = *header; | 5828 | dump_private.header = *header; |
| 5803 | dump_private.mark_bits = mark_bits[0]; | 5829 | dump_private.mark_bits = mark_bits[0]; |
| 5804 | dump_private.last_mark_bits = mark_bits[1]; | 5830 | dump_private.last_mark_bits = mark_bits[1]; |
| @@ -5815,8 +5841,8 @@ pdumper_load (const char *dump_filename, char *argv0) | |||
| 5815 | Lisp_Object hashes = zero_vector; | 5841 | Lisp_Object hashes = zero_vector; |
| 5816 | if (header->hash_list) | 5842 | if (header->hash_list) |
| 5817 | { | 5843 | { |
| 5818 | struct Lisp_Vector *hash_tables = | 5844 | struct Lisp_Vector *hash_tables |
| 5819 | (struct Lisp_Vector *) (dump_base + header->hash_list); | 5845 | = (struct Lisp_Vector *) (dump_base + header->hash_list); |
| 5820 | hashes = make_lisp_ptr (hash_tables, Lisp_Vectorlike); | 5846 | hashes = make_lisp_ptr (hash_tables, Lisp_Vectorlike); |
| 5821 | } | 5847 | } |
| 5822 | 5848 | ||
| @@ -5852,7 +5878,6 @@ pdumper_load (const char *dump_filename, char *argv0) | |||
| 5852 | dump_mmap_release (§ions[i]); | 5878 | dump_mmap_release (§ions[i]); |
| 5853 | if (dump_fd >= 0) | 5879 | if (dump_fd >= 0) |
| 5854 | emacs_close (dump_fd); | 5880 | emacs_close (dump_fd); |
| 5855 | |||
| 5856 | return err; | 5881 | return err; |
| 5857 | } | 5882 | } |
| 5858 | 5883 | ||