diff options
-rw-r--r-- | admin/notes/big-elc | 313 | ||||
-rw-r--r-- | configure.ac | 11 | ||||
-rw-r--r-- | lisp/emacs-lisp/cl-lib.el | 4 | ||||
-rw-r--r-- | lisp/emacs-lisp/cl-macs.el | 1 | ||||
-rw-r--r-- | lisp/emacs-lisp/macroexp.el | 3 | ||||
-rw-r--r-- | lisp/frame.el | 2 | ||||
-rw-r--r-- | lisp/international/mule.el | 4 | ||||
-rw-r--r-- | lisp/loadup.el | 383 | ||||
-rw-r--r-- | lisp/progmodes/elisp-mode.el | 22 | ||||
-rw-r--r-- | src/Makefile.in | 4 | ||||
-rw-r--r-- | src/alloc.c | 2 | ||||
-rw-r--r-- | src/charset.c | 2 | ||||
-rw-r--r-- | src/coding.c | 8 | ||||
-rw-r--r-- | src/doc.c | 66 | ||||
-rw-r--r-- | src/emacs.c | 37 | ||||
-rw-r--r-- | src/print.c | 52 | ||||
-rw-r--r-- | src/syntax.c | 13 | ||||
-rw-r--r-- | src/unexw32.c | 2 | ||||
-rw-r--r-- | src/xfaces.c | 7 |
19 files changed, 824 insertions, 112 deletions
diff --git a/admin/notes/big-elc b/admin/notes/big-elc new file mode 100644 index 00000000000..c63e84da731 --- /dev/null +++ b/admin/notes/big-elc @@ -0,0 +1,313 @@ +“Big elc file” startup approach -*- mode: org; coding: utf-8 -*- + +These notes discuss the design and implementation status of the “big +elc file” approach for saving and loading the Lisp environment. + +* Justification + +The original discussion in which the idea arose was on the possible +elimination of the “unexec” mechanism, which is troublesome to +maintain. + +The CANNOT_DUMP support, when it isn’t suffering bit-rot, does allow +for loading all of the Lisp code from scratch at startup. However, +doing so is rather slow. + +Stefan Monnier suggested (and implemented) loading the Lisp +environment via loadup.el, as we do now in the “unexec” world, and +writing out a single Lisp file with all of the resulting function and +variable settings in it. Then a normal Emacs invocation can load this +one Lisp file, instead of dozens, and complex data structures can +simply be read, instead of constructed at run time. + +It turned out to be desirable for a couple of others to be loaded at +run time as well, but the one big file loads most of the settings. + +* Implementation + +** Saving the Lisp environment + +In loadup.el, we iterate over the obarray, collecting names of faces +and coding systems and such for later processing. Each symbol’s +function, variable, and property values get turned into the +appropriate fset, set-default, or setplist calls. Calls to defvar and +make-variable-buffer-local may be generated as well. The resulting +forms are all emitted as part of one large “progn” form, so that the +print-circle support can correctly cross-link references to objects in +a way that the reader will reconstruct. + +A few variables are explicitly skipped because they’re in use during +the read process, or they’re intended to be reinitialized when emacs +starts up. Some others are skipped for now because they’re not +printable objects. + +Most of the support for the unexec path is present, but ignored or +commented out. This keeps diffs (and merging) simpler. + +*** charsets, coding systems, and faces + +Some changes to charset and coding system support were made so that +when a definition is created for a new name, a property gets attached +to the symbol with the relevant parameters so that we can write out +enough information to reconstruct the definition after reading it +back. + +After the main definitions are written out, we emit additional forms +to fix up charset definitions, face specs, and so on. These don’t +have to worry about cross-linked data structures, so breaking them out +into separate forms keeps things simpler. + +*** deferred loading + +The standard category table is huge if written out, so we load +international/characters indirectly via dumped.elc instead. We could +perhaps suppress the variables and functions defined in +international/characters from being output with the rest of the Lisp +environment. That information should be available via the load +history. We would be assuming that no other loaded Lisp code alters +the variables’ values; any modified function values will be overridden +by the defalias calls. + +Advice attached to a subr can’t be written out and read back in +because of the “#<subr...>” syntax; uniquify attaches advice to +rename-buffer, so loading of uniquify is deferred until loading +dumped.elc, or until we’ve determined that we’re not dumping at all. + +*** efficient symbol reading + +The symbol parser is not terribly fast. It reads one character at a +time (which involves reading one or more bytes, and figuring out the +possible encoding of a multibyte character) and figuring out where the +end of the symbol is; then the obarray needs to be scanned to see if +the symbol is already present. + +It turns out that the “#N#” processing is faster. So now there’s a +new option to the printer that will use this form for symbols that +show up more than once. Parsing “#24#” and doing the hash table +lookup works out better than parsing “setplist” and scanning the +obarray over and over, though it makes it much harder for a human to +read. + +** Loading the Lisp environment + +The default action to invoke on startup is now to load +“../src/dumped.elc”. For experimentation that name works fine, but +for installation it’ll probably be something like just “dumped.elc”, +found via the load path. + +New primitives are needed to deal with Emacs data that is not purely +Lisp data structures: + + + internal--set-standard-syntax-table + + define-charset-internal + + define-coding-system-internal + +*** Speeding up the reader + +Reading a very large Lisp file (over a couple of megabytes) is still +slow. + +While it seems unavoidable that loading a Lisp environment at run time +will be at least slightly slower than having that environment be part +of the executable image when the process is launched, we want to keep +the process startup time acceptably fast. (No, that’s not a precisely +defined goal.) + +So, a few changes have been made to speed up reading the large Lisp +file. Some of them may be generally applicable, even if the +big-elc-file approach isn’t adopted. Others may be too specific to +this use case to warrant the additional code. + + + Avoiding substitution recursion for #N# forms when the new object + is a cons cell. + + Using hash tables instead of lists for forms to substitute. + + Avoiding circular object checks in some cases. + + Handle substituting into a list iteratively instead of + recursively. (This one was more about making performance analysis + easier for certain tools than directly improving performance.) + + Special-case reading from a file. Avoid repeated checks of the + type of input source and associated dispatching to appropriate + support routines, and hard-code the file-based calls. Streamline + the input blocking and unblocking. + + Avoid string allocation when reading symbols already in the + obarray. + +* Open Issues + +** CANNOT_DUMP, purify-flag + +The branch has been rebased onto a recent enough “master” version that +CANNOT_DUMP works fairly well on GNU/Linux systems. The branch has +now been updated to set CANNOT_DUMP unconditionally, to disable the +unexec code. As long as dumped.elc does all the proper initialization +like the old loadup.el did, that should work well. + +The regular CANNOT_DUMP build does not work on mac OS, at least in the +otherwise-normal Nextstep, self-contained-app mode; it seems to be a +load-path problem. See bug #27760. + +Some code still looks at purify-flag, including eval.c requiring that +it be nil when autoloading. So we still let the big progn set its +value. + +** Building and bootstrapping + +The bootstrap process assumes it needs to build the emacs executable +twice, with different environments based on whether stuff has been +byte-compiled. + +In this branch, the executables should be the same, but the dumped +Lisp files will be different. Ideally we should build the executable +only once, and dump out different environment files. Possibly this +means that instead of “bootstrap-emacs” we should invoke something +like: + + ../path/to/emacs --no-loadup -l ../path/to/bootstrap-dump.elc ... + +It might also make sense for bootstrap-dump.elc to include the byte +compiler, and to byte-compile the byte compiler (and other +COMPILE_FIRST stuff) in memory before dumping. + +Re-examine whether the use of build numbers makes sense, if we’re not +rewriting the executable image. + +** installation + +Installing this version of Emacs hasn’t been tested much. + +** offset builds (srcdir=… or /path/to/configure …) + +Builds outside of the source tree (where srcdir is not the root of the +build tree) have not been tested much, and don’t currently work. + +The first problem, at least while bootstrapping: “../src/dumped.elc” +is relative to $lispdir which is in the source tree, so Emacs doesn’t +find the dumped.elc file that’s in the build tree. + +Moving dumped.elc under $lispdir would be inappropriate since the +directory is in the source tree and the file content is specific to +the configuration being built. We could create a “lisp” directory in +the build tree and write dumped.elc there, but since we don’t +currently have such a directory, that’ll mean some changes to the load +path computation, which is already pretty messy. + +** Unhandled aspects of environment saving + +*** unprintable objects + +global-buffers-menu-map has cdr slot set to nil, but this seems to get +fixed up at run time, so simply omitting it may be okay. + +advertised-signature-table has several subr entries. Perhaps we could +filter those out, dump the rest, and then emit additional code to +fetch the subr values via their symbol names and insert them into the +hash after its initial creation. + +Markers and overlays that aren’t associated with buffers are replaced +with newly created ones. This only works for variables with these +objects as their values; markers or overlays contained within lists or +elsewhere wouldn’t be fixed up, and any sharing of these objects would +be lost, but there don’t appear to be any such cases. + +Any obarrays will be dumped in an incomplete form. We can’t +distinguish them from vectors that contain symbols and zeros. +(Possible fix someday: Make obarrays their own type.) As a special +case of this, though, we do look for abbrev tables, and generate code +to recreate them at load time. + +*** make-local-variable + +Different flavors of locally-bound variables are hard to distinguish +and may not all be saved properly. + +*** defvaralias + +For variable aliases, we emit a defvaralias command and skip the +default-value processing; we keep the property list processing and the +rest. Is there anything else that needs to be changed? + +*** documentation strings + +We call Snarf-documentation at load time, because it’s the only way to +get documentation pointers for Lisp subrs loaded. That may be +addressable in other ways, but for the moment it’s outside the scope +of this branch. + +Since we do call Snarf-documentation at load time, we can remove the +doc strings in DOC from dumped.elc, but we have to be a little careful +because not all of the pre-loaded Lisp doc strings wind up in DOC. +The easy way to do that, of course, is to scan DOC and, for each doc +entry we find, remove the documentation from the live Lisp data before +dumping. So, Snarf-documentation now takes an optional argument to +tell it to do that; that cut about 22% of the size of dumped.elc at +the time. + +There are still a bunch of doc strings winding up in dumped.elc from +various sources; see bug #27748. (Not mentioned in the bug report: +Compiled lambda forms get “(fn N)” style doc strings in their bytecode +representations too. But because we key on function names, there’s no +way to accomodate them in the DOC file.) + +*** locations of definitions + +C-h v shows variables as having been defined by dumped.elc, not by the +original source file. + +** coding system definitions + +We repeatedly iterate over coding system names, trying to reload each +definition, and postponing those that fail. We should be able to work +out the dependencies between them and construct an order that requires +only one pass. (Is it worth it?) + +Fix coding-system-list; it seems to have duplicates now. + +** error reporting + +If dumped.elc can’t be found, Emacs will quietly exit with exit +code 42. Unfortunately, when running in X mode, it’s difficult for +Lisp code to print any messages to standard error when quitting. But +we need to quit, at least in tty mode (do we in X mode?), because +interactive usage requires some definitions provided only by the Lisp +environment. + +** garbage collection + +The dumped .elc file contains a very large Lisp form with most of the +definitions in it. Causing the garbage collector to always be invoked +during startup guarantees some minimum additional delay before the +user will be able to interact with Emacs. + +More clever heuristics for when to do GC are probably possible, but +outside the scope of this branch. For now, gc-cons-threshold has been +raised, arbitrarily, to a value that seems to allow for loading +“dumped.elc” on GNU/Linux without GC during or immediately after. + +** load path setting + +Environment variable support may be broken. + +** little niceties + +Maybe we should rename the file, so that we display “Loading +lisp-environment...” during startup. + +** bugs? + +The default value of charset-map-path is set based on the build tree +(or source tree?), so reverting via customize would probably result in +a bogus value. This bug exists in the master version as well when +using unexec; in CANNOT_DUMP mode (when the Lisp code is only loaded +from the installed tree) it doesn’t seem to be a problem. + +** other changes + +Dropped changes from previous revisions due to merge conflicts; may +reinstate later: + + + In lread.c, substitute in cons iteratively (on “cdr” slot) instead + of recursively. + + In lread.c, change “seen” list to hash table. + + In lread.c, add a separate read1 loop specialized for file reading, + with input blocking manipulated only when actually reading from the + file, not when just pulling the next byte from a buffer. diff --git a/configure.ac b/configure.ac index c3e440adcaa..144d6881fe6 100644 --- a/configure.ac +++ b/configure.ac @@ -1349,10 +1349,9 @@ AC_CACHE_CHECK([whether addresses are sanitized], 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 +dnl +dnl For the big-elc model, we never support dumping. +CANNOT_DUMP=yes if test "$CANNOT_DUMP" = "yes"; then AC_DEFINE(CANNOT_DUMP, 1, [Define if Emacs cannot be dumped on your system.]) @@ -2206,9 +2205,7 @@ system_malloc=yes test "$CANNOT_DUMP" = yes || case "$opsys" in ## darwin ld insists on the use of malloc routines in the System framework. - darwin | mingw32 | nacl | sol2-10) ;; - cygwin) hybrid_malloc=yes - system_malloc= ;; + cygwin | darwin | mingw32 | nacl | sol2-10) ;; *) test "$ac_cv_func_sbrk" = yes && system_malloc=$emacs_cv_sanitize_address;; esac diff --git a/lisp/emacs-lisp/cl-lib.el b/lisp/emacs-lisp/cl-lib.el index 6ac08d839b1..15622b3384e 100644 --- a/lisp/emacs-lisp/cl-lib.el +++ b/lisp/emacs-lisp/cl-lib.el @@ -666,8 +666,4 @@ of record objects." (t (advice-remove 'type-of #'cl--old-struct-type-of)))) -;; Local variables: -;; byte-compile-dynamic: t -;; End: - ;;; cl-lib.el ends here diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el index b1ada00f4a4..4f42d635d4b 100644 --- a/lisp/emacs-lisp/cl-macs.el +++ b/lisp/emacs-lisp/cl-macs.el @@ -3243,7 +3243,6 @@ STRUCT and SLOT-NAME are symbols. INST is a structure instance." (run-hooks 'cl-macs-load-hook) ;; Local variables: -;; byte-compile-dynamic: t ;; generated-autoload-file: "cl-loaddefs.el" ;; End: diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el index 9bc194c478c..2285968134e 100644 --- a/lisp/emacs-lisp/macroexp.el +++ b/lisp/emacs-lisp/macroexp.el @@ -439,7 +439,8 @@ symbol itself." (or (memq symbol '(nil t)) (keywordp symbol) (if any-value - (or (memq symbol byte-compile-const-variables) + (or (and (boundp 'byte-compile-const-variables) + (memq symbol byte-compile-const-variables)) ;; FIXME: We should provide a less intrusive way to find out ;; if a variable is "constant". (and (boundp symbol) diff --git a/lisp/frame.el b/lisp/frame.el index 2a14302e9fb..67b6bb53d87 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -2469,7 +2469,7 @@ See also `toggle-frame-maximized'." ;; F5 then produces the correct effect, the variable doesn't need ;; to be in this list; otherwise, it does. (mapc (lambda (var) - (add-variable-watcher var (symbol-function 'set-buffer-redisplay))) + (add-variable-watcher var 'set-buffer-redisplay)) '(line-spacing overline-margin line-prefix diff --git a/lisp/international/mule.el b/lisp/international/mule.el index 6cfb7e6d457..b6996d4b322 100644 --- a/lisp/international/mule.el +++ b/lisp/international/mule.el @@ -290,7 +290,7 @@ attribute." elt)) props)) (setcdr (assq :plist attrs) props) - + (put name 'internal--charset-args (mapcar #'cdr attrs)) (apply 'define-charset-internal name (mapcar 'cdr attrs)))) @@ -920,6 +920,8 @@ non-ASCII files. This attribute is meaningful only when (cons :name (cons name (cons :docstring (cons (purecopy docstring) props))))) (setcdr (assq :plist common-attrs) props) + (put name 'internal--cs-args + (mapcar #'cdr (append common-attrs spec-attrs))) (apply 'define-coding-system-internal name (mapcar 'cdr (append common-attrs spec-attrs))))) diff --git a/lisp/loadup.el b/lisp/loadup.el index af42cd97111..e063ad8fc54 100644 --- a/lisp/loadup.el +++ b/lisp/loadup.el @@ -1,4 +1,4 @@ -;;; loadup.el --- load up standardly loaded Lisp files for Emacs +;;; loadup.el --- load up standardly loaded Lisp files for Emacs -*- lexical-binding:t -*- ;; Copyright (C) 1985-1986, 1992, 1994, 2001-2017 Free Software ;; Foundation, Inc. @@ -57,6 +57,17 @@ ;; Add subdirectories to the load-path for files that might get ;; autoloaded when bootstrapping. ;; This is because PATH_DUMPLOADSEARCH is just "../lisp". +(let ((dir (car load-path))) + (message "load path is %S" load-path) + (setq load-path (list (expand-file-name "." dir) + (expand-file-name "emacs-lisp" dir) + (expand-file-name "language" dir) + (expand-file-name "international" dir) + (expand-file-name "textmodes" dir) + (expand-file-name "vc" dir)))) + +(setq purify-flag nil) + (if (or (equal (member "bootstrap" command-line-args) '("bootstrap")) ;; FIXME this is irritatingly fragile. (and (stringp (nth 4 command-line-args)) @@ -64,22 +75,13 @@ (nth 4 command-line-args))) (member (nth 7 command-line-args) '("unidata-gen-file" "unidata-gen-charprop")) - (if (fboundp 'dump-emacs) + (if t; (fboundp 'dump-emacs) (string-match "src/bootstrap-emacs" (nth 0 command-line-args)) t)) - (let ((dir (car 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 "language" dir) - (expand-file-name "international" dir) - (expand-file-name "textmodes" dir) - (expand-file-name "vc" dir))))) + ;; 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)) (if (eq t purify-flag) ;; Hash consing saved around 11% of pure space in my tests. @@ -88,7 +90,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) +(if (and t; (fboundp 'dump-emacs) (or (equal (member "bootstrap" command-line-args) '("bootstrap")) (equal (member "dump" command-line-args) '("dump")))) (progn @@ -314,9 +316,12 @@ ;; Preload some constants and floating point functions. (load "emacs-lisp/float-sup") +(load "emacs-lisp/cl-macs") +(load "emacs-lisp/cl-lib") +(load "emacs-lisp/gv") + (load "vc/vc-hooks") (load "vc/ediff-hook") -(load "uniquify") (load "electric") (load "emacs-lisp/eldoc") (load "cus-start") ;Late to reduce customize-rogue (needs loaddefs.el anyway) @@ -350,14 +355,14 @@ lost after dumping"))) ;; 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) + t; (fboundp 'dump-emacs) (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) + t; (fboundp 'dump-emacs) (not (eq system-type 'ms-dos))) (let* ((base (concat "emacs-" emacs-version ".")) (exelen (if (eq system-type 'windows-nt) -4)) @@ -375,9 +380,9 @@ lost after dumping"))) (message "Finding pointers to doc strings...") -(if (and (fboundp 'dump-emacs) +(if (and t; (fboundp 'dump-emacs) (equal (last command-line-args) '("dump"))) - (Snarf-documentation "DOC") + (Snarf-documentation "DOC" 'clear) (condition-case nil (Snarf-documentation "DOC") (error nil))) @@ -445,7 +450,7 @@ lost after dumping"))) ;; Make sure we will attempt bidi reordering henceforth. (setq redisplay--inhibit-bidi nil) -(if (and (fboundp 'dump-emacs) +(if (and t; (fboundp 'dump-emacs) (member (car (last command-line-args)) '("dump" "bootstrap"))) (progn ;; Prevent build-time PATH getting stored in the binary. @@ -461,29 +466,325 @@ lost after dumping"))) ;; 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) - ;; 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))) + ;; (dump-emacs "emacs" "temacs") + ;; (message "%d pure bytes used" pure-bytes-used) + (let ((exe (if (memq system-type '(cygwin windows-nt ms-dos)) ".exe" ""))) + (copy-file (expand-file-name (concat "temacs" exe) invocation-directory) + (expand-file-name (concat "emacs" exe) invocation-directory) + t) + ;; 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))) + (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))) + (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)))) + (message "Dumping into dumped.elc...preparing...") + + ;; Dump the current state into a file so we can reload it! + (message "Dumping into dumped.elc...generating...") + (let ((faces '()) + (coding-systems '()) (coding-system-aliases '()) + (charsets '()) (charset-aliases '()) + (unified-charsets '()) + (abbrev-tables (make-hash-table :test 'eq)) + (abbrev-assign-cmds '()) + (abbrev-make-cmds '()) + (abbrev-counter 0) + (cmds '())) + (setcdr global-buffers-menu-map nil) ;; Get rid of buffer objects! + (push `(internal--set-standard-syntax-table + ,(standard-syntax-table)) + cmds) + (mapatoms + (lambda (s) + (when (fboundp s) + (if (subrp (symbol-function s)) + ;; subr objects aren't readable! + (unless (equal (symbol-name s) (subr-name (symbol-function s))) + (push `(fset ',s (symbol-function ',(intern (subr-name (symbol-function s))))) cmds)) + (push `(fset ',s ,(macroexp-quote (symbol-function s))) + cmds))) + (if (not (eq (indirect-variable s) s)) + (push `(defvaralias ',s ',(indirect-variable s)) + cmds)) + (when (and (default-boundp s) + (not (macroexp--const-symbol-p s 'any-value)) + ;; I think we don't need/want these! + (not (memq s '(terminal-frame obarray + initial-window-system window-system + ;; custom-delayed-init-variables + current-load-list + coding-system-list + internal--text-quoting-flag + exec-path + process-environment + initial-environment + exec-directory + data-directory + charset-map-path + source-directory + invocation-directory + load-file-name + doc-directory + load-path + user-full-name + user-login-name + user-real-login-name + system-name + command-line-args noninteractive + load-history + ;; Any let-bound variables during + ;; dump process will be useless. + faces coding-systems coding-system-aliases + charsets charset-aliases unified-charsets + abbrev-tables abbrev-counter + abbrev-make-cmds abbrev-assign-cmds + cmds))) + (eq (indirect-variable s) s)) + (let ((v (default-value s))) + (push `(set-default + ',s + ,(cond + ;; FIXME: (Correct) hack to avoid + ;; unprintable objects. + ((eq s 'undo-auto--undoably-changed-buffers) nil) + ;; FIXME: Incorrect hack to avoid + ;; unprintable objects. + ((eq s 'advertised-signature-table) + (make-hash-table :test 'eq :weakness 'key)) + ((subrp v) + `(symbol-function ',(intern (subr-name v)))) + ((and (markerp v) (null (marker-buffer v))) + '(make-marker)) + ((and (overlayp v) (null (overlay-buffer v))) + (let (propsets + (props (overlay-properties v))) + (while props + (let ((prop (car props)) + (val (cadr props))) + (push `(overlay-put ol ',prop ',val) propsets) + (setq props (cddr props)))) + `(let ((ol (make-overlay (point-min) (point-min)))) + ,@propsets + (delete-overlay ol) + ol))) + ;; abbrev-table-p isn't very robust + ((condition-case nil + (abbrev-table-p v) + (error nil)) + (cl-labels ((replace-abbrevs-for-dump + (table) + (or (abbrev-table-empty-p table) + (error "Non-empty abbrev tables not handled")) + (let ((newval (gethash table abbrev-tables))) + (if newval + `(aref scratch-abbrev-tables ,newval) + (let* ((props (symbol-plist (obarray-get table "")))) + (cond ((plist-get props :parents) + (setq props (copy-sequence props)) + (plist-put props + :parents + (mapcar (lambda (value) + (list '\, (replace-abbrevs-for-dump value))) + (plist-get props :parents))) + (setq props (list '\` props))) + ((eq (length props) 2) + ;; Only :abbrev-table-modiff, which gets added at creation anyway. + (setq props nil))) + (push `(aset scratch-abbrev-tables + ,abbrev-counter + ,(if props + `(make-abbrev-table ,props) + '(make-abbrev-table))) + abbrev-make-cmds) + (puthash table abbrev-counter abbrev-tables) + (prog1 + `(aref scratch-abbrev-tables ,abbrev-counter) + (setq abbrev-counter (1+ abbrev-counter)))))))) + (push `(set-default ',s + ,(replace-abbrevs-for-dump v)) + abbrev-assign-cmds)) + ;; Placeholder to be used before we know + ;; we've defined make-abbrev-table. + 0) + (v (macroexp-quote v)))) + cmds) + ;; Local variables: make-variable-buffer-local, + ;; make-local-variable, and make-variable-frame-local. + ;; + ;; We may need better introspection facilities to get + ;; this right. For now, assume only the first kind is + ;; in use during loadup. + (if (local-variable-if-set-p s) + (push `(make-variable-buffer-local ',s) cmds)) + (if (special-variable-p s) + ;; A dummy initializer is needed for defvar to mark + ;; the variable as special. + (push `(defvar ,s 0) cmds)))) + (when (symbol-plist s) + (push `(setplist ',s ',(symbol-plist s)) cmds)) + (when (get s 'face-defface-spec) + (push s faces)) + (if (get s 'internal--cs-args) + (push s coding-systems)) + (when (and (coding-system-p s) + (not (eq s (car (coding-system-aliases s))))) + (push (cons s (car (coding-system-aliases s))) + coding-system-aliases)) + (if (get s 'internal--charset-args) + (progn + (push s charsets) + (if (member :unify-map + (nth 15 (get s 'internal--charset-args))) + (push s unified-charsets))) + (when (and (charsetp s) + (not (eq s (get-charset-property s :name)))) + (push (cons s (get-charset-property s :name)) + charset-aliases)))) + obarray) + + ;; Convert preloaded file names in load-history to relative + (let ((simple-file-name + ;; Look for simple.el or simple.elc and use their directory + ;; as the place where all Lisp files live. + (locate-file "simple" load-path (get-load-suffixes))) + lisp-dir lisp-dir-length) + ;; Don't abort if simple.el cannot be found, but print a warning. + ;; Although in most usage we are going to cryptically abort a moment + ;; later anyway, due to missing required bidi data files (eg bug#13430). + (if (null simple-file-name) + (let ((standard-output 'external-debugging-output) + (lispdir (expand-file-name "../lisp" data-directory))) + (princ "Warning: Could not find simple.el or simple.elc") + (terpri) + (when (getenv "EMACSLOADPATH") + (princ "The EMACSLOADPATH environment variable is set, \ +please check its value") + (terpri)) + (unless (file-readable-p lispdir) + (princ (format "Lisp directory %s not readable?" lispdir)) + (terpri))) + (setq lisp-dir (file-truename (file-name-directory simple-file-name))) + (setq lisp-dir-length (length lisp-dir)) + (let ((fake-load-history + (mapcar (lambda (elt) + (if (and (stringp (car elt)) + (file-name-absolute-p (car elt)) + (> (length (car elt)) lisp-dir-length) + (string-equal lisp-dir + (substring (car elt) 0 lisp-dir-length)) + ) + (cons (substring (car elt) lisp-dir-length) + (cdr elt)) + elt)) + load-history))) + (push `(setq load-history ',fake-load-history) + cmds)))) + + (message "Dumping into dumped.elc...printing...") + (with-current-buffer (generate-new-buffer "dumped.elc") + (setq default-directory invocation-directory) + (insert ";ELC\^W\^@\^@\^@\n;;; Compiled\n;;; in Emacs version " + emacs-version "\n") + (let ((print-circle t) + (print-gensym t) + (print-quoted t) + (print-level nil) + (print-length nil) + (print-escape-newlines t) + (print-symbols-as-references t) + (standard-output (current-buffer))) + (print '(setq purify-flag nil)) + (print '(get-buffer-create "*Messages*")) + (print `(progn . ,cmds)) + ;; Now that make-abbrev-table is defined, use it. + (print `(let ((scratch-abbrev-tables (make-vector ,abbrev-counter 0))) + ,@(nreverse abbrev-make-cmds) + ,@abbrev-assign-cmds)) + (print `(let ((css ',charsets)) + (dotimes (i 3) + (dolist (cs (prog1 css (setq css nil))) + ;; (message "Defining charset %S..." cs) + (condition-case nil + (progn + (apply #'define-charset-internal + cs (get cs 'internal--charset-args)) + ;; (message "Defining charset %S...done" cs) + ) + (error + ;; (message "Defining charset %S...postponed" + ;; cs) + (push cs css))))))) + (print `(dolist (cs ',charset-aliases) + (define-charset-alias (car cs) (cdr cs)))) + (print `(let ((css ',coding-systems)) + (dotimes (i 3) + (dolist (cs (prog1 css (setq css nil))) + ;; (message "Defining coding-system %S..." cs) + (condition-case nil + (progn + (apply #'define-coding-system-internal + cs (get cs 'internal--cs-args)) + ;; (message "Defining coding-system %S...done" cs) + ) + (error + ;; (message "Defining coding-system %S...postponed" + ;; cs) + (push cs css))))))) + (print `(mapcar 'unify-charset ',unified-charsets)) + (print `(dolist (f ',faces) + (face-spec-set f (get f 'face-defface-spec) + 'face-defface-spec))) + ;; This creates some rather large data structures that are + ;; more quickly reconstructed than read from the dumped + ;; Lisp state. + (print '(load "international/characters" nil t)) + ;; This sets advice on a subr, so cannot be preloaded. + (print '(load "uniquify" nil t)) + ;; Lisp functions have their DOC file offsets stored + ;; already, but for a subr it's hidden away from Lisp. + (print '(condition-case nil + (Snarf-documentation "DOC") + (file-missing + (message "Couldn't load DOC file")))) + (print `(dolist (cs ',coding-system-aliases) + (define-coding-system-alias (car cs) (cdr cs)))) + (print `(progn + ;; (message "Done preloading!") + ;; (message "custom-delayed-init-variables = %S" + ;; custom-delayed-init-variables) + ;; (message "Running top-level = %S" top-level) + (setq debug-on-error t) + (use-global-map global-map) + (eval top-level) + ;; (message "top-level done!?") + ))) + (goto-char (point-min)) + (while (re-search-forward " (\\(defvar\\|setplist\\|fset\\) " nil t) + (goto-char (match-beginning 0)) + (delete-char 1) (insert "\n")) + (message "Dumping into dumped.elc...saving...") + (let ((coding-system-for-write 'emacs-internal)) + (write-region (point-min) (point-max) (buffer-name))) + (message "Dumping into dumped.elc...done") + )) + (kill-emacs))) +(load "uniquify") + ;; For machines with CANNOT_DUMP defined in config.h, ;; this file must be loaded each time Emacs is run. ;; So run the startup code now. First, remove `-l loadup' from args. diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index b3f452ca5b9..11d741c0b9e 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -810,15 +810,21 @@ non-nil result supercedes the xrefs produced by (push (elisp--xref-find-definitions sym) lst)) (nreverse lst)))) +;; This used to use apply-partially, but that turned "obarray" into a +;; reference to the actual obarray, not the symbol, and that's +;; incompatible with the dumper code. (defvar elisp--xref-identifier-completion-table - (apply-partially #'completion-table-with-predicate - obarray - (lambda (sym) - (or (boundp sym) - (fboundp sym) - (featurep sym) - (facep sym))) - 'strict)) + (lambda (string pred2 action) + (completion-table-with-predicate obarray + (lambda (sym) + (or (boundp sym) + (fboundp sym) + (featurep sym) + (facep sym))) + 'strict + string + pred2 + action))) (cl-defmethod xref-backend-identifier-completion-table ((_backend (eql elisp))) elisp--xref-identifier-completion-table) diff --git a/src/Makefile.in b/src/Makefile.in index 57969d5fc58..ca250885033 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -529,10 +529,10 @@ ${lispintdir}/characters.elc: ${charscript:.el=.elc} emacs$(EXEEXT): temacs$(EXEEXT) \ lisp.mk $(etc)/DOC $(lisp) \ $(lispsource)/international/charprop.el ${charsets} + LC_ALL=C $(RUN_TEMACS) --no-loadup -batch $(BUILD_DETAILS) -l loadup dump ifeq ($(CANNOT_DUMP),yes) ln -f temacs$(EXEEXT) $@ else - LC_ALL=C $(RUN_TEMACS) -batch $(BUILD_DETAILS) -l loadup dump ifneq ($(PAXCTL_dumped),) $(PAXCTL_dumped) $@ endif @@ -733,10 +733,10 @@ $(lispsource)/loaddefs.el: $(VCSWITNESS) | bootstrap-emacs$(EXEEXT) ## files from loadup.el in source form. bootstrap-emacs$(EXEEXT): temacs$(EXEEXT) $(MAKE) -C ../lisp update-subdirs + $(RUN_TEMACS) --no-loadup --batch $(BUILD_DETAILS) --load loadup bootstrap ifeq ($(CANNOT_DUMP),yes) ln -f temacs$(EXEEXT) $@ else - $(RUN_TEMACS) --batch $(BUILD_DETAILS) --load loadup bootstrap ifneq ($(PAXCTL_dumped),) $(PAXCTL_dumped) emacs$(EXEEXT) endif diff --git a/src/alloc.c b/src/alloc.c index 2cee6462564..73d33564843 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -221,7 +221,7 @@ alloc_unexec_post (void) /* Default value of gc_cons_threshold (see below). */ -#define GC_DEFAULT_THRESHOLD (100000 * word_size) +#define GC_DEFAULT_THRESHOLD (3000000 * word_size) /* Global variables. */ struct emacs_globals globals; diff --git a/src/charset.c b/src/charset.c index 6ce2f902c81..15a50b29d0b 100644 --- a/src/charset.c +++ b/src/charset.c @@ -501,7 +501,6 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, large (larger than MAX_ALLOCA). */ head = record_xmalloc (sizeof *head); entries = head; - memset (entries, 0, sizeof (struct charset_map_entries)); n_entries = 0; int ch = -1; @@ -535,7 +534,6 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile, { entries->next = record_xmalloc (sizeof *entries->next); entries = entries->next; - memset (entries, 0, sizeof (struct charset_map_entries)); n_entries = 0; } int idx = n_entries; diff --git a/src/coding.c b/src/coding.c index 50ad206be69..0205358e312 100644 --- a/src/coding.c +++ b/src/coding.c @@ -10337,8 +10337,9 @@ usage: (define-coding-system-internal ...) */) CHECK_NUMBER_CAR (reg_usage); CHECK_NUMBER_CDR (reg_usage); - request = Fcopy_sequence (args[coding_arg_iso2022_request]); - for (tail = request; CONSP (tail); tail = XCDR (tail)) + request = Qnil; + for (tail = args[coding_arg_iso2022_request]; + CONSP (tail); tail = XCDR (tail)) { int id; Lisp_Object tmp1; @@ -10350,7 +10351,8 @@ usage: (define-coding-system-internal ...) */) CHECK_NATNUM_CDR (val); if (XINT (XCDR (val)) >= 4) error ("Invalid graphic register number: %"pI"d", XINT (XCDR (val))); - XSETCAR (val, make_number (id)); + request = Fcons (Fcons (make_number (id), XCDR (val)), + request); } flags = args[coding_arg_iso2022_flags]; diff --git a/src/doc.c b/src/doc.c index 345e18b9186..ae09a3179a8 100644 --- a/src/doc.c +++ b/src/doc.c @@ -305,7 +305,7 @@ static bool reread_doc_file (Lisp_Object file) { if (NILP (file)) - Fsnarf_documentation (Vdoc_file_name); + Fsnarf_documentation (Vdoc_file_name, Qnil); else Fload (file, Qt, Qt, Qt, Qnil); @@ -466,7 +466,7 @@ aren't strings. */) /* Scanning the DOC files and placing docstring offsets into functions. */ static void -store_function_docstring (Lisp_Object obj, EMACS_INT offset) +store_function_docstring (Lisp_Object obj, EMACS_INT offset, bool clear) { /* Don't use indirect_function here, or defaliases will apply their docstrings to the base functions (Bug#2603). */ @@ -486,10 +486,16 @@ store_function_docstring (Lisp_Object obj, EMACS_INT offset) || (EQ (tem, Qclosure) && (fun = XCDR (fun), 1))) { tem = Fcdr (Fcdr (fun)); - if (CONSP (tem) && INTEGERP (XCAR (tem))) - /* FIXME: This modifies typically pure hash-cons'd data, so its - correctness is quite delicate. */ - XSETCAR (tem, make_number (offset)); + if (CONSP (tem)) + { + if (clear && STRINGP (XCAR (tem))) + /* Discard any string we may have loaded. + Also, 0 is a shorter placeholder in the dumped + environment file than the actual offset. */ + XSETCAR (tem, make_number (0)); + else if (INTEGERP (XCAR (tem))) + XSETCAR (tem, make_number (offset)); + } } } @@ -503,7 +509,7 @@ store_function_docstring (Lisp_Object obj, EMACS_INT offset) /* This bytecode object must have a slot for the docstring, since we've found a docstring for it. */ if (PVSIZE (fun) > COMPILED_DOC_STRING) - ASET (fun, COMPILED_DOC_STRING, make_number (offset)); + ASET (fun, COMPILED_DOC_STRING, make_number (clear ? 0 : offset)); else { AUTO_STRING (format, "No docstring slot for %s"); @@ -517,15 +523,22 @@ store_function_docstring (Lisp_Object obj, EMACS_INT offset) DEFUN ("Snarf-documentation", Fsnarf_documentation, Ssnarf_documentation, - 1, 1, 0, + 1, 2, 0, doc: /* Used during Emacs initialization to scan the `etc/DOC...' file. This searches the `etc/DOC...' file for doc strings and records them in function and variable definitions. -The function takes one argument, FILENAME, a string; +The function takes one required argument, FILENAME, a string; it specifies the file name (without a directory) of the DOC file. That file is found in `../etc' now; later, when the dumped Emacs is run, -the same file name is found in the `doc-directory'. */) - (Lisp_Object filename) +the same file name is found in the `doc-directory'. + +Optional second argument CLEAR, if set, causes the removal of +variable-documentation properties and the replacement of function doc +strings with dummy DOC file offsets when the documentation is found in +the DOC file, to minimize storage use in preparation for dumping the +Lisp environment state, with the expectation that Snarf-documentation +will be called again after loading the dumped environment. */) + (Lisp_Object filename, Lisp_Object clear) { int fd; char buf[1024 + 1]; @@ -644,16 +657,39 @@ the same file name is found in the `doc-directory'. */) (doc starts with a `*'). */ if (!NILP (Fboundp (sym)) || !NILP (Fmemq (sym, delayed_init))) - Fput (sym, Qvariable_documentation, - make_number ((pos + end + 1 - buf) - * (end[1] == '*' ? -1 : 1))); + { + if (NILP (clear)) + Fput (sym, Qvariable_documentation, + make_number ((pos + end + 1 - buf) + * (end[1] == '*' ? -1 : 1))); + else + /* Remove the variable-documentation property, + if present, even if it's nil (which makes + Fget unhelpful). */ + { + Lisp_Object plist = Fsymbol_plist (sym); + Lisp_Object prev, prop; + if (EQ (Fcar (plist), Qvariable_documentation)) + set_symbol_plist (sym, Fcdr (Fcdr (plist))); + else + for (prev = Fcdr (plist), prop = Fcdr (prev); + !NILP (prop); + prev = Fcdr (prop), prop = Fcdr (prev)) + if (EQ (Fcar (prop), Qvariable_documentation)) + { + Fsetcdr (prev, Fcdr (Fcdr (prop))); + break; + } + } + } } /* Attach a docstring to a function? */ else if (p[1] == 'F') { if (!NILP (Ffboundp (sym))) - store_function_docstring (sym, pos + end + 1 - buf); + store_function_docstring (sym, pos + end + 1 - buf, + !NILP (clear)); } else if (p[1] == 'S') ; /* Just a source file name boundary marker. Ignore it. */ diff --git a/src/emacs.c b/src/emacs.c index 0fec7167588..4e812b19a0f 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -1610,20 +1610,17 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem keys_of_keymap (); keys_of_window (); } - else - { - /* Initialization that must be done even if the global variable - initialized is non zero. */ + /* Initialization that must be done even if the global variable + initialized is non zero. */ #ifdef HAVE_NTGUI - globals_of_w32font (); - globals_of_w32fns (); - globals_of_w32menu (); + globals_of_w32font (); + globals_of_w32fns (); + globals_of_w32menu (); #endif /* HAVE_NTGUI */ #if defined WINDOWSNT || defined HAVE_NTGUI - globals_of_w32select (); + globals_of_w32select (); #endif - } init_charset (); @@ -1673,9 +1670,26 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem #endif Vtop_level = list2 (Qload, build_unibyte_string (file)); } - /* Unless next switch is -nl, load "loadup.el" first thing. */ if (! no_loadup) - Vtop_level = list2 (Qload, build_string ("loadup.el")); + /* Unless next switch is -nl, load "dumped.elc" first thing. + If it fails, we won't be able to run. */ + { + /* We could let the user see that we're (still) loading the + Lisp environment, but the "done" message will hide the + "For information about..." message that we want displayed + when we're finished. */ + Lisp_Object load = list4 (Qload, + build_string ("../src/dumped.elc"), + Qnil, Qt); + /* XXX We need a way for Lisp to cause Emacs to exit, with + an error message to stderr after restoring tty modes. */ + /* (condition-case nil bodyform (file-missing (kill-emacs 42))) */ + Vtop_level = list4 (Qcondition_case, + Qnil, + load, + list2 (Qfile_missing, + list2 (Qkill_emacs, make_number (42)))); + } } /* Set up for profiling. This is known to work on FreeBSD, @@ -2506,6 +2520,7 @@ syms_of_emacs (void) DEFSYM (Qrisky_local_variable, "risky-local-variable"); DEFSYM (Qkill_emacs, "kill-emacs"); DEFSYM (Qkill_emacs_hook, "kill-emacs-hook"); + DEFSYM (Qcondition_case, "condition-case"); #ifndef CANNOT_DUMP defsubr (&Sdump_emacs); diff --git a/src/print.c b/src/print.c index 12edf015892..aca808f2750 100644 --- a/src/print.c +++ b/src/print.c @@ -1131,16 +1131,19 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) print_object (obj, printcharfun, escapeflag); } -#define PRINT_CIRCLE_CANDIDATE_P(obj) \ - (STRINGP (obj) || CONSP (obj) \ - || (VECTORLIKEP (obj) \ - && (VECTORP (obj) || COMPILEDP (obj) \ - || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj) \ - || HASH_TABLE_P (obj) || FONTP (obj) \ - || RECORDP (obj))) \ - || (! NILP (Vprint_gensym) \ - && SYMBOLP (obj) \ - && !SYMBOL_INTERNED_P (obj))) +#define PRINT_CIRCLE_CANDIDATE_P(obj) \ + (STRINGP (obj) || CONSP (obj) \ + || (VECTORLIKEP (obj) \ + && (VECTORP (obj) || COMPILEDP (obj) \ + || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj) \ + || HASH_TABLE_P (obj) || FONTP (obj) \ + || RECORDP (obj))) \ + || (SYMBOLP (obj) \ + && !SYMBOL_INTERNED_P (obj) \ + && ! NILP (Vprint_gensym)) \ + || (SYMBOLP (obj) \ + && SYMBOL_INTERNED_P (obj) \ + && ! NILP (Vprint_symbols_as_references))) /* Construct Vprint_number_table according to the structure of OBJ. OBJ itself and all its elements will be added to Vprint_number_table @@ -1181,8 +1184,9 @@ print_preprocess (Lisp_Object obj) if (!HASH_TABLE_P (Vprint_number_table)) Vprint_number_table = CALLN (Fmake_hash_table, QCtest, Qeq); - /* In case print-circle is nil and print-gensym is t, - add OBJ to Vprint_number_table only when OBJ is a symbol. */ + /* In case print-circle is nil and print-gensym or + print-symbols-as-references is t, add OBJ to Vprint_number_table only + when OBJ is a symbol. */ if (! NILP (Vprint_circle) || SYMBOLP (obj)) { Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil); @@ -2013,7 +2017,20 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) || EQ (XCAR (obj), Qcomma_at) || EQ (XCAR (obj), Qcomma_dot))) { - print_object (XCAR (obj), printcharfun, false); + /* If print-symbols-as-references is enabled, symbols may + print with "#N=" or "#N#" form. When we print a cons + cell with parens and separated elements, that's fine, but + for comma symbols we depend on the reader to generate the + cons cell from the special syntax. The Lisp reader will + treat "#1=,#2=foo" as setting reference 1 to ",foo", not + to ",", so we can't use print_object to print out the + comma symbols without breaking the ability to read the + result back properly. */ + printchar (',', printcharfun); + if (EQ (XCAR (obj), Qcomma_at)) + printchar ('@', printcharfun); + else if (EQ (XCAR (obj), Qcomma_dot)) + printchar ('.', printcharfun); new_backquote_output--; print_object (XCAR (XCDR (obj)), printcharfun, escapeflag); new_backquote_output++; @@ -2422,6 +2439,15 @@ the value is different from what is guessed in the current charset priorities. */); Vprint_charset_text_property = Qdefault; + DEFVAR_LISP ("print-symbols-as-references", Vprint_symbols_as_references, + doc: /* Non-nil means print interned symbols using #N= and #N# syntax. +If nil, symbols are printed normally. + +Setting this true makes the output harder for a human to read, but may +parse more efficiently as input to the Lisp reader if some symbols appear +in the output many times. */); + Vprint_symbols_as_references = Qnil; + /* prin1_to_string_buffer initialized in init_buffer_once in buffer.c */ staticpro (&Vprin1_to_string_buffer); diff --git a/src/syntax.c b/src/syntax.c index dcaca22f0e2..209acc2aed0 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -1029,6 +1029,18 @@ It is a copy of the TABLE, which defaults to the standard syntax table. */) return copy; } +DEFUN ("internal--set-standard-syntax-table", + Finternal_set_standard_syntax_table, + Sinternal_set_standard_syntax_table, 1, 1, 0, + doc: /* Replace the standard syntax table, used for new buffers. */) + (Lisp_Object table) +{ + check_syntax_table (table); + Vstandard_syntax_table = table; + Fset_char_table_parent (table, Qnil); + return table; +} + DEFUN ("set-syntax-table", Fset_syntax_table, Sset_syntax_table, 1, 1, 0, doc: /* Select a new syntax table for the current buffer. One argument, a syntax table. */) @@ -3769,6 +3781,7 @@ In both cases, LIMIT bounds the search. */); defsubr (&Sstring_to_syntax); defsubr (&Smodify_syntax_entry); defsubr (&Sinternal_describe_syntax_value); + defsubr (&Sinternal_set_standard_syntax_table); defsubr (&Sforward_word); diff --git a/src/unexw32.c b/src/unexw32.c index 904447c3ec9..65f24ca27c1 100644 --- a/src/unexw32.c +++ b/src/unexw32.c @@ -48,7 +48,7 @@ extern char *my_begbss_static; #include "w32heap.h" /* Basically, our "initialized" flag. */ -BOOL using_dynamic_heap = FALSE; +BOOL using_dynamic_heap = TRUE; void get_section_info (file_data *p_file); void copy_executable_and_dump_data (file_data *, file_data *); diff --git a/src/xfaces.c b/src/xfaces.c index 86bb9b0b496..b9ced74cd84 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -3212,6 +3212,13 @@ FRAME 0 means change the face on all frames, and change the default cons = XCAR (Vparam_value_alist); XSETCAR (cons, param); XSETCDR (cons, value); + + /* Fmodify_frame_parameters may update faces and use the + cache. */ + struct frame *f = XFRAME (frame); + if (FRAME_FACE_CACHE (f) == NULL) + FRAME_FACE_CACHE (f) = make_face_cache (f); + Fmodify_frame_parameters (frame, Vparam_value_alist); } } |