GNU bug report logs -
#40052
CC Mode 5.34 (C++//l); cc-mode hangs fontifying src/hotspot/share/runtime/globals.hpp in OpenJDK
Previous Next
Reported by: Nick Gasson <nick.gasson <at> arm.com>
Date: Fri, 13 Mar 2020 14:33:02 UTC
Severity: normal
Done: Alan Mackenzie <acm <at> muc.de>
Bug is archived. No further changes may be made.
Full log
View this message in rfc822 format
Hello, Nick.
On Fri, Mar 13, 2020 at 18:02:03 +0800, Nick Gasson wrote:
> Package: cc-mode
> Open this file with emacs --no-init-file, page down a few times and
> Emacs locks up:
> http://hg.openjdk.java.net/jdk/jdk/raw-file/29edf1cb3c02/src/hotspot/share/runtime/globals.hpp
Thanks for taking the trouble to report this bug. It has been a tough
one to crack.
When I tried it, my Emacs slowed down to a crawl rather than locking up
completely. I'm assuming that this would have been the case on your
machine, too.
Most obviously, there is a huge macro in globals.hpp. Although there
are some optimisations in CC Mode for large macros, they are incomplete,
so working on or around such a macro can be slow.
What is taking most of the time is a CC Mode function which goes back
over syntactic whitespace (spaces, tabs, comments, and when starting
outside of a macro, that macro).
This hits a bug in Emacs where it allows the backward search operation
for a comment start, when point is at the beginning of the line
following an escaped newline. Such a position can never be an end of a
comment in C++.
However, this search backwards for a comment start is being done many
thousand times in globals.hpp because of the consecutive escaped
newlines.
The fix to Emacs won't actually be getting released until Emacs 28, so
in the meantime, please try the following patch. The files to patch are
in directory ...../emacs/lisp/progmodes. After patching them, please
byte compile the two files. (If you want any help in patching or byte
compiling, feel free to send me private email.)
In my timings, scrolling with the patch applied is about four times as
fast as without it. I've also included a correction to a bug about
"regexp stack overflow" which happened when one tried actually to edit
this buffer. Clearly this speed is still not fast enough, but it might
be bearable at a pinch. I will carry on trying to speed it up.
Please let me know how you get on with the patch. Thanks!
diff -r 99da14f7dde7 cc-engine.el
--- a/cc-engine.el Sun Mar 08 15:07:06 2020 +0000
+++ b/cc-engine.el Thu Apr 16 19:33:34 2020 +0000
@@ -1648,6 +1648,16 @@
(forward-char 2)
t))))
+(defmacro c-forward-comment-minus-1 ()
+ "Call (forward-comment -1), taking care of escaped newlines.
+Return the result of `forward-comment' if it gets called, nil otherwise."
+ `(when
+ (or (not comment-end-can-be-escaped)
+ (progn (skip-chars-backward " \t\n")
+ (not (and (eq (char-after) ?\n)
+ (eq (char-before) ?\\)))))
+ (forward-comment -1)))
+
(defun c-backward-single-comment ()
"Move backward past whitespace and the closest preceding comment, if any.
Return t if a comment was found, nil otherwise. In either case, the
@@ -1681,12 +1691,12 @@
;; same line.
(re-search-forward "\\=\\s *[\n\r]" start t)
- (if (if (forward-comment -1)
+ (if (if (c-forward-comment-minus-1)
(if (eolp)
;; If forward-comment above succeeded and we're at eol
;; then the newline we moved over above didn't end a
;; line comment, so we give it another go.
- (forward-comment -1)
+ (c-forward-comment-minus-1)
t))
;; Emacs <= 20 and XEmacs move back over the closer of a
@@ -1715,7 +1725,7 @@
(if (let (moved-comment)
(while
- (and (not (setq moved-comment (forward-comment -1)))
+ (and (not (setq moved-comment (c-forward-comment-minus-1)))
;; Cope specifically with ^M^J here -
;; forward-comment sometimes gets stuck after ^Ms,
;; sometimes after ^M^J.
diff -r 99da14f7dde7 cc-mode.el
--- a/cc-mode.el Sun Mar 08 15:07:06 2020 +0000
+++ b/cc-mode.el Thu Apr 16 19:33:34 2020 +0000
@@ -1413,7 +1413,7 @@
;; Move to end of logical line (as it will be after the change, or as it
;; was before unescaping a NL.)
- (re-search-forward "\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r]\\)*" nil t)
+ (re-search-forward "\\(?:\\\\\\(?:.\\|\n\\)\\|[^\\\n\r]\\)*" nil t)
;; We're at an EOLL or point-max.
(if (equal (c-get-char-property (point) 'syntax-table) '(15))
(if (memq (char-after) '(?\n ?\r))
@@ -1521,7 +1521,7 @@
(progn
(goto-char (min (1+ end) ; 1+, in case a NL has become escaped.
(point-max)))
- (re-search-forward "\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r]\\)*"
+ (re-search-forward "\\(?:\\\\\\(?:.\\|\n\\)\\|[^\\\n\r]\\)*"
nil t)
(point))
c-new-END))
@@ -1602,8 +1602,8 @@
(c-beginning-of-macro))))
(goto-char (1+ end)) ; After the \
;; Search forward for EOLL
- (setq lim (re-search-forward "\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r]\\)*"
- nil t))
+ (setq lim (re-search-forward "\\(?:\\\\\\(?:.\\|\n\\)\\|[^\\\n\r]\\)*"
+ nil t))
(goto-char (1+ end))
(when (c-search-forward-char-property-with-value-on-char
'syntax-table '(15) ?\" lim)
> Emacs : GNU Emacs 27.0.90 (build 1, aarch64-unknown-linux-gnu, GTK+ Version 3.24.13)
> of 2020-03-09
> Package: CC Mode 5.34 (C++//l)
> Buffer Style: gnu
> c-emacs-features: (pps-extended-state col-0-paren posix-char-classes gen-string-delim gen-comment-delim syntax-properties 1-bit)
[ CC Mode state dump snipped, but appreciated. ]
--
Alan Mackenzie (Nuremberg, Germany).
This bug report was last modified 5 years and 65 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.