Mercurial > hg > xemacs-beta
diff src/syntax.c @ 5552:85210c453a97
Fix performance regression in refactored syntax cache setup.
More doc improvements.
* syntax.h (enum syntax_source):
New. Specify whether syntax is from property or buffer.
(struct syntax_cache):
Use enum syntax_source source, instead of no_syntax_table_prop
and use_code.
Improve comments.
(SOURCE_IS_TABLE):
New predicate.
(SYNTAX_CODE_FROM_CACHE):
Use it instead of use_code, and adjust logic.
* syntax.c (syntax_cache_table_was_changed):
Check cache->source (cache->no_syntax_table_prop is gone).
(reset_syntax_cache_range):
All information about OBJECT and BUFFER is in CACHE already.
Also reset markers in OBJECT if it is a buffer.
Rename INFINITE to VALID_EVERYWHERE.
(init_syntax_cache):
Initialize source (cache->no_syntax_table_prop is gone).
Maybe initialize start and end to null markers.
Initialize cache range with reset_syntax_cache_range.
(update_syntax_cache):
Use source instead of no_syntax_table_prop and use_code.
(setup_syntax_cache):
Add header comment. Improve other comments.
Make calls to reset_syntax_cache_range and init_syntax_cache match
their prototypes.
(init_buffer_syntax_cache):
Use init_syntax_cache to do the work.
(signal_syntax_cache_extent_changed):
Make call to reset_syntax_cache_range match its prototype.
Improve local variable naming.
author | Stephen J. Turnbull <stephen@xemacs.org> |
---|---|
date | Tue, 23 Aug 2011 04:41:45 +0900 |
parents | 69de75c48efa |
children | 56144c8593a8 |
line wrap: on
line diff
--- a/src/syntax.c Sun Aug 14 13:51:14 2011 +0200 +++ b/src/syntax.c Tue Aug 23 04:41:45 2011 +0900 @@ -273,7 +273,7 @@ syntax_cache_table_was_changed (struct buffer *buf) { struct syntax_cache *cache = buf->syntax_cache; - if (cache->no_syntax_table_prop) + if (cache->source == syntax_source_buffer_table) { cache->syntax_table = BUFFER_SYNTAX_TABLE (buf); @@ -284,59 +284,96 @@ static void reset_syntax_cache_range (struct syntax_cache *cache, /* initialized cache */ - Lisp_Object object) /* string or buffer */ + int valid_everywhere) /* non-zero if we can assume + syntax-table properties + never need be respected + in the life of the cache */ { - /* reinitialize cache parameters */ - if (BUFFERP (object)) + if (BUFFERP (cache->object)) { /* make known region zero-length and reset insertion behavior */ - Fset_marker (cache->start, make_int (1), object); - Fset_marker (cache->end, make_int (1), object); + Fset_marker (cache->start, make_int (1), cache->object); + Fset_marker (cache->end, make_int (1), cache->object); Fset_marker_insertion_type (cache->start, Qnil); Fset_marker_insertion_type (cache->end, Qt); } - else + /* #### Should reset "cache->source" here? + If so, also reset tables. */ + if (valid_everywhere) { - /* invalidate the known region markers */ - Fset_marker (cache->start, Qnil, Qnil); - Fset_marker (cache->end, Qnil, Qnil); + cache->prev_change = EMACS_INT_MIN; + cache->next_change = EMACS_INT_MAX; } - cache->no_syntax_table_prop = 1; - if (lookup_syntax_properties) + else /* valid nowhere */ { cache->prev_change = -1; cache->next_change = -1; } - else - { - cache->prev_change = EMACS_INT_MIN; - cache->next_change = EMACS_INT_MAX; - } } -/* init_syntax_cache - Arguments: - cache: pointer to a zero-ed struct syntax_cache - object: a Lisp string or buffer - buffer: NULL or the struct buffer of buffer */ static void -init_syntax_cache (struct syntax_cache *cache, /* cache must be zero'ed */ +init_syntax_cache (struct syntax_cache *cache, /* xzero'ed memory */ Lisp_Object object, /* string or buffer */ - struct buffer *buffer) /* may not be NULL */ + struct buffer *buffer) /* buffer; if OBJECT is a + buffer, this is the same */ { - /* initialize cache resources */ cache->object = object; cache->buffer = buffer; + + cache->source = syntax_source_buffer_table; cache->syntax_table = BUFFER_SYNTAX_TABLE (cache->buffer); cache->mirror_table = BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer); - cache->start = Fmake_marker(); - cache->end = Fmake_marker(); + + /* Qnil avoids GC'ing markers, which are useless for strings. */ + cache->start = BUFFERP (object) ? Fmake_marker () : Qnil; + cache->end = BUFFERP (object) ? Fmake_marker () : Qnil; + + reset_syntax_cache_range (cache, 0); } /* external syntax cache API */ +/* At this time (hg rev 5551:dab422055bab) setup_syntax_cache() is called + directly once in setup_buffer_syntax_cache and twice in regex.c. The + calls in regex.c are obfuscated, so it's hard to tell, but it looks like + they can be called with OBJECT being a buffer. + + "You are in a confusing maze of initializations, all alike." + + reset_syntax_cache_range (3 uses in setup_syntax_cache, + signal_syntax_cache_extent_changed, and init_buffer_syntax_cache) + reinitializes: + 1. if BUFFERP(OBJECT), marker positions to 1 (giving a null range) + 2. if BUFFERP(OBJECT), marker movement type + 3. cache range per VALID_EVERYWHERE + + init_syntax_cache (2 uses in init_buffer_syntax_cache and + setup_syntax_cache) initializes: + 1. source to syntax_source_buffer_table + 2. syntax_table and mirror_syntax table to BUFFER's tables + 3. marker members to BUFFERP(OBJECT) ? markers w/o position : Qnil + 4. cache range with VALID_EVERYWHERE==0 + 5. object and buffer to corresponding arguments. + + init_buffer_syntax_cache (1 use in buffer.c) initializes: + 0. allocation of buffer's cache memory (done by allocator) + 1. cache memory to zero (done by allocator) + 2. cache to buffer's cache + 3. cache members by init_syntax_cache with object==buffer==BUF. + + setup_buffer_syntax_cache (1 call in font-lock.c, 1 use in search.c, + and 7 uses in this file) initializes: + 0. buffer's syntax cache by calling setup_syntax_cache. + + setup_buffer_syntax_cache and setup_syntax_cache are called by functions + that analyze text using character syntax. They are called repeatedly on + the same cache. init_syntax_cache and init_buffer_syntax_cache are + conceptually called once for each cache. reset_syntax_cache_range may + be called repeatedly on the same cache. The last three are for internal + use by the syntax setup code and buffer initialization. */ + struct syntax_cache * /* return CACHE or the cache of OBJECT */ setup_syntax_cache (struct syntax_cache *cache, /* may be NULL only if OBJECT is a buffer */ @@ -344,22 +381,37 @@ is associated with */ struct buffer *buffer, /* the buffer to use as source of the syntax table */ - Charxpos UNUSED (from), /* initial position of cache */ - int UNUSED (count)) /* direction? see code */ + Charxpos from, /* initial position of cache */ + int count) /* direction? see code */ { - /* If OBJECT is a buffer, use its cache, otherwise use CACHE. - Initialize CACHE. Invalidate the cache if the syntax-table property is - being respected, otherwise make it valid for the whole object. */ + /* If OBJECT is a buffer, use its cache; else use CACHE and initialize it. + Invalidate the cache if the syntax-table property is being respected; + else make it valid for the whole object. */ if (BUFFERP (object)) { cache = XBUFFER (object)->syntax_cache; + if (!lookup_syntax_properties) + reset_syntax_cache_range (cache, 1); } else { xzero (*cache); init_syntax_cache (cache, object, buffer); } - reset_syntax_cache_range (cache, object); + + if (lookup_syntax_properties) + { + if (count <= 0) + { + --from; + from = buffer_or_string_clip_to_accessible_char (cache->object, + from); + } + /* If lookup_syntax_properties && BUFFERP (object), this + optimization may matter. */ + if (!(from >= cache->prev_change && from < cache->next_change)) + update_syntax_cache (cache, from, count); + } #ifdef NOT_WORTH_THE_EFFORT update_mirror_syntax_if_dirty (cache->mirror_table); @@ -454,24 +506,21 @@ if (!NILP (Fsyntax_table_p (tmp_table))) { - cache->use_code = 0; + cache->source = syntax_source_property_table; cache->syntax_table = tmp_table; cache->mirror_table = XCHAR_TABLE (tmp_table)->mirror_table; - cache->no_syntax_table_prop = 0; #ifdef NOT_WORTH_THE_EFFORT update_mirror_syntax_if_dirty (cache->mirror_table); #endif /* NOT_WORTH_THE_EFFORT */ } else if (CONSP (tmp_table) && INTP (XCAR (tmp_table))) { - cache->use_code = 1; + cache->source = syntax_source_property_code; cache->syntax_code = XINT (XCAR (tmp_table)); - cache->no_syntax_table_prop = 0; } else { - cache->use_code = 0; - cache->no_syntax_table_prop = 1; + cache->source = syntax_source_buffer_table; cache->syntax_table = BUFFER_SYNTAX_TABLE (cache->buffer); cache->mirror_table = BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer); #ifdef NOT_WORTH_THE_EFFORT @@ -501,14 +550,15 @@ void init_buffer_syntax_cache (struct buffer *buf) { + struct syntax_cache *cache; #ifdef NEW_GC - buf->syntax_cache = XSYNTAX_CACHE (ALLOC_NORMAL_LISP_OBJECT (syntax_cache)); + cache = XSYNTAX_CACHE (ALLOC_NORMAL_LISP_OBJECT (syntax_cache)); #else /* not NEW_GC */ - buf->syntax_cache = xnew_and_zero (struct syntax_cache); + cache = xnew_and_zero (struct syntax_cache); #endif /* not NEW_GC */ - init_syntax_cache (buf->syntax_cache, wrap_buffer(buf), buf); - reset_syntax_cache_range (buf->syntax_cache, wrap_buffer(buf)); + init_syntax_cache (cache, wrap_buffer (buf), buf); + buf->syntax_cache = cache; } /* finalize the syntax cache for BUF */ @@ -535,18 +585,18 @@ void signal_syntax_cache_extent_changed (EXTENT extent) { - Lisp_Object buffer = Fextent_object (wrap_extent (extent)); - if (BUFFERP (buffer)) + Lisp_Object object = Fextent_object (wrap_extent (extent)); + if (BUFFERP (object)) { - struct syntax_cache *cache = XBUFFER (buffer)->syntax_cache; - Bytexpos start = extent_endpoint_byte (extent, 0); - Bytexpos end = extent_endpoint_byte (extent, 1); - Bytexpos start2 = byte_marker_position (cache->start); - Bytexpos end2 = byte_marker_position (cache->end); + struct syntax_cache *cache = XBUFFER (object)->syntax_cache; + Bytexpos extent_start = extent_endpoint_byte (extent, 0); + Bytexpos extent_end = extent_endpoint_byte (extent, 1); + Bytexpos cache_start = byte_marker_position (cache->start); + Bytexpos cache_end = byte_marker_position (cache->end); /* If the extent is entirely before or entirely after the cache range, it doesn't overlap. Otherwise, invalidate the range. */ - if (!(end < start2 || start > end2)) - reset_syntax_cache_range (cache, buffer); + if (!(extent_end < cache_start || extent_start > cache_end)) + reset_syntax_cache_range (cache, 0); } }