Add portable dumper

Add a new portable dumper as an alternative to unexec.  Use it by default.

* src/dmpstruct.awk: New file.
* src/doc.c (get_doc_string): use will_dump_p().
* src/editfns.c (styled_format): silence compiler warning
with UNINIT.
* src/emacs-module.c (syms_of_module): staticpro ltv_mark.
* src/emacs.c (gflags): new variable.
(init_cmdargs): unwrap
(string_starts_with_p, find_argument, dump_error_to_string)
(load_pdump): new functions.
(main): detect pdumper and --temacs invocation; actually load
portable dump when detected; set gflags as appropriate; changes to
init functions throughout to avoid passing explicit
'initialized' argument.
* src/eval.c (inhibit_lisp_code): remove unused variable.
(init_eval_once_for_pdumper): new function.
(init_eval_once): call it.
* src/filelock.c: CANNOT_DUMP -> will_dump_p()
* src/fingerprint-dummy.c: new file
* src/fingerprint.h: new file
* src/fns.c: CANNOT_DUMP -> will_dump_p(), etc.
(weak_hash_tables): remove
(hashfn_equal, hashfn_eql): un-staticify
(make_hash_table): set new 'next_weak' hash table field; drop
global weak_hash_tables logic.
(copy_hash_table): drop global weak_hash_tables logic.
(hash_table_rehash): new function.
(hash_lookup, hash_put, hash_remove_from_table, hash_clear):
rehash if needed.
(sweep_weak_table): un-staticify; explain logic; bool-ify.
(sweep_weak_hash_tables): remove function.
* src/font.c (syms_of_font): remember pdumper stuff.
* src/fontset.c (syms_of_fontset): remember pdumper stuff.
* src/frame.c (make_initial_frame): don't reset Vframe_list.
(init_frame_once_for_pdumper, init_frame_once): new functions.
(syms_of_frame): remove redundant staticpro.
* src/fringe.c (init_fringe_once_for_pdumper): new functin.
(init_fringe_once): call it.
* src/ftcrfont.c (syms_of_ftcrfont_for_pdumper): new function.
(syms_of_ftcrfont): call it.
* src/ftfont.c (syms_of_ftfont_for_pdumper): new function.
(syms_of_ftfont): call it.
* src/ftxont.c (syms_of_ftxfont_for_pdumper): new function.
(syms_of_ftxfont): call it.
* src/gmalloc.c: adjust for pdumper througout
(DUMPED): remove weird custom dumped indicator.
* src/gnutls.c (syms_of_gnutls): pdumper note for
gnutls_global_initialized.
* src/image.c (syms_of_image): add pdumper comment,
initializer note.
* src/insdel.c (prepare_to_modify_buffer_1): account
for buffer contents possibly being in dump image.
* src/keyboard.c (syms_of_keyboard_for_pdumper): new function.
(syms_of_keyboard): staticpro more; call pdumper syms function.
* src/lisp.h: add comments throughout
(gflags): declare.
(will_dump_p, will_bootstrap_p, will_dump_with_pdumper_p)
(dumped_with_pdumper_p, will_dump_with_unexec_p)
(dumped_with_unexec_p, definitely_will_not_unexec_p): new
functions.
(POWER_OF_2, ROUNDUP): move macros.
(PSEUDOVECTOR_TYPE, PSEUDOVECTOR_TYPEP): take vectorlike header
pointer instead of vector; constify.
(Lisp_Hash_Table): add comment about need to rehash on access; add
comment for next_weak.
(HASH_KEY, HASH_VALUE, HASH_HASH, HASH_TABLE_SIZE): const-ify.
(hash_table_rehash): declare.
(hash_rehash_needed_p, hash_rehash_if_needed): new functions.
(finalizers, doomed_finalizers): declare extern.
(SUBR_SECTION_ATTRIBUTE): new macro.
(staticvec, staticidx): un-static-ify.
(sweep_weak_hash_tables): remove declaration.
(sweep_weak_table): declare.
(hashfn_eql, hashfn_equal): declare.
(number_finalizers_run): new variable.
(Vdead): externify when ENABLE_CHECKING.
(gc_root_type): new enumeration.
(gc_root_visitor): new struct.
(visit_static_gc_roots): declare.
(vectorlike_nbytes): declare.
(vector_nbytes): define as trivial inline function wrapper for
vectorlike_nbytes.
(init_obarray_once): change signature.
(primary_thread): extern-ify.
(init_buffer): change signature.
(init_frame_once): declare.
* src/lread.c (readevalloop): adjust for new dumped predicates.
(init_obarray_once): new function.
(ndefsubr): new variable.
(defsubr): increment it.
(load_path_check): adjust for pdumper.
(load_path_default): use pdumper functions; adjust for
dump search.
* src/macfont.m (macfont_init_font_change_handler): avoid
shadowing global.
(syms_of_macfont_for_pdumper): new function.
(syms_of_macfont): call it.
* src/menu.c (syms_of_menu): staticpro more stuff.
* src/minibuf.c (Ftry_completion): rehash if needed.
(init_minibuf_once_for_pdumper): new function.
(init_minibuf_once): call it.
* src/nsfont.m (syms_of_nsfns): staticpro more.
* src/nsfont.m (syms_of_nsfont_for_pdumper): new function.
(syms_of_nsfont): call it.
* src/nsterm.m (syms_of_nsfont): remember pdumper stuff.
* src/pdumper.c: new file.
* src/pdumper.h: new file.
* src/process.c (init_process_emacs): use new pdumper functions
instead of CANNOT_DUMP.
* src/profiler.c (syms_of_profiler_for_pdumper): new function.
(syms_of_profiler_for_pdumper): call it.
* src/search.c (syms_of_search_for_pdumper): new function.
(syms_of_search_for_pdumper): call it.
* src/sheap.c (bss_sbrk_did_unexec): remove.
* src/sheap.h (bss_sbrk_did_unexec): remove.
* src/syntax.c (syms_of_syntax): don't redundantly staticpro
re_match_object.
* src/sysdep.c: use will_dump_with_unexec_p() instead of bss
hack thing.
* src/syssignals.h (init_sigsegv): declare.
* src/systime.h (init_timefns): remove bool from signature.
* src/textprop.c (syms_of_textprop): move staticpro.
* src/thread.c (main_thread_p): constify.
* src/thread.h (main_thread_p): constify.
* src/timefns.c (init_timefns): remove bool from signature.
(syms_of_timefns_for_pdumper): new function.
(syms_of_timefns): call it.
* src/w32.c: rearrange code.
* src/w32.h (w32_relocate): declare.
* src/w32fns.c (syms_of_w32fns): add pdumper note.
* src/w32font.c (syms_of_w32font_for_pdumper): new function.
(syms_of_w32font): call it.
* src/w32heap.c (using_dynamic_heap): new variable.
(init_heap): use it.
* src/w32menu.c (syms_of_w32menu): add pdumper note.
* src/w32proc.c
(ctrl_c_handler, mainCRTStartup, _start, open_input_file)
(rva_to_section, close_file_data): move here.
* src/w32uniscribe.c (syms_of_w32uniscribe_for_pdumper):
new function.
(syms_of_w32uniscribe): call it.
* src/window.c (init_window_once_for_pdumper): new function.
(init_window_once): call it; staticpro more stuff.
* src/xfont.c (syms_of_xfont_for_pdumper): new function.
(syms_of_xfont): call it.
* src/xftfont.c (syms_of_xftfont_for_pdumper): new function.
(syms_of_xftfont): call it.
* src/xmenu.c (syms_of_xmenu_for_pdumper): new function.
(syms_of_xmenu): call it.
* src/xselect.c (syms_of_xselect_for_pdumper): new function.
(syms_of_xselect): call it.
* src/xsettings.c (syms_of_xsettings): add more pdumper notes.
* src/term.c (syms_of_xterm): add pdumper note.

* src/dispnew.c (init_faces_initial): new function.
(init_display_interactive): rename from init_display; use
will_dump_p instead of !initialized.  Initialize faces early for
pdumper if needed.
(init_display): new function.
(syms_of_display_for_pdumper): new function.
(syms_of_display): call it.

* src/dbusbind.c (syms_of_dbusbind): Add TODO for bus reset
on pdumper load.

* src/data.c (Fdefalias): Use will_dump_p
instead of Vpurify_flag.
(Fmake_variable_buffer_local): silence compiler warning with -Og
by making valcontents UNINIT.
(arith_driver): silence compiler warning with UNINIT.

* src/conf_post.h (ATTRIBUTE_SECTION): new macro.

* src/composite.c (composition_gstring_put_cache): rehash hash
table if needed.

* src/coding.c (init_coding_once, syms_of_coding): remember
pdumper stuff.

* src/charset.h (charset_table_size, charset_table_user): declare.

* src/charset.c (charset_table_used, charset_table_size): un-static.
(init_charset_oncem, syms_of_charset): remember pdumper stuff.

* src/category.c (category_table_version): remove obsolete
variable.

* src/callint.c (syms_of_callint): staticpro 'preserved_fns'
(init_callproc): use will_dump_p instead of !CANNOT_DUMP.

* src/bytecode.c (exec_byte_code): rehash table tables if needed

* src/buffer.c (alloc_buffer_text, free_buffer_text): account for
pdumper
(init_buffer_once): add TODO; remember stuff for pdumper.
(init_buffer): don't take initialized argument; adjust
for pdumper.

* src/atimer.c (init_atimer): initialize subr only if
!initialized.

* src/alloc.c: (vector_marked_p, set_vector_marked)
(vectorlike_marked_p, set_vectorlike_marked, cons_marked_p)
(set_cons_marked, string_marked_p, set_string_marked)
(symbol_marked_p, set_symbol_marked, interval_marked_p)
(set_interval_marked): new accessor routines.  Use them
instead of raw GC access throughout.
(Vdead): make non-static when ENABLE_CHECKING.
(vectorlike_nbytes): rename of 'vector_nbytes'; take a vectorlike
header as input instead of a vector.
(number_finalizers_run): new internal C variable.
(mark_maybe_object): check for pdumper objects.
(valid_pointer_p): don't be gratuitously inefficient under rr(1).
(make_pure_c_string): add support for size_byte = -2 mode
indicating that string data points into Emacs image rodata.
(visit_vectorlike_root): visits GC roots embedded in
vectorlike objects.
(visit_buffer_root): visits GC roots embedded in
our totally-not-a-buffer buffer global objects.
(visit_static_gc_roots): visit GC roots in the Emacs data section.
(mark_object_root_visitor): root callback used for conventional GC
marking
(weak_hash_tables): new internal variable for tracking found weak
hash tables during GC.
(mark_and_sweep_weak_table_contents): new weak hash table marking.
(garbage_collect_1): use new GC root visitor machinery.
(mark_vectorlike): accept a vectorlike_header instead of a
Lisp_Vector.
(mark_frame, mark_window, mark_hash_table): new functions.
(mark_object): initialize 'm'; check for pdumper objects and use
new mark-bit accessors throughout.  Remove some object-specific
marking code and move to helper functions above.
(survives_gc_p): check for pdumper objects.
(gc-sweep): clear pdumper mark bits.
(init_alloc_once_for_pdumper): new helper function for early init
called both during normal init and pdumper load.
(init_alloc_once): pdumper integration.

* src/Makefile.in: Rewrite dumping for pdumper; add pdumper.o;
invoke temacs with --temacs command line option; build dmpstruct.h
from dmpstruct.awk; stop relying on CANNOT_DUMP; clean up pdumper
intermediate files during build.

* nextstep/Makefile.in: build emacs.pdmp into NS packages

* lisp/startup.el: account for new '--temacs' and '--dump-file'
command line option.

* lisp/loadup.el: rewrite early init to account for pdumper; use
injected 'dump-mode' variable (set via the new '--temacs' option)
instead of parsing command line.

* lisp/cus-start.el: Check 'dump-mode' instead of 'purify-flag',
since the new 'dump-mode'

* lib-src/make-fingerprint.c: new program

* lib-src/Makefile.in: built make-fingerprint utility program

* configure.ac: Add --with-pdumper toggle to control pdumper
support; add --with-unexec toggle to control unexec support.
Add --with-dumping option to control which dumping strategy we use
by default.  Adjust for pdumper throughout.  Check for
posix_madvise.

* Makefile.in: Add @DUMPING@ substitution; add pdumper mode.

* .gitignore: Add make-fingerprint, temacs.in, fingerprint.c,
dmpstruct.h, and pdumper dump files.
This commit is contained in:
Daniel Colascione 2019-01-15 17:36:54 -05:00
parent 2a3bd6798e
commit d12e5d003d
92 changed files with 8312 additions and 965 deletions

5
.gitignore vendored
View file

@ -171,6 +171,7 @@ lib-src/emacsclient
lib-src/etags
lib-src/hexl
lib-src/make-docfile
lib-src/make-fingerprint
lib-src/movemail
lib-src/profile
lib-src/test-distrib
@ -184,6 +185,10 @@ src/bootstrap-emacs
src/emacs
src/emacs-[0-9]*
src/temacs
src/temacs.in
src/fingerprint.c
src/dmpstruct.h
src/*.pdmp
# Character-set info.
admin/charsets/jisx2131-filter

View file

@ -66,6 +66,8 @@
SHELL = @SHELL@
DUMPING=@DUMPING@
# This only matters when inheriting a CDPATH not starting with the
# current directory.
CDPATH=
@ -491,6 +493,9 @@ install-arch-dep: src install-arch-indep install-etcdoc install-$(NTDIR)
$(MAKE) -C lib-src install
ifeq (${ns_self_contained},no)
${INSTALL_PROGRAM} $(INSTALL_STRIP) src/emacs${EXEEXT} "$(DESTDIR)${bindir}/$(EMACSFULL)"
ifeq (${DUMPING},pdumper)
${INSTALL_DATA} src/emacs.pdmp "$(DESTDIR)${libexecdir}/emacs/${version}/${configuration}"/emacs.pdmp
endif
-chmod 755 "$(DESTDIR)${bindir}/$(EMACSFULL)"
ifndef NO_BIN_LINK
rm -f "$(DESTDIR)${bindir}/$(EMACS)"

View file

@ -311,6 +311,87 @@ this option's value should be 'yes', 'no', 'alsa', 'oss', or 'bsd-ossaudio'.])
],
[with_sound=$with_features])
AC_ARG_WITH([pdumper],
AS_HELP_STRING(
[--with-pdumper=VALUE],
[enable pdumper support unconditionally
('yes', 'no', or 'auto': default 'auto')]),
[ case "${withval}" in
yes|no|auto) val=$withval ;;
*) AC_MSG_ERROR(
['--with-pdumper=$withval' is invalid;
this option's value should be 'yes' or 'no'.]) ;;
esac
with_pdumper=$val
],
[with_pdumper=auto])
AC_ARG_WITH([unexec],
AS_HELP_STRING(
[--with-unexec=VALUE],
[enable unexec support unconditionally
('yes', 'no', or 'auto': default 'auto')]),
[ case "${withval}" in
yes|no|auto) val=$withval ;;
*) AC_MSG_ERROR(
['--with-unexec=$withval' is invalid;
this option's value should be 'yes' or 'no'.]) ;;
esac
with_unexec=$val
],
[with_unexec=auto])
AC_ARG_WITH([dumping],[AS_HELP_STRING([--with-dumping=VALUE],
[kind of dumping to use for initial Emacs build
(VALUE one of: pdumper, unexec, none; default pdumper)])],
[ case "${withval}" in
pdumper|unexec|none) val=$withval ;;
*) AC_MSG_ERROR(['--with-dumping=$withval is invalid;
this option's value should be 'pdumper', 'unexec', or 'none'.])
;;
esac
with_dumping=$val
],
[with_dumping=pdumper])
if test "$with_pdumper" = "auto"; then
if test "$with_dumping" = "pdumper"; then
with_pdumper=yes
else
with_pdumper=no
fi
fi
if test "$with_unexec" = "auto"; then
if test "$with_dumping" = "unexec"; then
with_unexec=yes
else
with_unexec=no
fi
fi
if test "$with_dumping" = "pdumper" && test "$with_pdumper" = "no"; then
AC_MSG_ERROR(['--with-dumping=pdumper' requires pdumper support])
fi
if test "$with_dumping" = "unexec" && test "$with_unexec" = "no"; then
AC_MSG_ERROR(['--with-dumping=unexec' requires unexec support])
fi
if test "$with_pdumper" = "yes"; then
AC_DEFINE(HAVE_PDUMPER, 1, [Define to build with portable dumper support])
fi
if test "$with_unexec" = "yes"; then
CANNOT_DUMP=no
else
CANNOT_DUMP=yes
fi
DUMPING=$with_dumping
AC_SUBST(DUMPING)
AC_SUBST(CANNOT_DUMP)
dnl FIXME currently it is not the last.
dnl This should be the last --with option, because --with-x is
dnl added later on when we find the file name of X, and it's best to
@ -1215,6 +1296,10 @@ AC_PATH_PROG(GZIP_PROG, gzip)
test $with_compress_install != yes && test -n "$GZIP_PROG" && \
GZIP_PROG=" # $GZIP_PROG # (disabled by configure --without-compress-install)"
if test "$with_dumping" = "unexec" && test "$opsys" = "nacl"; then
AC_MSG_ERROR([nacl is not compatible with --with-dumping=unexec])
fi
AC_CACHE_CHECK([for 'find' args to delete a file],
[emacs_cv_find_delete],
[if touch conftest.tmp && find conftest.tmp -delete 2>/dev/null &&
@ -1227,25 +1312,21 @@ AC_SUBST([FIND_DELETE])
PAXCTL_dumped=
PAXCTL_notdumped=
if test "$CANNOT_DUMP" != yes; then
if test $opsys = gnu-linux; then
if test "${SETFATTR+set}" != set; then
AC_CACHE_CHECK([for setfattr],
[emacs_cv_prog_setfattr],
[touch conftest.tmp
if (setfattr -n user.pax.flags conftest.tmp) >/dev/null 2>&1; then
emacs_cv_prog_setfattr=yes
else
emacs_cv_prog_setfattr=no
fi])
if test "$emacs_cv_prog_setfattr" = yes; then
PAXCTL_notdumped='$(SETFATTR) -n user.pax.flags -v er'
SETFATTR=setfattr
else
SETFATTR=
fi
rm -f conftest.tmp
AC_SUBST([SETFATTR])
if test "$CANNOT_DUMP" = "no" && test $opsys = gnu-linux; then
if test "${SETFATTR+set}" != set; then
AC_CACHE_CHECK([for setfattr],
[emacs_cv_prog_setfattr],
[touch conftest.tmp
if (setfattr -n user.pax.flags conftest.tmp) >/dev/null 2>&1; then
emacs_cv_prog_setfattr=yes
else
emacs_cv_prog_setfattr=no
fi])
if test "$emacs_cv_prog_setfattr" = yes; then
PAXCTL_notdumped='$(SETFATTR) -n user.pax.flags -v er'
SETFATTR=setfattr
else
SETFATTR=
fi
fi
case $opsys,$PAXCTL_notdumped,$emacs_uname_r in
@ -1382,22 +1463,12 @@ AC_CACHE_CHECK([whether addresses are sanitized],
[emacs_cv_sanitize_address=yes],
[emacs_cv_sanitize_address=no])])
dnl The function dump-emacs will not be defined and temacs will do
dnl (load "loadup") automatically unless told otherwise.
test "x$CANNOT_DUMP" = "x" && CANNOT_DUMP=no
case "$opsys" in
nacl) CANNOT_DUMP=yes ;;
esac
if test "$CANNOT_DUMP" = "yes"; then
AC_DEFINE(CANNOT_DUMP, 1, [Define if Emacs cannot be dumped on your system.])
AC_DEFINE(CANNOT_DUMP, 1, [Define if Emacs should not support unexec.])
elif test "$emacs_cv_sanitize_address" = yes; then
AC_MSG_WARN([[Addresses are sanitized; suggest CANNOT_DUMP=yes]])
fi
AC_SUBST(CANNOT_DUMP)
UNEXEC_OBJ=unexelf.o
case "$opsys" in
# MSDOS uses unexcoff.o
@ -1476,8 +1547,9 @@ case "$opsys" in
LD_SWITCH_SYSTEM="\$(LD_SWITCH_X_SITE_RPATH) $LD_SWITCH_SYSTEM" ;;
esac
C_SWITCH_MACHINE=
test "$CANNOT_DUMP" = yes ||
case $canonical in
alpha*)
AC_CHECK_DECL([__ELF__])
@ -4064,6 +4136,9 @@ dnl No need to check for posix_memalign if aligned_alloc works.
AC_CHECK_FUNCS([aligned_alloc posix_memalign], [break])
AC_CHECK_DECLS([aligned_alloc], [], [], [[#include <stdlib.h>]])
# Dump loading
AC_CHECK_FUNCS([posix_madvise])
dnl Cannot use AC_CHECK_FUNCS
AC_CACHE_CHECK([for __builtin_frame_address],
[emacs_cv_func___builtin_frame_address],
@ -5540,6 +5615,9 @@ AS_ECHO([" Does Emacs use -lXaw3d? ${HAVE_XAW3D
Does Emacs use toolkit scroll bars? ${USE_TOOLKIT_SCROLL_BARS}
Does Emacs support Xwidgets (requires gtk3)? ${HAVE_XWIDGETS}
Does Emacs have threading support in lisp? ${threads_enabled}
Does Emacs support the portable dumper? ${with_pdumper}
Does Emacs support legacy unexec dumping? ${with_unexec}
Which dumping strategy does Emacs use? ${with_dumping}
"])
if test -n "${EMACSDATA}"; then

View file

@ -167,7 +167,7 @@ UTILITIES = profile${EXEEXT} hexl${EXEEXT} \
$(if $(with_mailutils), , movemail${EXEEXT}) \
$(and $(use_gamedir), update-game-score${EXEEXT})
DONT_INSTALL= make-docfile${EXEEXT}
DONT_INSTALL= make-docfile${EXEEXT} make-fingerprint${EXEEXT}
# Like UTILITIES, but they're not system-dependent, and should not be
# deleted by the distclean target.
@ -385,6 +385,9 @@ profile${EXEEXT}: ${srcdir}/profile.c $(NTLIB) $(config_h)
make-docfile${EXEEXT}: ${srcdir}/make-docfile.c $(NTLIB) $(config_h)
$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} $< $(NTLIB) $(LOADLIBES) -o $@
make-fingerprint${EXEEXT}: ${srcdir}/make-fingerprint.c $(NTLIB) $(config_h)
$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} $< $(NTLIB) $(LOADLIBES) -o $@
movemail${EXEEXT}: ${srcdir}/movemail.c pop.o $(NTLIB) $(config_h)
$(AM_V_CCLD)$(CC) ${ALL_CFLAGS} ${MOVE_FLAGS} $< pop.o \
$(NTLIB) $(LOADLIBES) $(LIBS_MOVE) -o $@

113
lib-src/make-fingerprint.c Normal file
View file

@ -0,0 +1,113 @@
/* Hash inputs and generate C file with the digest.
Copyright (C) 1985-1986, 1992-1994, 1997, 1999-2016 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* The arguments given to this program are all the object files that
go into building GNU Emacs. There is no special search logic to find
the files. */
#include <config.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysstdio.h>
#include <sha256.h>
#include <getopt.h>
#ifdef WINDOWSNT
/* Defined to be sys_fopen in ms-w32.h, but only #ifdef emacs, so this
is really just insurance. */
#undef fopen
#include <direct.h>
#endif /* WINDOWSNT */
int
main (int argc, char **argv)
{
int c;
bool raw = false;
while (0 <= (c = getopt (argc, argv, "rh")))
{
switch (c)
{
case 'r':
raw = true;
break;
case 'h':
printf ("make-fingerprint [-r] FILES...: compute a hash\n");
return 0;
default:
return 1;
}
}
struct sha256_ctx ctx;
sha256_init_ctx (&ctx);
for (int i = optind; i < argc; ++i)
{
FILE *f = fopen (argv[i], "r" FOPEN_BINARY);
if (!f)
{
fprintf (stderr, "%s: Error: could not open %s\n",
argv[0], argv[i]);
return 1;
}
char buf[128*1024];
do
{
size_t chunksz = fread (buf, 1, sizeof (buf), f);
if (ferror (f))
{
fprintf (stderr, "%s: Error: could not read %s\n",
argv[0], argv[i]);
return 1;
}
sha256_process_bytes (buf, chunksz, &ctx);
} while (!feof (f));
fclose (f);
}
uint8_t digest[32];
sha256_finish_ctx (&ctx, digest);
if (raw)
{
for (int i = 0; i < 32; ++i)
printf ("%02X", digest[i]);
}
else
{
printf ("#include \"fingerprint.h\"\n");
printf ("\n");
printf ("const uint8_t fingerprint[32] = { ");
for (int i = 0; i < 32; ++i)
printf ("%s0x%02X", i ? ", " : "", digest[i]);
printf (" };\n");
}
return EXIT_SUCCESS;
}
/* make-fingerprint.c ends here */

View file

@ -730,7 +730,7 @@ since it could result in memory overflow and make Emacs crash."
;; If this is NOT while dumping Emacs, set up the rest of the
;; customization info. This is the stuff that is not needed
;; until someone does M-x customize etc.
(unless purify-flag
(unless dump-mode
;; Add it to the right group(s).
(if (listp group)
(dolist (g group)
@ -752,7 +752,7 @@ since it could result in memory overflow and make Emacs crash."
;; Record cus-start as loaded if we have set up all the info that we can.
;; Don't record it as loaded if we have only set up the standard values
;; and safe/risky properties.
(unless purify-flag
(unless dump-mode
(provide 'cus-start))
;;; cus-start.el ends here

View file

@ -63,6 +63,7 @@
;; FIXME: Now that macroexpansion is also performed when loading an interpreted
;; file, this is not a real problem any more.
(defconst pcase--memoize (make-hash-table :weakness 'key :test 'eq))
;; (defconst pcase--memoize (make-hash-table :test 'eq))
;; (defconst pcase--memoize-1 (make-hash-table :test 'eq))
;; (defconst pcase--memoize-2 (make-hash-table :weakness 'key :test 'equal))

View file

@ -1009,7 +1009,7 @@ directory if it does not exist."
;; Make sure `user-emacs-directory' exists,
;; unless we're in batch mode or dumping Emacs.
(or noninteractive
purify-flag
dump-mode
(let (errtype)
(if (file-directory-p user-emacs-directory)
(or (file-accessible-directory-p user-emacs-directory)

View file

@ -1334,7 +1334,7 @@ Setup char-width-table appropriate for non-CJK language environment."
;; Setting char-script-table.
(if purify-flag
(if dump-mode
;; While dumping, we can't use require, and international is not
;; in load-path.
(load "international/charscript")

View file

@ -343,7 +343,7 @@ Return t if file exists."
;; Have the original buffer current while we eval.
(eval-buffer buffer nil
;; This is compatible with what `load' does.
(if purify-flag file fullname)
(if dump-mode file fullname)
nil t))
(let (kill-buffer-hook kill-buffer-query-functions)
(kill-buffer buffer)))

View file

@ -26,6 +26,9 @@
;; This is loaded into a bare Emacs to make a dumpable one.
;; Emacs injects the variable `dump-mode' to tell us how to dump.
;; We unintern it before allowing user code to run.
;; If you add a file to be loaded here, keep the following points in mind:
;; i) If the file is no-byte-compile, explicitly load the .el version.
@ -54,33 +57,58 @@
;; bidi.c needs for its job.
(setq redisplay--inhibit-bidi t)
(message "dump mode: %s" dump-mode)
;; Add subdirectories to the load-path for files that might get
;; autoloaded when bootstrapping.
;; autoloaded when bootstrapping or running Emacs normally.
;; This is because PATH_DUMPLOADSEARCH is just "../lisp".
(if (or (equal (member "bootstrap" command-line-args) '("bootstrap"))
(if (or (member dump-mode '("bootstrap" "pbootstrap"))
;; FIXME this is irritatingly fragile.
(and (stringp (nth 4 command-line-args))
(string-match "^unidata-gen\\(\\.elc?\\)?$"
(nth 4 command-line-args)))
(member (nth 7 command-line-args) '("unidata-gen-file"
"unidata-gen-charprop"))
(if (fboundp 'dump-emacs)
(string-match "src/bootstrap-emacs" (nth 0 command-line-args))
t))
(let ((dir (car load-path)))
(and (stringp (nth 4 command-line-args))
(string-match "^unidata-gen\\(\\.elc?\\)?$"
(nth 4 command-line-args)))
(member (nth 7 command-line-args) '("unidata-gen-file"
"unidata-gen-charprop"))
(null dump-mode))
(progn
;; Find the entry in load-path that contains Emacs elisp and
;; splice some additional directories in there for the benefit
;; of autoload and regular Emacs use.
(let ((subdirs '("emacs-lisp"
"progmodes"
"language"
"international"
"textmodes"
"vc"))
(iter load-path))
(while iter
(let ((dir (car iter))
(subdirs subdirs)
esubdirs esubdir)
(while subdirs
(setq esubdir (expand-file-name (car subdirs) dir))
(setq subdirs (cdr subdirs))
(if (file-directory-p esubdir)
(setq esubdirs (cons esubdir esubdirs))
(setq subdirs nil esubdirs nil)))
(if esubdirs
(progn
(setcdr iter (nconc (nreverse esubdirs) (cdr iter)))
(setq iter nil))
(setq iter (cdr iter))
(if (null iter)
(signal
'error (list
(format-message
"Could not find elisp load-path: searched %S"
load-path))))))))
;; We'll probably overflow the pure space.
(setq purify-flag nil)
;; Value of max-lisp-eval-depth when compiling initially.
;; During bootstrapping the byte-compiler is run interpreted when
;; compiling itself, which uses a lot more stack than usual.
(setq max-lisp-eval-depth 2200)
(setq load-path (list (expand-file-name "." dir)
(expand-file-name "emacs-lisp" dir)
(expand-file-name "progmodes" dir)
(expand-file-name "language" dir)
(expand-file-name "international" dir)
(expand-file-name "textmodes" dir)
(expand-file-name "vc" dir)))))
;; During bootstrapping the byte-compiler is run interpreted
;; when compiling itself, which uses a lot more stack
;; than usual.
(setq max-lisp-eval-depth 2200)))
(if (eq t purify-flag)
;; Hash consing saved around 11% of pure space in my tests.
@ -88,10 +116,7 @@
(message "Using load-path %s" load-path)
;; This is a poor man's `last', since we haven't loaded subr.el yet.
(if (and (fboundp 'dump-emacs)
(or (equal (member "bootstrap" command-line-args) '("bootstrap"))
(equal (member "dump" command-line-args) '("dump"))))
(if dump-mode
(progn
;; To reduce the size of dumped Emacs, we avoid making huge char-tables.
(setq inhibit-load-charset-map t)
@ -350,15 +375,16 @@ lost after dumping")))
;; file primitive. So the only workable solution to support building
;; in non-ASCII directories is to manipulate unibyte strings in the
;; current locale's encoding.
(if (and (member (car (last command-line-args)) '("dump" "bootstrap"))
(fboundp 'dump-emacs)
(multibyte-string-p default-directory))
(if (and dump-mode (multibyte-string-p default-directory))
(error "default-directory must be unibyte when dumping Emacs!"))
;; Determine which build number to use
;; based on the executables that now exist.
(if (and (equal (last command-line-args) '("dump"))
(fboundp 'dump-emacs)
(if (and (or
(and (equal dump-mode "dump")
(fboundp 'dump-emacs))
(and (equal dump-mode "pdump")
(fboundp 'dump-emacs-portable)))
(not (eq system-type 'ms-dos)))
(let* ((base (concat "emacs-" emacs-version "."))
(exelen (if (eq system-type 'windows-nt) -4))
@ -376,8 +402,10 @@ lost after dumping")))
(message "Finding pointers to doc strings...")
(if (and (fboundp 'dump-emacs)
(equal (last command-line-args) '("dump")))
(if (and (or (and (fboundp 'dump-emacs)
(equal dump-mode "dump"))
(and (fboundp 'dump-emacs-portable)
(equal dump-mode "pdump"))))
(Snarf-documentation "DOC")
(condition-case nil
(Snarf-documentation "DOC")
@ -446,43 +474,55 @@ lost after dumping")))
;; Make sure we will attempt bidi reordering henceforth.
(setq redisplay--inhibit-bidi nil)
(if (and (fboundp 'dump-emacs)
(member (car (last command-line-args)) '("dump" "bootstrap")))
(progn
;; Prevent build-time PATH getting stored in the binary.
;; Mainly cosmetic, but helpful for Guix. (Bug#20330)
;; Do this here, rather than earlier, so that the above code
;; can invoke Git commands and the like.
(setq exec-path nil)
(message "Dumping under the name emacs")
(if dump-mode
(let ((output (cond ((equal dump-mode "pdump") "emacs.pdmp")
((equal dump-mode "dump") "emacs")
((equal dump-mode "bootstrap") "emacs")
((equal dump-mode "pbootstrap") "bootstrap-emacs.pdmp")
(t (error "unrecognized dump mode %s" dump-mode)))))
(message "Dumping under the name %s" output)
(condition-case ()
(delete-file "emacs")
(file-error nil))
;; We used to dump under the name xemacs, but that occasionally
;; confused people installing Emacs (they'd install the file
;; under the name `xemacs'), and it's inconsistent with every
;; other GNU program's build process.
(dump-emacs "emacs" "temacs")
(message "%d pure bytes used" pure-bytes-used)
(delete-file output)
(file-error nil))
;; On MS-Windows, the current directory is not necessarily the
;; same as invocation-directory.
(let (success)
(unwind-protect
(progn
(if (member dump-mode '("pdump" "pbootstrap"))
(dump-emacs-portable (expand-file-name output invocation-directory))
(dump-emacs output "temacs")
(message "%d pure bytes used" pure-bytes-used))
(setq success t))
(unless success
(ignore-errors
(delete-file output)))))
;; Recompute NAME now, so that it isn't set when we dump.
(if (not (or (eq system-type 'ms-dos)
;; Don't bother adding another name if we're just
;; building bootstrap-emacs.
(equal (last command-line-args) '("bootstrap"))))
(let ((name (format "emacs-%s.%d" emacs-version emacs-build-number))
(exe (if (eq system-type 'windows-nt) ".exe" "")))
(while (string-match "[^-+_.a-zA-Z0-9]+" name)
(setq name (concat (downcase (substring name 0 (match-beginning 0)))
"-"
(substring name (match-end 0)))))
(setq name (concat name exe))
(message "Adding name %s" name)
;; When this runs on Windows, invocation-directory is not
;; necessarily the current directory.
(add-name-to-file (expand-file-name (concat "emacs" exe)
invocation-directory)
(expand-file-name name invocation-directory)
t)))
(member dump-mode '("pbootstrap" "bootstrap"))))
(let ((name (format "emacs-%s.%d" emacs-version emacs-build-number))
(exe (if (eq system-type 'windows-nt) ".exe" "")))
(while (string-match "[^-+_.a-zA-Z0-9]+" name)
(setq name (concat (downcase (substring name 0 (match-beginning 0)))
"-"
(substring name (match-end 0)))))
(message "Adding name %s" (concat name exe))
;; When this runs on Windows, invocation-directory is not
;; necessarily the current directory.
(add-name-to-file (expand-file-name (concat "emacs" exe)
invocation-directory)
(expand-file-name (concat name exe)
invocation-directory)
t)
(when (equal dump-mode "pdump")
(message "Adding name %s" (concat name ".pdmp"))
(add-name-to-file (expand-file-name "emacs.pdmp"
invocation-directory)
(expand-file-name (concat name ".pdmp")
invocation-directory)
t))))
(kill-emacs)))
;; For machines with CANNOT_DUMP defined in config.h,

View file

@ -1056,7 +1056,8 @@ please check its value")
(let* ((longopts '(("--no-init-file") ("--no-site-file")
("--no-x-resources") ("--debug-init")
("--user") ("--iconic") ("--icon-type") ("--quick")
("--no-blinking-cursor") ("--basic-display")))
("--no-blinking-cursor") ("--basic-display")
("--dump-file") ("--temacs")))
(argi (pop args))
(orig-argi argi)
argval)
@ -1108,6 +1109,9 @@ please check its value")
(push '(visibility . icon) initial-frame-alist))
((member argi '("-nbc" "-no-blinking-cursor"))
(setq no-blinking-cursor t))
((member argi '("-dump-file" "-temacs")) ; Handled in C
(or argval (pop args))
(setq argval nil))
;; Push the popped arg back on the list of arguments.
(t
(push argi args)

View file

@ -44,7 +44,7 @@ ns_check_file = @ns_appdir@/@ns_check_file@
.PHONY: all
all: ${ns_appdir} ${ns_appbindir}/Emacs
all: ${ns_appdir} ${ns_appbindir}/Emacs ${ns_appbindir}/emacs.pdmp
${ns_check_file} ${ns_appdir}: ${srcdir}/${ns_appsrc} ${ns_appsrc}
rm -rf ${ns_appdir}
@ -63,6 +63,10 @@ ${ns_appbindir}/Emacs: ${ns_appdir} ${ns_check_file} ../src/emacs${EXEEXT}
${MKDIR_P} ${ns_appbindir}
cp -f ../src/emacs${EXEEXT} $@
${ns_appbindir}/emacs.pdmp: ${ns_appdir} ${ns_check_file} ../src/emacs${EXEEXT}.pdmp
${MKDIR_P} ${ns_appbindir}
cp -f ../src/emacs${EXEEXT}.pdmp $@
.PHONY: FORCE
../src/emacs${EXEEXT}: FORCE

View file

@ -54,8 +54,6 @@ lwlibdir = ../lwlib
# Configuration files for .o files to depend on.
config_h = config.h $(srcdir)/conf_post.h
bootstrap_exe = ../src/bootstrap-emacs$(EXEEXT)
## ns-app if HAVE_NS, else empty.
OTHER_FILES = @OTHER_FILES@
@ -332,7 +330,7 @@ BUILD_DETAILS = @BUILD_DETAILS@
UNEXEC_OBJ = @UNEXEC_OBJ@
CANNOT_DUMP=@CANNOT_DUMP@
DUMPING=@DUMPING@
# 'make' verbosity.
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
@ -357,6 +355,15 @@ am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
bootstrap_exe = ../src/bootstrap-emacs$(EXEEXT)
ifeq ($(DUMPING),pdumper)
bootstrap_pdmp := bootstrap-emacs.pdmp # Keep in sync with loadup.el
pdmp := emacs.pdmp
else
bootstrap_pdmp :=
pdmp :=
endif
# Flags that might be in WARN_CFLAGS but are not valid for Objective C.
NON_OBJC_CFLAGS = -Wignored-attributes -Wignored-qualifiers -Wopenmp-simd
@ -395,7 +402,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
bignum.o buffer.o filelock.o insdel.o marker.o \
minibuf.o fileio.o dired.o \
cmds.o casetab.o casefiddle.o indent.o search.o regex-emacs.o undo.o \
alloc.o data.o doc.o editfns.o callint.o \
alloc.o pdumper.o data.o doc.o editfns.o callint.o \
eval.o floatfns.o fns.o font.o print.o lread.o $(MODULES_OBJ) \
syntax.o $(UNEXEC_OBJ) bytecode.o \
process.o gnutls.o callproc.o \
@ -446,9 +453,17 @@ FIRSTFILE_OBJ=@FIRSTFILE_OBJ@
ALLOBJS = $(FIRSTFILE_OBJ) $(VMLIMIT_OBJ) $(obj) $(otherobj)
# Must be first, before dep inclusion!
all: emacs$(EXEEXT) $(OTHER_FILES)
all: emacs$(EXEEXT) $(pdmp) $(OTHER_FILES)
.PHONY: all
dmpstruct_headers=$(srcdir)/lisp.h $(srcdir)/buffer.h \
$(srcdir)/intervals.h $(srcdir)/charset.h $(srcdir)/bignum.h
pdumper.o: dmpstruct.h
dmpstruct.h: $(srcdir)/dmpstruct.awk
dmpstruct.h: $(libsrc)/make-fingerprint$(EXEEXT) $(dmpstruct_headers)
POSIXLY_CORRECT=1 awk -f $(srcdir)/dmpstruct.awk \
$(dmpstruct_headers) > $@
AUTO_DEPEND = @AUTO_DEPEND@
DEPDIR = deps
ifeq ($(AUTO_DEPEND),yes)
@ -511,7 +526,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
## and emacs (which recreates bootstrap-emacs) depends on charprop,
## in practice this rule was always run anyway.
$(srcdir)/macuvs.h $(lispsource)/international/charprop.el: \
bootstrap-emacs$(EXEEXT) FORCE
bootstrap-emacs$(EXEEXT) $(bootstrap_pdmp) FORCE
$(MAKE) -C ../admin/unidata all EMACS="../$(bootstrap_exe)"
## We require charprop.el to exist before ucs-normalize.el is
@ -542,14 +557,20 @@ ${lispintdir}/characters.elc: ${charscript:.el=.elc}
emacs$(EXEEXT): temacs$(EXEEXT) \
lisp.mk $(etc)/DOC $(lisp) \
$(lispsource)/international/charprop.el ${charsets}
ifeq ($(CANNOT_DUMP),yes)
ln -f temacs$(EXEEXT) $@
else
LC_ALL=C $(RUN_TEMACS) -batch $(BUILD_DETAILS) -l loadup dump
ifeq ($(DUMPING),unexec)
LC_ALL=C $(RUN_TEMACS) -batch $(BUILD_DETAILS) -l loadup --temacs=dump
ifneq ($(PAXCTL_dumped),)
$(PAXCTL_dumped) $@
$(PAXCTL_dumped) emacs$(EXEEXT)
endif
ln -f $@ bootstrap-emacs$(EXEEXT)
cp -f $@ bootstrap-emacs$(EXEEXT)
else
cp -f temacs$(EXEEXT) emacs$(EXEEXT)
endif
ifeq ($(DUMPING),pdumper)
$(pdmp): emacs$(EXEEXT)
LC_ALL=C $(RUN_TEMACS) -batch $(BUILD_DETAILS) -l loadup --temacs=pdump
cp -f $@ $(bootstrap_pdmp)
endif
## We run make-docfile twice because the command line may get too long
@ -602,16 +623,30 @@ LIBEGNU_ARCHIVE = $(lib)/lib$(if $(HYBRID_MALLOC),e)gnu.a
$(LIBEGNU_ARCHIVE): $(config_h)
$(MAKE) -C $(lib) all
EMACS_DEPS_PRE=$(LIBXMENU) $(ALLOBJS)
EMACS_DEPS_POST=$(LIBEGNU_ARCHIVE) $(EMACSRES) ${charsets} ${charscript}
BUILD_EMACS_PRE=$(AM_V_CCLD)$(CC) $(ALL_CFLAGS) $(TEMACS_LDFLAGS) $(LDFLAGS) \
-o $@ $(ALLOBJS)
BUILD_EMACS_POST=$(LIBEGNU_ARCHIVE) $(W32_RES_LINK) $(LIBES)
## We hash this file to generate the build fingerprint
temacs.in$(EXEEXT): $(EMACS_DEPS_PRE) fingerprint-dummy.o $(EMACS_DEPS_POST)
$(BUILD_EMACS_PRE) fingerprint-dummy.o $(BUILD_EMACS_POST)
$(libsrc)/make-fingerprint$(EXEEXT): $(libsrc)/make-fingerprint.c $(lib)/libgnu.a
$(MAKE) -C $(libsrc) make-fingerprint$(EXEEXT)
fingerprint.c: temacs.in$(EXEEXT) $(libsrc)/make-fingerprint$(EXEEXT)
$(libsrc)/make-fingerprint$(EXEEXT) temacs.in$(EXEEXT) > fingerprint.c
## We have to create $(etc) here because init_cmdargs tests its
## existence when setting Vinstallation_directory (FIXME?).
## This goes on to affect various things, and the emacs binary fails
## to start if Vinstallation_directory has the wrong value.
temacs$(EXEEXT): $(LIBXMENU) $(ALLOBJS) \
$(LIBEGNU_ARCHIVE) $(EMACSRES) ${charsets} ${charscript}
$(AM_V_CCLD)$(CC) $(ALL_CFLAGS) $(TEMACS_LDFLAGS) $(LDFLAGS) \
-o temacs $(ALLOBJS) $(LIBEGNU_ARCHIVE) $(W32_RES_LINK) $(LIBES)
temacs$(EXEEXT): $(EMACS_DEPS_PRE) fingerprint.o $(EMACS_DEPS_POST)
$(BUILD_EMACS_PRE) fingerprint.o $(BUILD_EMACS_POST)
$(MKDIR_P) $(etc)
ifneq ($(CANNOT_DUMP),yes)
ifeq ($(DUMPING),unexec)
ifneq ($(PAXCTL_notdumped),)
$(PAXCTL_notdumped) $@
endif
@ -638,7 +673,7 @@ emacs.res: FORCE
$(MAKE) -C ../nt ../src/emacs.res
.PHONY: ns-app
ns-app: emacs$(EXEEXT)
ns-app: emacs$(EXEEXT) $(pdmp)
$(MAKE) -C ../nextstep all
.PHONY: mostlyclean clean bootstrap-clean distclean maintainer-clean
@ -646,8 +681,11 @@ ns-app: emacs$(EXEEXT)
mostlyclean:
rm -f temacs$(EXEEXT) core ./*.core \#* ./*.o
rm -f temacs.in$(EXEEXT) fingerprint.c dmpstruct.h
rm -f emacs.pdmp
rm -f ../etc/DOC
rm -f bootstrap-emacs$(EXEEXT) emacs-$(version)$(EXEEXT)
rm -f bootstrap-emacs$(EXEEXT) $(bootstrap_pdmp)
rm -f emacs-$(version)$(EXEEXT)
rm -f buildobj.h
rm -f globals.h gl-stamp
rm -f ./*.res ./*.tmp
@ -732,7 +770,7 @@ tags: TAGS ../lisp/TAGS $(lwlibdir)/TAGS
## but now that we require GNU make, we can simply specify
## bootstrap-emacs$(EXEEXT) as an order-only prerequisite.
%.elc: %.el | bootstrap-emacs$(EXEEXT)
%.elc: %.el | bootstrap-emacs$(EXEEXT) $(bootstrap_pdmp)
@$(MAKE) -C ../lisp EMACS="$(bootstrap_exe)" THEFILE=$< $<c
## VCSWITNESS points to the file that holds info about the current checkout.
@ -740,24 +778,35 @@ tags: TAGS ../lisp/TAGS $(lwlibdir)/TAGS
## If empty it is ignored; the parent makefile can set it to some other value.
VCSWITNESS =
$(lispsource)/loaddefs.el: $(VCSWITNESS) | bootstrap-emacs$(EXEEXT)
$(lispsource)/loaddefs.el: $(VCSWITNESS) | \
bootstrap-emacs$(EXEEXT) $(bootstrap_pdmp)
$(MAKE) -C ../lisp autoloads EMACS="$(bootstrap_exe)"
## Dump an Emacs executable named bootstrap-emacs containing the
## files from loadup.el in source form.
bootstrap-emacs$(EXEEXT): temacs$(EXEEXT)
$(MAKE) -C ../lisp update-subdirs
ifeq ($(CANNOT_DUMP),yes)
ln -f temacs$(EXEEXT) $@
else
$(RUN_TEMACS) --batch $(BUILD_DETAILS) --load loadup bootstrap
ifeq ($(DUMPING),unexec)
$(RUN_TEMACS) --batch $(BUILD_DETAILS) -l loadup --temacs=bootstrap
ifneq ($(PAXCTL_dumped),)
$(PAXCTL_dumped) emacs$(EXEEXT)
endif
mv -f emacs$(EXEEXT) $@
endif
mv -f emacs$(EXEEXT) bootstrap-emacs$(EXEEXT)
@: Compile some files earlier to speed up further compilation.
$(MAKE) -C ../lisp compile-first EMACS="$(bootstrap_exe)"
else
@: In the pdumper case, make compile-first after the dump
cp -f temacs$(EXEEXT) bootstrap-emacs$(EXEEXT)
endif
ifeq ($(DUMPING),pdumper)
$(bootstrap_pdmp): bootstrap-emacs$(EXEEXT)
rm -f $@
$(RUN_TEMACS) --batch $(BUILD_DETAILS) -l loadup --temacs=pbootstrap
@: Compile some files earlier to speed up further compilation.
$(MAKE) -C ../lisp compile-first EMACS="$(bootstrap_exe)"
endif
### Flymake support (for C only)
check-syntax:

File diff suppressed because it is too large Load diff

View file

@ -584,6 +584,7 @@ init_atimer (void)
sigaction (SIGALRM, &action, 0);
#ifdef ENABLE_CHECKING
defsubr (&Sdebug_timer_check);
if (!initialized)
defsubr (&Sdebug_timer_check);
#endif
}

View file

@ -44,6 +44,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "keymap.h"
#include "frame.h"
#include "xwidget.h"
#include "pdumper.h"
#ifdef WINDOWSNT
#include "w32heap.h" /* for mmap_* */
@ -529,6 +530,8 @@ even if it is dead. The return value is never nil. */)
/* No one shows us now. */
b->window_count = 0;
memset (&b->local_flags, 0, sizeof (b->local_flags));
BUF_GAP_SIZE (b) = 20;
block_input ();
/* We allocate extra 1-byte at the tail and keep it always '\0' for
@ -781,6 +784,8 @@ CLONE nil means the indirect buffer's state is reset to default values. */)
/* Always -1 for an indirect buffer. */
b->window_count = -1;
memset (&b->local_flags, 0, sizeof (b->local_flags));
b->pt = b->base_buffer->pt;
b->begv = b->base_buffer->begv;
b->zv = b->base_buffer->zv;
@ -5001,24 +5006,37 @@ alloc_buffer_text (struct buffer *b, ptrdiff_t nbytes)
void
enlarge_buffer_text (struct buffer *b, ptrdiff_t delta)
{
void *p;
ptrdiff_t nbytes = (BUF_Z_BYTE (b) - BUF_BEG_BYTE (b) + BUF_GAP_SIZE (b) + 1
+ delta);
block_input ();
void *p;
unsigned char *old_beg = b->text->beg;
ptrdiff_t old_nbytes =
BUF_Z_BYTE (b) - BUF_BEG_BYTE (b) + BUF_GAP_SIZE (b) + 1;
ptrdiff_t new_nbytes = old_nbytes + delta;
if (pdumper_object_p (old_beg))
b->text->beg = NULL;
else
old_beg = NULL;
#if defined USE_MMAP_FOR_BUFFERS
p = mmap_realloc ((void **) &b->text->beg, nbytes);
p = mmap_realloc ((void **) &b->text->beg, new_nbytes);
#elif defined REL_ALLOC
p = r_re_alloc ((void **) &b->text->beg, nbytes);
p = r_re_alloc ((void **) &b->text->beg, new_nbytes);
#else
p = xrealloc (b->text->beg, nbytes);
p = xrealloc (b->text->beg, new_nbytes);
#endif
if (p == NULL)
{
if (old_beg)
b->text->beg = old_beg;
unblock_input ();
memory_full (nbytes);
memory_full (new_nbytes);
}
if (old_beg)
memcpy (p, old_beg, min (old_nbytes, new_nbytes));
BUF_BEG_ADDR (b) = p;
unblock_input ();
}
@ -5031,13 +5049,16 @@ free_buffer_text (struct buffer *b)
{
block_input ();
if (!pdumper_object_p (b->text->beg))
{
#if defined USE_MMAP_FOR_BUFFERS
mmap_free ((void **) &b->text->beg);
mmap_free ((void **) &b->text->beg);
#elif defined REL_ALLOC
r_alloc_free ((void **) &b->text->beg);
r_alloc_free ((void **) &b->text->beg);
#else
xfree (b->text->beg);
xfree (b->text->beg);
#endif
}
BUF_BEG_ADDR (b) = NULL;
unblock_input ();
@ -5048,14 +5069,25 @@ free_buffer_text (struct buffer *b)
/***********************************************************************
Initialization
***********************************************************************/
void
init_buffer_once (void)
{
/* TODO: clean up the buffer-local machinery. Right now,
we have:
buffer_defaults: default values of buffer-locals
buffer_local_flags: metadata
buffer_permanent_local_flags: metadata
buffer_local_symbols: metadata
There must be a simpler way to store the metadata.
*/
int idx;
/* Items flagged permanent get an explicit permanent-local property
added in bindings.el, for clarity. */
PDUMPER_REMEMBER_SCALAR (buffer_permanent_local_flags);
memset (buffer_permanent_local_flags, 0, sizeof buffer_permanent_local_flags);
/* 0 means not a lisp var, -1 means always local, else mask. */
@ -5144,10 +5176,15 @@ init_buffer_once (void)
XSETFASTINT (BVAR (&buffer_local_flags, extra_line_spacing), idx); ++idx;
XSETFASTINT (BVAR (&buffer_local_flags, cursor_in_non_selected_windows), idx); ++idx;
/* buffer_local_flags contains no pointers, so it's safe to treat it
as a blob for pdumper. */
PDUMPER_REMEMBER_SCALAR (buffer_local_flags);
/* Need more room? */
if (idx >= MAX_PER_BUFFER_VARS)
emacs_abort ();
last_per_buffer_idx = idx;
PDUMPER_REMEMBER_SCALAR (last_per_buffer_idx);
/* Make sure all markable slots in buffer_defaults
are initialized reasonably, so mark_buffer won't choke. */
@ -5242,7 +5279,9 @@ init_buffer_once (void)
Vbuffer_alist = Qnil;
current_buffer = 0;
pdumper_remember_lv_ptr_raw (&current_buffer, Lisp_Vectorlike);
all_buffers = 0;
pdumper_remember_lv_ptr_raw (&all_buffers, Lisp_Vectorlike);
QSFundamental = build_pure_c_string ("Fundamental");
@ -5266,12 +5305,12 @@ init_buffer_once (void)
}
void
init_buffer (int initialized)
init_buffer (void)
{
Lisp_Object temp;
#ifdef USE_MMAP_FOR_BUFFERS
if (initialized)
if (dumped_with_unexec_p ())
{
struct buffer *b;
@ -5312,9 +5351,6 @@ init_buffer (int initialized)
eassert (b->text->beg != NULL);
}
}
#else /* not USE_MMAP_FOR_BUFFERS */
/* Avoid compiler warnings. */
(void) initialized;
#endif /* USE_MMAP_FOR_BUFFERS */
AUTO_STRING (scratch, "*scratch*");

View file

@ -1398,10 +1398,11 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
search as the jump table. */
Lisp_Object jmp_table = POP;
if (BYTE_CODE_SAFE && !HASH_TABLE_P (jmp_table))
emacs_abort ();
emacs_abort ();
Lisp_Object v1 = POP;
ptrdiff_t i;
struct Lisp_Hash_Table *h = XHASH_TABLE (jmp_table);
hash_rehash_if_needed (h);
/* h->count is a faster approximation for HASH_TABLE_SIZE (h)
here. */

View file

@ -818,7 +818,8 @@ syms_of_callint (void)
intern_c_string ("region-beginning"),
intern_c_string ("region-end"),
intern_c_string ("point"),
intern_c_string ("mark"));
intern_c_string ("mark"));
staticpro (&preserved_fns);
DEFSYM (Qlist, "list");
DEFSYM (Qlet, "let");

View file

@ -1588,9 +1588,7 @@ init_callproc (void)
}
}
#ifndef CANNOT_DUMP
if (initialized)
#endif
if (!will_dump_p ())
{
tempdir = Fdirectory_file_name (Vexec_directory);
if (! file_accessible_directory_p (tempdir))

View file

@ -42,15 +42,6 @@ bset_category_table (struct buffer *b, Lisp_Object val)
b->category_table_ = val;
}
/* The version number of the latest category table. Each category
table has a unique version number. It is assigned a new number
also when it is modified. When a regular expression is compiled
into the struct re_pattern_buffer, the version number of the
category table (of the current buffer) at that moment is also
embedded in the structure.
For the moment, we are not using this feature. */
static int category_table_version;
/* Category set staff. */
@ -512,6 +503,4 @@ See the documentation of the variable `word-combining-categories'. */);
defsubr (&Schar_category_set);
defsubr (&Scategory_set_mnemonics);
defsubr (&Smodify_category_entry);
category_table_version = 0;
}

View file

@ -39,6 +39,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "coding.h"
#include "buffer.h"
#include "sysstdio.h"
#include "pdumper.h"
/*** GENERAL NOTES on CODED CHARACTER SETS (CHARSETS) ***
@ -61,9 +62,8 @@ Lisp_Object Vcharset_hash_table;
/* Table of struct charset. */
struct charset *charset_table;
static ptrdiff_t charset_table_size;
static int charset_table_used;
ptrdiff_t charset_table_size;
int charset_table_used;
/* Special charsets corresponding to symbols. */
int charset_ascii;
@ -851,6 +851,8 @@ usage: (define-charset-internal ...) */)
bool new_definition_p;
int nchars;
memset (&charset, 0, sizeof (charset));
if (nargs != charset_arg_max)
Fsignal (Qwrong_number_of_arguments,
Fcons (intern ("define-charset-internal"),
@ -1142,9 +1144,9 @@ usage: (define-charset-internal ...) */)
struct charset *new_table =
xpalloc (0, &new_size, 1,
min (INT_MAX, MOST_POSITIVE_FIXNUM),
sizeof *charset_table);
memcpy (new_table, charset_table, old_size * sizeof *new_table);
charset_table = new_table;
sizeof *charset_table);
memcpy (new_table, charset_table, old_size * sizeof *new_table);
charset_table = new_table;
charset_table_size = new_size;
/* FIXME: This leaks memory, as the old charset_table becomes
unreachable. If the old charset table is charset_table_init
@ -2316,15 +2318,26 @@ init_charset_once (void)
for (i = 0; i < ISO_MAX_DIMENSION; i++)
for (j = 0; j < ISO_MAX_CHARS; j++)
for (k = 0; k < ISO_MAX_FINAL; k++)
iso_charset_table[i][j][k] = -1;
iso_charset_table[i][j][k] = -1;
PDUMPER_REMEMBER_SCALAR (iso_charset_table);
for (i = 0; i < 256; i++)
emacs_mule_charset[i] = -1;
PDUMPER_REMEMBER_SCALAR (emacs_mule_charset);
charset_jisx0201_roman = -1;
PDUMPER_REMEMBER_SCALAR (charset_jisx0201_roman);
charset_jisx0208_1978 = -1;
PDUMPER_REMEMBER_SCALAR (charset_jisx0208_1978);
charset_jisx0208 = -1;
PDUMPER_REMEMBER_SCALAR (charset_jisx0208);
charset_ksc5601 = -1;
PDUMPER_REMEMBER_SCALAR (charset_ksc5601);
}
/* Allocate an initial charset table that is large enough to handle
@ -2365,7 +2378,9 @@ syms_of_charset (void)
charset_table = charset_table_init;
charset_table_size = ARRAYELTS (charset_table_init);
PDUMPER_REMEMBER_SCALAR (charset_table_size);
charset_table_used = 0;
PDUMPER_REMEMBER_SCALAR (charset_table_used);
defsubr (&Scharsetp);
defsubr (&Smap_charset_chars);
@ -2411,19 +2426,30 @@ the value may be a list of mnemonics. */);
charset_ascii
= define_charset_internal (Qascii, 1, "\x00\x7F\0\0\0\0\0",
0, 127, 'B', -1, 0, 1, 0, 0);
0, 127, 'B', -1, 0, 1, 0, 0);
PDUMPER_REMEMBER_SCALAR (charset_ascii);
charset_iso_8859_1
= define_charset_internal (Qiso_8859_1, 1, "\x00\xFF\0\0\0\0\0",
0, 255, -1, -1, -1, 1, 0, 0);
0, 255, -1, -1, -1, 1, 0, 0);
PDUMPER_REMEMBER_SCALAR (charset_iso_8859_1);
charset_unicode
= define_charset_internal (Qunicode, 3, "\x00\xFF\x00\xFF\x00\x10\0",
0, MAX_UNICODE_CHAR, -1, 0, -1, 1, 0, 0);
0, MAX_UNICODE_CHAR, -1, 0, -1, 1, 0, 0);
PDUMPER_REMEMBER_SCALAR (charset_unicode);
charset_emacs
= define_charset_internal (Qemacs, 3, "\x00\xFF\x00\xFF\x00\x3F\0",
0, MAX_5_BYTE_CHAR, -1, 0, -1, 1, 1, 0);
0, MAX_5_BYTE_CHAR, -1, 0, -1, 1, 1, 0);
PDUMPER_REMEMBER_SCALAR (charset_emacs);
charset_eight_bit
= define_charset_internal (Qeight_bit, 1, "\x80\xFF\0\0\0\0\0",
128, 255, -1, 0, -1, 0, 1,
MAX_5_BYTE_CHAR + 1);
MAX_5_BYTE_CHAR + 1);
PDUMPER_REMEMBER_SCALAR (charset_eight_bit);
charset_unibyte = charset_iso_8859_1;
PDUMPER_REMEMBER_SCALAR (charset_unibyte);
}

View file

@ -248,6 +248,8 @@ extern Lisp_Object Vcharset_hash_table;
/* Table of struct charset. */
extern struct charset *charset_table;
extern ptrdiff_t charset_table_size;
extern int charset_table_used;
#define CHARSET_FROM_ID(id) (charset_table + (id))

View file

@ -298,6 +298,7 @@ encode_coding_XXX (struct coding_system *coding)
#include "composite.h"
#include "coding.h"
#include "termhooks.h"
#include "pdumper.h"
Lisp_Object Vcoding_system_hash_table;
@ -10737,6 +10738,9 @@ init_coding_once (void)
coding_priorities[i] = i;
}
PDUMPER_REMEMBER_SCALAR (coding_categories);
PDUMPER_REMEMBER_SCALAR (coding_priorities);
/* ISO2022 specific initialize routine. */
for (i = 0; i < 0x20; i++)
iso_code_class[i] = ISO_control_0;
@ -10756,6 +10760,8 @@ init_coding_once (void)
iso_code_class[ISO_CODE_SS3] = ISO_single_shift_3;
iso_code_class[ISO_CODE_CSI] = ISO_control_sequence_introducer;
PDUMPER_REMEMBER_SCALAR (iso_code_class);
for (i = 0; i < 256; i++)
{
emacs_mule_bytes[i] = 1;
@ -10764,6 +10770,8 @@ init_coding_once (void)
emacs_mule_bytes[EMACS_MULE_LEADING_CODE_PRIVATE_12] = 3;
emacs_mule_bytes[EMACS_MULE_LEADING_CODE_PRIVATE_21] = 4;
emacs_mule_bytes[EMACS_MULE_LEADING_CODE_PRIVATE_22] = 4;
PDUMPER_REMEMBER_SCALAR (emacs_mule_bytes);
}
void
@ -10785,6 +10793,7 @@ syms_of_coding (void)
Vcode_conversion_workbuf_name = build_pure_c_string (" *code-conversion-work*");
reused_workbuf_in_use = 0;
PDUMPER_REMEMBER_SCALAR (reused_workbuf_in_use);
DEFSYM (Qcharset, "charset");
DEFSYM (Qtarget_idx, "target-idx");

View file

@ -654,6 +654,7 @@ Lisp_Object
composition_gstring_put_cache (Lisp_Object gstring, ptrdiff_t len)
{
struct Lisp_Hash_Table *h = XHASH_TABLE (gstring_hash_table);
hash_rehash_if_needed (h);
Lisp_Object header = LGSTRING_HEADER (gstring);
EMACS_UINT hash = h->test.hashfn (&h->test, header);
if (len < 0)

View file

@ -299,8 +299,10 @@ extern int emacs_setenv_TZ (char const *);
#if 3 <= __GNUC__
# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
# define ATTRIBUTE_SECTION(name) __attribute__((section (name)))
#else
# define ATTRIBUTE_MALLOC
#define ATTRIBUTE_SECTION(name)
#endif
#if __has_attribute (alloc_size)

View file

@ -804,7 +804,7 @@ The return value is undefined. */)
{
bool autoload = AUTOLOADP (definition);
if (NILP (Vpurify_flag) || !autoload)
if (!will_dump_p () || !autoload)
{ /* Only add autoload entries after dumping, because the ones before are
not useful and else we get loads of them from the loaddefs.el. */
@ -1826,7 +1826,7 @@ The function `default-value' gets the default value and `set-default' sets it.
{
struct Lisp_Symbol *sym;
struct Lisp_Buffer_Local_Value *blv = NULL;
union Lisp_Val_Fwd valcontents;
union Lisp_Val_Fwd valcontents UNINIT;
bool forwarded UNINIT;
CHECK_SYMBOL (variable);
@ -1893,7 +1893,7 @@ Instead, use `add-hook' and specify t for the LOCAL argument. */)
{
Lisp_Object tem;
bool forwarded UNINIT;
union Lisp_Val_Fwd valcontents;
union Lisp_Val_Fwd valcontents UNINIT;
struct Lisp_Symbol *sym;
struct Lisp_Buffer_Local_Value *blv = NULL;
@ -2958,7 +2958,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args,
/* Set ACCUM to the next operation's result if it fits,
else exit the loop. */
bool overflow = false;
intmax_t a;
intmax_t a UNINIT;
switch (code)
{
case Aadd : overflow = INT_ADD_WRAPV (accum, next, &a); break;

View file

@ -1831,6 +1831,8 @@ be called when the D-Bus reply message arrives. */);
xd_registered_buses = Qnil;
staticpro (&xd_registered_buses);
// TODO: reset buses on dump load
Fprovide (intern_c_string ("dbusbind"), Qnil);
}

View file

@ -42,6 +42,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "systime.h"
#include "tparam.h"
#include "xwidget.h"
#include "pdumper.h"
#ifdef HAVE_WINDOW_SYSTEM
#include TERM_HEADER
@ -5987,12 +5988,24 @@ pass nil for VARIABLE. */)
Initialization
***********************************************************************/
static void
init_faces_initial (void)
{
/* For the initial frame, we don't have any way of knowing what
are the foreground and background colors of the terminal. */
struct frame *sf = SELECTED_FRAME ();
FRAME_FOREGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_FG_COLOR;
FRAME_BACKGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_BG_COLOR;
call0 (intern ("tty-set-up-initial-frame-faces"));
}
/* Initialization done when Emacs fork is started, before doing stty.
Determine terminal type and set terminal_driver. Then invoke its
decoding routine to set up variables in the terminal package. */
void
init_display (void)
static void
init_display_interactive (void)
{
char *terminal_type;
@ -6012,9 +6025,7 @@ init_display (void)
with. Otherwise newly opened tty frames will not resize
automatically. */
#ifdef SIGWINCH
#ifndef CANNOT_DUMP
if (initialized)
#endif /* CANNOT_DUMP */
if (!will_dump_p ())
{
struct sigaction action;
emacs_sigaction_init (&action, deliver_window_change_signal);
@ -6078,11 +6089,7 @@ init_display (void)
#endif /* HAVE_NTGUI */
#ifdef HAVE_NS
if (!inhibit_window_system
#ifndef CANNOT_DUMP
&& initialized
#endif
)
if (!inhibit_window_system && !will_dump_p ())
{
Vinitial_window_system = Qns;
Vwindow_system_version = make_fixnum (10);
@ -6170,21 +6177,22 @@ init_display (void)
calculate_costs (XFRAME (selected_frame));
/* Set up faces of the initial terminal frame of a dumped Emacs. */
if (initialized
&& !noninteractive
&& NILP (Vinitial_window_system))
{
/* For the initial frame, we don't have any way of knowing what
are the foreground and background colors of the terminal. */
struct frame *sf = SELECTED_FRAME ();
FRAME_FOREGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_FG_COLOR;
FRAME_BACKGROUND_PIXEL (sf) = FACE_TTY_DEFAULT_BG_COLOR;
call0 (intern ("tty-set-up-initial-frame-faces"));
}
/* Set up faces of the initial terminal frame. */
if (!noninteractive && NILP (Vinitial_window_system))
init_faces_initial ();
}
void
init_display (void)
{
if (noninteractive)
{
if (dumped_with_pdumper_p ())
init_faces_initial ();
}
else
init_display_interactive ();
}
/***********************************************************************
@ -6220,6 +6228,8 @@ WINDOW nil or omitted means report on the selected window. */)
Initialization
***********************************************************************/
static void syms_of_display_for_pdumper (void);
void
syms_of_display (void)
{
@ -6327,11 +6337,12 @@ See `buffer-display-table' for more information. */);
beginning of the next redisplay). */
redisplay_dont_pause = true;
#ifdef CANNOT_DUMP
if (noninteractive)
#endif
{
Vinitial_window_system = Qnil;
Vwindow_system_version = Qnil;
}
pdumper_do_now_and_after_load (syms_of_display_for_pdumper);
}
static void
syms_of_display_for_pdumper (void)
{
Vinitial_window_system = Qnil;
Vwindow_system_version = Qnil;
}

28
src/dmpstruct.awk Executable file
View file

@ -0,0 +1,28 @@
BEGIN {
print "/* Generated by dmpstruct.awk */"
print "#ifndef EMACS_DMPSTRUCT_H"
print "#define EMACS_DMPSTRUCT_H"
struct_name = ""
tmpfile = "dmpstruct.tmp"
}
# Match a type followed by optional syntactic whitespace
/^(enum|struct|union) [a-zA-Z0-9_]+([\t ]|\/\*.*\*\/)*$/ {
struct_name = $2
close (tmpfile)
}
/^(enum|struct|union) [a-zA-Z0-9_]+([\t ]|\/\*.*\*\/)*$/, /^( )?};$/ {
print $0 > tmpfile
}
/^( )?} *(GCALIGNED_STRUCT)? *;$/ {
if (struct_name != "") {
fflush (tmpfile)
cmd = "../lib-src/make-fingerprint -r " tmpfile
cmd | getline hash
close (cmd)
printf "#define HASH_%s_%.10s\n", struct_name, hash
struct_name = ""
}
}
END {
print "#endif /* EMACS_DMPSTRUCT_H */"
}

View file

@ -118,17 +118,15 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
Lisp_Object docdir
= NILP (tem) ? ENCODE_FILE (Vdoc_directory) : empty_unibyte_string;
ptrdiff_t docdir_sizemax = SBYTES (docdir) + 1;
#ifndef CANNOT_DUMP
docdir_sizemax = max (docdir_sizemax, sizeof sibling_etc);
#endif
if (will_dump_p ())
docdir_sizemax = max (docdir_sizemax, sizeof sibling_etc);
name = SAFE_ALLOCA (docdir_sizemax + SBYTES (file));
lispstpcpy (lispstpcpy (name, docdir), file);
fd = emacs_open (name, O_RDONLY, 0);
if (fd < 0)
{
#ifndef CANNOT_DUMP
if (!NILP (Vpurify_flag))
if (will_dump_p ())
{
/* Preparing to dump; DOC file is probably not installed.
So check in ../etc. */
@ -136,7 +134,6 @@ get_doc_string (Lisp_Object filepos, bool unibyte, bool definition)
fd = emacs_open (name, O_RDONLY, 0);
}
#endif
if (fd < 0)
{
if (errno == EMFILE || errno == ENFILE)
@ -545,12 +542,7 @@ the same file name is found in the `doc-directory'. */)
CHECK_STRING (filename);
if
#ifndef CANNOT_DUMP
(!NILP (Vpurify_flag))
#else /* CANNOT_DUMP */
(0)
#endif /* CANNOT_DUMP */
if (will_dump_p ())
{
dirname = sibling_etc;
dirlen = sizeof sibling_etc - 1;

View file

@ -3454,7 +3454,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
bool format_as_long_double = false;
double darg;
long double ldarg;
long double ldarg UNINIT;
if (FLOATP (arg))
darg = XFLOAT_DATA (arg);

View file

@ -1191,7 +1191,10 @@ void
syms_of_module (void)
{
if (!plain_values)
ltv_mark = Fcons (Qnil, Qnil);
{
ltv_mark = Fcons (Qnil, Qnil);
staticpro (&ltv_mark);
}
eassert (NILP (value_to_lisp (module_nil)));
DEFSYM (Qmodule_refs_hash, "module-refs-hash");

View file

@ -118,6 +118,9 @@ extern char etext;
#include <sys/resource.h>
#endif
#include "pdumper.h"
#include "epaths.h"
static const char emacs_version[] = PACKAGE_VERSION;
static const char emacs_copyright[] = COPYRIGHT;
static const char emacs_bugreport[] = PACKAGE_BUGREPORT;
@ -130,19 +133,9 @@ Lisp_Object empty_unibyte_string, empty_multibyte_string;
Lisp_Object Vlibrary_cache;
#endif
/* Set after Emacs has started up the first time.
Prevents reinitialization of the Lisp world and keymaps
on subsequent starts. */
struct gflags gflags;
bool initialized;
#ifndef CANNOT_DUMP
/* Set to true if this instance of Emacs might dump. */
# ifndef DOUG_LEA_MALLOC
static
# endif
bool might_dump;
#endif
/* If true, Emacs should not attempt to use a window-specific code,
but instead should use the virtual terminal under which it was started. */
bool inhibit_window_system;
@ -519,8 +512,7 @@ init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd)
etc_exists = Ffile_exists_p (tem);
if (!NILP (etc_exists))
{
Vinstallation_directory
= Ffile_name_as_directory (dir);
Vinstallation_directory = Ffile_name_as_directory (dir);
break;
}
}
@ -545,8 +537,7 @@ init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd)
if (!NILP (etc_exists))
{
tem = Fexpand_file_name (build_string (".."), dir);
Vinstallation_directory
= Ffile_name_as_directory (tem);
Vinstallation_directory = Ffile_name_as_directory (tem);
break;
}
}
@ -659,6 +650,43 @@ argmatch (char **argv, int argc, const char *sstr, const char *lstr,
}
}
static bool
string_starts_with_p (const char* string, const char* prefix)
{
return strncmp (string, prefix, strlen (prefix)) == 0;
}
/* Return the value of GNU-style long argument ARGUMENT if given on
command line. ARGUMENT must begin with "-". If ARGUMENT is not
given, return NULL. */
static char *
find_argument (const char *argument, int argc, char **argv)
{
char *found = NULL;
int i;
eassert (argument[0] == '-');
for (i = 1; i < argc; ++i)
if (string_starts_with_p (argv[i], argument) &&
((argv[i] + strlen (argument))[0] == '=' ||
(argv[i] + strlen (argument))[0] == '\0'))
{
int j = i;
found = argv[j++] + strlen (argument);
if (*found == '=')
++found;
else if (i < argc)
found = argv[j++];
else
fatal ("no argument given for %s", argument);
break;
}
else if (strcmp (argv[i], "--") == 0)
break;
return found;
}
/* Close standard output and standard error, reporting any write
errors as best we can. This is intended for use with atexit. */
static void
@ -677,6 +705,114 @@ close_output_streams (void)
_exit (EXIT_FAILURE);
}
#ifdef HAVE_PDUMPER
static const char *
dump_error_to_string (enum pdumper_load_result result)
{
switch (result)
{
case PDUMPER_LOAD_SUCCESS:
return "success";
case PDUMPER_LOAD_OOM:
return "out of memory";
case PDUMPER_NOT_LOADED:
return "not loaded";
case PDUMPER_LOAD_FILE_NOT_FOUND:
return "could not open file";
case PDUMPER_LOAD_BAD_FILE_TYPE:
return "not a dump file";
case PDUMPER_LOAD_FAILED_DUMP:
return "dump file is result of failed dump attempt";
case PDUMPER_LOAD_VERSION_MISMATCH:
return "not built for this Emacs executable";
default:
return "generic error";
}
}
#define PDUMP_FILE_ARG "--dump-file"
static enum pdumper_load_result
load_pdump (int argc, char **argv)
{
const char *const suffix = ".pdmp";
const char *const argv0_base = "emacs";
enum pdumper_load_result result;
#ifdef WINDOWSNT
size_t argv0_len;
#endif
/* TODO: maybe more thoroughly scrub process environment in order to
make this use case (loading a pdumper image in an unexeced emacs)
possible? Right now, we assume that things we don't touch are
zero-initialized, and in an unexeced Emacs, this assumption
doesn't hold. */
if (initialized)
fatal ("cannot load pdumper image in unexeced Emacs");
/* Look for an explicitly-specified dump file. */
const char *path_exec = PATH_EXEC;
char *dump_file = find_argument (PDUMP_FILE_ARG, argc, argv);
result = PDUMPER_NOT_LOADED;
if (dump_file)
result = pdumper_load (dump_file);
if (dump_file && result != PDUMPER_LOAD_SUCCESS)
fatal ("could not load dump file \"%s\": %s",
dump_file, dump_error_to_string (result));
if (result == PDUMPER_LOAD_SUCCESS)
goto out;
/* Look for a dump file in the same directory as the executable; it
should have the same basename. */
dump_file = alloca (strlen (argv[0]) + strlen (suffix) + 1);
#ifdef WINDOWSNT
/* Remove the .exe extension if present. */
argv0_len = strlen (argv[0]);
if (argv0_len >= 4 && c_strcasecmp (argv[0] + argv0_len - 4, ".exe") == 0)
sprintf (dump_file, "%.*s%s", argv0_len - 4, argv[0], suffix);
else
#endif
sprintf (dump_file, "%s%s", argv[0], suffix);
result = pdumper_load (dump_file);
if (result == PDUMPER_LOAD_SUCCESS)
goto out;
if (result != PDUMPER_LOAD_FILE_NOT_FOUND)
fatal ("could not load dump file \"%s\": %s",
dump_file, dump_error_to_string (result));
/* Finally, look for "emacs.pdmp" in PATH_EXEC. We hardcode
"emacs" in "emacs.pdmp" so that the Emacs binary still works
if the user copies and renames it.
FIXME: this doesn't work with emacs-XX.YY.ZZ.pdmp versioned files. */
#ifdef WINDOWSNT
/* On MS-Windows, PATH_EXEC normally starts with a literal
"%emacs_dir%", so it will never work without some tweaking. */
path_exec = w32_relocate (path_exec);
#endif
dump_file = alloca (strlen (path_exec)
+ 1
+ strlen (argv0_base)
+ strlen (suffix)
+ 1);
sprintf (dump_file, "%s%c%s%s",
path_exec, DIRECTORY_SEP, argv0_base, suffix);
result = pdumper_load (dump_file);
if (result != PDUMPER_LOAD_SUCCESS)
dump_file = NULL;
out:
return result;
}
#endif /* HAVE_PDUMPER */
/* ARGSUSED */
int
main (int argc, char **argv)
@ -686,7 +822,6 @@ main (int argc, char **argv)
void *stack_bottom_variable;
bool do_initial_setlocale;
bool dumping;
int skip_args = 0;
bool no_loadup = false;
char *junk = 0;
@ -702,25 +837,62 @@ main (int argc, char **argv)
/* Record (approximately) where the stack begins. */
stack_bottom = (char *) &stack_bottom_variable;
#ifndef CANNOT_DUMP
dumping = !initialized && (strcmp (argv[argc - 1], "dump") == 0
|| strcmp (argv[argc - 1], "bootstrap") == 0);
#else
dumping = false;
const char *dump_mode = NULL;
const char *temacs = find_argument ("--temacs", argc, argv);
#ifdef HAVE_PDUMPER
bool attempt_load_pdump = false;
#endif
argc = maybe_disable_address_randomization (dumping, argc, argv);
/* Look for this argument first, before any heap allocation, so we
can set heap flags properly if we're going to unexec. */
if (!initialized && temacs)
{
#ifndef CANNOT_DUMP
if (strcmp (temacs, "dump") == 0 ||
strcmp (temacs, "bootstrap") == 0)
gflags.will_dump_with_unexec_ = true;
#endif
#ifdef HAVE_PDUMPER
if (strcmp (temacs, "pdump") == 0 ||
strcmp (temacs, "pbootstrap") == 0)
gflags.will_dump_with_pdumper_ = true;
#endif
#if defined (HAVE_PDUMPER) || !defined (CANNOT_DUMP)
if (strcmp (temacs, "bootstrap") == 0 ||
strcmp (temacs, "pbootstrap") == 0)
gflags.will_bootstrap_ = true;
gflags.will_dump_ =
will_dump_with_pdumper_p () ||
will_dump_with_unexec_p ();
if (will_dump_p ())
dump_mode = temacs;
#endif
if (!dump_mode)
fatal ("Invalid temacs mode '%s'", temacs);
}
else if (temacs)
{
fatal ("--temacs not supported for unexeced emacs");
}
else if (initialized)
{
#ifdef HAVE_PDUMPER
if (find_argument (PDUMP_FILE_ARG, argc, argv))
fatal ("%s not supported in unexeced emacs", PDUMP_FILE_ARG);
#endif
}
else
{
eassert (!initialized);
eassert (!temacs);
#ifdef PDUMP_FILE_ARG
attempt_load_pdump = true;
#endif
}
#ifndef CANNOT_DUMP
might_dump = !initialized;
# ifdef GNU_LINUX
if (!initialized)
{
char *heap_start = my_heap_start ();
heap_bss_diff = heap_start - max (my_endbss, my_endbss_static);
}
# endif
if (!will_dump_with_unexec_p ())
gflags.will_not_unexec_ = true;
#endif
#if defined WINDOWSNT || defined HAVE_NTGUI
@ -742,6 +914,22 @@ main (int argc, char **argv)
w32_init_main_thread ();
#endif
#ifdef HAVE_PDUMPER
if (attempt_load_pdump)
load_pdump (argc, argv);
#endif
argc = maybe_disable_address_randomization (
will_dump_with_unexec_p (), argc, argv);
#if defined (GNU_LINUX) && !defined (CANNOT_DUMP)
if (!initialized)
{
char *heap_start = my_heap_start ();
heap_bss_diff = heap_start - max (my_endbss, my_endbss_static);
}
#endif
#ifdef RUN_TIME_REMAP
if (initialized)
run_time_remap (argv[0]);
@ -850,10 +1038,7 @@ main (int argc, char **argv)
frames. */
int extra = (30 * 1000) * 50;
bool try_to_grow_stack = true;
#ifndef CANNOT_DUMP
try_to_grow_stack = !noninteractive || initialized;
#endif
bool try_to_grow_stack = !noninteractive || initialized;
if (try_to_grow_stack)
{
@ -1184,17 +1369,15 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
#if defined HAVE_PTHREAD && !defined SYSTEM_MALLOC \
&& !defined DOUG_LEA_MALLOC && !defined HYBRID_MALLOC
# ifndef CANNOT_DUMP
/* Do not make gmalloc thread-safe when creating bootstrap-emacs, as
that causes an infinite recursive loop with FreeBSD. See
Bug#14569. The part of this bug involving Cygwin is no longer
relevant, now that Cygwin defines HYBRID_MALLOC. */
if (!noninteractive || initialized)
# endif
if (!noninteractive || !will_dump_p ())
malloc_enable_thread ();
#endif
init_signals (dumping);
init_signals ();
noninteractive1 = noninteractive;
@ -1204,7 +1387,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
{
init_alloc_once ();
init_threads_once ();
init_obarray ();
init_obarray_once ();
init_eval_once ();
init_charset_once ();
init_coding_once ();
@ -1242,7 +1425,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
/* Before init_window_once, because it sets up the
Vcoding_system_hash_table. */
syms_of_coding (); /* This should be after syms_of_fileio. */
init_frame_once (); /* Before init_window_once. */
init_window_once (); /* Init the window system. */
#ifdef HAVE_WINDOW_SYSTEM
init_fringe_once (); /* Swap bitmaps if necessary. */
@ -1282,7 +1465,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
bool module_assertions
= argmatch (argv, argc, "-module-assertions", "--module-assertions", 15,
NULL, &skip_args);
if (dumping && module_assertions)
if (will_dump_p () && module_assertions)
{
fputs ("Module assertions are not supported during dumping\n", stderr);
exit (1);
@ -1419,7 +1602,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
/* egetenv is a pretty low-level facility, which may get called in
many circumstances; it seems flimsy to put off initializing it
until calling init_callproc. Do not do it when dumping. */
if (! dumping)
if (!will_dump_p ())
set_initial_environment ();
#ifdef WINDOWSNT
@ -1433,7 +1616,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
variables from the parent process without modifications from
Emacs. */
init_environment (argv);
init_ntproc (dumping); /* must precede init_editfns. */
init_ntproc (will_dump_p ()); /* must precede init_editfns. */
#endif
/* AIX crashes are reported in system versions 3.2.3 and 3.2.4
@ -1445,7 +1628,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
#endif
/* Init buffer storage and default directory of main buffer. */
init_buffer (initialized);
init_buffer ();
init_callproc_1 (); /* Must precede init_cmdargs and init_sys_modes. */
@ -1620,6 +1803,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
syms_of_threads ();
syms_of_profiler ();
syms_of_pdumper ();
#ifdef HAVE_JSON
syms_of_json ();
@ -1650,7 +1834,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
init_charset ();
/* This calls putenv and so must precede init_process_emacs. */
init_timefns (dumping);
init_timefns ();
/* This sets Voperating_system_release, which init_process_emacs uses. */
init_editfns ();
@ -1669,10 +1853,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
init_process_emacs (sockfd);
init_keyboard (); /* This too must precede init_sys_modes. */
if (!noninteractive)
init_display (); /* Determine terminal type. Calls init_sys_modes. */
init_display (); /* Determine terminal type. Calls init_sys_modes. */
#if HAVE_W32NOTIFY
else
if (noninteractive)
init_crit (); /* w32notify.c needs this in batch mode. */
#endif /* HAVE_W32NOTIFY */
init_xdisp ();
@ -1716,7 +1899,10 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
moncontrol (0);
#endif
initialized = 1;
initialized = true;
if (dump_mode)
Vdump_mode = build_string (dump_mode);
/* Enter editor command loop. This never returns. */
Frecursive_edit ();
@ -2166,8 +2352,11 @@ You must run Emacs in batch mode in order to dump it. */)
if (! noninteractive)
error ("Dumping Emacs works only in batch mode");
if (!might_dump)
error ("Emacs can be dumped only once");
if (dumped_with_unexec_p ())
error ("Emacs can be dumped using unexec only once");
if (definitely_will_not_unexec_p ())
error ("This Emacs instance was not started in temacs mode");
#if defined GNU_LINUX && !defined CANNOT_DUMP
@ -2231,12 +2420,19 @@ You must run Emacs in batch mode in order to dump it. */)
#endif /* not WINDOWSNT */
#endif /* not SYSTEM_MALLOC and not HYBRID_MALLOC */
struct gflags old_gflags = gflags;
gflags.will_dump_ = false;
gflags.will_dump_with_unexec_ = false;
gflags.dumped_with_unexec_ = true;
alloc_unexec_pre ();
unexec (SSDATA (filename), !NILP (symfile) ? SSDATA (symfile) : 0);
alloc_unexec_post ();
gflags = old_gflags;
#ifdef WINDOWSNT
Vlibrary_cache = Qnil;
#endif
@ -2250,6 +2446,7 @@ You must run Emacs in batch mode in order to dump it. */)
}
#endif /* not CANNOT_DUMP */
#if HAVE_SETLOCALE
/* Recover from setlocale (LC_ALL, ""). */
@ -2585,7 +2782,7 @@ Don't rely on it for testing whether a feature you want to use is available. */
Vsystem_configuration_features = build_string (EMACS_CONFIG_FEATURES);
DEFVAR_BOOL ("noninteractive", noninteractive1,
doc: /* Non-nil means Emacs is running without interactive terminal. */);
doc: /* Non-nil means Emacs is running without interactive terminal. */);
DEFVAR_LISP ("kill-emacs-hook", Vkill_emacs_hook,
doc: /* Hook run when `kill-emacs' is called.
@ -2670,6 +2867,9 @@ component .BUILD is present. This is now stored separately in
doc: /* Address of mailing list for GNU Emacs bugs. */);
Vreport_emacs_bug_address = build_string (emacs_bugreport);
DEFVAR_LISP ("dump-mode", Vdump_mode,
doc: /* Non-nil when Emacs is dumping itself. */);
DEFVAR_LISP ("dynamic-library-alist", Vdynamic_library_alist,
doc: /* Alist of dynamic libraries vs external files implementing them.
Each element is a list (LIBRARY FILE...), where the car is a symbol

View file

@ -29,6 +29,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "keyboard.h"
#include "dispextern.h"
#include "buffer.h"
#include "pdumper.h"
/* CACHEABLE is ordinarily nothing, except it is 'volatile' if
necessary to cajole GCC into not warning incorrectly that a
@ -89,10 +90,6 @@ static EMACS_INT when_entered_debugger;
/* FIXME: We should probably get rid of this! */
Lisp_Object Vsignaling_function;
/* If non-nil, Lisp code must not be run since some part of Emacs is in
an inconsistent state. Currently unused. */
Lisp_Object inhibit_lisp_code;
/* These would ordinarily be static, but they need to be visible to GDB. */
bool backtrace_p (union specbinding *) EXTERNALLY_VISIBLE;
Lisp_Object *backtrace_args (union specbinding *) EXTERNALLY_VISIBLE;
@ -235,6 +232,8 @@ backtrace_next (union specbinding *pdl)
return pdl;
}
static void init_eval_once_for_pdumper (void);
static union specbinding *
backtrace_thread_next (struct thread_state *tstate, union specbinding *pdl)
{
@ -247,15 +246,20 @@ backtrace_thread_next (struct thread_state *tstate, union specbinding *pdl)
void
init_eval_once (void)
{
enum { size = 50 };
union specbinding *pdlvec = xmalloc ((size + 1) * sizeof *specpdl);
specpdl_size = size;
specpdl = specpdl_ptr = pdlvec + 1;
/* Don't forget to update docs (lispref node "Local Variables"). */
max_specpdl_size = 1300; /* 1000 is not enough for CEDET's c-by.el. */
max_lisp_eval_depth = 800;
Vrun_hooks = Qnil;
pdumper_do_now_and_after_load (init_eval_once_for_pdumper);
}
static void
init_eval_once_for_pdumper (void)
{
enum { size = 50 };
union specbinding *pdlvec = malloc ((size + 1) * sizeof *specpdl);
specpdl_size = size;
specpdl = specpdl_ptr = pdlvec + 1;
}
/* static struct handler handlerlist_sentinel; */
@ -2084,7 +2088,7 @@ it defines a macro. */)
/* This is to make sure that loadup.el gives a clear picture
of what files are preloaded and when. */
if (! NILP (Vpurify_flag))
if (will_dump_p () && !will_bootstrap_p ())
error ("Attempt to autoload %s while preparing to dump",
SDATA (SYMBOL_NAME (funname)));
@ -4002,7 +4006,7 @@ mark_specpdl (union specbinding *first, union specbinding *ptr)
for (pdl = first; pdl != ptr; pdl++)
{
switch (pdl->kind)
{
{
case SPECPDL_UNWIND:
mark_object (specpdl_arg (pdl));
break;
@ -4039,7 +4043,7 @@ mark_specpdl (union specbinding *first, union specbinding *ptr)
case SPECPDL_UNWIND_PTR:
case SPECPDL_UNWIND_INT:
case SPECPDL_UNWIND_VOID:
case SPECPDL_UNWIND_VOID:
break;
default:
@ -4225,8 +4229,6 @@ alist of active lexical bindings. */);
staticpro (&Vsignaling_function);
Vsignaling_function = Qnil;
inhibit_lisp_code = Qnil;
DEFSYM (Qcatch_all_memory_full, "catch-all-memory-full");
Funintern (Qcatch_all_memory_full, Qnil);

View file

@ -171,13 +171,10 @@ get_boot_time (void)
}
#if defined (BOOT_TIME)
#ifndef CANNOT_DUMP
/* The utmp routines maintain static state.
Don't touch that state unless we are initialized,
since it might not survive dumping. */
if (! initialized)
/* The utmp routines maintain static state. Don't touch that state
if we are going to dump, since it might not survive dumping. */
if (will_dump_p ())
return boot_time;
#endif /* not CANNOT_DUMP */
/* Try to get boot time from utmp before wtmp,
since utmp is typically much smaller than wtmp.
@ -666,7 +663,7 @@ lock_file (Lisp_Object fn)
/* Don't do locking while dumping Emacs.
Uncompressing wtmp files uses call-process, which does not work
in an uninitialized Emacs. */
if (! NILP (Vpurify_flag))
if (will_dump_p ())
return;
orig_fn = fn;

24
src/fingerprint-dummy.c Normal file
View file

@ -0,0 +1,24 @@
/* Dummy fingerprint
Copyright (C) 2016 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include "fingerprint.h"
/* Dummy fingerprint to use as hash input. */
const uint8_t fingerprint[32] = { 0 };

32
src/fingerprint.h Normal file
View file

@ -0,0 +1,32 @@
/* Header file for the Emacs build fingerprint.
Copyright (C) 2016 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifndef EMACS_FINGERPRINT_H
#define EMACS_FINGERPRINT_H
#include <stdint.h>
/* We generate fingerprint.c and fingerprint.o from all the sources in
Emacs. This way, we have a unique value that we can use to pair
data files (like a portable dump image) with a specific build of
Emacs. */
extern const uint8_t fingerprint[32];
#endif

139
src/fns.c
View file

@ -2949,7 +2949,7 @@ suppressed. */)
/* This is to make sure that loadup.el gives a clear picture
of what files are preloaded and when. */
if (! NILP (Vpurify_flag))
if (will_dump_p () && !will_bootstrap_p ())
error ("(require %s) while preparing to dump",
SDATA (SYMBOL_NAME (feature)));
@ -3648,10 +3648,6 @@ base64_decode_1 (const char *from, char *to, ptrdiff_t length,
if a `:linear-search t' argument is given to make-hash-table. */
/* The list of all weak hash tables. Don't staticpro this one. */
static struct Lisp_Hash_Table *weak_hash_tables;
/***********************************************************************
Utilities
@ -3866,7 +3862,7 @@ hashfn_eq (struct hash_table_test *ht, Lisp_Object key)
`equal' to compare keys. The hash code returned is guaranteed to fit
in a Lisp integer. */
static EMACS_UINT
EMACS_UINT
hashfn_equal (struct hash_table_test *ht, Lisp_Object key)
{
return sxhash (key, 0);
@ -3876,7 +3872,7 @@ hashfn_equal (struct hash_table_test *ht, Lisp_Object key)
`eql' to compare keys. The hash code returned is guaranteed to fit
in a Lisp integer. */
static EMACS_UINT
EMACS_UINT
hashfn_eql (struct hash_table_test *ht, Lisp_Object key)
{
return ((FLOATP (key) || BIGNUMP (key))
@ -3984,6 +3980,7 @@ make_hash_table (struct hash_table_test test, EMACS_INT size,
h->hash = make_nil_vector (size);
h->next = make_vector (size, make_fixnum (-1));
h->index = make_vector (index_size, make_fixnum (-1));
h->next_weak = NULL;
h->pure = pure;
/* Set up the free list. */
@ -3995,13 +3992,6 @@ make_hash_table (struct hash_table_test test, EMACS_INT size,
eassert (HASH_TABLE_P (table));
eassert (XHASH_TABLE (table) == h);
/* Maybe add this hash table to the list of all weak hash tables. */
if (! NILP (weak))
{
h->next_weak = weak_hash_tables;
weak_hash_tables = h;
}
return table;
}
@ -4023,13 +4013,6 @@ copy_hash_table (struct Lisp_Hash_Table *h1)
h2->index = Fcopy_sequence (h1->index);
XSET_HASH_TABLE (table, h2);
/* Maybe add this hash table to the list of all weak hash tables. */
if (!NILP (h2->weak))
{
h2->next_weak = h1->next_weak;
h1->next_weak = h2;
}
return table;
}
@ -4115,6 +4098,43 @@ maybe_resize_hash_table (struct Lisp_Hash_Table *h)
}
}
void
hash_table_rehash (struct Lisp_Hash_Table *h)
{
ptrdiff_t size = HASH_TABLE_SIZE (h);
/* Recompute the actual hash codes for each entry in the table.
Order is still invalid. */
for (ptrdiff_t i = 0; i < size; ++i)
if (!NILP (HASH_HASH (h, i)))
{
Lisp_Object key = HASH_KEY (h, i);
EMACS_UINT hash_code = h->test.hashfn (&h->test, key);
set_hash_hash_slot (h, i, make_fixnum (hash_code));
}
/* Reset the index so that any slot we don't fill below is marked
invalid. */
Ffillarray (h->index, make_fixnum (-1));
/* Rebuild the collision chains. */
for (ptrdiff_t i = 0; i < size; ++i)
if (!NILP (HASH_HASH (h, i)))
{
EMACS_UINT hash_code = XUFIXNUM (HASH_HASH (h, i));
ptrdiff_t start_of_bucket = hash_code % ASIZE (h->index);
set_hash_next_slot (h, i, HASH_INDEX (h, start_of_bucket));
set_hash_index_slot (h, start_of_bucket, i);
eassert (HASH_NEXT (h, i) != i); /* Stop loops. */
}
/* Finally, mark the hash table as having a valid hash order.
Do this last so that if we're interrupted, we retry on next
access. */
eassert (h->count < 0);
h->count = -h->count;
eassert (!hash_rehash_needed_p (h));
}
/* Lookup KEY in hash table H. If HASH is non-null, return in *HASH
the hash code of KEY. Value is the index of the entry in H
@ -4126,6 +4146,8 @@ hash_lookup (struct Lisp_Hash_Table *h, Lisp_Object key, EMACS_UINT *hash)
EMACS_UINT hash_code;
ptrdiff_t start_of_bucket, i;
hash_rehash_if_needed (h);
hash_code = h->test.hashfn (&h->test, key);
eassert ((hash_code & ~INTMASK) == 0);
if (hash)
@ -4154,6 +4176,8 @@ hash_put (struct Lisp_Hash_Table *h, Lisp_Object key, Lisp_Object value,
{
ptrdiff_t start_of_bucket, i;
hash_rehash_if_needed (h);
eassert ((hash & ~INTMASK) == 0);
/* Increment count after resizing because resizing may fail. */
@ -4187,6 +4211,8 @@ hash_remove_from_table (struct Lisp_Hash_Table *h, Lisp_Object key)
ptrdiff_t start_of_bucket = hash_code % ASIZE (h->index);
ptrdiff_t prev = -1;
hash_rehash_if_needed (h);
for (ptrdiff_t i = HASH_INDEX (h, start_of_bucket);
0 <= i;
i = HASH_NEXT (h, i))
@ -4255,7 +4281,7 @@ hash_clear (struct Lisp_Hash_Table *h)
!REMOVE_ENTRIES_P means mark entries that are in use. Value is
true if anything was marked. */
static bool
bool
sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p)
{
ptrdiff_t n = gc_asize (h->index);
@ -4263,12 +4289,14 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p)
for (ptrdiff_t bucket = 0; bucket < n; ++bucket)
{
/* Follow collision chain, removing entries that
don't survive this garbage collection. */
/* Follow collision chain, removing entries that don't survive
this garbage collection. It's okay if hash_rehash_needed_p
(h) is true, since we're operating entirely on the cached
hash values. */
ptrdiff_t prev = -1;
ptrdiff_t next;
for (ptrdiff_t i = HASH_INDEX (h, bucket); 0 <= i; i = next)
{
{
bool key_known_to_survive_p = survives_gc_p (HASH_KEY (h, i));
bool value_known_to_survive_p = survives_gc_p (HASH_VALUE (h, i));
bool remove_p;
@ -4303,10 +4331,11 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p)
/* Clear key, value, and hash. */
set_hash_key_slot (h, i, Qnil);
set_hash_value_slot (h, i, Qnil);
set_hash_hash_slot (h, i, Qnil);
set_hash_hash_slot (h, i, Qnil);
h->count--;
}
eassert (h->count != 0);
h->count += h->count > 0 ? -1 : 1;
}
else
{
prev = i;
@ -4320,13 +4349,13 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p)
if (!key_known_to_survive_p)
{
mark_object (HASH_KEY (h, i));
marked = 1;
marked = true;
}
if (!value_known_to_survive_p)
{
mark_object (HASH_VALUE (h, i));
marked = 1;
marked = true;
}
}
}
@ -4336,55 +4365,6 @@ sweep_weak_table (struct Lisp_Hash_Table *h, bool remove_entries_p)
return marked;
}
/* Remove elements from weak hash tables that don't survive the
current garbage collection. Remove weak tables that don't survive
from Vweak_hash_tables. Called from gc_sweep. */
NO_INLINE /* For better stack traces */
void
sweep_weak_hash_tables (void)
{
struct Lisp_Hash_Table *h, *used, *next;
bool marked;
/* Mark all keys and values that are in use. Keep on marking until
there is no more change. This is necessary for cases like
value-weak table A containing an entry X -> Y, where Y is used in a
key-weak table B, Z -> Y. If B comes after A in the list of weak
tables, X -> Y might be removed from A, although when looking at B
one finds that it shouldn't. */
do
{
marked = 0;
for (h = weak_hash_tables; h; h = h->next_weak)
{
if (h->header.size & ARRAY_MARK_FLAG)
marked |= sweep_weak_table (h, 0);
}
}
while (marked);
/* Remove tables and entries that aren't used. */
for (h = weak_hash_tables, used = NULL; h; h = next)
{
next = h->next_weak;
if (h->header.size & ARRAY_MARK_FLAG)
{
/* TABLE is marked as used. Sweep its contents. */
if (h->count > 0)
sweep_weak_table (h, 1);
/* Add table to the list of used weak hash tables. */
h->next_weak = used;
used = h;
}
}
weak_hash_tables = used;
}
/***********************************************************************
Hash Code Computation
@ -5294,6 +5274,7 @@ disregarding any coding systems. If nil, use the current buffer. */ )
}
void
syms_of_fns (void)
{

View file

@ -38,6 +38,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "fontset.h"
#include "font.h"
#include "termhooks.h"
#include "pdumper.h"
#ifdef HAVE_WINDOW_SYSTEM
#include TERM_HEADER
@ -5309,9 +5310,10 @@ syms_of_font (void)
sort_shift_bits[FONT_SIZE_INDEX] = 16;
sort_shift_bits[FONT_WIDTH_INDEX] = 23;
/* Note that the other elements in sort_shift_bits are not used. */
PDUMPER_REMEMBER_SCALAR (sort_shift_bits);
staticpro (&font_charset_alist);
font_charset_alist = Qnil;
staticpro (&font_charset_alist);
DEFSYM (Qopentype, "opentype");
@ -5349,13 +5351,13 @@ syms_of_font (void)
DEFSYM (QCuser_spec, ":user-spec");
staticpro (&scratch_font_spec);
scratch_font_spec = Ffont_spec (0, NULL);
staticpro (&scratch_font_prefer);
staticpro (&scratch_font_spec);
scratch_font_prefer = Ffont_spec (0, NULL);
staticpro (&scratch_font_prefer);
staticpro (&Vfont_log_deferred);
Vfont_log_deferred = make_nil_vector (3);
staticpro (&Vfont_log_deferred);
#if 0
#ifdef HAVE_LIBOTF

View file

@ -39,6 +39,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include TERM_HEADER
#endif /* HAVE_WINDOW_SYSTEM */
#include "font.h"
#include "pdumper.h"
/* FONTSET
@ -2127,6 +2128,7 @@ syms_of_fontset (void)
build_pure_c_string ("-*-*-*-*-*-*-*-*-*-*-*-*-fontset-default"));
ASET (Vfontset_table, 0, Vdefault_fontset);
next_fontset_id = 1;
PDUMPER_REMEMBER_SCALAR (next_fontset_id);
auto_fontset_alist = Qnil;
staticpro (&auto_fontset_alist);

View file

@ -53,6 +53,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifdef USE_X_TOOLKIT
#include "widget.h"
#endif
#include "pdumper.h"
/* The currently selected frame. */
Lisp_Object selected_frame;
@ -1051,10 +1052,7 @@ make_initial_frame (void)
Lisp_Object frame;
eassert (initial_kboard);
/* The first call must initialize Vframe_list. */
if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
Vframe_list = Qnil;
eassert (NILP (Vframe_list) || CONSP (Vframe_list));
terminal = init_initial_terminal ();
@ -5626,6 +5624,26 @@ make_monitor_attribute_list (struct MonitorInfo *monitors,
Initialization
***********************************************************************/
static void init_frame_once_for_pdumper (void);
void
init_frame_once (void)
{
staticpro (&Vframe_list);
staticpro (&selected_frame);
PDUMPER_IGNORE (last_nonminibuf_frame);
Vframe_list = Qnil;
selected_frame = Qnil;
pdumper_do_now_and_after_load (init_frame_once_for_pdumper);
}
static void
init_frame_once_for_pdumper (void)
{
PDUMPER_RESET_LV (Vframe_list, Qnil);
PDUMPER_RESET_LV (selected_frame, Qnil);
}
void
syms_of_frame (void)
{
@ -6107,8 +6125,6 @@ making the child frame unresponsive to user actions, the default is to
iconify the top level frame instead. */);
iconify_child_frame = Qiconify_top_level;
staticpro (&Vframe_list);
defsubr (&Sframep);
defsubr (&Sframe_live_p);
defsubr (&Swindow_system);

View file

@ -30,6 +30,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "buffer.h"
#include "blockinput.h"
#include "termhooks.h"
#include "pdumper.h"
/* Fringe bitmaps are represented in three different ways:
@ -1739,12 +1740,18 @@ mark_fringe_data (void)
/* Initialize this module when Emacs starts. */
static void init_fringe_once_for_pdumper (void);
void
init_fringe_once (void)
{
int bt;
pdumper_do_now_and_after_load (init_fringe_once_for_pdumper);
}
for (bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
static void
init_fringe_once_for_pdumper (void)
{
for (int bt = NO_FRINGE_BITMAP + 1; bt < MAX_STANDARD_FRINGE_BITMAPS; bt++)
init_fringe_bitmap (bt, &standard_bitmaps[bt], 1);
}

View file

@ -26,6 +26,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "blockinput.h"
#include "font.h"
#include "ftfont.h"
#include "pdumper.h"
/* FTCR font driver. */
@ -282,6 +283,8 @@ ftcrfont_draw (struct glyph_string *s,
static void syms_of_ftcrfont_for_pdumper (void);
struct font_driver const ftcrfont_driver =
{
.type = LISPSYM_INITIALLY (Qftcr),
@ -317,5 +320,11 @@ syms_of_ftcrfont (void)
abort ();
DEFSYM (Qftcr, "ftcr");
pdumper_do_now_and_after_load (syms_of_ftcrfont_for_pdumper);
}
static void
syms_of_ftcrfont_for_pdumper (void)
{
register_font_driver (&ftcrfont_driver, NULL);
}

View file

@ -34,6 +34,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "composite.h"
#include "font.h"
#include "ftfont.h"
#include "pdumper.h"
static struct font_driver const ftfont_driver;
@ -2701,6 +2702,8 @@ ftfont_combining_capability (struct font *font)
#endif
}
static void syms_of_ftfont_for_pdumper (void);
static struct font_driver const ftfont_driver =
{
/* We can't draw a text without device dependent functions. */
@ -2752,5 +2755,12 @@ syms_of_ftfont (void)
staticpro (&ft_face_cache);
ft_face_cache = Qnil;
pdumper_do_now_and_after_load (syms_of_ftfont_for_pdumper);
}
static void
syms_of_ftfont_for_pdumper (void)
{
PDUMPER_RESET_LV (ft_face_cache, Qnil);
register_font_driver (&ftfont_driver, NULL);
}

View file

@ -28,6 +28,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "frame.h"
#include "blockinput.h"
#include "font.h"
#include "pdumper.h"
/* FTX font driver. */
@ -339,6 +340,8 @@ ftxfont_end_for_frame (struct frame *f)
static void syms_of_ftxfont_for_pdumper (void);
struct font_driver const ftxfont_driver =
{
/* We can't draw a text without device dependent functions. */
@ -373,5 +376,11 @@ void
syms_of_ftxfont (void)
{
DEFSYM (Qftx, "ftx");
pdumper_do_now_and_after_load (syms_of_ftxfont_for_pdumper);
}
static void
syms_of_ftxfont_for_pdumper (void)
{
register_font_driver (&ftxfont_driver, NULL);
}

View file

@ -76,7 +76,6 @@ extern void *(*__morecore) (ptrdiff_t);
#ifdef HYBRID_MALLOC
# include "sheap.h"
# define DUMPED bss_sbrk_did_unexec
#endif
#ifdef __cplusplus
@ -1508,7 +1507,7 @@ static void *
gdefault_morecore (ptrdiff_t increment)
{
#ifdef HYBRID_MALLOC
if (!DUMPED)
if (!definitely_will_not_unexec_p ())
{
return bss_sbrk (increment);
}
@ -1726,6 +1725,8 @@ extern int posix_memalign (void **memptr, size_t alignment, size_t size);
static bool
allocated_via_gmalloc (void *ptr)
{
if (!__malloc_initialized)
return false;
size_t block = BLOCK (ptr);
size_t blockmax = _heaplimit - 1;
return block <= blockmax && _heapinfo[block].busy.type != 0;
@ -1737,7 +1738,7 @@ allocated_via_gmalloc (void *ptr)
void *
hybrid_malloc (size_t size)
{
if (DUMPED)
if (definitely_will_not_unexec_p ())
return malloc (size);
return gmalloc (size);
}
@ -1745,7 +1746,7 @@ hybrid_malloc (size_t size)
void *
hybrid_calloc (size_t nmemb, size_t size)
{
if (DUMPED)
if (definitely_will_not_unexec_p ())
return calloc (nmemb, size);
return gcalloc (nmemb, size);
}
@ -1763,7 +1764,7 @@ hybrid_free (void *ptr)
void *
hybrid_aligned_alloc (size_t alignment, size_t size)
{
if (!DUMPED)
if (!definitely_will_not_unexec_p ())
return galigned_alloc (alignment, size);
/* The following is copied from alloc.c */
#ifdef HAVE_ALIGNED_ALLOC
@ -1786,7 +1787,7 @@ hybrid_realloc (void *ptr, size_t size)
return hybrid_malloc (size);
if (!allocated_via_gmalloc (ptr))
return realloc (ptr, size);
if (!DUMPED)
if (!definitely_will_not_unexec_p ())
return grealloc (ptr, size);
/* The dumped emacs is trying to realloc storage allocated before

View file

@ -25,6 +25,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "gnutls.h"
#include "coding.h"
#include "buffer.h"
#include "pdumper.h"
#if GNUTLS_VERSION_NUMBER >= 0x030014
# define HAVE_GNUTLS_X509_SYSTEM_TRUST
@ -2626,6 +2627,7 @@ syms_of_gnutls (void)
);
#ifdef HAVE_GNUTLS
gnutls_global_initialized = 0;
PDUMPER_IGNORE (gnutls_global_initialized);
DEFSYM (Qgnutls_code, "gnutls-code");
DEFSYM (Qgnutls_anon, "gnutls-anon");

View file

@ -46,6 +46,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "coding.h"
#include "termhooks.h"
#include "font.h"
#include "pdumper.h"
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
@ -10003,7 +10004,9 @@ void
syms_of_image (void)
{
/* Initialize this only once; it will be reset before dumping. */
/* The portable dumper will just leave it NULL, so no need to reset. */
image_types = NULL;
PDUMPER_IGNORE (image_types);
/* Must be defined now because we're going to update it below, while
defining the supported image types. */

View file

@ -29,6 +29,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "buffer.h"
#include "window.h"
#include "region-cache.h"
#include "pdumper.h"
static void insert_from_string_1 (Lisp_Object, ptrdiff_t, ptrdiff_t, ptrdiff_t,
ptrdiff_t, bool, bool);
@ -1927,6 +1928,14 @@ prepare_to_modify_buffer_1 (ptrdiff_t start, ptrdiff_t end,
if (!NILP (BVAR (current_buffer, read_only)))
Fbarf_if_buffer_read_only (temp);
/* If we're about to modify a buffer the contents of which come from
a dump file, copy the contents to private storage first so we
don't take a COW fault on the buffer text and keep it around
forever. */
if (pdumper_object_p (BEG_ADDR))
enlarge_buffer_text (current_buffer, 0);
eassert (!pdumper_object_p (BEG_ADDR));
run_undoable_change();
bset_redisplay (current_buffer);

View file

@ -29,7 +29,6 @@ INLINE_HEADER_BEGIN
struct interval
{
/* The first group of entries deal with the tree structure. */
ptrdiff_t total_length; /* Length of myself and both children. */
ptrdiff_t position; /* Cache of interval's character position. */
/* This field is usually updated

View file

@ -68,6 +68,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <ignore-value.h>
#include "pdumper.h"
#ifdef HAVE_WINDOW_SYSTEM
#include TERM_HEADER
#endif /* HAVE_WINDOW_SYSTEM */
@ -10977,6 +10979,8 @@ static const struct event_head head_table[] = {
{SYMBOL_INDEX (Qselect_window), SYMBOL_INDEX (Qswitch_frame)}
};
static void syms_of_keyboard_for_pdumper (void);
void
syms_of_keyboard (void)
{
@ -10987,9 +10991,11 @@ syms_of_keyboard (void)
staticpro (&Vlispy_mouse_stem);
regular_top_level_message = build_pure_c_string ("Back to top level");
staticpro (&regular_top_level_message);
#ifdef HAVE_STACK_OVERFLOW_HANDLING
recover_top_level_message
= build_pure_c_string ("Re-entering top level after C stack overflow");
staticpro (&recover_top_level_message);
#endif
DEFVAR_LISP ("internal--top-level-message", Vinternal__top_level_message,
doc: /* Message displayed by `normal-top-level'. */);
@ -11828,7 +11834,38 @@ preserve data in modified buffers that would otherwise be lost.
If nil, Emacs crashes immediately in response to fatal signals. */);
attempt_orderly_shutdown_on_fatal_signal = true;
pdumper_do_now_and_after_load (syms_of_keyboard_for_pdumper);
}
static void
syms_of_keyboard_for_pdumper (void)
{
/* Make sure input state is pristine when restoring from a dump.
init_keyboard() also resets some of these, but the duplication
doesn't hurt and makes sure that allocate_kboard and subsequent
early init functions see the environment they expect. */
PDUMPER_RESET_LV (pending_funcalls, Qnil);
PDUMPER_RESET_LV (unread_switch_frame, Qnil);
PDUMPER_RESET_LV (internal_last_event_frame, Qnil);
PDUMPER_RESET_LV (last_command_event, Qnil);
PDUMPER_RESET_LV (last_nonmenu_event, Qnil);
PDUMPER_RESET_LV (last_input_event, Qnil);
PDUMPER_RESET_LV (Vunread_command_events, Qnil);
PDUMPER_RESET_LV (Vunread_post_input_method_events, Qnil);
PDUMPER_RESET_LV (Vunread_input_method_events, Qnil);
PDUMPER_RESET_LV (Vthis_command, Qnil);
PDUMPER_RESET_LV (Vreal_this_command, Qnil);
PDUMPER_RESET_LV (Vthis_command_keys_shift_translated, Qnil);
PDUMPER_RESET_LV (Vthis_original_command, Qnil);
PDUMPER_RESET (num_input_keys, 0);
PDUMPER_RESET (num_nonmacro_input_events, 0);
PDUMPER_RESET_LV (Vlast_event_frame, Qnil);
PDUMPER_RESET_LV (Vdeferred_action_list, Qnil);
PDUMPER_RESET_LV (Vdelayed_warnings_list, Qnil);
/* Create the initial keyboard. Qt means 'unset'. */
eassert (initial_kboard == NULL);
initial_kboard = allocate_kboard (Qt);
DEFVAR_LISP ("while-no-input-ignore-events",
@ -11940,8 +11977,8 @@ mark_kboards (void)
for (kb = all_kboards; kb; kb = kb->next_kboard)
{
if (kb->kbd_macro_buffer)
for (p = kb->kbd_macro_buffer; p < kb->kbd_macro_ptr; p++)
mark_object (*p);
for (p = kb->kbd_macro_buffer; p < kb->kbd_macro_ptr; p++)
mark_object (*p);
mark_object (KVAR (kb, Voverriding_terminal_local_map));
mark_object (KVAR (kb, Vlast_command));
mark_object (KVAR (kb, Vreal_last_command));

View file

@ -527,6 +527,7 @@ enum Lisp_Type
/* Cons. XCONS (object) points to a struct Lisp_Cons. */
Lisp_Cons = USE_LSB_TAG ? 3 : 6,
/* Must be last entry in Lisp_Type enumeration. */
Lisp_Float = 7
};
@ -623,16 +624,110 @@ extern void char_table_set (Lisp_Object, int, Lisp_Object);
extern _Noreturn void wrong_type_argument (Lisp_Object, Lisp_Object);
#ifdef CANNOT_DUMP
enum { might_dump = false };
#elif defined DOUG_LEA_MALLOC
/* Defined in emacs.c. */
extern bool might_dump;
#endif
/* True means Emacs has already been initialized.
Used during startup to detect startup of dumped Emacs. */
/* Set after Emacs has started up the first time.
Prevents reinitialization of the Lisp world and keymaps on
subsequent starts. */
extern bool initialized;
extern struct gflags {
/* True means this Emacs instance was born to dump. */
#if defined (HAVE_PDUMPER) || !defined (CANNOT_DUMP)
bool will_dump_ : 1;
bool will_bootstrap_ : 1;
#endif
#if defined (HAVE_PDUMPER)
/* Set in an Emacs process that will likely dump with pdumper; all
Emacs processes may dump with pdumper, however. */
bool will_dump_with_pdumper_ : 1;
/* Set in an Emacs process that has been restored from a portable
dump. */
bool dumped_with_pdumper_ : 1;
#endif
#ifndef CANNOT_DUMP
bool will_dump_with_unexec_ : 1;
/* Set in an Emacs process that has been restored from an unexec
dump. */
bool dumped_with_unexec_ : 1;
/* We promise not to unexec: useful for hybrid malloc. */
bool will_not_unexec_ : 1;
#endif
} gflags;
INLINE bool
will_dump_p (void)
{
#if HAVE_PDUMPER || !defined (CANNOT_DUMP)
return gflags.will_dump_;
#else
return false;
#endif
}
INLINE bool
will_bootstrap_p (void)
{
#if HAVE_PDUMPER || !defined (CANNOT_DUMP)
return gflags.will_bootstrap_;
#else
return false;
#endif
}
INLINE bool
will_dump_with_pdumper_p (void)
{
#if HAVE_PDUMPER
return gflags.will_dump_with_pdumper_;
#else
return false;
#endif
}
INLINE bool
dumped_with_pdumper_p (void)
{
#if HAVE_PDUMPER
return gflags.dumped_with_pdumper_;
#else
return false;
#endif
}
INLINE bool
will_dump_with_unexec_p (void)
{
#ifdef CANNOT_DUMP
return false;
#else
return gflags.will_dump_with_unexec_;
#endif
}
INLINE bool
dumped_with_unexec_p (void)
{
#ifdef CANNOT_DUMP
return false;
#else
return gflags.dumped_with_unexec_;
#endif
}
/* This function is the opposite of will_dump_with_unexec_p(), except
that it returns false before main runs. It's important to use
gmalloc for any pre-main allocations if we're going to unexec. */
INLINE bool
definitely_will_not_unexec_p (void)
{
#ifdef CANNOT_DUMP
return true;
#else
return gflags.will_not_unexec_;
#endif
}
/* Defined in floatfns.c. */
extern double extract_float (Lisp_Object);
@ -862,6 +957,19 @@ typedef EMACS_UINT Lisp_Word_tag;
# define DEFINE_NON_NIL_Q_SYMBOL_MACROS true
#endif
/* True if N is a power of 2. N should be positive. */
#define POWER_OF_2(n) (((n) & ((n) - 1)) == 0)
/* Return X rounded to the next multiple of Y. Y should be positive,
and Y - 1 + X should not overflow. Arguments should not have side
effects, as they are evaluated more than once. Tune for Y being a
power of 2. */
#define ROUNDUP(x, y) (POWER_OF_2 (y) \
? ((y) - 1 + (x)) & ~ ((y) - 1) \
: ((y) - 1 + (x)) - ((y) - 1 + (x)) % (y))
#include "globals.h"
/* Header of vector-like objects. This documents the layout constraints on
@ -1568,7 +1676,7 @@ CHECK_VECTOR (Lisp_Object x)
/* A pseudovector is like a vector, but has other non-Lisp components. */
INLINE enum pvec_type
PSEUDOVECTOR_TYPE (struct Lisp_Vector *v)
PSEUDOVECTOR_TYPE (const struct Lisp_Vector *v)
{
ptrdiff_t size = v->header.size;
return (size & PSEUDOVECTOR_FLAG
@ -1578,7 +1686,7 @@ PSEUDOVECTOR_TYPE (struct Lisp_Vector *v)
/* Can't be used with PVEC_NORMAL_VECTOR. */
INLINE bool
PSEUDOVECTOR_TYPEP (union vectorlike_header *a, enum pvec_type code)
PSEUDOVECTOR_TYPEP (const union vectorlike_header *a, enum pvec_type code)
{
/* We don't use PSEUDOVECTOR_TYPE here so as to avoid a shift
* operation when `code' is known. */
@ -2168,6 +2276,12 @@ struct hash_table_test
struct Lisp_Hash_Table
{
/* Change pdumper.c if you change the fields here.
IMPORTANT!!!!!!!
Call hash_rehash_if_needed() before accessing. */
/* This is for Lisp; the hash table code does not refer to it. */
union vectorlike_header header;
@ -2224,8 +2338,9 @@ struct Lisp_Hash_Table
/* The comparison and hash functions. */
struct hash_table_test test;
/* Next weak hash table if this is a weak hash table. The head
of the list is in weak_hash_tables. */
/* Next weak hash table if this is a weak hash table. The head of
the list is in weak_hash_tables. Used only during garbage
collection --- at other times, it is NULL. */
struct Lisp_Hash_Table *next_weak;
} GCALIGNED_STRUCT;
@ -2250,32 +2365,47 @@ XHASH_TABLE (Lisp_Object a)
/* Value is the key part of entry IDX in hash table H. */
INLINE Lisp_Object
HASH_KEY (struct Lisp_Hash_Table *h, ptrdiff_t idx)
HASH_KEY (const struct Lisp_Hash_Table *h, ptrdiff_t idx)
{
return AREF (h->key_and_value, 2 * idx);
}
/* Value is the value part of entry IDX in hash table H. */
INLINE Lisp_Object
HASH_VALUE (struct Lisp_Hash_Table *h, ptrdiff_t idx)
HASH_VALUE (const struct Lisp_Hash_Table *h, ptrdiff_t idx)
{
return AREF (h->key_and_value, 2 * idx + 1);
}
/* Value is the hash code computed for entry IDX in hash table H. */
INLINE Lisp_Object
HASH_HASH (struct Lisp_Hash_Table *h, ptrdiff_t idx)
HASH_HASH (const struct Lisp_Hash_Table *h, ptrdiff_t idx)
{
return AREF (h->hash, idx);
}
/* Value is the size of hash table H. */
INLINE ptrdiff_t
HASH_TABLE_SIZE (struct Lisp_Hash_Table *h)
HASH_TABLE_SIZE (const struct Lisp_Hash_Table *h)
{
return ASIZE (h->next);
}
void hash_table_rehash (struct Lisp_Hash_Table *h);
INLINE bool
hash_rehash_needed_p (const struct Lisp_Hash_Table *h)
{
return h->count < 0;
}
INLINE void
hash_rehash_if_needed (struct Lisp_Hash_Table *h)
{
if (hash_rehash_needed_p (h))
hash_table_rehash (h);
}
/* Default size for hash tables if not specified. */
enum DEFAULT_HASH_SIZE { DEFAULT_HASH_SIZE = 65 };
@ -2441,6 +2571,9 @@ struct Lisp_Finalizer
struct Lisp_Finalizer *next;
} GCALIGNED_STRUCT;
extern struct Lisp_Finalizer finalizers;
extern struct Lisp_Finalizer doomed_finalizers;
INLINE bool
FINALIZERP (Lisp_Object x)
{
@ -2895,6 +3028,20 @@ CHECK_INTEGER (Lisp_Object x)
CHECK_TYPE (INTEGERP (x), Qnumber_or_marker_p, x); \
} while (false)
/* If we're not dumping using the legacy dumper and we might be using
the portable dumper, try to bunch all the subr structures together
for more efficient dump loading. */
#ifdef CANNOT_DUMP
# ifdef DARWIN_OS
# define SUBR_SECTION_ATTRIBUTE ATTRIBUTE_SECTION ("__DATA,subrs")
# else
# define SUBR_SECTION_ATTRIBUTE ATTRIBUTE_SECTION (".subrs")
# endif
#else
# define SUBR_SECTION_ATTRIBUTE
#endif
/* Define a built-in function for calling from Lisp.
`lname' should be the name to give the function in Lisp,
as a null-terminated C string.
@ -2923,7 +3070,8 @@ CHECK_INTEGER (Lisp_Object x)
/* This version of DEFUN declares a function prototype with the right
arguments, so we can catch errors with maxargs at compile-time. */
#define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \
static union Aligned_Lisp_Subr sname = \
SUBR_SECTION_ATTRIBUTE \
static union Aligned_Lisp_Subr sname = \
{{{ PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \
{ .a ## maxargs = fnname }, \
minargs, maxargs, lname, intspec, 0}}; \
@ -3169,6 +3317,11 @@ extern Lisp_Object Vascii_canon_table;
/* Call staticpro (&var) to protect static variable `var'. */
void staticpro (Lisp_Object *);
enum { NSTATICS = 2048 };
extern Lisp_Object *staticvec[NSTATICS];
extern int staticidx;
/* Forward declarations for prototypes. */
struct window;
@ -3416,12 +3569,14 @@ enum { NEXT_ALMOST_PRIME_LIMIT = 11 };
extern ptrdiff_t list_length (Lisp_Object);
extern EMACS_INT next_almost_prime (EMACS_INT) ATTRIBUTE_CONST;
extern Lisp_Object larger_vector (Lisp_Object, ptrdiff_t, ptrdiff_t);
extern void sweep_weak_hash_tables (void);
extern bool sweep_weak_table (struct Lisp_Hash_Table *, bool);
extern char *extract_data_from_object (Lisp_Object, ptrdiff_t *, ptrdiff_t *);
EMACS_UINT hash_string (char const *, ptrdiff_t);
EMACS_UINT sxhash (Lisp_Object, int);
EMACS_UINT hashfn_eql (struct hash_table_test *ht, Lisp_Object key);
EMACS_UINT hashfn_equal (struct hash_table_test *ht, Lisp_Object key);
Lisp_Object make_hash_table (struct hash_table_test, EMACS_INT, float, float,
Lisp_Object, bool);
Lisp_Object, bool);
ptrdiff_t hash_lookup (struct Lisp_Hash_Table *, Lisp_Object, EMACS_UINT *);
ptrdiff_t hash_put (struct Lisp_Hash_Table *, Lisp_Object, Lisp_Object,
EMACS_UINT);
@ -3592,6 +3747,12 @@ typedef uintptr_t byte_ct; /* System byte counts reported by GC. */
extern byte_ct consing_since_gc;
extern byte_ct gc_relative_threshold;
extern byte_ct memory_full_cons_threshold;
#ifdef HAVE_PDUMPER
extern int number_finalizers_run;
#endif
#ifdef ENABLE_CHECKING
extern Lisp_Object Vdead;
#endif
extern Lisp_Object list1 (Lisp_Object);
extern Lisp_Object list2 (Lisp_Object, Lisp_Object);
extern Lisp_Object list3 (Lisp_Object, Lisp_Object, Lisp_Object);
@ -3601,6 +3762,21 @@ extern Lisp_Object list5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object,
enum constype {CONSTYPE_HEAP, CONSTYPE_PURE};
extern Lisp_Object listn (enum constype, ptrdiff_t, Lisp_Object, ...);
enum gc_root_type {
GC_ROOT_STATICPRO,
GC_ROOT_BUFFER_LOCAL_DEFAULT,
GC_ROOT_BUFFER_LOCAL_NAME,
GC_ROOT_C_SYMBOL
};
struct gc_root_visitor {
void (*visit)(Lisp_Object *root_ptr,
enum gc_root_type type,
void *data);
void *data;
};
extern void visit_static_gc_roots (struct gc_root_visitor visitor);
/* Build a frequently used 2/3/4-integer lists. */
INLINE Lisp_Object
@ -3629,6 +3805,13 @@ extern Lisp_Object make_string (const char *, ptrdiff_t);
extern Lisp_Object make_formatted_string (char *, const char *, ...)
ATTRIBUTE_FORMAT_PRINTF (2, 3);
extern Lisp_Object make_unibyte_string (const char *, ptrdiff_t);
extern ptrdiff_t vectorlike_nbytes (const union vectorlike_header *hdr);
INLINE ptrdiff_t
vector_nbytes (const struct Lisp_Vector *v)
{
return vectorlike_nbytes (&v->header);
}
/* Make unibyte string from C string when the length isn't known. */
@ -3824,7 +4007,7 @@ extern Lisp_Object string_to_number (char const *, int, ptrdiff_t *);
extern void map_obarray (Lisp_Object, void (*) (Lisp_Object, Lisp_Object),
Lisp_Object);
extern void dir_warning (const char *, Lisp_Object);
extern void init_obarray (void);
extern void init_obarray_once (void);
extern void init_lread (void);
extern void syms_of_lread (void);
@ -3989,6 +4172,7 @@ extern void syms_of_module (void);
#endif
/* Defined in thread.c. */
extern struct thread_state primary_thread;
extern void mark_threads (void);
extern void unmark_main_thread (void);
@ -4017,7 +4201,7 @@ extern bool overlay_touches_p (ptrdiff_t);
extern Lisp_Object other_buffer_safely (Lisp_Object);
extern Lisp_Object get_truename_buffer (Lisp_Object);
extern void init_buffer_once (void);
extern void init_buffer (int);
extern void init_buffer (void);
extern void syms_of_buffer (void);
extern void keys_of_buffer (void);
@ -4160,6 +4344,7 @@ extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object);
extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object);
extern Lisp_Object get_frame_param (struct frame *, Lisp_Object);
extern void frames_discard_buffer (Lisp_Object);
extern void init_frame_once (void);
extern void syms_of_frame (void);
/* Defined in emacs.c. */

View file

@ -42,6 +42,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "systime.h"
#include "termhooks.h"
#include "blockinput.h"
#include "pdumper.h"
#include <c-ctype.h>
#ifdef MSDOS
@ -1969,7 +1970,7 @@ readevalloop (Lisp_Object readcharfun,
? Qnil : list1 (Qt)));
/* Try to ensure sourcename is a truename, except whilst preloading. */
if (NILP (Vpurify_flag)
if (!will_dump_p ()
&& !NILP (sourcename) && !NILP (Ffile_name_absolute_p (sourcename))
&& !NILP (Ffboundp (Qfile_truename)))
sourcename = call1 (Qfile_truename, sourcename) ;
@ -4373,7 +4374,7 @@ OBARRAY defaults to the value of `obarray'. */)
#define OBARRAY_SIZE 15121
void
init_obarray (void)
init_obarray_once (void)
{
Vobarray = make_vector (OBARRAY_SIZE, make_fixnum (0));
initial_obarray = Vobarray;
@ -4394,12 +4395,15 @@ init_obarray (void)
make_symbol_constant (Qt);
XSYMBOL (Qt)->u.s.declared_special = true;
/* Qt is correct even if CANNOT_DUMP. loadup.el will set to nil at end. */
/* Qt is correct even if not dumping. loadup.el will set to nil at end. */
Vpurify_flag = Qt;
DEFSYM (Qvariable_documentation, "variable-documentation");
}
int ndefsubr;
void
defsubr (union Aligned_Lisp_Subr *aname)
{
@ -4409,6 +4413,7 @@ defsubr (union Aligned_Lisp_Subr *aname)
XSETPVECTYPE (sname, PVEC_SUBR);
XSETSUBR (tem, sname);
set_symbol_function (sym, tem);
++ndefsubr;
}
#ifdef NOTDEF /* Use fset in subr.el now! */
@ -4526,11 +4531,9 @@ load_path_check (Lisp_Object lpath)
are running uninstalled.
Uses the following logic:
If CANNOT_DUMP:
If Vinstallation_directory is not nil (ie, running uninstalled),
use PATH_DUMPLOADSEARCH (ie, build path). Else use PATH_LOADSEARCH.
The remainder is what happens when dumping works:
If purify-flag (ie dumping) just use PATH_DUMPLOADSEARCH.
If !will_dump: Use PATH_LOADSEARCH.
The remainder is what happens when dumping is about to happen:
If dumping, just use PATH_DUMPLOADSEARCH.
Otherwise use PATH_LOADSEARCH.
If !initialized, then just return PATH_DUMPLOADSEARCH.
@ -4553,131 +4556,109 @@ load_path_check (Lisp_Object lpath)
static Lisp_Object
load_path_default (void)
{
if (will_dump_p ())
/* PATH_DUMPLOADSEARCH is the lisp dir in the source directory.
We used to add ../lisp (ie the lisp dir in the build
directory) at the front here, but that should not be
necessary, since in out of tree builds lisp/ is empty, save
for Makefile. */
return decode_env_path (0, PATH_DUMPLOADSEARCH, 0);
Lisp_Object lpath = Qnil;
const char *normal;
const char *normal = PATH_LOADSEARCH;
const char *loadpath = NULL;
#ifdef CANNOT_DUMP
#ifdef HAVE_NS
const char *loadpath = ns_load_path ();
loadpath = ns_load_path ();
#endif
normal = PATH_LOADSEARCH;
if (!NILP (Vinstallation_directory)) normal = PATH_DUMPLOADSEARCH;
#ifdef HAVE_NS
lpath = decode_env_path (0, loadpath ? loadpath : normal, 0);
#else
lpath = decode_env_path (0, normal, 0);
#endif
#else /* !CANNOT_DUMP */
normal = NILP (Vpurify_flag) ? PATH_LOADSEARCH : PATH_DUMPLOADSEARCH;
if (initialized)
if (!NILP (Vinstallation_directory))
{
#ifdef HAVE_NS
const char *loadpath = ns_load_path ();
lpath = decode_env_path (0, loadpath ? loadpath : normal, 0);
#else
lpath = decode_env_path (0, normal, 0);
#endif
if (!NILP (Vinstallation_directory))
{
Lisp_Object tem, tem1;
Lisp_Object tem, tem1;
/* Add to the path the lisp subdir of the installation
dir, if it is accessible. Note: in out-of-tree builds,
this directory is empty save for Makefile. */
tem = Fexpand_file_name (build_string ("lisp"),
/* Add to the path the lisp subdir of the installation
dir, if it is accessible. Note: in out-of-tree builds,
this directory is empty save for Makefile. */
tem = Fexpand_file_name (build_string ("lisp"),
Vinstallation_directory);
tem1 = Ffile_accessible_directory_p (tem);
if (!NILP (tem1))
{
if (NILP (Fmember (tem, lpath)))
{
/* We are running uninstalled. The default load-path
points to the eventual installed lisp directories.
We should not use those now, even if they exist,
so start over from a clean slate. */
lpath = list1 (tem);
}
}
else
/* That dir doesn't exist, so add the build-time
Lisp dirs instead. */
{
Lisp_Object dump_path =
decode_env_path (0, PATH_DUMPLOADSEARCH, 0);
lpath = nconc2 (lpath, dump_path);
}
/* Add site-lisp under the installation dir, if it exists. */
if (!no_site_lisp)
{
tem = Fexpand_file_name (build_string ("site-lisp"),
Vinstallation_directory);
tem1 = Ffile_accessible_directory_p (tem);
if (!NILP (tem1))
{
if (NILP (Fmember (tem, lpath)))
{
/* We are running uninstalled. The default load-path
points to the eventual installed lisp directories.
We should not use those now, even if they exist,
so start over from a clean slate. */
lpath = list1 (tem);
}
}
else
/* That dir doesn't exist, so add the build-time
Lisp dirs instead. */
{
Lisp_Object dump_path =
decode_env_path (0, PATH_DUMPLOADSEARCH, 0);
lpath = nconc2 (lpath, dump_path);
lpath = Fcons (tem, lpath);
}
}
/* Add site-lisp under the installation dir, if it exists. */
if (!no_site_lisp)
/* If Emacs was not built in the source directory,
and it is run from where it was built, add to load-path
the lisp and site-lisp dirs under that directory. */
if (NILP (Fequal (Vinstallation_directory, Vsource_directory)))
{
Lisp_Object tem2;
tem = Fexpand_file_name (build_string ("src/Makefile"),
Vinstallation_directory);
tem1 = Ffile_exists_p (tem);
/* Don't be fooled if they moved the entire source tree
AFTER dumping Emacs. If the build directory is indeed
different from the source dir, src/Makefile.in and
src/Makefile will not be found together. */
tem = Fexpand_file_name (build_string ("src/Makefile.in"),
Vinstallation_directory);
tem2 = Ffile_exists_p (tem);
if (!NILP (tem1) && NILP (tem2))
{
tem = Fexpand_file_name (build_string ("site-lisp"),
Vinstallation_directory);
tem1 = Ffile_accessible_directory_p (tem);
if (!NILP (tem1))
tem = Fexpand_file_name (build_string ("lisp"),
Vsource_directory);
if (NILP (Fmember (tem, lpath)))
lpath = Fcons (tem, lpath);
if (!no_site_lisp)
{
if (NILP (Fmember (tem, lpath)))
lpath = Fcons (tem, lpath);
}
}
/* If Emacs was not built in the source directory,
and it is run from where it was built, add to load-path
the lisp and site-lisp dirs under that directory. */
if (NILP (Fequal (Vinstallation_directory, Vsource_directory)))
{
Lisp_Object tem2;
tem = Fexpand_file_name (build_string ("src/Makefile"),
Vinstallation_directory);
tem1 = Ffile_exists_p (tem);
/* Don't be fooled if they moved the entire source tree
AFTER dumping Emacs. If the build directory is indeed
different from the source dir, src/Makefile.in and
src/Makefile will not be found together. */
tem = Fexpand_file_name (build_string ("src/Makefile.in"),
Vinstallation_directory);
tem2 = Ffile_exists_p (tem);
if (!NILP (tem1) && NILP (tem2))
{
tem = Fexpand_file_name (build_string ("lisp"),
tem = Fexpand_file_name (build_string ("site-lisp"),
Vsource_directory);
if (NILP (Fmember (tem, lpath)))
lpath = Fcons (tem, lpath);
if (!no_site_lisp)
tem1 = Ffile_accessible_directory_p (tem);
if (!NILP (tem1))
{
tem = Fexpand_file_name (build_string ("site-lisp"),
Vsource_directory);
tem1 = Ffile_accessible_directory_p (tem);
if (!NILP (tem1))
{
if (NILP (Fmember (tem, lpath)))
lpath = Fcons (tem, lpath);
}
if (NILP (Fmember (tem, lpath)))
lpath = Fcons (tem, lpath);
}
}
} /* Vinstallation_directory != Vsource_directory */
}
} /* Vinstallation_directory != Vsource_directory */
} /* if Vinstallation_directory */
}
else /* !initialized */
{
/* NORMAL refers to PATH_DUMPLOADSEARCH, ie the lisp dir in the
source directory. We used to add ../lisp (ie the lisp dir in
the build directory) at the front here, but that should not
be necessary, since in out of tree builds lisp/ is empty, save
for Makefile. */
lpath = decode_env_path (0, normal, 0);
}
#endif /* !CANNOT_DUMP */
} /* if Vinstallation_directory */
return lpath;
}
@ -4691,11 +4672,7 @@ init_lread (void)
/* First, set Vload_path. */
/* Ignore EMACSLOADPATH when dumping. */
#ifdef CANNOT_DUMP
bool use_loadpath = true;
#else
bool use_loadpath = NILP (Vpurify_flag);
#endif
bool use_loadpath = !will_dump_p ();
if (use_loadpath && egetenv ("EMACSLOADPATH"))
{
@ -4746,7 +4723,7 @@ init_lread (void)
load_path_check (Vload_path);
/* Add the site-lisp directories at the front. */
if (initialized && !no_site_lisp && PATH_SITELOADSEARCH[0] != '\0')
if (!will_dump_p () && !no_site_lisp && PATH_SITELOADSEARCH[0] != '\0')
{
Lisp_Object sitelisp;
sitelisp = decode_env_path (0, PATH_SITELOADSEARCH, 0);

View file

@ -35,6 +35,7 @@
#include "nsterm.h"
#include "macfont.h"
#include "macuvs.h"
#include "pdumper.h"
#include <libkern/OSByteOrder.h>
@ -1029,12 +1030,12 @@ sorted in the canonical order (CTFontManagerCompareFontFamilyNames on
static void
macfont_init_font_change_handler (void)
{
static bool initialized = false;
static bool xinitialized = false;
if (initialized)
if (xinitialized)
return;
initialized = true;
xinitialized = true;
CFNotificationCenterAddObserver
(CFNotificationCenterGetLocalCenter (), NULL,
macfont_handle_font_change_notification,
@ -1646,7 +1647,7 @@ static int macfont_variation_glyphs (struct font *, int c,
unsigned variations[256]);
static void macfont_filter_properties (Lisp_Object, Lisp_Object);
static struct font_driver const macfont_driver =
static struct font_driver macfont_driver =
{
.type = LISPSYM_INITIALLY (Qmac_ct),
.get_cache = macfont_get_cache,
@ -4028,12 +4029,14 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no
}
static void syms_of_macfont_for_pdumper (void);
void
syms_of_macfont (void)
{
/* Core Text, for macOS. */
DEFSYM (Qmac_ct, "mac-ct");
register_font_driver (&macfont_driver, NULL);
/* The font property key specifying the font design destination. The
value is an unsigned integer code: 0 for WYSIWYG, and 1 for Video
@ -4048,4 +4051,18 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no
macfont_family_cache = Qnil;
staticpro (&macfont_family_cache);
pdumper_do_now_and_after_load (syms_of_macfont_for_pdumper);
}
static void
syms_of_macfont_for_pdumper (void)
{
if (dumped_with_pdumper_p ())
macfont_family_cache = Qnil;
else
eassert (NILP (macfont_family_cache));
macfont_driver.type = Qmac_ct;
register_font_driver (&macfont_driver, NULL);
}

View file

@ -1576,9 +1576,10 @@ for instance using the window manager, then this produces a quit and
void
syms_of_menu (void)
{
staticpro (&menu_items);
menu_items = Qnil;
staticpro (&menu_items);
menu_items_inuse = Qnil;
staticpro (&menu_items_inuse);
defsubr (&Sx_popup_menu);
defsubr (&Sx_popup_dialog);

View file

@ -32,6 +32,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "keymap.h"
#include "sysstdio.h"
#include "systty.h"
#include "pdumper.h"
/* List of buffers for use as minibuffers.
The first element of the list is used for the outermost minibuffer
@ -1198,6 +1199,9 @@ is used to further constrain the set of candidates. */)
bucket = AREF (collection, idx);
}
if (HASH_TABLE_P (collection))
hash_rehash_if_needed (XHASH_TABLE (collection));
while (1)
{
/* Get the next element of the alist, obarray, or hash-table. */
@ -1858,21 +1862,36 @@ If no minibuffer is active, return nil. */)
}
static void init_minibuf_once_for_pdumper (void);
void
init_minibuf_once (void)
{
Vminibuffer_list = Qnil;
staticpro (&Vminibuffer_list);
pdumper_do_now_and_after_load (init_minibuf_once_for_pdumper);
}
static void
init_minibuf_once_for_pdumper (void)
{
PDUMPER_IGNORE (minibuf_level);
PDUMPER_IGNORE (minibuf_prompt_width);
/* We run this function on first initialization and whenever we
restore from a pdumper image. pdumper doesn't try to preserve
frames, windows, and so on, so reset everything related here. */
Vminibuffer_list = Qnil;
minibuf_level = 0;
minibuf_prompt = Qnil;
minibuf_save_list = Qnil;
last_minibuf_string = Qnil;
}
void
syms_of_minibuf (void)
{
minibuf_level = 0;
minibuf_prompt = Qnil;
staticpro (&minibuf_prompt);
minibuf_save_list = Qnil;
staticpro (&minibuf_save_list);
DEFSYM (Qcompletion_ignore_case, "completion-ignore-case");
@ -1882,7 +1901,6 @@ syms_of_minibuf (void)
DEFSYM (Qminibuffer_completion_table, "minibuffer-completion-table");
staticpro (&last_minibuf_string);
last_minibuf_string = Qnil;
DEFSYM (Qcustom_variable_history, "custom-variable-history");
Fset (Qcustom_variable_history, Qnil);

View file

@ -49,7 +49,6 @@ Updated by Christian Limpach (chris@nice.ch)
#include "macfont.h"
#endif
#ifdef HAVE_NS
static EmacsTooltip *ns_tooltip = nil;
@ -3125,7 +3124,6 @@ - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
========================================================================== */
void
syms_of_nsfns (void)
{
@ -3215,5 +3213,6 @@ - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
as_status = 0;
as_script = Qnil;
staticpro (&as_script);
as_result = 0;
}

View file

@ -36,6 +36,7 @@
#include "character.h"
#include "font.h"
#include "termchar.h"
#include "pdumper.h"
/* TODO: Drop once we can assume gnustep-gui 0.17.1. */
#ifdef NS_IMPL_GNUSTEP
@ -1483,6 +1484,8 @@ - (void)setIntAttribute: (NSInteger)attributeTag value: (NSInteger)val
fprintf (stderr, "\n");
}
static void syms_of_nsfont_for_pdumper (void);
struct font_driver const nsfont_driver =
{
.type = LISPSYM_INITIALLY (Qns),
@ -1502,13 +1505,17 @@ - (void)setIntAttribute: (NSInteger)attributeTag value: (NSInteger)val
void
syms_of_nsfont (void)
{
register_font_driver (&nsfont_driver, NULL);
DEFSYM (Qcondensed, "condensed");
DEFSYM (Qexpanded, "expanded");
DEFSYM (Qapple, "apple");
DEFSYM (Qmedium, "medium");
DEFVAR_LISP ("ns-reg-to-script", Vns_reg_to_script,
doc: /* Internal use: maps font registry to Unicode script. */);
ascii_printable = NULL;
pdumper_do_now_and_after_load (syms_of_nsfont_for_pdumper);
}
static void
syms_of_nsfont_for_pdumper (void)
{
register_font_driver (&nsfont_driver, NULL);
}

View file

@ -37,6 +37,7 @@
#include "termhooks.h"
#include "keyboard.h"
#include "menu.h"
#include "pdumper.h"
#define NSMENUPROFILE 0
@ -1893,6 +1894,7 @@ - (Lisp_Object)runDialogAt: (NSPoint)p
/* Don't know how to keep track of this in Next/Open/GNUstep. Always
update menus there. */
trackingMenu = 1;
PDUMPER_REMEMBER_SCALAR (trackingMenu);
#endif
defsubr (&Sns_reset_menu);
defsubr (&Smenu_or_popup_active_p);

View file

@ -60,6 +60,7 @@ Updated by Christian Limpach (chris@nice.ch)
#include "keyboard.h"
#include "buffer.h"
#include "font.h"
#include "pdumper.h"
#ifdef NS_IMPL_GNUSTEP
#include "process.h"
@ -9326,6 +9327,7 @@ Convert an X font name (XLFD) to an NS font name.
NSTRACE ("syms_of_nsterm");
ns_antialias_threshold = 10.0;
PDUMPER_REMEMBER_SCALAR (ns_antialias_threshold);
/* From 23+ we need to tell emacs what modifiers there are. */
DEFSYM (Qmodifier_value, "modifier-value");

5593
src/pdumper.c Normal file

File diff suppressed because it is too large Load diff

267
src/pdumper.h Normal file
View file

@ -0,0 +1,267 @@
/* Header file for the portable dumper.
Copyright (C) 2016 Free Software Foundation,
Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#ifndef EMACS_PDUMPER_H
#define EMACS_PDUMPER_H
#include "lisp.h"
INLINE_HEADER_BEGIN
#define PDUMPER_NO_OBJECT ((enum Lisp_Type) -1)
/* Indicate in source code that we're deliberately relying on pdumper
not preserving the given value. Compiles to nothing --- for humans
only. */
#define PDUMPER_IGNORE(thing) ((void) &(thing))
/* The portable dumper automatically preserves the Lisp heap and any C
variables to which the Lisp heap points. It doesn't know anything
about other C variables. The functions below allow code from other
parts of Emacs to tell the portable dumper about other bits of
information to preserve in dumped images.
These memory-records are themselves preserved in the dump, so call
the functions below only on the !initialized init path, just
like staticpro.
There are no special functions to preserve a global Lisp_Object.
You should just staticpro these. */
/* Remember the value of THING in dumped images. THING must not
contain any pointers or Lisp_Object variables: these values are not
valid across dump and load. */
#define PDUMPER_REMEMBER_SCALAR(thing) \
pdumper_remember_scalar (&(thing), sizeof (thing))
extern void pdumper_remember_scalar_impl (void *data, ptrdiff_t nbytes);
INLINE
void
pdumper_remember_scalar (void *data, ptrdiff_t nbytes)
{
#ifdef HAVE_PDUMPER
pdumper_remember_scalar_impl (data, nbytes);
#else
(void) data;
(void) nbytes;
#endif
}
extern void pdumper_remember_lv_ptr_raw_impl (
void *ptr, enum Lisp_Type type);
/* Remember the pointer at *PTR. *PTR must be null or point to a Lisp
object. TYPE is the rough type of Lisp object to which *PTR
points. */
INLINE
void
pdumper_remember_lv_ptr_raw (void* ptr, enum Lisp_Type type)
{
#ifdef HAVE_PDUMPER
pdumper_remember_lv_ptr_raw_impl (ptr, type);
#else
(void) ptr;
(void) type;
#endif
}
typedef void (*pdumper_hook)(void);
extern void pdumper_do_now_and_after_load_impl (pdumper_hook hook);
INLINE void
pdumper_do_now_and_after_load (pdumper_hook hook)
{
#ifdef HAVE_PDUMPER
pdumper_do_now_and_after_load_impl (hook);
#else
hook ();
#endif
}
/* Macros useful in pdumper callback functions. Assign a value if
we're loading a dump and the value needs to be reset to its
original value, and if we're initializing for the first time,
assert that the value has the expected original value. */
#define PDUMPER_RESET(variable, value) \
do { \
if (dumped_with_pdumper_p ()) \
(variable) = (value); \
else \
eassert ((variable) == (value)); \
} while (0)
#define PDUMPER_RESET_LV(variable, value) \
do { \
if (dumped_with_pdumper_p ()) \
(variable) = (value); \
else \
eassert (EQ ((variable), (value))); \
} while (0)
/* Actually load a dump. */
enum pdumper_load_result
{
PDUMPER_LOAD_SUCCESS,
PDUMPER_NOT_LOADED /* Not returned: useful for callers */,
PDUMPER_LOAD_FILE_NOT_FOUND,
PDUMPER_LOAD_BAD_FILE_TYPE,
PDUMPER_LOAD_FAILED_DUMP,
PDUMPER_LOAD_OOM,
PDUMPER_LOAD_VERSION_MISMATCH,
PDUMPER_LOAD_ERROR,
};
enum pdumper_load_result pdumper_load (const char *dump_filename);
struct pdumper_loaded_dump {
uintptr_t start;
uintptr_t end;
};
#ifdef HAVE_PDUMPER
extern struct pdumper_loaded_dump dump_public;
#endif
/* Return whether the OBJ points somewhere into the loaded dump image.
Works even when we have no dump loaded --- in this case, it just
returns false. */
INLINE _GL_ATTRIBUTE_CONST
bool
pdumper_object_p (const void *obj)
{
#ifdef HAVE_PDUMPER
uintptr_t obj_addr = (uintptr_t) obj;
return dump_public.start <= obj_addr && obj_addr < dump_public.end;
#else
(void) obj;
return false;
#endif
}
extern bool pdumper_cold_object_p_impl (const void *obj);
/* Return whether the OBJ is in the cold section of the dump.
Only bool-vectors and floats should end up there.
pdumper_object_p() and pdumper_object_p_precise() must have
returned true for OBJ before calling this function. */
INLINE _GL_ATTRIBUTE_CONST
bool
pdumper_cold_object_p (const void *obj)
{
#ifdef HAVE_PDUMPER
return pdumper_cold_object_p_impl (obj);
#else
(void) obj;
return false;
#endif
}
extern enum Lisp_Type pdumper_find_object_type_impl (const void *obj);
/* Return the type of the dumped object that starts at OBJ. It is a
programming error to call this routine for an OBJ for which
pdumper_object_p would return false. */
INLINE _GL_ATTRIBUTE_CONST
enum Lisp_Type
pdumper_find_object_type (const void *obj)
{
#ifdef HAVE_PDUMPER
return pdumper_find_object_type_impl (obj);
#else
(void) obj;
emacs_abort ();
#endif
}
/* Return whether OBJ points exactly to the start of some object in
the loaded dump image. It is a programming error to call this
routine for an OBJ for which pdumper_object_p would return
false. */
INLINE _GL_ATTRIBUTE_CONST
bool
pdumper_object_p_precise (const void *obj)
{
#ifdef HAVE_PDUMPER
return pdumper_find_object_type (obj) != PDUMPER_NO_OBJECT;
#else
(void) obj;
emacs_abort ();
#endif
}
extern bool pdumper_marked_p_impl (const void *obj);
/* Return whether OBJ is marked according to the portable dumper.
It is an error to call this routine for an OBJ for which
pdumper_object_p_precise would return false. */
INLINE
bool
pdumper_marked_p (const void *obj)
{
#ifdef HAVE_PDUMPER
return pdumper_marked_p_impl (obj);
#else
(void) obj;
emacs_abort ();
#endif
}
extern void pdumper_set_marked_impl (const void *obj);
/* Set the pdumper mark bit for OBJ. It is a programming error to
call this function with an OBJ for which pdumper_object_p_precise
would return false. */
INLINE
void
pdumper_set_marked (const void *obj)
{
#ifdef HAVE_PDUMPER
pdumper_set_marked_impl (obj);
#else
(void) obj;
emacs_abort ();
#endif
}
extern void pdumper_clear_marks_impl (void);
/* Clear all the mark bits for pdumper objects. */
INLINE
void
pdumper_clear_marks (void)
{
#ifdef HAVE_PDUMPER
pdumper_clear_marks_impl ();
#endif
}
/* Handle a page fault that occurs when we access the portable dumper
mapping. Return true iff the fault should be considered handled
and execution should resume. */
bool pdumper_handle_page_fault (void *fault_addr_ptr);
void syms_of_pdumper (void);
INLINE_HEADER_END
#endif

View file

@ -8028,9 +8028,7 @@ init_process_emacs (int sockfd)
inhibit_sentinels = 0;
#ifndef CANNOT_DUMP
if (! noninteractive || initialized)
#endif
if (!will_dump_with_unexec_p ())
{
#if defined HAVE_GLIB && !defined WINDOWSNT
/* Tickle glib's child-handling code. Ask glib to wait for Emacs itself;

View file

@ -21,6 +21,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "lisp.h"
#include "syssignal.h"
#include "systime.h"
#include "pdumper.h"
/* Return A + B, but return the maximum fixnum if the result would overflow.
Assume A and B are nonnegative and in fixnum range. */
@ -570,6 +571,8 @@ hashfn_profiler (struct hash_table_test *ht, Lisp_Object bt)
return XHASH (bt);
}
static void syms_of_profiler_for_pdumper (void);
void
syms_of_profiler (void)
{
@ -608,4 +611,22 @@ to make room for new entries. */);
defsubr (&Sprofiler_memory_stop);
defsubr (&Sprofiler_memory_running_p);
defsubr (&Sprofiler_memory_log);
pdumper_do_now_and_after_load (syms_of_profiler_for_pdumper);
}
static void
syms_of_profiler_for_pdumper (void)
{
if (dumped_with_pdumper_p ())
{
cpu_log = Qnil;
memory_log = Qnil;
}
else
{
eassert (NILP (cpu_log));
eassert (NILP (memory_log));
}
}

View file

@ -29,6 +29,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "region-cache.h"
#include "blockinput.h"
#include "intervals.h"
#include "pdumper.h"
#include "regex-emacs.h"
@ -3386,26 +3387,17 @@ the buffer. If the buffer doesn't have a cache, the value is nil. */)
}
static void syms_of_search_for_pdumper (void);
void
syms_of_search (void)
{
register int i;
for (i = 0; i < REGEXP_CACHE_SIZE; ++i)
for (int i = 0; i < REGEXP_CACHE_SIZE; ++i)
{
searchbufs[i].buf.allocated = 100;
searchbufs[i].buf.buffer = xmalloc (100);
searchbufs[i].buf.fastmap = searchbufs[i].fastmap;
searchbufs[i].regexp = Qnil;
searchbufs[i].f_whitespace_regexp = Qnil;
searchbufs[i].busy = false;
searchbufs[i].syntax_table = Qnil;
staticpro (&searchbufs[i].regexp);
staticpro (&searchbufs[i].f_whitespace_regexp);
staticpro (&searchbufs[i].syntax_table);
searchbufs[i].next = (i == REGEXP_CACHE_SIZE-1 ? 0 : &searchbufs[i+1]);
}
searchbuf_head = &searchbufs[0];
/* Error condition used for failing searches. */
DEFSYM (Qsearch_failed, "search-failed");
@ -3476,4 +3468,23 @@ is to bind it with `let' around a small expression. */);
defsubr (&Sset_match_data);
defsubr (&Sregexp_quote);
defsubr (&Snewline_cache_check);
pdumper_do_now_and_after_load (syms_of_search_for_pdumper);
}
static void
syms_of_search_for_pdumper (void)
{
for (int i = 0; i < REGEXP_CACHE_SIZE; ++i)
{
searchbufs[i].buf.allocated = 100;
searchbufs[i].buf.buffer = xmalloc (100);
searchbufs[i].buf.fastmap = searchbufs[i].fastmap;
searchbufs[i].regexp = Qnil;
searchbufs[i].f_whitespace_regexp = Qnil;
searchbufs[i].busy = false;
searchbufs[i].syntax_table = Qnil;
searchbufs[i].next = (i == REGEXP_CACHE_SIZE-1 ? 0 : &searchbufs[i+1]);
}
searchbuf_head = &searchbufs[0];
}

View file

@ -31,7 +31,6 @@ static int debug_sheap;
char bss_sbrk_buffer[STATIC_HEAP_SIZE];
char *max_bss_sbrk_ptr;
bool bss_sbrk_did_unexec;
void *
bss_sbrk (ptrdiff_t request_size)

View file

@ -27,5 +27,4 @@ enum { STATIC_HEAP_SIZE = sizeof (Lisp_Object) << 22 };
extern char bss_sbrk_buffer[STATIC_HEAP_SIZE];
extern char *max_bss_sbrk_ptr;
extern bool bss_sbrk_did_unexec;
extern void *bss_sbrk (ptrdiff_t);

View file

@ -3730,9 +3730,6 @@ syms_of_syntax (void)
staticpro (&gl_state.current_syntax_table);
staticpro (&gl_state.old_prop);
/* Defined in regex-emacs.c. */
staticpro (&re_match_object);
DEFSYM (Qscan_error, "scan-error");
Fput (Qscan_error, Qerror_conditions,
listn (CONSTYPE_PURE, 2, Qscan_error, Qerror));

View file

@ -270,7 +270,7 @@ get_current_dir_name_or_unreachable (void)
# if HAVE_GET_CURRENT_DIR_NAME && !BROKEN_GET_CURRENT_DIR_NAME
# ifdef HYBRID_MALLOC
bool use_libc = bss_sbrk_did_unexec;
bool use_libc = will_dump_with_unexec_p ();
# else
bool use_libc = true;
# endif
@ -1893,7 +1893,7 @@ handle_sigsegv (int sig, siginfo_t *siginfo, void *arg)
/* Return true if we have successfully set up SIGSEGV handler on alternate
stack. Otherwise we just treat SIGSEGV among the rest of fatal signals. */
static bool
bool
init_sigsegv (void)
{
struct sigaction sa;
@ -1908,12 +1908,15 @@ init_sigsegv (void)
sigfillset (&sa.sa_mask);
sa.sa_sigaction = handle_sigsegv;
sa.sa_flags = SA_SIGINFO | SA_ONSTACK | emacs_sigaction_flags ();
return sigaction (SIGSEGV, &sa, NULL) < 0 ? 0 : 1;
if (sigaction (SIGSEGV, &sa, NULL) < 0)
return 0;
return 1;
}
#else /* not HAVE_STACK_OVERFLOW_HANDLING or WINDOWSNT */
static bool
bool
init_sigsegv (void)
{
return 0;
@ -1963,7 +1966,7 @@ maybe_fatal_sig (int sig)
}
void
init_signals (bool dumping)
init_signals (void)
{
struct sigaction thread_fatal_action;
struct sigaction action;
@ -2114,7 +2117,7 @@ init_signals (bool dumping)
/* Don't alter signal handlers if dumping. On some machines,
changing signal handlers sets static data that would make signals
fail to work right when the dumped Emacs is run. */
if (dumping)
if (will_dump_p ())
return;
sigfillset (&process_fatal_action.sa_mask);

View file

@ -22,7 +22,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <signal.h>
extern void init_signals (bool);
extern void init_signals (void);
extern bool init_sigsegv (void);
extern void block_child_signal (sigset_t *);
extern void unblock_child_signal (sigset_t const *);
extern void block_interrupt_signal (sigset_t *);

View file

@ -93,7 +93,7 @@ extern bool list4_to_timespec (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, struct timespec *);
extern struct timespec lisp_time_argument (Lisp_Object);
extern _Noreturn void time_overflow (void);
extern void init_timefns (bool);
extern void init_timefns (void);
extern void syms_of_timefns (void);
INLINE_HEADER_END

View file

@ -2319,11 +2319,10 @@ inherits it if NONSTICKINESS is nil. The `front-sticky' and
Vtext_property_default_nonsticky
= list2 (Fcons (Qsyntax_table, Qt), Fcons (Qdisplay, Qt));
staticpro (&interval_insert_behind_hooks);
staticpro (&interval_insert_in_front_hooks);
interval_insert_behind_hooks = Qnil;
interval_insert_in_front_hooks = Qnil;
staticpro (&interval_insert_behind_hooks);
staticpro (&interval_insert_in_front_hooks);
/* Common attributes one might give text. */

View file

@ -25,6 +25,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "process.h"
#include "coding.h"
#include "syssignal.h"
#include "pdumper.h"
#include "keyboard.h"
union aligned_thread_state
@ -1064,7 +1065,7 @@ init_main_thread (void)
}
bool
main_thread_p (void *ptr)
main_thread_p (const void *ptr)
{
return ptr == &main_thread.s;
}

View file

@ -295,7 +295,7 @@ extern void maybe_reacquire_global_lock (void);
extern void init_threads_once (void);
extern void init_threads (void);
extern void syms_of_threads (void);
extern bool main_thread_p (void *);
extern bool main_thread_p (const void *);
extern bool in_current_thread (void);
typedef int select_func (int, fd_set *, fd_set *, fd_set *,

View file

@ -25,6 +25,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "bignum.h"
#include "coding.h"
#include "lisp.h"
#include "pdumper.h"
#include <strftime.h>
@ -291,7 +292,7 @@ tzlookup (Lisp_Object zone, bool settz)
}
void
init_timefns (bool dumping)
init_timefns (void)
{
#ifndef CANNOT_DUMP
/* A valid but unlikely setting for the TZ environment variable.
@ -300,7 +301,7 @@ init_timefns (bool dumping)
/* When just dumping out, set the time zone to a known unlikely value
and skip the rest of this function. */
if (dumping)
if (will_dump_with_unexec_p ())
{
xputenv (dump_tz_string);
tzset ();
@ -1729,6 +1730,19 @@ emacs_setenv_TZ (const char *tzstring)
return 0;
}
#if (ULONG_MAX < TRILLION || !FASTER_TIMEFNS) && !defined ztrillion
# define NEED_ZTRILLION_INIT 1
#endif
#ifdef NEED_ZTRILLION_INIT
static void
syms_of_timefns_for_pdumper (void)
{
mpz_init_set_ui (ztrillion, 1000000);
mpz_mul_ui (ztrillion, ztrillion, 1000000);
}
#endif
void
syms_of_timefns (void)
{
@ -1740,10 +1754,6 @@ syms_of_timefns (void)
trillion = make_int (1000000000000);
staticpro (&trillion);
#endif
#if (ULONG_MAX < TRILLION || !FASTER_TIMEFNS) && !defined ztrillion
mpz_init_set_ui (ztrillion, 1000000);
mpz_mul_ui (ztrillion, ztrillion, 1000000);
#endif
DEFSYM (Qencode_time, "encode-time");
@ -1759,4 +1769,7 @@ syms_of_timefns (void)
defsubr (&Scurrent_time_string);
defsubr (&Scurrent_time_zone);
defsubr (&Sset_time_zone_rule);
#ifdef NEED_ZTRILLION_INIT
pdumper_do_now_and_after_load (syms_of_timefns_for_pdumper);
#endif
}

View file

@ -39,8 +39,6 @@ PIMAGE_NT_HEADERS (__stdcall * pfnCheckSumMappedFile) (LPVOID BaseAddress,
LPDWORD HeaderSum,
LPDWORD CheckSum);
extern BOOL ctrl_c_handler (unsigned long type);
extern char my_begdata[];
extern char my_begbss[];
extern char *my_begbss_static;
@ -70,84 +68,10 @@ PCHAR bss_start_static = 0;
DWORD_PTR bss_size_static = 0;
DWORD_PTR extra_bss_size_static = 0;
/* MinGW64 doesn't add a leading underscore to external symbols,
whereas configure.ac sets up LD_SWITCH_SYSTEM_TEMACS to force the
entry point at __start, with two underscores. */
#ifdef __MINGW64__
#define _start __start
#endif
extern void mainCRTStartup (void);
/* Startup code for running on NT. When we are running as the dumped
version, we need to bootstrap our heap and .bss section into our
address space before we can actually hand off control to the startup
code supplied by NT (primarily because that code relies upon malloc ()). */
void _start (void);
void
_start (void)
{
#if 1
/* Give us a way to debug problems with crashes on startup when
running under the MSVC profiler. */
if (GetEnvironmentVariable ("EMACS_DEBUG", NULL, 0) > 0)
DebugBreak ();
#endif
/* Cache system info, e.g., the NT page size. */
cache_system_info ();
/* Grab our malloc arena space now, before CRT starts up. */
init_heap ();
/* This prevents ctrl-c's in shells running while we're suspended from
having us exit. */
SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrl_c_handler, TRUE);
/* Prevent Emacs from being locked up (eg. in batch mode) when
accessing devices that aren't mounted (eg. removable media drives). */
SetErrorMode (SEM_FAILCRITICALERRORS);
mainCRTStartup ();
}
/* File handling. */
/* Implementation note: this and the next functions work with ANSI
codepage encoded file names! */
int
open_input_file (file_data *p_file, char *filename)
{
HANDLE file;
HANDLE file_mapping;
void *file_base;
unsigned long size, upper_size;
file = CreateFileA (filename, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (file == INVALID_HANDLE_VALUE)
return FALSE;
size = GetFileSize (file, &upper_size);
file_mapping = CreateFileMapping (file, NULL, PAGE_READONLY,
0, size, NULL);
if (!file_mapping)
return FALSE;
file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size);
if (file_base == 0)
return FALSE;
p_file->name = filename;
p_file->size = size;
p_file->file = file;
p_file->file_mapping = file_mapping;
p_file->file_base = file_base;
return TRUE;
}
int
open_output_file (file_data *p_file, char *filename, unsigned long size)
@ -187,18 +111,6 @@ open_output_file (file_data *p_file, char *filename, unsigned long size)
return TRUE;
}
/* Close the system structures associated with the given file. */
void
close_file_data (file_data *p_file)
{
UnmapViewOfFile (p_file->file_base);
CloseHandle (p_file->file_mapping);
/* For the case of output files, set final size. */
SetFilePointer (p_file->file, p_file->size, NULL, FILE_BEGIN);
SetEndOfFile (p_file->file);
CloseHandle (p_file->file);
}
/* Routines to manipulate NT executable file sections. */
@ -220,34 +132,6 @@ find_section (const char * name, IMAGE_NT_HEADERS * nt_header)
return NULL;
}
/* Return pointer to section header for section containing the given
relative virtual address. */
IMAGE_SECTION_HEADER *
rva_to_section (DWORD_PTR rva, IMAGE_NT_HEADERS * nt_header)
{
PIMAGE_SECTION_HEADER section;
int i;
section = IMAGE_FIRST_SECTION (nt_header);
for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
{
/* Some linkers (eg. the NT SDK linker I believe) swapped the
meaning of these two values - or rather, they ignored
VirtualSize entirely and always set it to zero. This affects
some very old exes (eg. gzip dated Dec 1993). Since
w32_executable_type relies on this function to work reliably,
we need to cope with this. */
DWORD_PTR real_size = max (section->SizeOfRawData,
section->Misc.VirtualSize);
if (rva >= section->VirtualAddress
&& rva < section->VirtualAddress + real_size)
return section;
section++;
}
return NULL;
}
#if 0 /* unused */
/* Return pointer to section header for section containing the given
offset in its raw data area. */

View file

@ -9926,6 +9926,40 @@ maybe_load_unicows_dll (void)
}
}
/* Relocate a directory specified by epaths.h, using the location of
our binary as an anchor. Note: this runs early during startup, so
we cannot rely on the usual file-related facilities, and in
particular the argument is assumed to be a unibyte string in system
codepage encoding. */
const char *
w32_relocate (const char *epath_dir)
{
if (strncmp (epath_dir, "%emacs_dir%/", 12) == 0)
{
static char relocated_dir[MAX_PATH];
/* Replace "%emacs_dir%" with the parent of the directory where
our binary lives. Note that init_environment was not yet
called, so we cannot rely on emacs_dir being set in the
environment. */
if (GetModuleFileNameA (NULL, relocated_dir, MAX_PATH))
{
char *p = _mbsrchr (relocated_dir, '\\');
if (p)
{
*p = '\0';
if ((p = _mbsrchr (relocated_dir, '\\')) != NULL)
{
strcpy (p, epath_dir + 11);
epath_dir = relocated_dir;
}
}
}
}
return epath_dir;
}
/*
globals_of_w32 is used to initialize those global variables that
must always be initialized on startup even when the global variable

View file

@ -185,6 +185,8 @@ extern MultiByteToWideChar_Proc pMultiByteToWideChar;
extern WideCharToMultiByte_Proc pWideCharToMultiByte;
extern DWORD multiByteToWideCharFlags;
extern const char *w32_relocate (const char *);
extern void init_environment (char **);
extern void check_windows_init_file (void);
extern void syms_of_ntproc (void);

View file

@ -56,6 +56,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "w32.h"
#endif
#include "pdumper.h"
#include <basetyps.h>
#include <unknwn.h>
#include <commctrl.h>
@ -10209,6 +10211,7 @@ syms_of_w32fns (void)
track_mouse_window = NULL;
w32_visible_system_caret_hwnd = NULL;
PDUMPER_IGNORE (w32_visible_system_caret_hwnd);
DEFSYM (Qundefined_color, "undefined-color");
DEFSYM (Qcancel_timer, "cancel-timer");

View file

@ -33,6 +33,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "w32.h"
#endif
#include "pdumper.h"
/* Cleartype available on Windows XP, cleartype_natural from XP SP1.
The latter does not try to fit cleartype smoothed fonts into the
same bounding box as the non-antialiased version of the font.
@ -2624,6 +2626,9 @@ struct font_driver w32font_driver =
/* Initialize state that does not change between invocations. This is only
called when Emacs is dumped. */
static void syms_of_w32font_for_pdumper (void);
void
syms_of_w32font (void)
{
@ -2803,6 +2808,12 @@ versions of Windows) characters. */);
defsubr (&Sx_select_font);
pdumper_do_now_and_after_load (syms_of_w32font_for_pdumper);
}
static void
syms_of_w32font_for_pdumper (void)
{
register_font_driver (&w32font_driver, NULL);
}

View file

@ -223,9 +223,16 @@ typedef enum _HEAP_INFORMATION_CLASS {
typedef WINBASEAPI BOOL (WINAPI * HeapSetInformation_Proc)(HANDLE,HEAP_INFORMATION_CLASS,PVOID,SIZE_T);
#endif
#ifdef HAVE_PDUMPER
BOOL using_dynamic_heap = FALSE;
#endif
void
init_heap (void)
{
#ifdef HAVE_PDUMPER
using_dynamic_heap = TRUE;
#endif
if (using_dynamic_heap)
{
#ifndef MINGW_W64

View file

@ -30,6 +30,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "buffer.h"
#include "coding.h" /* for ENCODE_SYSTEM */
#include "menu.h"
#include "pdumper.h"
/* This may include sys/types.h, and that somehow loses
if this is not done before the other system files. */
@ -1586,6 +1587,7 @@ syms_of_w32menu (void)
globals_of_w32menu ();
current_popup_menu = NULL;
PDUMPER_IGNORE (current_popup_menu);
DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
DEFSYM (Qunsupported__w32_dialog, "unsupported--w32-dialog");

View file

@ -81,6 +81,51 @@ static sigset_t sig_mask;
static CRITICAL_SECTION crit_sig;
extern BOOL ctrl_c_handler (unsigned long type);
/* MinGW64 doesn't add a leading underscore to external symbols,
whereas configure.ac sets up LD_SWITCH_SYSTEM_TEMACS to force the
entry point at __start, with two underscores. */
#ifdef __MINGW64__
#define _start __start
#endif
extern void mainCRTStartup (void);
/* Startup code for running on NT. When we are running as the dumped
version, we need to bootstrap our heap and .bss section into our
address space before we can actually hand off control to the startup
code supplied by NT (primarily because that code relies upon malloc ()). */
void _start (void);
void
_start (void)
{
#if 1
/* Give us a way to debug problems with crashes on startup when
running under the MSVC profiler. */
if (GetEnvironmentVariable ("EMACS_DEBUG", NULL, 0) > 0)
DebugBreak ();
#endif
/* Cache system info, e.g., the NT page size. */
cache_system_info ();
/* Grab our malloc arena space now, before CRT starts up. */
init_heap ();
/* This prevents ctrl-c's in shells running while we're suspended from
having us exit. */
SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrl_c_handler, TRUE);
/* Prevent Emacs from being locked up (eg. in batch mode) when
accessing devices that aren't mounted (eg. removable media drives). */
SetErrorMode (SEM_FAILCRITICALERRORS);
mainCRTStartup ();
}
/* Improve on the CRT 'signal' implementation so that we could record
the SIGCHLD handler and fake interval timers. */
signal_handler
@ -1528,6 +1573,78 @@ waitpid (pid_t pid, int *status, int options)
return pid;
}
int
open_input_file (file_data *p_file, char *filename)
{
HANDLE file;
HANDLE file_mapping;
void *file_base;
unsigned long size, upper_size;
file = CreateFileA (filename, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (file == INVALID_HANDLE_VALUE)
return FALSE;
size = GetFileSize (file, &upper_size);
file_mapping = CreateFileMapping (file, NULL, PAGE_READONLY,
0, size, NULL);
if (!file_mapping)
return FALSE;
file_base = MapViewOfFile (file_mapping, FILE_MAP_READ, 0, 0, size);
if (file_base == 0)
return FALSE;
p_file->name = filename;
p_file->size = size;
p_file->file = file;
p_file->file_mapping = file_mapping;
p_file->file_base = file_base;
return TRUE;
}
/* Return pointer to section header for section containing the given
relative virtual address. */
IMAGE_SECTION_HEADER *
rva_to_section (DWORD_PTR rva, IMAGE_NT_HEADERS * nt_header)
{
PIMAGE_SECTION_HEADER section;
int i;
section = IMAGE_FIRST_SECTION (nt_header);
for (i = 0; i < nt_header->FileHeader.NumberOfSections; i++)
{
/* Some linkers (eg. the NT SDK linker I believe) swapped the
meaning of these two values - or rather, they ignored
VirtualSize entirely and always set it to zero. This affects
some very old exes (eg. gzip dated Dec 1993). Since
w32_executable_type relies on this function to work reliably,
we need to cope with this. */
DWORD_PTR real_size = max (section->SizeOfRawData,
section->Misc.VirtualSize);
if (rva >= section->VirtualAddress
&& rva < section->VirtualAddress + real_size)
return section;
section++;
}
return NULL;
}
/* Close the system structures associated with the given file. */
void
close_file_data (file_data *p_file)
{
UnmapViewOfFile (p_file->file_base);
CloseHandle (p_file->file_mapping);
/* For the case of output files, set final size. */
SetFilePointer (p_file->file, p_file->size, NULL, FILE_BEGIN);
SetEndOfFile (p_file->file);
CloseHandle (p_file->file);
}
/* Old versions of w32api headers don't have separate 32-bit and
64-bit defines, but the one they have matches the 32-bit variety. */
#ifndef IMAGE_NT_OPTIONAL_HDR32_MAGIC

View file

@ -36,6 +36,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "composite.h"
#include "font.h"
#include "w32font.h"
#include "pdumper.h"
#include "w32common.h"
struct uniscribe_font_info
@ -1176,8 +1177,16 @@ struct font_driver uniscribe_font_driver =
as it needs to test for the existence of the Uniscribe library. */
void syms_of_w32uniscribe (void);
static void syms_of_w32uniscribe_for_pdumper (void);
void
syms_of_w32uniscribe (void)
{
pdumper_do_now_and_after_load (syms_of_w32uniscribe_for_pdumper);
}
static void
syms_of_w32uniscribe_for_pdumper (void)
{
HMODULE uniscribe;

View file

@ -42,6 +42,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifdef MSDOS
#include "msdos.h"
#endif
#include "pdumper.h"
static ptrdiff_t count_windows (struct window *);
static ptrdiff_t get_leaf_windows (struct window *, struct window **,
@ -7876,10 +7877,59 @@ and scrolling positions. */)
return Qnil;
}
static void init_window_once_for_pdumper (void);
void
init_window_once (void)
{
minibuf_window = Qnil;
staticpro (&minibuf_window);
selected_window = Qnil;
staticpro (&selected_window);
Vwindow_list = Qnil;
staticpro (&Vwindow_list);
minibuf_selected_window = Qnil;
staticpro (&minibuf_selected_window);
pdumper_do_now_and_after_load (init_window_once_for_pdumper);
}
static void init_window_once_for_pdumper (void)
{
window_scroll_pixel_based_preserve_x = -1;
window_scroll_pixel_based_preserve_y = -1;
window_scroll_preserve_hpos = -1;
window_scroll_preserve_vpos = -1;
PDUMPER_IGNORE (sequence_number);
PDUMPER_RESET_LV (minibuf_window, Qnil);
PDUMPER_RESET_LV (selected_window, Qnil);
PDUMPER_RESET_LV (Vwindow_list, Qnil);
PDUMPER_RESET_LV (minibuf_selected_window, Qnil);
/* Hack: if mode_line_in_non_selected_windows is true (which it may
be, if we're restoring from a dump) the guts of
make_initial_frame will try to access selected_window, which is
invalid at this point, and lose. For the purposes of creating
the initial frame and window, this variable must be false. */
bool old_mode_line_in_non_selected_windows;
/* Snapshot dumped_with_pdumper to suppress compiler warning. */
bool saved_dumped_with_pdumper = dumped_with_pdumper_p ();
if (saved_dumped_with_pdumper)
{
old_mode_line_in_non_selected_windows
= mode_line_in_non_selected_windows;
mode_line_in_non_selected_windows = false;
}
struct frame *f = make_initial_frame ();
if (saved_dumped_with_pdumper)
mode_line_in_non_selected_windows =
old_mode_line_in_non_selected_windows;
XSETFRAME (selected_frame, f);
old_selected_frame = Vterminal_frame = selected_frame;
minibuf_window = f->minibuffer_window;
@ -7932,16 +7982,6 @@ syms_of_window (void)
DEFSYM (Qmode_line_format, "mode-line-format");
DEFSYM (Qheader_line_format, "header-line-format");
staticpro (&Vwindow_list);
minibuf_selected_window = Qnil;
staticpro (&minibuf_selected_window);
window_scroll_pixel_based_preserve_x = -1;
window_scroll_pixel_based_preserve_y = -1;
window_scroll_preserve_hpos = -1;
window_scroll_preserve_vpos = -1;
DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function,
doc: /* Non-nil means call as function to display a help buffer.
The function is called with one argument, the buffer to be displayed.

View file

@ -31,6 +31,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "character.h"
#include "charset.h"
#include "font.h"
#include "pdumper.h"
/* X core font driver. */
@ -1077,6 +1078,7 @@ xfont_check (struct frame *f, struct font *font)
}
static void syms_of_xfont_for_pdumper (void);
struct font_driver const xfont_driver =
{
@ -1102,5 +1104,11 @@ syms_of_xfont (void)
xfont_scripts_cache = CALLN (Fmake_hash_table, QCtest, Qequal);
staticpro (&xfont_scratch_props);
xfont_scratch_props = make_nil_vector (8);
pdumper_do_now_and_after_load (syms_of_xfont_for_pdumper);
}
static void
syms_of_xfont_for_pdumper (void)
{
register_font_driver (&xfont_driver, NULL);
}

View file

@ -32,6 +32,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "composite.h"
#include "font.h"
#include "ftfont.h"
#include "pdumper.h"
/* Xft font driver. */
@ -751,6 +752,8 @@ xftfont_cached_font_ok (struct frame *f, Lisp_Object font_object,
return ok;
}
static void syms_of_xftfont_for_pdumper (void);
struct font_driver const xftfont_driver =
{
/* We can't draw a text without device dependent functions. */
@ -802,7 +805,11 @@ syms_of_xftfont (void)
This is needed with some fonts to correct vertical overlap of glyphs. */);
xft_font_ascent_descent_override = 0;
ascii_printable[0] = 0;
pdumper_do_now_and_after_load (syms_of_xftfont_for_pdumper);
}
static void
syms_of_xftfont_for_pdumper (void)
{
register_font_driver (&xftfont_driver, NULL);
}

View file

@ -45,6 +45,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "buffer.h"
#include "coding.h"
#include "sysselect.h"
#include "pdumper.h"
#ifdef MSDOS
#include "msdos.h"
@ -2401,15 +2402,12 @@ DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_
return (popup_activated ()) ? Qt : Qnil;
}
static void syms_of_xmenu_for_pdumper (void);
void
syms_of_xmenu (void)
{
#ifdef USE_X_TOOLKIT
enum { WIDGET_ID_TICK_START = 1 << 16 };
widget_id_tick = WIDGET_ID_TICK_START;
next_menubar_widget_id = 1;
#endif
DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
defsubr (&Smenu_or_popup_active_p);
@ -2422,4 +2420,16 @@ syms_of_xmenu (void)
Ffset (intern_c_string ("accelerate-menu"),
intern_c_string (Sx_menu_bar_open_internal.s.symbol_name));
#endif
pdumper_do_now_and_after_load (syms_of_xmenu_for_pdumper);
}
static void
syms_of_xmenu_for_pdumper (void)
{
#ifdef USE_X_TOOLKIT
enum { WIDGET_ID_TICK_START = 1 << 16 };
widget_id_tick = WIDGET_ID_TICK_START;
next_menubar_widget_id = 1;
#endif
}

View file

@ -35,6 +35,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "blockinput.h"
#include "termhooks.h"
#include "keyboard.h"
#include "pdumper.h"
#include <X11/Xproto.h>
@ -2613,6 +2614,9 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
}
static void syms_of_xselect_for_pdumper (void);
void
syms_of_xselect (void)
{
@ -2628,17 +2632,9 @@ syms_of_xselect (void)
reading_selection_reply = Fcons (Qnil, Qnil);
staticpro (&reading_selection_reply);
reading_selection_window = 0;
reading_which_selection = 0;
property_change_wait_list = 0;
prop_location_identifier = 0;
property_change_reply = Fcons (Qnil, Qnil);
staticpro (&property_change_reply);
converted_selections = NULL;
conversion_fail_tag = None;
/* FIXME: Duplicate definition in nsselect.c. */
DEFVAR_LISP ("selection-converter-alist", Vselection_converter_alist,
doc: /* An alist associating X Windows selection-types with functions.
@ -2717,4 +2713,18 @@ A value of 0 means wait as long as necessary. This is initialized from the
DEFSYM (Qforeign_selection, "foreign-selection");
DEFSYM (Qx_lost_selection_functions, "x-lost-selection-functions");
DEFSYM (Qx_sent_selection_functions, "x-sent-selection-functions");
pdumper_do_now_and_after_load (syms_of_xselect_for_pdumper);
}
static void
syms_of_xselect_for_pdumper (void)
{
reading_selection_window = 0;
reading_which_selection = 0;
property_change_wait_list = 0;
prop_location_identifier = 0;
property_change_reply = Fcons (Qnil, Qnil);
converted_selections = NULL;
conversion_fail_tag = None;
}

View file

@ -32,6 +32,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "keyboard.h"
#include "blockinput.h"
#include "termhooks.h"
#include "pdumper.h"
#include <X11/Xproto.h>
@ -1023,13 +1024,18 @@ void
syms_of_xsettings (void)
{
current_mono_font = NULL;
PDUMPER_IGNORE (current_mono_font);
current_font = NULL;
PDUMPER_IGNORE (current_font);
first_dpyinfo = NULL;
PDUMPER_IGNORE (first_dpyinfo);
#ifdef HAVE_GSETTINGS
gsettings_client = NULL;
PDUMPER_IGNORE (gsettings_client);
#endif
#ifdef HAVE_GCONF
gconf_client = NULL;
PDUMPER_IGNORE (gconf_client);
#endif
DEFSYM (Qmonospace_font_name, "monospace-font-name");

View file

@ -74,6 +74,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "xsettings.h"
#include "sysselect.h"
#include "menu.h"
#include "pdumper.h"
#ifdef USE_X_TOOLKIT
#include <X11/Shell.h>
@ -13298,6 +13299,7 @@ void
syms_of_xterm (void)
{
x_error_message = NULL;
PDUMPER_IGNORE (x_error_message);
DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
DEFSYM (Qlatin_1, "latin-1");