comparison 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
comparison
equal deleted inserted replaced
5551:40a52efbf3a3 5552:85210c453a97
271 271
272 static void 272 static void
273 syntax_cache_table_was_changed (struct buffer *buf) 273 syntax_cache_table_was_changed (struct buffer *buf)
274 { 274 {
275 struct syntax_cache *cache = buf->syntax_cache; 275 struct syntax_cache *cache = buf->syntax_cache;
276 if (cache->no_syntax_table_prop) 276 if (cache->source == syntax_source_buffer_table)
277 { 277 {
278 cache->syntax_table = 278 cache->syntax_table =
279 BUFFER_SYNTAX_TABLE (buf); 279 BUFFER_SYNTAX_TABLE (buf);
280 cache->mirror_table = 280 cache->mirror_table =
281 BUFFER_MIRROR_SYNTAX_TABLE (buf); 281 BUFFER_MIRROR_SYNTAX_TABLE (buf);
282 } 282 }
283 } 283 }
284 284
285 static void 285 static void
286 reset_syntax_cache_range (struct syntax_cache *cache, /* initialized cache */ 286 reset_syntax_cache_range (struct syntax_cache *cache, /* initialized cache */
287 Lisp_Object object) /* string or buffer */ 287 int valid_everywhere) /* non-zero if we can assume
288 { 288 syntax-table properties
289 /* reinitialize cache parameters */ 289 never need be respected
290 if (BUFFERP (object)) 290 in the life of the cache */
291 {
292 if (BUFFERP (cache->object))
291 { 293 {
292 /* make known region zero-length and reset insertion behavior */ 294 /* make known region zero-length and reset insertion behavior */
293 Fset_marker (cache->start, make_int (1), object); 295 Fset_marker (cache->start, make_int (1), cache->object);
294 Fset_marker (cache->end, make_int (1), object); 296 Fset_marker (cache->end, make_int (1), cache->object);
295 Fset_marker_insertion_type (cache->start, Qnil); 297 Fset_marker_insertion_type (cache->start, Qnil);
296 Fset_marker_insertion_type (cache->end, Qt); 298 Fset_marker_insertion_type (cache->end, Qt);
297 } 299 }
298 else 300 /* #### Should reset "cache->source" here?
299 { 301 If so, also reset tables. */
300 /* invalidate the known region markers */ 302 if (valid_everywhere)
301 Fset_marker (cache->start, Qnil, Qnil); 303 {
302 Fset_marker (cache->end, Qnil, Qnil); 304 cache->prev_change = EMACS_INT_MIN;
303 } 305 cache->next_change = EMACS_INT_MAX;
304 cache->no_syntax_table_prop = 1; 306 }
305 if (lookup_syntax_properties) 307 else /* valid nowhere */
306 { 308 {
307 cache->prev_change = -1; 309 cache->prev_change = -1;
308 cache->next_change = -1; 310 cache->next_change = -1;
309 } 311 }
310 else 312 }
311 { 313
312 cache->prev_change = EMACS_INT_MIN;
313 cache->next_change = EMACS_INT_MAX;
314 }
315 }
316
317 /* init_syntax_cache
318 Arguments:
319 cache: pointer to a zero-ed struct syntax_cache
320 object: a Lisp string or buffer
321 buffer: NULL or the struct buffer of buffer */
322 static void 314 static void
323 init_syntax_cache (struct syntax_cache *cache, /* cache must be zero'ed */ 315 init_syntax_cache (struct syntax_cache *cache, /* xzero'ed memory */
324 Lisp_Object object, /* string or buffer */ 316 Lisp_Object object, /* string or buffer */
325 struct buffer *buffer) /* may not be NULL */ 317 struct buffer *buffer) /* buffer; if OBJECT is a
326 { 318 buffer, this is the same */
327 /* initialize cache resources */ 319 {
328 cache->object = object; 320 cache->object = object;
329 cache->buffer = buffer; 321 cache->buffer = buffer;
322
323 cache->source = syntax_source_buffer_table;
330 cache->syntax_table = 324 cache->syntax_table =
331 BUFFER_SYNTAX_TABLE (cache->buffer); 325 BUFFER_SYNTAX_TABLE (cache->buffer);
332 cache->mirror_table = 326 cache->mirror_table =
333 BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer); 327 BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer);
334 cache->start = Fmake_marker(); 328
335 cache->end = Fmake_marker(); 329 /* Qnil avoids GC'ing markers, which are useless for strings. */
330 cache->start = BUFFERP (object) ? Fmake_marker () : Qnil;
331 cache->end = BUFFERP (object) ? Fmake_marker () : Qnil;
332
333 reset_syntax_cache_range (cache, 0);
336 } 334 }
337 335
338 /* external syntax cache API */ 336 /* external syntax cache API */
337
338 /* At this time (hg rev 5551:dab422055bab) setup_syntax_cache() is called
339 directly once in setup_buffer_syntax_cache and twice in regex.c. The
340 calls in regex.c are obfuscated, so it's hard to tell, but it looks like
341 they can be called with OBJECT being a buffer.
342
343 "You are in a confusing maze of initializations, all alike."
344
345 reset_syntax_cache_range (3 uses in setup_syntax_cache,
346 signal_syntax_cache_extent_changed, and init_buffer_syntax_cache)
347 reinitializes:
348 1. if BUFFERP(OBJECT), marker positions to 1 (giving a null range)
349 2. if BUFFERP(OBJECT), marker movement type
350 3. cache range per VALID_EVERYWHERE
351
352 init_syntax_cache (2 uses in init_buffer_syntax_cache and
353 setup_syntax_cache) initializes:
354 1. source to syntax_source_buffer_table
355 2. syntax_table and mirror_syntax table to BUFFER's tables
356 3. marker members to BUFFERP(OBJECT) ? markers w/o position : Qnil
357 4. cache range with VALID_EVERYWHERE==0
358 5. object and buffer to corresponding arguments.
359
360 init_buffer_syntax_cache (1 use in buffer.c) initializes:
361 0. allocation of buffer's cache memory (done by allocator)
362 1. cache memory to zero (done by allocator)
363 2. cache to buffer's cache
364 3. cache members by init_syntax_cache with object==buffer==BUF.
365
366 setup_buffer_syntax_cache (1 call in font-lock.c, 1 use in search.c,
367 and 7 uses in this file) initializes:
368 0. buffer's syntax cache by calling setup_syntax_cache.
369
370 setup_buffer_syntax_cache and setup_syntax_cache are called by functions
371 that analyze text using character syntax. They are called repeatedly on
372 the same cache. init_syntax_cache and init_buffer_syntax_cache are
373 conceptually called once for each cache. reset_syntax_cache_range may
374 be called repeatedly on the same cache. The last three are for internal
375 use by the syntax setup code and buffer initialization. */
339 376
340 struct syntax_cache * /* return CACHE or the cache of OBJECT */ 377 struct syntax_cache * /* return CACHE or the cache of OBJECT */
341 setup_syntax_cache (struct syntax_cache *cache, /* may be NULL only if 378 setup_syntax_cache (struct syntax_cache *cache, /* may be NULL only if
342 OBJECT is a buffer */ 379 OBJECT is a buffer */
343 Lisp_Object object, /* the object (if any) cache 380 Lisp_Object object, /* the object (if any) cache
344 is associated with */ 381 is associated with */
345 struct buffer *buffer, /* the buffer to use as source 382 struct buffer *buffer, /* the buffer to use as source
346 of the syntax table */ 383 of the syntax table */
347 Charxpos UNUSED (from), /* initial position of cache */ 384 Charxpos from, /* initial position of cache */
348 int UNUSED (count)) /* direction? see code */ 385 int count) /* direction? see code */
349 { 386 {
350 /* If OBJECT is a buffer, use its cache, otherwise use CACHE. 387 /* If OBJECT is a buffer, use its cache; else use CACHE and initialize it.
351 Initialize CACHE. Invalidate the cache if the syntax-table property is 388 Invalidate the cache if the syntax-table property is being respected;
352 being respected, otherwise make it valid for the whole object. */ 389 else make it valid for the whole object. */
353 if (BUFFERP (object)) 390 if (BUFFERP (object))
354 { 391 {
355 cache = XBUFFER (object)->syntax_cache; 392 cache = XBUFFER (object)->syntax_cache;
393 if (!lookup_syntax_properties)
394 reset_syntax_cache_range (cache, 1);
356 } 395 }
357 else 396 else
358 { 397 {
359 xzero (*cache); 398 xzero (*cache);
360 init_syntax_cache (cache, object, buffer); 399 init_syntax_cache (cache, object, buffer);
361 } 400 }
362 reset_syntax_cache_range (cache, object); 401
402 if (lookup_syntax_properties)
403 {
404 if (count <= 0)
405 {
406 --from;
407 from = buffer_or_string_clip_to_accessible_char (cache->object,
408 from);
409 }
410 /* If lookup_syntax_properties && BUFFERP (object), this
411 optimization may matter. */
412 if (!(from >= cache->prev_change && from < cache->next_change))
413 update_syntax_cache (cache, from, count);
414 }
363 415
364 #ifdef NOT_WORTH_THE_EFFORT 416 #ifdef NOT_WORTH_THE_EFFORT
365 update_mirror_syntax_if_dirty (cache->mirror_table); 417 update_mirror_syntax_if_dirty (cache->mirror_table);
366 #endif /* NOT_WORTH_THE_EFFORT */ 418 #endif /* NOT_WORTH_THE_EFFORT */
367 return cache; 419 return cache;
452 ? Qt : Qnil); 504 ? Qt : Qnil);
453 } 505 }
454 506
455 if (!NILP (Fsyntax_table_p (tmp_table))) 507 if (!NILP (Fsyntax_table_p (tmp_table)))
456 { 508 {
457 cache->use_code = 0; 509 cache->source = syntax_source_property_table;
458 cache->syntax_table = tmp_table; 510 cache->syntax_table = tmp_table;
459 cache->mirror_table = XCHAR_TABLE (tmp_table)->mirror_table; 511 cache->mirror_table = XCHAR_TABLE (tmp_table)->mirror_table;
460 cache->no_syntax_table_prop = 0;
461 #ifdef NOT_WORTH_THE_EFFORT 512 #ifdef NOT_WORTH_THE_EFFORT
462 update_mirror_syntax_if_dirty (cache->mirror_table); 513 update_mirror_syntax_if_dirty (cache->mirror_table);
463 #endif /* NOT_WORTH_THE_EFFORT */ 514 #endif /* NOT_WORTH_THE_EFFORT */
464 } 515 }
465 else if (CONSP (tmp_table) && INTP (XCAR (tmp_table))) 516 else if (CONSP (tmp_table) && INTP (XCAR (tmp_table)))
466 { 517 {
467 cache->use_code = 1; 518 cache->source = syntax_source_property_code;
468 cache->syntax_code = XINT (XCAR (tmp_table)); 519 cache->syntax_code = XINT (XCAR (tmp_table));
469 cache->no_syntax_table_prop = 0;
470 } 520 }
471 else 521 else
472 { 522 {
473 cache->use_code = 0; 523 cache->source = syntax_source_buffer_table;
474 cache->no_syntax_table_prop = 1;
475 cache->syntax_table = BUFFER_SYNTAX_TABLE (cache->buffer); 524 cache->syntax_table = BUFFER_SYNTAX_TABLE (cache->buffer);
476 cache->mirror_table = BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer); 525 cache->mirror_table = BUFFER_MIRROR_SYNTAX_TABLE (cache->buffer);
477 #ifdef NOT_WORTH_THE_EFFORT 526 #ifdef NOT_WORTH_THE_EFFORT
478 update_mirror_syntax_if_dirty (cache->mirror_table); 527 update_mirror_syntax_if_dirty (cache->mirror_table);
479 #endif /* NOT_WORTH_THE_EFFORT */ 528 #endif /* NOT_WORTH_THE_EFFORT */
499 } 548 }
500 549
501 void 550 void
502 init_buffer_syntax_cache (struct buffer *buf) 551 init_buffer_syntax_cache (struct buffer *buf)
503 { 552 {
553 struct syntax_cache *cache;
504 #ifdef NEW_GC 554 #ifdef NEW_GC
505 buf->syntax_cache = XSYNTAX_CACHE (ALLOC_NORMAL_LISP_OBJECT (syntax_cache)); 555 cache = XSYNTAX_CACHE (ALLOC_NORMAL_LISP_OBJECT (syntax_cache));
506 #else /* not NEW_GC */ 556 #else /* not NEW_GC */
507 buf->syntax_cache = xnew_and_zero (struct syntax_cache); 557 cache = xnew_and_zero (struct syntax_cache);
508 #endif /* not NEW_GC */ 558 #endif /* not NEW_GC */
509 559
510 init_syntax_cache (buf->syntax_cache, wrap_buffer(buf), buf); 560 init_syntax_cache (cache, wrap_buffer (buf), buf);
511 reset_syntax_cache_range (buf->syntax_cache, wrap_buffer(buf)); 561 buf->syntax_cache = cache;
512 } 562 }
513 563
514 /* finalize the syntax cache for BUF */ 564 /* finalize the syntax cache for BUF */
515 565
516 void 566 void
533 the value of EXTENT's syntax-table property is changing. */ 583 the value of EXTENT's syntax-table property is changing. */
534 584
535 void 585 void
536 signal_syntax_cache_extent_changed (EXTENT extent) 586 signal_syntax_cache_extent_changed (EXTENT extent)
537 { 587 {
538 Lisp_Object buffer = Fextent_object (wrap_extent (extent)); 588 Lisp_Object object = Fextent_object (wrap_extent (extent));
539 if (BUFFERP (buffer)) 589 if (BUFFERP (object))
540 { 590 {
541 struct syntax_cache *cache = XBUFFER (buffer)->syntax_cache; 591 struct syntax_cache *cache = XBUFFER (object)->syntax_cache;
542 Bytexpos start = extent_endpoint_byte (extent, 0); 592 Bytexpos extent_start = extent_endpoint_byte (extent, 0);
543 Bytexpos end = extent_endpoint_byte (extent, 1); 593 Bytexpos extent_end = extent_endpoint_byte (extent, 1);
544 Bytexpos start2 = byte_marker_position (cache->start); 594 Bytexpos cache_start = byte_marker_position (cache->start);
545 Bytexpos end2 = byte_marker_position (cache->end); 595 Bytexpos cache_end = byte_marker_position (cache->end);
546 /* If the extent is entirely before or entirely after the cache 596 /* If the extent is entirely before or entirely after the cache
547 range, it doesn't overlap. Otherwise, invalidate the range. */ 597 range, it doesn't overlap. Otherwise, invalidate the range. */
548 if (!(end < start2 || start > end2)) 598 if (!(extent_end < cache_start || extent_start > cache_end))
549 reset_syntax_cache_range (cache, buffer); 599 reset_syntax_cache_range (cache, 0);
550 } 600 }
551 } 601 }
552 602
553 /* Extents have been adjusted for insertion or deletion, so we need to 603 /* Extents have been adjusted for insertion or deletion, so we need to
554 refetch the start and end position of the extent */ 604 refetch the start and end position of the extent */