Mercurial > hg > xemacs-beta
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 */ |