mirror of
https://github.com/masscollaborationlabs/emacs.git
synced 2025-07-05 11:49:37 +00:00
Fix a cacheing bug, which led to inordinately slow c-beginning-of-defun.
* lisp/progmodes/cc-defs.el (c-self-bind-state-cache): New macro. * lisp/progmodes/cc-engine.el (c-ssb-lit-begin): Always call c-parse-state rather than just using the cache variable c-state-cache. (c-syntactic-skip-backward): Invoke c-self-bind-state-cache to isolate calls to c-parse-state from other uses of the parse state cache. * lisp/progmodes/cc-cmds.el (c-beginning-of-defun, c-end-of-defun): Invoke c-self-bind-state-cache around the processing, replacing flawed bindings of c-state-cache.
This commit is contained in:
parent
0ce37eac45
commit
5cc6919308
3 changed files with 225 additions and 201 deletions
|
@ -1594,69 +1594,70 @@ defun."
|
||||||
(c-region-is-active-p)
|
(c-region-is-active-p)
|
||||||
(push-mark))
|
(push-mark))
|
||||||
|
|
||||||
(c-save-buffer-state
|
(c-self-bind-state-cache ; We must not share with other users of c-state-cache.
|
||||||
(beginning-of-defun-function end-of-defun-function
|
(c-save-buffer-state
|
||||||
(start (point))
|
(beginning-of-defun-function
|
||||||
(paren-state (copy-tree (c-parse-state))) ; This must not share list
|
end-of-defun-function
|
||||||
; structure with other users of c-state-cache.
|
(start (point))
|
||||||
(orig-point-min (point-min)) (orig-point-max (point-max))
|
(paren-state (c-parse-state))
|
||||||
lim ; Position of { which has been widened to.
|
(orig-point-min (point-min)) (orig-point-max (point-max))
|
||||||
where pos case-fold-search)
|
lim ; Position of { which has been widened to.
|
||||||
|
where pos case-fold-search)
|
||||||
|
|
||||||
(save-restriction
|
(save-restriction
|
||||||
(if (eq c-defun-tactic 'go-outward)
|
(if (eq c-defun-tactic 'go-outward)
|
||||||
(setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace.
|
(setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace.
|
||||||
paren-state orig-point-min orig-point-max)))
|
paren-state orig-point-min orig-point-max)))
|
||||||
|
|
||||||
;; Move back out of any macro/comment/string we happen to be in.
|
;; Move back out of any macro/comment/string we happen to be in.
|
||||||
(c-beginning-of-macro)
|
(c-beginning-of-macro)
|
||||||
(setq pos (c-literal-limits))
|
(setq pos (c-literal-limits))
|
||||||
(if pos (goto-char (car pos)))
|
(if pos (goto-char (car pos)))
|
||||||
|
|
||||||
(setq where (c-where-wrt-brace-construct))
|
(setq where (c-where-wrt-brace-construct))
|
||||||
|
|
||||||
(if (< arg 0)
|
(if (< arg 0)
|
||||||
;; Move forward to the closing brace of a function.
|
;; Move forward to the closing brace of a function.
|
||||||
(progn
|
(progn
|
||||||
(if (memq where '(at-function-end outwith-function))
|
(if (memq where '(at-function-end outwith-function))
|
||||||
(setq arg (1+ arg)))
|
(setq arg (1+ arg)))
|
||||||
(if (< arg 0)
|
(if (< arg 0)
|
||||||
(c-while-widening-to-decl-block
|
(c-while-widening-to-decl-block
|
||||||
(< (setq arg (- (c-forward-to-nth-EOF-} (- arg) where))) 0)))
|
(< (setq arg (- (c-forward-to-nth-EOF-} (- arg) where))) 0)))
|
||||||
;; Move forward to the next opening brace....
|
;; Move forward to the next opening brace....
|
||||||
(when (and (= arg 0)
|
(when (and (= arg 0)
|
||||||
(progn
|
(progn
|
||||||
(c-while-widening-to-decl-block
|
(c-while-widening-to-decl-block
|
||||||
(not (c-syntactic-re-search-forward "{" nil 'eob)))
|
(not (c-syntactic-re-search-forward "{" nil 'eob)))
|
||||||
(eq (char-before) ?{)))
|
(eq (char-before) ?{)))
|
||||||
(backward-char)
|
(backward-char)
|
||||||
;; ... and backward to the function header.
|
;; ... and backward to the function header.
|
||||||
(c-beginning-of-decl-1)
|
(c-beginning-of-decl-1)
|
||||||
t))
|
t))
|
||||||
|
|
||||||
;; Move backward to the opening brace of a function, making successively
|
;; Move backward to the opening brace of a function, making successively
|
||||||
;; larger portions of the buffer visible as necessary.
|
;; larger portions of the buffer visible as necessary.
|
||||||
(when (> arg 0)
|
(when (> arg 0)
|
||||||
(c-while-widening-to-decl-block
|
(c-while-widening-to-decl-block
|
||||||
(> (setq arg (c-backward-to-nth-BOF-{ arg where)) 0)))
|
(> (setq arg (c-backward-to-nth-BOF-{ arg where)) 0)))
|
||||||
|
|
||||||
(when (eq arg 0)
|
(when (eq arg 0)
|
||||||
;; Go backward to this function's header.
|
;; Go backward to this function's header.
|
||||||
(c-beginning-of-decl-1)
|
(c-beginning-of-decl-1)
|
||||||
|
|
||||||
(setq pos (point))
|
(setq pos (point))
|
||||||
;; We're now there, modulo comments and whitespace.
|
;; We're now there, modulo comments and whitespace.
|
||||||
;; Try to be line oriented; position point at the closest
|
;; Try to be line oriented; position point at the closest
|
||||||
;; preceding boi that isn't inside a comment, but if we hit
|
;; preceding boi that isn't inside a comment, but if we hit
|
||||||
;; the previous declaration then we use the current point
|
;; the previous declaration then we use the current point
|
||||||
;; instead.
|
;; instead.
|
||||||
(while (and (/= (point) (c-point 'boi))
|
(while (and (/= (point) (c-point 'boi))
|
||||||
(c-backward-single-comment)))
|
(c-backward-single-comment)))
|
||||||
(if (/= (point) (c-point 'boi))
|
(if (/= (point) (c-point 'boi))
|
||||||
(goto-char pos)))
|
(goto-char pos)))
|
||||||
|
|
||||||
(c-keep-region-active)
|
(c-keep-region-active)
|
||||||
(= arg 0)))))
|
(= arg 0))))))
|
||||||
|
|
||||||
(defun c-forward-to-nth-EOF-} (n where)
|
(defun c-forward-to-nth-EOF-} (n where)
|
||||||
;; Skip to the closing brace of the Nth function after point. If
|
;; Skip to the closing brace of the Nth function after point. If
|
||||||
|
@ -1718,66 +1719,68 @@ the open-parenthesis that starts a defun; see `beginning-of-defun'."
|
||||||
(c-region-is-active-p)
|
(c-region-is-active-p)
|
||||||
(push-mark))
|
(push-mark))
|
||||||
|
|
||||||
(c-save-buffer-state
|
(c-self-bind-state-cache ; c-state-cache's list structure must not be shared
|
||||||
(beginning-of-defun-function end-of-defun-function
|
; with other users.
|
||||||
(start (point))
|
(c-save-buffer-state
|
||||||
(paren-state (copy-tree (c-parse-state))) ; This must not share list
|
(beginning-of-defun-function
|
||||||
; structure with other users of c-state-cache.
|
end-of-defun-function
|
||||||
(orig-point-min (point-min)) (orig-point-max (point-max))
|
(start (point))
|
||||||
lim
|
(paren-state (c-parse-state))
|
||||||
where pos case-fold-search)
|
(orig-point-min (point-min)) (orig-point-max (point-max))
|
||||||
|
lim
|
||||||
|
where pos case-fold-search)
|
||||||
|
|
||||||
(save-restriction
|
(save-restriction
|
||||||
(if (eq c-defun-tactic 'go-outward)
|
(if (eq c-defun-tactic 'go-outward)
|
||||||
(setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace
|
(setq lim (c-widen-to-enclosing-decl-scope ; e.g. class, namespace
|
||||||
paren-state orig-point-min orig-point-max)))
|
paren-state orig-point-min orig-point-max)))
|
||||||
|
|
||||||
;; Move back out of any macro/comment/string we happen to be in.
|
;; Move back out of any macro/comment/string we happen to be in.
|
||||||
(c-beginning-of-macro)
|
(c-beginning-of-macro)
|
||||||
(setq pos (c-literal-limits))
|
(setq pos (c-literal-limits))
|
||||||
(if pos (goto-char (car pos)))
|
(if pos (goto-char (car pos)))
|
||||||
|
|
||||||
(setq where (c-where-wrt-brace-construct))
|
(setq where (c-where-wrt-brace-construct))
|
||||||
|
|
||||||
(if (< arg 0)
|
(if (< arg 0)
|
||||||
;; Move backwards to the } of a function
|
;; Move backwards to the } of a function
|
||||||
(progn
|
(progn
|
||||||
(if (memq where '(at-header outwith-function))
|
(if (memq where '(at-header outwith-function))
|
||||||
(setq arg (1+ arg)))
|
(setq arg (1+ arg)))
|
||||||
(if (< arg 0)
|
(if (< arg 0)
|
||||||
(c-while-widening-to-decl-block
|
(c-while-widening-to-decl-block
|
||||||
(< (setq arg (- (c-backward-to-nth-BOF-{ (- arg) where))) 0)))
|
(< (setq arg (- (c-backward-to-nth-BOF-{ (- arg) where))) 0)))
|
||||||
(if (= arg 0)
|
(if (= arg 0)
|
||||||
(c-while-widening-to-decl-block
|
(c-while-widening-to-decl-block
|
||||||
(progn (c-syntactic-skip-backward "^}")
|
(progn (c-syntactic-skip-backward "^}")
|
||||||
(not (eq (char-before) ?}))))))
|
(not (eq (char-before) ?}))))))
|
||||||
|
|
||||||
;; Move forward to the } of a function
|
;; Move forward to the } of a function
|
||||||
(if (> arg 0)
|
(if (> arg 0)
|
||||||
(c-while-widening-to-decl-block
|
(c-while-widening-to-decl-block
|
||||||
(> (setq arg (c-forward-to-nth-EOF-} arg where)) 0))))
|
(> (setq arg (c-forward-to-nth-EOF-} arg where)) 0))))
|
||||||
|
|
||||||
;; Do we need to move forward from the brace to the semicolon?
|
;; Do we need to move forward from the brace to the semicolon?
|
||||||
(when (eq arg 0)
|
(when (eq arg 0)
|
||||||
(if (c-in-function-trailer-p) ; after "}" of struct/enum, etc.
|
(if (c-in-function-trailer-p) ; after "}" of struct/enum, etc.
|
||||||
(c-syntactic-re-search-forward ";"))
|
(c-syntactic-re-search-forward ";"))
|
||||||
|
|
||||||
(setq pos (point))
|
(setq pos (point))
|
||||||
;; We're there now, modulo comments and whitespace.
|
;; We're there now, modulo comments and whitespace.
|
||||||
;; Try to be line oriented; position point after the next
|
;; Try to be line oriented; position point after the next
|
||||||
;; newline that isn't inside a comment, but if we hit the
|
;; newline that isn't inside a comment, but if we hit the
|
||||||
;; next declaration then we use the current point instead.
|
;; next declaration then we use the current point instead.
|
||||||
(while (and (not (bolp))
|
(while (and (not (bolp))
|
||||||
(not (looking-at "\\s *$"))
|
(not (looking-at "\\s *$"))
|
||||||
(c-forward-single-comment)))
|
(c-forward-single-comment)))
|
||||||
(cond ((bolp))
|
(cond ((bolp))
|
||||||
((looking-at "\\s *$")
|
((looking-at "\\s *$")
|
||||||
(forward-line 1))
|
(forward-line 1))
|
||||||
(t
|
(t
|
||||||
(goto-char pos))))
|
(goto-char pos))))
|
||||||
|
|
||||||
(c-keep-region-active)
|
(c-keep-region-active)
|
||||||
(= arg 0))))
|
(= arg 0)))))
|
||||||
|
|
||||||
(defun c-defun-name ()
|
(defun c-defun-name ()
|
||||||
"Return the name of the current defun, or NIL if there isn't one.
|
"Return the name of the current defun, or NIL if there isn't one.
|
||||||
|
|
|
@ -1258,7 +1258,8 @@ been put there by c-put-char-property. POINT remains unchanged."
|
||||||
(def-edebug-spec c-clear-char-property t)
|
(def-edebug-spec c-clear-char-property t)
|
||||||
(def-edebug-spec c-clear-char-properties t)
|
(def-edebug-spec c-clear-char-properties t)
|
||||||
(def-edebug-spec c-put-overlay t)
|
(def-edebug-spec c-put-overlay t)
|
||||||
(def-edebug-spec c-delete-overlay t) ;))
|
(def-edebug-spec c-delete-overlay t)
|
||||||
|
(def-edebug-spec c-self-bind-state-cache t);))
|
||||||
|
|
||||||
|
|
||||||
;;; Functions.
|
;;; Functions.
|
||||||
|
@ -1397,6 +1398,26 @@ been put there by c-put-char-property. POINT remains unchanged."
|
||||||
(save-restriction
|
(save-restriction
|
||||||
(widen)
|
(widen)
|
||||||
(c-set-cpp-delimiters ,beg ,end)))))
|
(c-set-cpp-delimiters ,beg ,end)))))
|
||||||
|
|
||||||
|
(defmacro c-self-bind-state-cache (&rest forms)
|
||||||
|
;; Bind the state cache to itself and execute the FORMS. It is assumed that no
|
||||||
|
;; buffer changes will happen in FORMS, and no hidden buffer changes which could
|
||||||
|
;; affect the parsing will be made by FORMS.
|
||||||
|
`(let ((c-state-cache (copy-tree c-state-cache))
|
||||||
|
(c-state-cache-good-pos c-state-cache-good-pos)
|
||||||
|
;(c-state-nonlit-pos-cache (copy-tree c-state-nonlit-pos-cache))
|
||||||
|
;(c-state-nonlit-pos-cache-limit c-state-nonlit-pos-cache-limit)
|
||||||
|
;(c-state-semi-nonlit-pos-cache (copy-treec c-state-semi-nonlit-pos-cache))
|
||||||
|
;(c-state-semi-nonlit-pos-cache-limit c-state-semi-nonlit-pos-cache)
|
||||||
|
(c-state-brace-pair-desert (copy-tree c-state-brace-pair-desert))
|
||||||
|
(c-state-point-min c-state-point-min)
|
||||||
|
(c-state-point-min-lit-type c-state-point-min-lit-type)
|
||||||
|
(c-state-point-min-lit-start c-state-point-min-lit-start)
|
||||||
|
(c-state-min-scan-pos c-state-min-scan-pos)
|
||||||
|
(c-state-old-cpp-beg c-state-old-cpp-beg)
|
||||||
|
(c-state-old-cpp-end c-state-old-cpp-end))
|
||||||
|
,@forms))
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; The following macros are to be used only in `c-parse-state' and its
|
;; The following macros are to be used only in `c-parse-state' and its
|
||||||
|
|
|
@ -4259,8 +4259,7 @@ comment at the start of cc-engine.el for more info."
|
||||||
(setq safe-pos-list (cdr safe-pos-list)))
|
(setq safe-pos-list (cdr safe-pos-list)))
|
||||||
(unless (setq safe-pos (car-safe safe-pos-list))
|
(unless (setq safe-pos (car-safe safe-pos-list))
|
||||||
(setq safe-pos (max (or (c-safe-position
|
(setq safe-pos (max (or (c-safe-position
|
||||||
(point) (or c-state-cache
|
(point) (c-parse-state))
|
||||||
(c-parse-state)))
|
|
||||||
0)
|
0)
|
||||||
(point-min))
|
(point-min))
|
||||||
safe-pos-list (list safe-pos)))
|
safe-pos-list (list safe-pos)))
|
||||||
|
@ -4308,107 +4307,108 @@ Non-nil is returned if the point moved, nil otherwise.
|
||||||
Note that this function might do hidden buffer changes. See the
|
Note that this function might do hidden buffer changes. See the
|
||||||
comment at the start of cc-engine.el for more info."
|
comment at the start of cc-engine.el for more info."
|
||||||
|
|
||||||
(let ((start (point))
|
(c-self-bind-state-cache
|
||||||
state-2
|
(let ((start (point))
|
||||||
;; A list of syntactically relevant positions in descending
|
state-2
|
||||||
;; order. It's used to avoid scanning repeatedly over
|
;; A list of syntactically relevant positions in descending
|
||||||
;; potentially large regions with `parse-partial-sexp' to verify
|
;; order. It's used to avoid scanning repeatedly over
|
||||||
;; each position. Used in `c-ssb-lit-begin'
|
;; potentially large regions with `parse-partial-sexp' to verify
|
||||||
safe-pos-list
|
;; each position. Used in `c-ssb-lit-begin'
|
||||||
;; The result from `c-beginning-of-macro' at the start position or the
|
safe-pos-list
|
||||||
;; start position itself if it isn't within a macro. Evaluated on
|
;; The result from `c-beginning-of-macro' at the start position or the
|
||||||
;; demand.
|
;; start position itself if it isn't within a macro. Evaluated on
|
||||||
start-macro-beg
|
;; demand.
|
||||||
;; The earliest position after the current one with the same paren
|
start-macro-beg
|
||||||
;; level. Used only when `paren-level' is set.
|
;; The earliest position after the current one with the same paren
|
||||||
lit-beg
|
;; level. Used only when `paren-level' is set.
|
||||||
(paren-level-pos (point)))
|
lit-beg
|
||||||
|
(paren-level-pos (point)))
|
||||||
|
|
||||||
(while
|
(while
|
||||||
(progn
|
(progn
|
||||||
;; The next loop "tries" to find the end point each time round,
|
;; The next loop "tries" to find the end point each time round,
|
||||||
;; loops when it hasn't succeeded.
|
;; loops when it hasn't succeeded.
|
||||||
(while
|
(while
|
||||||
(and
|
(and
|
||||||
(let ((pos (point)))
|
(let ((pos (point)))
|
||||||
(while (and
|
(while (and
|
||||||
(< (skip-chars-backward skip-chars limit) 0)
|
(< (skip-chars-backward skip-chars limit) 0)
|
||||||
;; Don't stop inside a literal.
|
;; Don't stop inside a literal.
|
||||||
(when (setq lit-beg (c-ssb-lit-begin))
|
(when (setq lit-beg (c-ssb-lit-begin))
|
||||||
(goto-char lit-beg)
|
(goto-char lit-beg)
|
||||||
t)))
|
t)))
|
||||||
(< (point) pos))
|
(< (point) pos))
|
||||||
|
|
||||||
(let ((pos (point)) state-2 pps-end-pos)
|
(let ((pos (point)) state-2 pps-end-pos)
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
((and paren-level
|
((and paren-level
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(setq state-2 (parse-partial-sexp
|
(setq state-2 (parse-partial-sexp
|
||||||
pos paren-level-pos -1)
|
pos paren-level-pos -1)
|
||||||
pps-end-pos (point))
|
pps-end-pos (point))
|
||||||
(/= (car state-2) 0)))
|
(/= (car state-2) 0)))
|
||||||
;; Not at the right level.
|
;; Not at the right level.
|
||||||
|
|
||||||
(if (and (< (car state-2) 0)
|
(if (and (< (car state-2) 0)
|
||||||
;; We stop above if we go out of a paren.
|
;; We stop above if we go out of a paren.
|
||||||
;; Now check whether it precedes or is
|
;; Now check whether it precedes or is
|
||||||
;; nested in the starting sexp.
|
;; nested in the starting sexp.
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(setq state-2
|
(setq state-2
|
||||||
(parse-partial-sexp
|
(parse-partial-sexp
|
||||||
pps-end-pos paren-level-pos
|
pps-end-pos paren-level-pos
|
||||||
nil nil state-2))
|
nil nil state-2))
|
||||||
(< (car state-2) 0)))
|
(< (car state-2) 0)))
|
||||||
|
|
||||||
;; We've stopped short of the starting position
|
;; We've stopped short of the starting position
|
||||||
;; so the hit was inside a nested list. Go up
|
;; so the hit was inside a nested list. Go up
|
||||||
;; until we are at the right level.
|
;; until we are at the right level.
|
||||||
(condition-case nil
|
(condition-case nil
|
||||||
(progn
|
(progn
|
||||||
(goto-char (scan-lists pos -1
|
(goto-char (scan-lists pos -1
|
||||||
(- (car state-2))))
|
(- (car state-2))))
|
||||||
(setq paren-level-pos (point))
|
(setq paren-level-pos (point))
|
||||||
(if (and limit (>= limit paren-level-pos))
|
(if (and limit (>= limit paren-level-pos))
|
||||||
(progn
|
(progn
|
||||||
(goto-char limit)
|
(goto-char limit)
|
||||||
nil)
|
nil)
|
||||||
t))
|
t))
|
||||||
(error
|
(error
|
||||||
(goto-char (or limit (point-min)))
|
(goto-char (or limit (point-min)))
|
||||||
nil))
|
nil))
|
||||||
|
|
||||||
;; The hit was outside the list at the start
|
;; The hit was outside the list at the start
|
||||||
;; position. Go to the start of the list and exit.
|
;; position. Go to the start of the list and exit.
|
||||||
(goto-char (1+ (elt state-2 1)))
|
(goto-char (1+ (elt state-2 1)))
|
||||||
nil))
|
nil))
|
||||||
|
|
||||||
((c-beginning-of-macro limit)
|
((c-beginning-of-macro limit)
|
||||||
;; Inside a macro.
|
;; Inside a macro.
|
||||||
(if (< (point)
|
(if (< (point)
|
||||||
(or start-macro-beg
|
(or start-macro-beg
|
||||||
(setq start-macro-beg
|
(setq start-macro-beg
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(goto-char start)
|
(goto-char start)
|
||||||
(c-beginning-of-macro limit)
|
(c-beginning-of-macro limit)
|
||||||
(point)))))
|
(point)))))
|
||||||
t
|
t
|
||||||
|
|
||||||
;; It's inside the same macro we started in so it's
|
;; It's inside the same macro we started in so it's
|
||||||
;; a relevant match.
|
;; a relevant match.
|
||||||
(goto-char pos)
|
(goto-char pos)
|
||||||
nil))))))
|
nil))))))
|
||||||
|
|
||||||
(> (point)
|
(> (point)
|
||||||
(progn
|
(progn
|
||||||
;; Skip syntactic ws afterwards so that we don't stop at the
|
;; Skip syntactic ws afterwards so that we don't stop at the
|
||||||
;; end of a comment if `skip-chars' is something like "^/".
|
;; end of a comment if `skip-chars' is something like "^/".
|
||||||
(c-backward-syntactic-ws)
|
(c-backward-syntactic-ws)
|
||||||
(point)))))
|
(point)))))
|
||||||
|
|
||||||
;; We might want to extend this with more useful return values in
|
;; We might want to extend this with more useful return values in
|
||||||
;; the future.
|
;; the future.
|
||||||
(/= (point) start)))
|
(/= (point) start))))
|
||||||
|
|
||||||
;; The following is an alternative implementation of
|
;; The following is an alternative implementation of
|
||||||
;; `c-syntactic-skip-backward' that uses backward movement to keep
|
;; `c-syntactic-skip-backward' that uses backward movement to keep
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue