emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r107485: Depessimize the handling of


From: Alan Mackenzie
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r107485: Depessimize the handling of very large macros.
Date: Fri, 02 Mar 2012 22:16:21 +0000
User-agent: Bazaar (2.3.1)

------------------------------------------------------------
revno: 107485
committer: Alan Mackenzie <address@hidden>
branch nick: cc-mode
timestamp: Fri 2012-03-02 22:16:21 +0000
message:
  Depessimize the handling of very large macros.
modified:
  lisp/ChangeLog
  lisp/progmodes/cc-engine.el
  lisp/progmodes/cc-langs.el
=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2012-03-02 15:29:28 +0000
+++ b/lisp/ChangeLog    2012-03-02 22:16:21 +0000
@@ -1,3 +1,25 @@
+2012-03-02  Alan Mackenzie  <address@hidden>
+
+       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  <address@hidden>
 
        * jka-compr.el (jka-compr-call-process): Apply

=== modified file 'lisp/progmodes/cc-engine.el'
--- a/lisp/progmodes/cc-engine.el       2012-02-12 11:06:42 +0000
+++ b/lisp/progmodes/cc-engine.el       2012-03-02 22:16:21 +0000
@@ -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 @@
 
 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 @@
 
 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 @@
   ;; 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 @@
 ;; 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 @@
     (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)
-
-            ;; 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 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)))))
-
-         (setq pos npos)
-         (setq c-state-nonlit-pos-cache (cons pos c-state-nonlit-pos-cache)))
+       (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.  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.  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)))
+         ;; 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 @@
   ;;
   ;; 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 @@
 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 @@
 
   (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 @@
   ;; 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)

=== modified file 'lisp/progmodes/cc-langs.el'
--- a/lisp/progmodes/cc-langs.el        2012-01-19 07:21:25 +0000
+++ b/lisp/progmodes/cc-langs.el        2012-03-02 22:16:21 +0000
@@ -459,8 +459,10 @@
   ;; 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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]