aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2014-12-05 12:17:15 +0200
committerEli Zaretskii2014-12-05 12:17:15 +0200
commitfcc4da3e5227f64b57e5e7ac497df28229b88f7d (patch)
treeae2dbadb71fb2552277410415a5753c8edf9a2ac
parent96e6fd3c155b1851e0acd477789535a45b8d3187 (diff)
downloademacs-fcc4da3e5227f64b57e5e7ac497df28229b88f7d.tar.gz
emacs-fcc4da3e5227f64b57e5e7ac497df28229b88f7d.zip
Reduce memory footprint of struct bidi_it by a factor of 5.
src/dispextern.h (enum bidi_dir_t): Force NEUTRAL_DIR to be zero. (struct bidi_stack): Reduce size by using bit fields and by packing sos, override, and isolate_status into a single 8-bit byte called 'flags'. src/bidi.c (ISOLATE_STATUS, OVERRIDE): New macros. (bidi_push_embedding_level): Construct flags from individual bits. Adapt to changes in prev_for_neutral and next_for_neutral members. (bidi_pop_embedding_level): Use ISOLATE_STATUS. Extract 'sos' from flags. Adapt to changes in prev_for_neutral, next_for_neutral, and last_strong members. (bidi_line_init): Initialize flags to zero. (bidi_resolve_explicit, bidi_resolve_weak, bidi_resolve_brackets) (bidi_resolve_neutral): Use ISOLATE_STATUS and OVERRIDE.
-rw-r--r--src/ChangeLog18
-rw-r--r--src/bidi.c64
-rw-r--r--src/dispextern.h19
3 files changed, 63 insertions, 38 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 2f64a9758bc..82aabb389a3 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,21 @@
12014-12-05 Eli Zaretskii <eliz@gnu.org>
2
3 * dispextern.h (enum bidi_dir_t): Force NEUTRAL_DIR to be zero.
4 (struct bidi_stack): Reduce size by using bit fields and by
5 packing sos, override, and isolate_status into a single 8-bit
6 byte called 'flags'.
7
8 * bidi.c (ISOLATE_STATUS, OVERRIDE): New macros.
9 (bidi_push_embedding_level): Construct flags from individual
10 bits. Adapt to changes in prev_for_neutral and next_for_neutral
11 members.
12 (bidi_pop_embedding_level): Use ISOLATE_STATUS. Extract 'sos'
13 from flags. Adapt to changes in prev_for_neutral,
14 next_for_neutral, and last_strong members.
15 (bidi_line_init): Initialize flags to zero.
16 (bidi_resolve_explicit, bidi_resolve_weak, bidi_resolve_brackets)
17 (bidi_resolve_neutral): Use ISOLATE_STATUS and OVERRIDE.
18
12014-12-04 Stefan Monnier <monnier@iro.umontreal.ca> 192014-12-04 Stefan Monnier <monnier@iro.umontreal.ca>
2 20
3 * eval.c (backtrace_eval_unrewind): Rewind also the excursions. 21 * eval.c (backtrace_eval_unrewind): Rewind also the excursions.
diff --git a/src/bidi.c b/src/bidi.c
index a0bcf528e12..cc70d08f01e 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -433,6 +433,9 @@ bidi_set_sos_type (struct bidi_it *bidi_it, int level_before, int level_after)
433 = bidi_it->next_for_neutral.orig_type = UNKNOWN_BT; 433 = bidi_it->next_for_neutral.orig_type = UNKNOWN_BT;
434} 434}
435 435
436#define ISOLATE_STATUS(BIDI_IT, IDX) ((BIDI_IT)->level_stack[IDX].flags & 1)
437#define OVERRIDE(BIDI_IT, IDX) (((BIDI_IT)->level_stack[IDX].flags >> 1) & 3)
438
436/* Push the current embedding level and override status; reset the 439/* Push the current embedding level and override status; reset the
437 current level to LEVEL and the current override status to OVERRIDE. */ 440 current level to LEVEL and the current override status to OVERRIDE. */
438static void 441static void
@@ -447,14 +450,14 @@ bidi_push_embedding_level (struct bidi_it *bidi_it,
447 st = &bidi_it->level_stack[bidi_it->stack_idx]; 450 st = &bidi_it->level_stack[bidi_it->stack_idx];
448 eassert (level <= (1 << 7)); 451 eassert (level <= (1 << 7));
449 st->level = level; 452 st->level = level;
450 st->override = override; 453 st->flags = (((override & 3) << 1) | (isolate_status != 0));
451 st->isolate_status = isolate_status;
452 if (isolate_status) 454 if (isolate_status)
453 { 455 {
454 st->last_strong = bidi_it->last_strong; 456 st->last_strong_type = bidi_it->last_strong.type;
455 st->prev_for_neutral = bidi_it->prev_for_neutral; 457 st->prev_for_neutral_type = bidi_it->prev_for_neutral.type;
456 st->next_for_neutral = bidi_it->next_for_neutral; 458 st->next_for_neutral_type = bidi_it->next_for_neutral.type;
457 st->sos = bidi_it->sos; 459 st->next_for_neutral_pos = bidi_it->next_for_neutral.charpos;
460 st->flags |= ((bidi_it->sos == L2R ? 0 : 1) << 3);
458 } 461 }
459 /* We've got a new isolating sequence, compute the directional type 462 /* We've got a new isolating sequence, compute the directional type
460 of sos and initialize per-sequence variables (UAX#9, clause X10). */ 463 of sos and initialize per-sequence variables (UAX#9, clause X10). */
@@ -473,8 +476,7 @@ bidi_pop_embedding_level (struct bidi_it *bidi_it)
473 and PDIs (X6a, 2nd bullet). */ 476 and PDIs (X6a, 2nd bullet). */
474 if (bidi_it->stack_idx > 0) 477 if (bidi_it->stack_idx > 0)
475 { 478 {
476 bool isolate_status 479 bool isolate_status = ISOLATE_STATUS (bidi_it, bidi_it->stack_idx);
477 = bidi_it->level_stack[bidi_it->stack_idx].isolate_status;
478 int old_level = bidi_it->level_stack[bidi_it->stack_idx].level; 480 int old_level = bidi_it->level_stack[bidi_it->stack_idx].level;
479 481
480 struct bidi_stack st; 482 struct bidi_stack st;
@@ -482,6 +484,7 @@ bidi_pop_embedding_level (struct bidi_it *bidi_it)
482 st = bidi_it->level_stack[bidi_it->stack_idx]; 484 st = bidi_it->level_stack[bidi_it->stack_idx];
483 if (isolate_status) 485 if (isolate_status)
484 { 486 {
487 bidi_dir_t sos = ((st.flags >> 3) & 1);
485 /* PREV is used in W1 for resolving WEAK_NSM. By the time 488 /* PREV is used in W1 for resolving WEAK_NSM. By the time
486 we get to an NSM, we must have gotten past at least one 489 we get to an NSM, we must have gotten past at least one
487 character: the PDI that ends the isolate from which we 490 character: the PDI that ends the isolate from which we
@@ -490,10 +493,11 @@ bidi_pop_embedding_level (struct bidi_it *bidi_it)
490 UNKNOWN_BT to be able to catch any blunders in this 493 UNKNOWN_BT to be able to catch any blunders in this
491 logic. */ 494 logic. */
492 bidi_it->prev.orig_type = bidi_it->prev.type = UNKNOWN_BT; 495 bidi_it->prev.orig_type = bidi_it->prev.type = UNKNOWN_BT;
493 bidi_it->last_strong = st.last_strong; 496 bidi_it->last_strong.type = st.last_strong_type;
494 bidi_it->prev_for_neutral = st.prev_for_neutral; 497 bidi_it->prev_for_neutral.type = st.prev_for_neutral_type;
495 bidi_it->next_for_neutral = st.next_for_neutral; 498 bidi_it->next_for_neutral.type = st.next_for_neutral_type;
496 bidi_it->sos = st.sos; 499 bidi_it->next_for_neutral.charpos = st.next_for_neutral_pos;
500 bidi_it->sos = (sos == 0 ? L2R : R2L);
497 } 501 }
498 else 502 else
499 bidi_set_sos_type (bidi_it, old_level, 503 bidi_set_sos_type (bidi_it, old_level,
@@ -1104,8 +1108,7 @@ bidi_line_init (struct bidi_it *bidi_it)
1104 bidi_it->scan_dir = 1; /* FIXME: do we need to have control on this? */ 1108 bidi_it->scan_dir = 1; /* FIXME: do we need to have control on this? */
1105 bidi_it->stack_idx = 0; 1109 bidi_it->stack_idx = 0;
1106 bidi_it->resolved_level = bidi_it->level_stack[0].level; 1110 bidi_it->resolved_level = bidi_it->level_stack[0].level;
1107 bidi_it->level_stack[0].override = NEUTRAL_DIR; /* X1 */ 1111 bidi_it->level_stack[0].flags = 0; /* NEUTRAL_DIR, false per X1 */
1108 bidi_it->level_stack[0].isolate_status = false; /* X1 */
1109 bidi_it->invalid_levels = 0; 1112 bidi_it->invalid_levels = 0;
1110 bidi_it->isolate_level = 0; /* X1 */ 1113 bidi_it->isolate_level = 0; /* X1 */
1111 bidi_it->invalid_isolates = 0; /* X1 */ 1114 bidi_it->invalid_isolates = 0; /* X1 */
@@ -1858,8 +1861,8 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
1858 prev_type = NEUTRAL_B; 1861 prev_type = NEUTRAL_B;
1859 1862
1860 current_level = bidi_it->level_stack[bidi_it->stack_idx].level; /* X1 */ 1863 current_level = bidi_it->level_stack[bidi_it->stack_idx].level; /* X1 */
1861 override = bidi_it->level_stack[bidi_it->stack_idx].override; 1864 isolate_status = ISOLATE_STATUS (bidi_it, bidi_it->stack_idx);
1862 isolate_status = bidi_it->level_stack[bidi_it->stack_idx].isolate_status; 1865 override = OVERRIDE (bidi_it, bidi_it->stack_idx);
1863 new_level = current_level; 1866 new_level = current_level;
1864 1867
1865 if (bidi_it->charpos >= (string_p ? bidi_it->string.schars : ZV)) 1868 if (bidi_it->charpos >= (string_p ? bidi_it->string.schars : ZV))
@@ -2033,7 +2036,7 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
2033 else if (bidi_it->isolate_level > 0) 2036 else if (bidi_it->isolate_level > 0)
2034 { 2037 {
2035 bidi_it->invalid_levels = 0; 2038 bidi_it->invalid_levels = 0;
2036 while (!bidi_it->level_stack[bidi_it->stack_idx].isolate_status) 2039 while (!ISOLATE_STATUS (bidi_it, bidi_it->stack_idx))
2037 bidi_pop_embedding_level (bidi_it); 2040 bidi_pop_embedding_level (bidi_it);
2038 eassert (bidi_it->stack_idx > 0); 2041 eassert (bidi_it->stack_idx > 0);
2039 new_level = bidi_pop_embedding_level (bidi_it); 2042 new_level = bidi_pop_embedding_level (bidi_it);
@@ -2041,12 +2044,15 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
2041 } 2044 }
2042 bidi_it->resolved_level = new_level; 2045 bidi_it->resolved_level = new_level;
2043 /* Unicode 8.0 correction. */ 2046 /* Unicode 8.0 correction. */
2044 if (bidi_it->level_stack[bidi_it->stack_idx].override == L2R) 2047 {
2045 bidi_it->type_after_wn = STRONG_L; 2048 bidi_dir_t stack_override = OVERRIDE (bidi_it, bidi_it->stack_idx);
2046 else if (bidi_it->level_stack[bidi_it->stack_idx].override == R2L) 2049 if (stack_override == L2R)
2047 bidi_it->type_after_wn = STRONG_R; 2050 bidi_it->type_after_wn = STRONG_L;
2048 else 2051 else if (stack_override == R2L)
2049 bidi_it->type_after_wn = type; 2052 bidi_it->type_after_wn = STRONG_R;
2053 else
2054 bidi_it->type_after_wn = type;
2055 }
2050 break; 2056 break;
2051 case PDF: /* X7 */ 2057 case PDF: /* X7 */
2052 bidi_it->type_after_wn = type; 2058 bidi_it->type_after_wn = type;
@@ -2089,7 +2095,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
2089 ? bidi_it->string.schars : ZV); 2095 ? bidi_it->string.schars : ZV);
2090 2096
2091 type = bidi_it->type; 2097 type = bidi_it->type;
2092 override = bidi_it->level_stack[bidi_it->stack_idx].override; 2098 override = OVERRIDE (bidi_it, bidi_it->stack_idx);
2093 2099
2094 eassert (!(type == UNKNOWN_BT 2100 eassert (!(type == UNKNOWN_BT
2095 || type == LRE 2101 || type == LRE
@@ -2557,9 +2563,9 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it)
2557 /* Skip level runs excluded from this isolating run sequence. */ 2563 /* Skip level runs excluded from this isolating run sequence. */
2558 new_sidx = bidi_it->stack_idx; 2564 new_sidx = bidi_it->stack_idx;
2559 if (bidi_it->level_stack[new_sidx].level > current_level 2565 if (bidi_it->level_stack[new_sidx].level > current_level
2560 && (bidi_it->level_stack[new_sidx].isolate_status 2566 && (ISOLATE_STATUS (bidi_it, new_sidx)
2561 || (new_sidx > old_sidx + 1 2567 || (new_sidx > old_sidx + 1
2562 && bidi_it->level_stack[new_sidx - 1].isolate_status))) 2568 && ISOLATE_STATUS (bidi_it, new_sidx - 1))))
2563 { 2569 {
2564 while (bidi_it->level_stack[bidi_it->stack_idx].level 2570 while (bidi_it->level_stack[bidi_it->stack_idx].level
2565 > current_level) 2571 > current_level)
@@ -2729,7 +2735,7 @@ bidi_resolve_brackets (struct bidi_it *bidi_it)
2729 the prev_for_neutral and next_for_neutral information, so 2735 the prev_for_neutral and next_for_neutral information, so
2730 that it will be picked up when we advance to that next run. */ 2736 that it will be picked up when we advance to that next run. */
2731 if (bidi_it->level_stack[bidi_it->stack_idx].level > prev_level 2737 if (bidi_it->level_stack[bidi_it->stack_idx].level > prev_level
2732 && bidi_it->level_stack[bidi_it->stack_idx].isolate_status) 2738 && ISOLATE_STATUS (bidi_it, bidi_it->stack_idx))
2733 { 2739 {
2734 bidi_record_type_for_neutral (&prev_for_neutral, prev_level, 0); 2740 bidi_record_type_for_neutral (&prev_for_neutral, prev_level, 0);
2735 bidi_record_type_for_neutral (&next_for_neutral, prev_level, 1); 2741 bidi_record_type_for_neutral (&next_for_neutral, prev_level, 1);
@@ -2919,14 +2925,14 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
2919 /* Skip level runs excluded from this isolating run sequence. */ 2925 /* Skip level runs excluded from this isolating run sequence. */
2920 new_sidx = bidi_it->stack_idx; 2926 new_sidx = bidi_it->stack_idx;
2921 if (bidi_it->level_stack[new_sidx].level > current_level 2927 if (bidi_it->level_stack[new_sidx].level > current_level
2922 && (bidi_it->level_stack[new_sidx].isolate_status 2928 && (ISOLATE_STATUS (bidi_it, new_sidx)
2923 /* This is for when we have an isolate initiator 2929 /* This is for when we have an isolate initiator
2924 immediately followed by an embedding or 2930 immediately followed by an embedding or
2925 override initiator, in which case we get the 2931 override initiator, in which case we get the
2926 level stack pushed twice by the single call to 2932 level stack pushed twice by the single call to
2927 bidi_resolve_weak above. */ 2933 bidi_resolve_weak above. */
2928 || (new_sidx > old_sidx + 1 2934 || (new_sidx > old_sidx + 1
2929 && bidi_it->level_stack[new_sidx - 1].isolate_status))) 2935 && ISOLATE_STATUS (bidi_it, new_sidx - 1))))
2930 { 2936 {
2931 while (bidi_it->level_stack[bidi_it->stack_idx].level 2937 while (bidi_it->level_stack[bidi_it->stack_idx].level
2932 > current_level) 2938 > current_level)
diff --git a/src/dispextern.h b/src/dispextern.h
index 0ee5fd62f7d..5510a1f50c1 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1908,7 +1908,7 @@ typedef enum {
1908} bidi_bracket_type_t; 1908} bidi_bracket_type_t;
1909 1909
1910/* The basic directionality data type. */ 1910/* The basic directionality data type. */
1911typedef enum { NEUTRAL_DIR, L2R, R2L } bidi_dir_t; 1911typedef enum { NEUTRAL_DIR = 0, L2R, R2L } bidi_dir_t;
1912 1912
1913/* Data type for storing information about characters we need to 1913/* Data type for storing information about characters we need to
1914 remember. */ 1914 remember. */
@@ -1920,15 +1920,16 @@ struct bidi_saved_info {
1920 1920
1921/* Data type for keeping track of information about saved embedding 1921/* Data type for keeping track of information about saved embedding
1922 levels, override status, isolate status, and isolating sequence 1922 levels, override status, isolate status, and isolating sequence
1923 runs. */ 1923 runs. This should be as tightly packed as possible, because there
1924 are 127 such entries in each iterator state, and so the size of
1925 cache is directly affected by the size of this struct. */
1924struct bidi_stack { 1926struct bidi_stack {
1925 struct bidi_saved_info last_strong; 1927 ptrdiff_t next_for_neutral_pos;
1926 struct bidi_saved_info next_for_neutral; 1928 unsigned next_for_neutral_type : 3;
1927 struct bidi_saved_info prev_for_neutral; 1929 unsigned last_strong_type : 3;
1928 unsigned level : 7; 1930 unsigned prev_for_neutral_type : 3;
1929 bool_bf isolate_status : 1; 1931 unsigned char level;
1930 unsigned override : 2; 1932 unsigned char flags; /* sos, override, isolate_status */
1931 unsigned sos : 2;
1932}; 1933};
1933 1934
1934/* Data type for storing information about a string being iterated on. */ 1935/* Data type for storing information about a string being iterated on. */