aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2012-03-02 22:16:21 +0000
committerAlan Mackenzie2012-03-02 22:16:21 +0000
commit56d093a9c8cc3628b028c695c11815f6bb190d3f (patch)
treec895058cf037d7836fd9ab5f68d2c85bb47f6a22
parent3e441275a89ba751d227b514981ccb413034b3bb (diff)
downloademacs-56d093a9c8cc3628b028c695c11815f6bb190d3f.tar.gz
emacs-56d093a9c8cc3628b028c695c11815f6bb190d3f.zip
Depessimize the handling of very large macros.
-rw-r--r--lisp/ChangeLog22
-rw-r--r--lisp/progmodes/cc-engine.el233
-rw-r--r--lisp/progmodes/cc-langs.el6
3 files changed, 204 insertions, 57 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 7e229f8643d..dd4650017d6 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,25 @@
12012-03-02 Alan Mackenzie <acm@muc.de>
2
3 Depessimize the handling of very large macros.
4
5 * progmodes/cc-engine.el (c-macro-cache, c-macro-cache-start-pos):
6 (c-macro-cache-syntactic): New variables to implement a one
7 element macro cache.
8 (c-invalidate-macro-cache): New function.
9 (c-beginning-of-macro, c-end-of-macro, c-syntactic-end-of-macro):
10 Adapt to use the new cache.
11 (c-state-safe-place): Use better the cache of safe positions.
12 (c-state-semi-nonlit-pos-cache)
13 (c-state-semi-nonlit-pos-cache-limit):
14 New variables for...
15 (c-state-semi-safe-place): New function. Here, in a macro is "safe".
16 (c-invalidate-state-cache-1): New stuff for c-state-semi-safe-place.
17 (c-in-literal, c-literal-limits, c-determine-limit-get-base): Use
18 c-state-semi-safe-place.
19
20 * progmodes/cc-langs.el (c-get-state-before-change-functions): Add
21 c-invalidate-macro-cache to the C, C++, Obj entries.
22
12012-03-02 Michael Albinus <michael.albinus@gmx.de> 232012-03-02 Michael Albinus <michael.albinus@gmx.de>
2 24
3 * jka-compr.el (jka-compr-call-process): Apply 25 * jka-compr.el (jka-compr-call-process): Apply
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 95b43e763d5..3b33ac894f2 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -219,6 +219,38 @@
219 (point)))) 219 (point))))
220 c-macro-start)) 220 c-macro-start))
221 221
222;; One element macro cache to cope with continual movement within very large
223;; CPP macros.
224(defvar c-macro-cache nil)
225(make-variable-buffer-local 'c-macro-cache)
226;; Nil or cons of the bounds of the most recent CPP form probed by
227;; `c-beginning-of-macro', `c-end-of-macro' or `c-syntactic-end-of-macro'.
228;; The cdr will be nil if we know only the start of the CPP form.
229(defvar c-macro-cache-start-pos nil)
230(make-variable-buffer-local 'c-macro-cache-start-pos)
231;; The starting position from where we determined `c-macro-cache'.
232(defvar c-macro-cache-syntactic nil)
233(make-variable-buffer-local 'c-macro-cache-syntactic)
234;; non-nil iff `c-macro-cache' has both elements set AND the cdr is at a
235;; syntactic end of macro, not merely an apparent one.
236
237(defun c-invalidate-macro-cache (beg end)
238 ;; Called from a before-change function. If the change region is before or
239 ;; in the macro characterised by `c-macro-cache' etc., nullify it
240 ;; appropriately. BEG and END are the standard before-change-functions
241 ;; parameters. END isn't used.
242 (cond
243 ((null c-macro-cache))
244 ((< beg (car c-macro-cache))
245 (setq c-macro-cache nil
246 c-macro-cache-start-pos nil
247 c-macro-cache-syntactic nil))
248 ((and (cdr c-macro-cache)
249 (< beg (cdr c-macro-cache)))
250 (setcdr c-macro-cache nil)
251 (setq c-macro-cache-start-pos beg
252 c-macro-cache-syntactic nil))))
253
222(defun c-beginning-of-macro (&optional lim) 254(defun c-beginning-of-macro (&optional lim)
223 "Go to the beginning of a preprocessor directive. 255 "Go to the beginning of a preprocessor directive.
224Leave point at the beginning of the directive and return t if in one, 256Leave point at the beginning of the directive and return t if in one,
@@ -226,19 +258,36 @@ otherwise return nil and leave point unchanged.
226 258
227Note that this function might do hidden buffer changes. See the 259Note that this function might do hidden buffer changes. See the
228comment at the start of cc-engine.el for more info." 260comment at the start of cc-engine.el for more info."
229 (when c-opt-cpp-prefix 261 (let ((here (point)))
230 (let ((here (point))) 262 (when c-opt-cpp-prefix
231 (save-restriction 263 (if (and (car c-macro-cache)
232 (if lim (narrow-to-region lim (point-max))) 264 (>= (point) (car c-macro-cache))
233 (beginning-of-line) 265 (or (and (cdr c-macro-cache)
234 (while (eq (char-before (1- (point))) ?\\) 266 (<= (point) (cdr c-macro-cache)))
235 (forward-line -1)) 267 (<= (point) c-macro-cache-start-pos)))
236 (back-to-indentation) 268 (unless (< (car c-macro-cache) (or lim (point-min)))
237 (if (and (<= (point) here) 269 (progn (goto-char (max (or lim (point-min)) (car c-macro-cache)))
238 (looking-at c-opt-cpp-start)) 270 (setq c-macro-cache-start-pos
239 t 271 (max c-macro-cache-start-pos here))
240 (goto-char here) 272 t))
241 nil))))) 273 (setq c-macro-cache nil
274 c-macro-cache-start-pos nil
275 c-macro-cache-syntactic nil)
276
277 (save-restriction
278 (if lim (narrow-to-region lim (point-max)))
279 (beginning-of-line)
280 (while (eq (char-before (1- (point))) ?\\)
281 (forward-line -1))
282 (back-to-indentation)
283 (if (and (<= (point) here)
284 (looking-at c-opt-cpp-start))
285 (progn
286 (setq c-macro-cache (cons (point) nil)
287 c-macro-cache-start-pos here)
288 t)
289 (goto-char here)
290 nil))))))
242 291
243(defun c-end-of-macro () 292(defun c-end-of-macro ()
244 "Go to the end of a preprocessor directive. 293 "Go to the end of a preprocessor directive.
@@ -248,12 +297,24 @@ done that the point is inside a cpp directive to begin with.
248 297
249Note that this function might do hidden buffer changes. See the 298Note that this function might do hidden buffer changes. See the
250comment at the start of cc-engine.el for more info." 299comment at the start of cc-engine.el for more info."
251 (while (progn 300 (if (and (cdr c-macro-cache)
252 (end-of-line) 301 (<= (point) (cdr c-macro-cache))
253 (when (and (eq (char-before) ?\\) 302 (>= (point) (car c-macro-cache)))
254 (not (eobp))) 303 (goto-char (cdr c-macro-cache))
255 (forward-char) 304 (unless (and (car c-macro-cache)
256 t)))) 305 (<= (point) c-macro-cache-start-pos)
306 (>= (point) (car c-macro-cache)))
307 (setq c-macro-cache nil
308 c-macro-cache-start-pos nil
309 c-macro-cache-syntactic nil))
310 (while (progn
311 (end-of-line)
312 (when (and (eq (char-before) ?\\)
313 (not (eobp)))
314 (forward-char)
315 t)))
316 (when (car c-macro-cache)
317 (setcdr c-macro-cache (point)))))
257 318
258(defun c-syntactic-end-of-macro () 319(defun c-syntactic-end-of-macro ()
259 ;; Go to the end of a CPP directive, or a "safe" pos just before. 320 ;; 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."
268 ;; at the start of cc-engine.el for more info. 329 ;; at the start of cc-engine.el for more info.
269 (let* ((here (point)) 330 (let* ((here (point))
270 (there (progn (c-end-of-macro) (point))) 331 (there (progn (c-end-of-macro) (point)))
271 (s (parse-partial-sexp here there))) 332 s)
272 (while (and (or (nth 3 s) ; in a string 333 (unless c-macro-cache-syntactic
273 (nth 4 s)) ; in a comment (maybe at end of line comment) 334 (setq s (parse-partial-sexp here there))
274 (> there here)) ; No infinite loops, please. 335 (while (and (or (nth 3 s) ; in a string
275 (setq there (1- (nth 8 s))) 336 (nth 4 s)) ; in a comment (maybe at end of line comment)
276 (setq s (parse-partial-sexp here there))) 337 (> there here)) ; No infinite loops, please.
338 (setq there (1- (nth 8 s)))
339 (setq s (parse-partial-sexp here there)))
340 (setq c-macro-cache-syntactic (car c-macro-cache)))
277 (point))) 341 (point)))
278 342
279(defun c-forward-over-cpp-define-id () 343(defun c-forward-over-cpp-define-id ()
@@ -2089,6 +2153,18 @@ comment at the start of cc-engine.el for more info."
2089;; reduced by buffer changes, and increased by invocations of 2153;; reduced by buffer changes, and increased by invocations of
2090;; `c-state-literal-at'. 2154;; `c-state-literal-at'.
2091 2155
2156(defvar c-state-semi-nonlit-pos-cache nil)
2157(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache)
2158;; A list of buffer positions which are known not to be in a literal. This is
2159;; ordered with higher positions at the front of the list. Only those which
2160;; are less than `c-state-semi-nonlit-pos-cache-limit' are valid.
2161
2162(defvar c-state-semi-nonlit-pos-cache-limit 1)
2163(make-variable-buffer-local 'c-state-semi-nonlit-pos-cache-limit)
2164;; An upper limit on valid entries in `c-state-semi-nonlit-pos-cache'. This is
2165;; reduced by buffer changes, and increased by invocations of
2166;; `c-state-literal-at'. FIMXE!!!
2167
2092(defsubst c-state-pp-to-literal (from to) 2168(defsubst c-state-pp-to-literal (from to)
2093 ;; Do a parse-partial-sexp from FROM to TO, returning either 2169 ;; Do a parse-partial-sexp from FROM to TO, returning either
2094 ;; (STATE TYPE (BEG . END)) if TO is in a literal; or 2170 ;; (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."
2129 (widen) 2205 (widen)
2130 (save-excursion 2206 (save-excursion
2131 (let ((c c-state-nonlit-pos-cache) 2207 (let ((c c-state-nonlit-pos-cache)
2132 pos npos lit macro-beg macro-end) 2208 pos npos high-pos lit macro-beg macro-end)
2133 ;; Trim the cache to take account of buffer changes. 2209 ;; Trim the cache to take account of buffer changes.
2134 (while (and c (> (car c) c-state-nonlit-pos-cache-limit)) 2210 (while (and c (> (car c) c-state-nonlit-pos-cache-limit))
2135 (setq c (cdr c))) 2211 (setq c (cdr c)))
2136 (setq c-state-nonlit-pos-cache c) 2212 (setq c-state-nonlit-pos-cache c)
2137 2213
2138 (while (and c (> (car c) here)) 2214 (while (and c (> (car c) here))
2215 (setq high-pos (car c))
2139 (setq c (cdr c))) 2216 (setq c (cdr c)))
2140 (setq pos (or (car c) (point-min))) 2217 (setq pos (or (car c) (point-min)))
2141 2218
2142 (while 2219 (unless high-pos
2143 ;; Add an element to `c-state-nonlit-pos-cache' each iteration. 2220 (while
2144 (and 2221 ;; Add an element to `c-state-nonlit-pos-cache' each iteration.
2145 (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here) 2222 (and
2223 (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
2146 2224
2147 ;; Test for being in a literal. 2225 ;; Test for being in a literal. If so, go to after it.
2148 (progn 2226 (progn
2149 (setq lit (car (cddr (c-state-pp-to-literal pos npos)))) 2227 (setq lit (car (cddr (c-state-pp-to-literal pos npos))))
2150 (or (null lit) 2228 (or (null lit)
2151 (prog1 (<= (cdr lit) here) 2229 (prog1 (<= (cdr lit) here)
2152 (setq npos (cdr lit))))) 2230 (setq npos (cdr lit)))))
2153 2231
2154 ;; Test for being in a macro. 2232 ;; Test for being in a macro. If so, go to after it.
2155 (progn 2233 (progn
2156 (goto-char npos) 2234 (goto-char npos)
2157 (setq macro-beg 2235 (setq macro-beg
2158 (and (c-beginning-of-macro) (/= (point) npos) (point))) 2236 (and (c-beginning-of-macro) (/= (point) npos) (point)))
2159 (when macro-beg 2237 (when macro-beg
2160 (c-syntactic-end-of-macro) 2238 (c-syntactic-end-of-macro)
2161 (or (eobp) (forward-char)) 2239 (or (eobp) (forward-char))
2162 (setq macro-end (point))) 2240 (setq macro-end (point)))
2163 (or (null macro-beg) 2241 (or (null macro-beg)
2164 (prog1 (<= macro-end here) 2242 (prog1 (<= macro-end here)
2165 (setq npos macro-end))))) 2243 (setq npos macro-end)))))
2166 2244
2167 (setq pos npos) 2245 (setq pos npos)
2168 (setq c-state-nonlit-pos-cache (cons pos c-state-nonlit-pos-cache))) 2246 (setq c-state-nonlit-pos-cache (cons pos c-state-nonlit-pos-cache)))
2247 ;; Add one extra element above HERE so as to to avoid the previous
2248 ;; expensive calculation when the next call is close to the current
2249 ;; one. This is especially useful when inside a large macro.
2250 (setq c-state-nonlit-pos-cache (cons npos c-state-nonlit-pos-cache)))
2169 2251
2170 (if (> pos c-state-nonlit-pos-cache-limit) 2252 (if (> pos c-state-nonlit-pos-cache-limit)
2171 (setq c-state-nonlit-pos-cache-limit pos)) 2253 (setq c-state-nonlit-pos-cache-limit pos))
2172 pos)))) 2254 pos))))
2173 2255
2256(defun c-state-semi-safe-place (here)
2257 ;; Return a buffer position before HERE which is "safe", i.e. outside any
2258 ;; string or comment. It may be in a macro.
2259 (save-restriction
2260 (widen)
2261 (save-excursion
2262 (let ((c c-state-semi-nonlit-pos-cache)
2263 pos npos high-pos lit macro-beg macro-end)
2264 ;; Trim the cache to take account of buffer changes.
2265 (while (and c (> (car c) c-state-semi-nonlit-pos-cache-limit))
2266 (setq c (cdr c)))
2267 (setq c-state-semi-nonlit-pos-cache c)
2268
2269 (while (and c (> (car c) here))
2270 (setq high-pos (car c))
2271 (setq c (cdr c)))
2272 (setq pos (or (car c) (point-min)))
2273
2274 (unless high-pos
2275 (while
2276 ;; Add an element to `c-state-semi-nonlit-pos-cache' each iteration.
2277 (and
2278 (<= (setq npos (+ pos c-state-nonlit-pos-interval)) here)
2279
2280 ;; Test for being in a literal. If so, go to after it.
2281 (progn
2282 (setq lit (car (cddr (c-state-pp-to-literal pos npos))))
2283 (or (null lit)
2284 (prog1 (<= (cdr lit) here)
2285 (setq npos (cdr lit))))))
2286
2287 (setq pos npos)
2288 (setq c-state-semi-nonlit-pos-cache
2289 (cons pos c-state-semi-nonlit-pos-cache))))
2290
2291 (if (> pos c-state-semi-nonlit-pos-cache-limit)
2292 (setq c-state-semi-nonlit-pos-cache-limit pos))
2293 pos))))
2294
2174(defun c-state-literal-at (here) 2295(defun c-state-literal-at (here)
2175 ;; If position HERE is inside a literal, return (START . END), the 2296 ;; If position HERE is inside a literal, return (START . END), the
2176 ;; boundaries of the literal (which may be outside the accessible bit of the 2297 ;; 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."
2985 ;; 3106 ;;
2986 ;; This function is called from c-after-change. 3107 ;; This function is called from c-after-change.
2987 3108
2988 ;; The cache of non-literals: 3109 ;; The caches of non-literals:
2989 (if (< here c-state-nonlit-pos-cache-limit) 3110 (if (< here c-state-nonlit-pos-cache-limit)
2990 (setq c-state-nonlit-pos-cache-limit here)) 3111 (setq c-state-nonlit-pos-cache-limit here))
3112 (if (< here c-state-semi-nonlit-pos-cache-limit)
3113 (setq c-state-semi-nonlit-pos-cache-limit here))
2991 3114
2992 ;; `c-state-cache': 3115 ;; `c-state-cache':
2993 ;; Case 1: if `here' is in a literal containing point-min, everything 3116 ;; 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
4230comment at the start of cc-engine.el for more info." 4353comment at the start of cc-engine.el for more info."
4231 (save-restriction 4354 (save-restriction
4232 (widen) 4355 (widen)
4233 (let* ((safe-place (c-state-safe-place (point))) 4356 (let* ((safe-place (c-state-semi-safe-place (point)))
4234 (lit (c-state-pp-to-literal safe-place (point)))) 4357 (lit (c-state-pp-to-literal safe-place (point))))
4235 (or (cadr lit) 4358 (or (cadr lit)
4236 (and detect-cpp 4359 (and detect-cpp
@@ -4254,7 +4377,7 @@ comment at the start of cc-engine.el for more info."
4254 4377
4255 (save-excursion 4378 (save-excursion
4256 (let* ((pos (point)) 4379 (let* ((pos (point))
4257 (lim (or lim (c-state-safe-place pos))) 4380 (lim (or lim (c-state-semi-safe-place pos)))
4258 (pp-to-lit (save-restriction 4381 (pp-to-lit (save-restriction
4259 (widen) 4382 (widen)
4260 (c-state-pp-to-literal lim pos))) 4383 (c-state-pp-to-literal lim pos)))
@@ -4372,7 +4495,7 @@ comment at the start of cc-engine.el for more info."
4372 ;; Get a "safe place" approximately TRY-SIZE characters before START. 4495 ;; Get a "safe place" approximately TRY-SIZE characters before START.
4373 ;; This doesn't preserve point. 4496 ;; This doesn't preserve point.
4374 (let* ((pos (max (- start try-size) (point-min))) 4497 (let* ((pos (max (- start try-size) (point-min)))
4375 (base (c-state-safe-place pos)) 4498 (base (c-state-semi-safe-place pos))
4376 (s (parse-partial-sexp base pos))) 4499 (s (parse-partial-sexp base pos)))
4377 (if (or (nth 4 s) (nth 3 s)) ; comment or string 4500 (if (or (nth 4 s) (nth 3 s)) ; comment or string
4378 (nth 8 s) 4501 (nth 8 s)
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index fafbfb70552..493f3db0961 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -459,8 +459,10 @@ so that all identifiers are recognized as words.")
459 ;; For documentation see the following c-lang-defvar of the same name. 459 ;; For documentation see the following c-lang-defvar of the same name.
460 ;; The value here may be a list of functions or a single function. 460 ;; The value here may be a list of functions or a single function.
461 t nil 461 t nil
462 c++ '(c-extend-region-for-CPP c-before-change-check-<>-operators) 462 c++ '(c-extend-region-for-CPP
463 (c objc) 'c-extend-region-for-CPP 463 c-before-change-check-<>-operators
464 c-invalidate-macro-cache)
465 (c objc) '(c-extend-region-for-CPP c-invalidate-macro-cache)
464 ;; java 'c-before-change-check-<>-operators 466 ;; java 'c-before-change-check-<>-operators
465 awk 'c-awk-record-region-clear-NL) 467 awk 'c-awk-record-region-clear-NL)
466(c-lang-defvar c-get-state-before-change-functions 468(c-lang-defvar c-get-state-before-change-functions