mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2025-01-31 20:02:42 +00:00
Depessimize the handling of very large macros.
This commit is contained in:
parent
3e441275a8
commit
56d093a9c8
@ -1,3 +1,25 @@
|
||||
2012-03-02 Alan Mackenzie <acm@muc.de>
|
||||
|
||||
Depessimize the handling of very large macros.
|
||||
|
||||
* progmodes/cc-engine.el (c-macro-cache, c-macro-cache-start-pos):
|
||||
(c-macro-cache-syntactic): New variables to implement a one
|
||||
element macro cache.
|
||||
(c-invalidate-macro-cache): New function.
|
||||
(c-beginning-of-macro, c-end-of-macro, c-syntactic-end-of-macro):
|
||||
Adapt to use the new cache.
|
||||
(c-state-safe-place): Use better the cache of safe positions.
|
||||
(c-state-semi-nonlit-pos-cache)
|
||||
(c-state-semi-nonlit-pos-cache-limit):
|
||||
New variables for...
|
||||
(c-state-semi-safe-place): New function. Here, in a macro is "safe".
|
||||
(c-invalidate-state-cache-1): New stuff for c-state-semi-safe-place.
|
||||
(c-in-literal, c-literal-limits, c-determine-limit-get-base): Use
|
||||
c-state-semi-safe-place.
|
||||
|
||||
* progmodes/cc-langs.el (c-get-state-before-change-functions): Add
|
||||
c-invalidate-macro-cache to the C, C++, Obj entries.
|
||||
|
||||
2012-03-02 Michael Albinus <michael.albinus@gmx.de>
|
||||
|
||||
* jka-compr.el (jka-compr-call-process): Apply
|
||||
|
@ -219,6 +219,38 @@
|
||||
(point))))
|
||||
c-macro-start))
|
||||
|
||||
;; One element macro cache to cope with continual movement within very large
|
||||
;; CPP macros.
|
||||
(defvar c-macro-cache nil)
|
||||
(make-variable-buffer-local 'c-macro-cache)
|
||||
;; Nil or cons of the bounds of the most recent CPP form probed by
|
||||
;; `c-beginning-of-macro', `c-end-of-macro' or `c-syntactic-end-of-macro'.
|
||||
;; The cdr will be nil if we know only the start of the CPP form.
|
||||
(defvar c-macro-cache-start-pos nil)
|
||||
(make-variable-buffer-local 'c-macro-cache-start-pos)
|
||||
;; The starting position from where we determined `c-macro-cache'.
|
||||
(defvar c-macro-cache-syntactic nil)
|
||||
(make-variable-buffer-local 'c-macro-cache-syntactic)
|
||||
;; non-nil iff `c-macro-cache' has both elements set AND the cdr is at a
|
||||
;; syntactic end of macro, not merely an apparent one.
|
||||
|
||||
(defun c-invalidate-macro-cache (beg end)
|
||||
;; Called from a before-change function. If the change region is before or
|
||||
;; in the macro characterised by `c-macro-cache' etc., nullify it
|
||||
;; appropriately. BEG and END are the standard before-change-functions
|
||||
;; parameters. END isn't used.
|
||||
(cond
|
||||
((null c-macro-cache))
|
||||
((< beg (car c-macro-cache))
|
||||
(setq c-macro-cache nil
|
||||
c-macro-cache-start-pos nil
|
||||
c-macro-cache-syntactic nil))
|
||||
((and (cdr c-macro-cache)
|
||||
(< beg (cdr c-macro-cache)))
|
||||
(setcdr c-macro-cache nil)
|
||||
(setq c-macro-cache-start-pos beg
|
||||
c-macro-cache-syntactic nil))))
|
||||
|
||||
(defun c-beginning-of-macro (&optional lim)
|
||||
"Go to the beginning of a preprocessor directive.
|
||||
Leave point at the beginning of the directive and return t if in one,
|
||||
@ -226,19 +258,36 @@ otherwise return nil and leave point unchanged.
|
||||
|
||||
Note that this function might do hidden buffer changes. See the
|
||||
comment at the start of cc-engine.el for more info."
|
||||
(when c-opt-cpp-prefix
|
||||
(let ((here (point)))
|
||||
(save-restriction
|
||||
(if lim (narrow-to-region lim (point-max)))
|
||||
(beginning-of-line)
|
||||
(while (eq (char-before (1- (point))) ?\\)
|
||||
(forward-line -1))
|
||||
(back-to-indentation)
|
||||
(if (and (<= (point) here)
|
||||
(looking-at c-opt-cpp-start))
|
||||
t
|
||||
(goto-char here)
|
||||
nil)))))
|
||||
(let ((here (point)))
|
||||
(when c-opt-cpp-prefix
|
||||
(if (and (car c-macro-cache)
|
||||
(>= (point) (car c-macro-cache))
|
||||
(or (and (cdr c-macro-cache)
|
||||
(<= (point) (cdr c-macro-cache)))
|
||||
(<= (point) c-macro-cache-start-pos)))
|
||||
(unless (< (car c-macro-cache) (or lim (point-min)))
|
||||
(progn (goto-char (max (or lim (point-min)) (car c-macro-cache)))
|
||||
(setq c-macro-cache-start-pos
|
||||
(max c-macro-cache-start-pos here))
|
||||
t))
|
||||
(setq c-macro-cache nil
|
||||
c-macro-cache-start-pos nil
|
||||
c-macro-cache-syntactic nil)
|
||||
|
||||
(save-restriction
|
||||
(if lim (narrow-to-region lim (point-max)))
|
||||
(beginning-of-line)
|
||||
(while (eq (char-before (1- (point))) ?\\)
|
||||
(forward-line -1))
|
||||
(back-to-indentation)
|
||||
(if (and (<= (point) here)
|
||||
(looking-at c-opt-cpp-start))
|
||||
(progn
|
||||
(setq c-macro-cache (cons (point) nil)
|
||||
c-macro-cache-start-pos here)
|
||||
t)
|
||||
(goto-char here)
|
||||
nil))))))
|
||||
|
||||
(defun c-end-of-macro ()
|
||||
"Go to the end of a preprocessor directive.
|
||||
@ -248,12 +297,24 @@ done that the point is inside a cpp directive to begin with.
|
||||
|
||||
Note that this function might do hidden buffer changes. See the
|
||||
comment at the start of cc-engine.el for more info."
|
||||
(while (progn
|
||||
(end-of-line)
|
||||
(when (and (eq (char-before) ?\\)
|
||||
(not (eobp)))
|
||||
(forward-char)
|
||||
t))))
|
||||
(if (and (cdr c-macro-cache)
|
||||
(<= (point) (cdr c-macro-cache))
|
||||
(>= (point) (car c-macro-cache)))
|
||||
(goto-char (cdr c-macro-cache))
|
||||
(unless (and (car c-macro-cache)
|
||||
(<= (point) c-macro-cache-start-pos)
|
||||
(>= (point) (car c-macro-cache)))
|
||||
(setq c-macro-cache nil
|
||||
c-macro-cache-start-pos nil
|
||||
c-macro-cache-syntactic nil))
|
||||
(while (progn
|
||||
(end-of-line)
|
||||
(when (and (eq (char-before) ?\\)
|
||||
(not (eobp)))
|
||||
(forward-char)
|
||||
t)))
|
||||
(when (car c-macro-cache)
|
||||
(setcdr c-macro-cache (point)))))
|
||||
|
||||
(defun c-syntactic-end-of-macro ()
|
||||
;; Go to the end of a CPP directive, or a "safe" pos just before.
|
||||
@ -268,12 +329,15 @@ comment at the start of cc-engine.el for more info."
|
||||
;; at the start of cc-engine.el for more info.
|
||||
(let* ((here (point))
|
||||
(there (progn (c-end-of-macro) (point)))
|
||||
(s (parse-partial-sexp here there)))
|
||||
(while (and (or (nth 3 s) ; in a string
|
||||
(nth 4 s)) ; in a comment (maybe at end of line comment)
|
||||
(> there here)) ; No infinite loops, please.
|
||||
(setq there (1- (nth 8 s)))
|
||||
(setq s (parse-partial-sexp here there)))
|
||||
s)
|
||||
(unless c-macro-cache-syntactic
|
||||
(setq s (parse-partial-sexp here there))
|
||||
(while (and (or (nth 3 s) ; in a string
|
||||
(nth 4 s)) ; in a comment (maybe at end of line comment)
|
||||
(> there here)) ; No infinite loops, please.
|
||||
(setq there (1- (nth 8 s)))
|
||||
(setq s (parse-partial-sexp here there)))
|
||||
(setq c-macro-cache-syntactic (car c-macro-cache)))
|
||||
(point)))
|
||||
|
||||
(defun c-forward-over-cpp-define-id ()
|
||||
@ -2089,6 +2153,18 @@ comment at the start of cc-engine.el for more info."
|
||||
;; reduced by buffer changes, and increased by invocations of
|
||||
;; `c-state-literal-at'.
|
||||
|
||||
(defvar c-state-semi-nonlit-pos-cache nil)
|
||||
(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache)
|
||||
;; A list of buffer positions which are known not to be in a literal. This is
|
||||
;; ordered with higher positions at the front of the list. Only those which
|
||||
;; are less than `c-state-semi-nonlit-pos-cache-limit' are valid.
|
||||
|
||||
(defvar c-state-semi-nonlit-pos-cache-limit 1)
|
||||
(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache-limit)
|
||||
;; An upper limit on valid entries in `c-state-semi-nonlit-pos-cache'. This is
|
||||
;; reduced by buffer changes, and increased by invocations of
|
||||
;; `c-state-literal-at'. FIMXE!!!
|
||||
|
||||
(defsubst c-state-pp-to-literal (from to)
|
||||
;; Do a parse-partial-sexp from FROM to TO, returning either
|
||||
;; (STATE TYPE (BEG . END)) if TO is in a literal; or
|
||||
@ -2129,48 +2205,93 @@ comment at the start of cc-engine.el for more info."
|
||||
(widen)
|
||||
(save-excursion
|
||||
(let ((c c-state-nonlit-pos-cache)
|
||||
pos npos lit macro-beg macro-end)
|
||||
pos npos high-pos lit macro-beg macro-end)
|
||||
;; Trim the cache to take account of buffer changes.
|
||||
(while (and c (> (car c) c-state-nonlit-pos-cache-limit))
|
||||
(setq c (cdr c)))
|
||||
(setq c-state-nonlit-pos-cache c)
|
||||
|
||||
(while (and c (> (car c) here))
|
||||
(setq high-pos (car c))
|
||||
(setq c (cdr c)))
|
||||
(setq pos (or (car c) (point-min)))
|
||||
|
||||
(while
|
||||
;; Add an element to `c-state-nonlit-pos-cache' each iteration.
|
||||
(and
|
||||
(<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
|
||||
(unless high-pos
|
||||
(while
|
||||
;; Add an element to `c-state-nonlit-pos-cache' each iteration.
|
||||
(and
|
||||
(<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
|
||||
|
||||
;; Test for being in a literal.
|
||||
(progn
|
||||
(setq lit (car (cddr (c-state-pp-to-literal pos npos))))
|
||||
(or (null lit)
|
||||
(prog1 (<= (cdr lit) here)
|
||||
(setq npos (cdr lit)))))
|
||||
;; Test for being in a literal. If so, go to after it.
|
||||
(progn
|
||||
(setq lit (car (cddr (c-state-pp-to-literal pos npos))))
|
||||
(or (null lit)
|
||||
(prog1 (<= (cdr lit) here)
|
||||
(setq npos (cdr lit)))))
|
||||
|
||||
;; Test for being in a macro.
|
||||
(progn
|
||||
(goto-char npos)
|
||||
(setq macro-beg
|
||||
(and (c-beginning-of-macro) (/= (point) npos) (point)))
|
||||
(when macro-beg
|
||||
(c-syntactic-end-of-macro)
|
||||
(or (eobp) (forward-char))
|
||||
(setq macro-end (point)))
|
||||
(or (null macro-beg)
|
||||
(prog1 (<= macro-end here)
|
||||
(setq npos macro-end)))))
|
||||
;; Test for being in a macro. If so, go to after it.
|
||||
(progn
|
||||
(goto-char npos)
|
||||
(setq macro-beg
|
||||
(and (c-beginning-of-macro) (/= (point) npos) (point)))
|
||||
(when macro-beg
|
||||
(c-syntactic-end-of-macro)
|
||||
(or (eobp) (forward-char))
|
||||
(setq macro-end (point)))
|
||||
(or (null macro-beg)
|
||||
(prog1 (<= macro-end here)
|
||||
(setq npos macro-end)))))
|
||||
|
||||
(setq pos npos)
|
||||
(setq c-state-nonlit-pos-cache (cons pos c-state-nonlit-pos-cache)))
|
||||
(setq pos npos)
|
||||
(setq c-state-nonlit-pos-cache (cons pos c-state-nonlit-pos-cache)))
|
||||
;; Add one extra element above HERE so as to to avoid the previous
|
||||
;; expensive calculation when the next call is close to the current
|
||||
;; one. This is especially useful when inside a large macro.
|
||||
(setq c-state-nonlit-pos-cache (cons npos c-state-nonlit-pos-cache)))
|
||||
|
||||
(if (> pos c-state-nonlit-pos-cache-limit)
|
||||
(setq c-state-nonlit-pos-cache-limit pos))
|
||||
pos))))
|
||||
|
||||
(defun c-state-semi-safe-place (here)
|
||||
;; Return a buffer position before HERE which is "safe", i.e. outside any
|
||||
;; string or comment. It may be in a macro.
|
||||
(save-restriction
|
||||
(widen)
|
||||
(save-excursion
|
||||
(let ((c c-state-semi-nonlit-pos-cache)
|
||||
pos npos high-pos lit macro-beg macro-end)
|
||||
;; Trim the cache to take account of buffer changes.
|
||||
(while (and c (> (car c) c-state-semi-nonlit-pos-cache-limit))
|
||||
(setq c (cdr c)))
|
||||
(setq c-state-semi-nonlit-pos-cache c)
|
||||
|
||||
(while (and c (> (car c) here))
|
||||
(setq high-pos (car c))
|
||||
(setq c (cdr c)))
|
||||
(setq pos (or (car c) (point-min)))
|
||||
|
||||
(unless high-pos
|
||||
(while
|
||||
;; Add an element to `c-state-semi-nonlit-pos-cache' each iteration.
|
||||
(and
|
||||
(<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
|
||||
|
||||
;; Test for being in a literal. If so, go to after it.
|
||||
(progn
|
||||
(setq lit (car (cddr (c-state-pp-to-literal pos npos))))
|
||||
(or (null lit)
|
||||
(prog1 (<= (cdr lit) here)
|
||||
(setq npos (cdr lit))))))
|
||||
|
||||
(setq pos npos)
|
||||
(setq c-state-semi-nonlit-pos-cache
|
||||
(cons pos c-state-semi-nonlit-pos-cache))))
|
||||
|
||||
(if (> pos c-state-semi-nonlit-pos-cache-limit)
|
||||
(setq c-state-semi-nonlit-pos-cache-limit pos))
|
||||
pos))))
|
||||
|
||||
(defun c-state-literal-at (here)
|
||||
;; If position HERE is inside a literal, return (START . END), the
|
||||
;; boundaries of the literal (which may be outside the accessible bit of the
|
||||
@ -2985,9 +3106,11 @@ comment at the start of cc-engine.el for more info."
|
||||
;;
|
||||
;; This function is called from c-after-change.
|
||||
|
||||
;; The cache of non-literals:
|
||||
;; The caches of non-literals:
|
||||
(if (< here c-state-nonlit-pos-cache-limit)
|
||||
(setq c-state-nonlit-pos-cache-limit here))
|
||||
(if (< here c-state-semi-nonlit-pos-cache-limit)
|
||||
(setq c-state-semi-nonlit-pos-cache-limit here))
|
||||
|
||||
;; `c-state-cache':
|
||||
;; Case 1: if `here' is in a literal containing point-min, everything
|
||||
@ -4230,7 +4353,7 @@ Note that this function might do hidden buffer changes. See the
|
||||
comment at the start of cc-engine.el for more info."
|
||||
(save-restriction
|
||||
(widen)
|
||||
(let* ((safe-place (c-state-safe-place (point)))
|
||||
(let* ((safe-place (c-state-semi-safe-place (point)))
|
||||
(lit (c-state-pp-to-literal safe-place (point))))
|
||||
(or (cadr lit)
|
||||
(and detect-cpp
|
||||
@ -4254,7 +4377,7 @@ comment at the start of cc-engine.el for more info."
|
||||
|
||||
(save-excursion
|
||||
(let* ((pos (point))
|
||||
(lim (or lim (c-state-safe-place pos)))
|
||||
(lim (or lim (c-state-semi-safe-place pos)))
|
||||
(pp-to-lit (save-restriction
|
||||
(widen)
|
||||
(c-state-pp-to-literal lim pos)))
|
||||
@ -4372,7 +4495,7 @@ comment at the start of cc-engine.el for more info."
|
||||
;; Get a "safe place" approximately TRY-SIZE characters before START.
|
||||
;; This doesn't preserve point.
|
||||
(let* ((pos (max (- start try-size) (point-min)))
|
||||
(base (c-state-safe-place pos))
|
||||
(base (c-state-semi-safe-place pos))
|
||||
(s (parse-partial-sexp base pos)))
|
||||
(if (or (nth 4 s) (nth 3 s)) ; comment or string
|
||||
(nth 8 s)
|
||||
|
@ -459,8 +459,10 @@ so that all identifiers are recognized as words.")
|
||||
;; For documentation see the following c-lang-defvar of the same name.
|
||||
;; The value here may be a list of functions or a single function.
|
||||
t nil
|
||||
c++ '(c-extend-region-for-CPP c-before-change-check-<>-operators)
|
||||
(c objc) 'c-extend-region-for-CPP
|
||||
c++ '(c-extend-region-for-CPP
|
||||
c-before-change-check-<>-operators
|
||||
c-invalidate-macro-cache)
|
||||
(c objc) '(c-extend-region-for-CPP c-invalidate-macro-cache)
|
||||
;; java 'c-before-change-check-<>-operators
|
||||
awk 'c-awk-record-region-clear-NL)
|
||||
(c-lang-defvar c-get-state-before-change-functions
|
||||
|
Loading…
Reference in New Issue
Block a user