emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master fcc4da3: Reduce memory footprint of struct bidi_it


From: Eli Zaretskii
Subject: [Emacs-diffs] master fcc4da3: Reduce memory footprint of struct bidi_it by a factor of 5.
Date: Fri, 05 Dec 2014 10:19:18 +0000

branch: master
commit fcc4da3e5227f64b57e5e7ac497df28229b88f7d
Author: Eli Zaretskii <address@hidden>
Commit: Eli Zaretskii <address@hidden>

    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.
---
 src/ChangeLog    |   18 +++++++++++++++
 src/bidi.c       |   64 +++++++++++++++++++++++++++++------------------------
 src/dispextern.h |   19 ++++++++-------
 3 files changed, 63 insertions(+), 38 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index 2f64a97..82aabb3 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,21 @@
+2014-12-05  Eli Zaretskii  <address@hidden>
+
+       * 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'.
+
+       * 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.
+
 2014-12-04  Stefan Monnier  <address@hidden>
 
        * eval.c (backtrace_eval_unrewind): Rewind also the excursions.
diff --git a/src/bidi.c b/src/bidi.c
index a0bcf52..cc70d08 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)
     = bidi_it->next_for_neutral.orig_type = UNKNOWN_BT;
 }
 
+#define ISOLATE_STATUS(BIDI_IT, IDX)  ((BIDI_IT)->level_stack[IDX].flags & 1)
+#define OVERRIDE(BIDI_IT, IDX)  (((BIDI_IT)->level_stack[IDX].flags >> 1) & 3)
+
 /* Push the current embedding level and override status; reset the
    current level to LEVEL and the current override status to OVERRIDE.  */
 static void
@@ -447,14 +450,14 @@ bidi_push_embedding_level (struct bidi_it *bidi_it,
   st = &bidi_it->level_stack[bidi_it->stack_idx];
   eassert (level <= (1 << 7));
   st->level = level;
-  st->override = override;
-  st->isolate_status = isolate_status;
+  st->flags = (((override & 3) << 1) | (isolate_status != 0));
   if (isolate_status)
     {
-      st->last_strong = bidi_it->last_strong;
-      st->prev_for_neutral = bidi_it->prev_for_neutral;
-      st->next_for_neutral = bidi_it->next_for_neutral;
-      st->sos = bidi_it->sos;
+      st->last_strong_type = bidi_it->last_strong.type;
+      st->prev_for_neutral_type = bidi_it->prev_for_neutral.type;
+      st->next_for_neutral_type = bidi_it->next_for_neutral.type;
+      st->next_for_neutral_pos = bidi_it->next_for_neutral.charpos;
+      st->flags |= ((bidi_it->sos == L2R ? 0 : 1) << 3);
     }
   /* We've got a new isolating sequence, compute the directional type
      of sos and initialize per-sequence variables (UAX#9, clause X10).  */
@@ -473,8 +476,7 @@ bidi_pop_embedding_level (struct bidi_it *bidi_it)
      and PDIs (X6a, 2nd bullet).  */
   if (bidi_it->stack_idx > 0)
     {
-      bool isolate_status
-       = bidi_it->level_stack[bidi_it->stack_idx].isolate_status;
+      bool isolate_status = ISOLATE_STATUS (bidi_it, bidi_it->stack_idx);
       int old_level = bidi_it->level_stack[bidi_it->stack_idx].level;
 
       struct bidi_stack st;
@@ -482,6 +484,7 @@ bidi_pop_embedding_level (struct bidi_it *bidi_it)
       st = bidi_it->level_stack[bidi_it->stack_idx];
       if (isolate_status)
        {
+         bidi_dir_t sos = ((st.flags >> 3) & 1);
          /* PREV is used in W1 for resolving WEAK_NSM.  By the time
             we get to an NSM, we must have gotten past at least one
             character: the PDI that ends the isolate from which we
@@ -490,10 +493,11 @@ bidi_pop_embedding_level (struct bidi_it *bidi_it)
             UNKNOWN_BT to be able to catch any blunders in this
             logic.  */
          bidi_it->prev.orig_type = bidi_it->prev.type = UNKNOWN_BT;
-         bidi_it->last_strong = st.last_strong;
-         bidi_it->prev_for_neutral = st.prev_for_neutral;
-         bidi_it->next_for_neutral = st.next_for_neutral;
-         bidi_it->sos = st.sos;
+         bidi_it->last_strong.type = st.last_strong_type;
+         bidi_it->prev_for_neutral.type = st.prev_for_neutral_type;
+         bidi_it->next_for_neutral.type = st.next_for_neutral_type;
+         bidi_it->next_for_neutral.charpos = st.next_for_neutral_pos;
+         bidi_it->sos = (sos == 0 ? L2R : R2L);
        }
       else
        bidi_set_sos_type (bidi_it, old_level,
@@ -1104,8 +1108,7 @@ bidi_line_init (struct bidi_it *bidi_it)
   bidi_it->scan_dir = 1; /* FIXME: do we need to have control on this? */
   bidi_it->stack_idx = 0;
   bidi_it->resolved_level = bidi_it->level_stack[0].level;
-  bidi_it->level_stack[0].override = NEUTRAL_DIR; /* X1 */
-  bidi_it->level_stack[0].isolate_status = false; /* X1 */
+  bidi_it->level_stack[0].flags = 0; /* NEUTRAL_DIR, false per X1 */
   bidi_it->invalid_levels = 0;
   bidi_it->isolate_level = 0;   /* X1 */
   bidi_it->invalid_isolates = 0; /* X1 */
@@ -1858,8 +1861,8 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
     prev_type = NEUTRAL_B;
 
   current_level = bidi_it->level_stack[bidi_it->stack_idx].level; /* X1 */
-  override = bidi_it->level_stack[bidi_it->stack_idx].override;
-  isolate_status = bidi_it->level_stack[bidi_it->stack_idx].isolate_status;
+  isolate_status = ISOLATE_STATUS (bidi_it, bidi_it->stack_idx);
+  override = OVERRIDE (bidi_it, bidi_it->stack_idx);
   new_level = current_level;
 
   if (bidi_it->charpos >= (string_p ? bidi_it->string.schars : ZV))
@@ -2033,7 +2036,7 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
       else if (bidi_it->isolate_level > 0)
        {
          bidi_it->invalid_levels = 0;
-         while (!bidi_it->level_stack[bidi_it->stack_idx].isolate_status)
+         while (!ISOLATE_STATUS (bidi_it, bidi_it->stack_idx))
            bidi_pop_embedding_level (bidi_it);
          eassert (bidi_it->stack_idx > 0);
          new_level = bidi_pop_embedding_level (bidi_it);
@@ -2041,12 +2044,15 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
        }
       bidi_it->resolved_level = new_level;
       /* Unicode 8.0 correction.  */
-      if (bidi_it->level_stack[bidi_it->stack_idx].override == L2R)
-       bidi_it->type_after_wn = STRONG_L;
-      else if (bidi_it->level_stack[bidi_it->stack_idx].override == R2L)
-       bidi_it->type_after_wn = STRONG_R;
-      else
-       bidi_it->type_after_wn = type;
+      {
+       bidi_dir_t stack_override = OVERRIDE (bidi_it, bidi_it->stack_idx);
+       if (stack_override == L2R)
+         bidi_it->type_after_wn = STRONG_L;
+       else if (stack_override == R2L)
+         bidi_it->type_after_wn = STRONG_R;
+       else
+         bidi_it->type_after_wn = type;
+      }
       break;
     case PDF:  /* X7 */
       bidi_it->type_after_wn = type;
@@ -2089,7 +2095,7 @@ bidi_resolve_weak (struct bidi_it *bidi_it)
        ? bidi_it->string.schars : ZV);
 
   type = bidi_it->type;
-  override = bidi_it->level_stack[bidi_it->stack_idx].override;
+  override = OVERRIDE (bidi_it, bidi_it->stack_idx);
 
   eassert (!(type == UNKNOWN_BT
             || type == LRE
@@ -2557,9 +2563,9 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it)
          /* Skip level runs excluded from this isolating run sequence.  */
          new_sidx = bidi_it->stack_idx;
          if (bidi_it->level_stack[new_sidx].level > current_level
-             && (bidi_it->level_stack[new_sidx].isolate_status
+             && (ISOLATE_STATUS (bidi_it, new_sidx)
                  || (new_sidx > old_sidx + 1
-                     && bidi_it->level_stack[new_sidx - 1].isolate_status)))
+                     && ISOLATE_STATUS (bidi_it, new_sidx - 1))))
            {
              while (bidi_it->level_stack[bidi_it->stack_idx].level
                     > current_level)
@@ -2729,7 +2735,7 @@ bidi_resolve_brackets (struct bidi_it *bidi_it)
         the prev_for_neutral and next_for_neutral information, so
         that it will be picked up when we advance to that next run.  */
       if (bidi_it->level_stack[bidi_it->stack_idx].level > prev_level
-         && bidi_it->level_stack[bidi_it->stack_idx].isolate_status)
+         && ISOLATE_STATUS (bidi_it, bidi_it->stack_idx))
        {
          bidi_record_type_for_neutral (&prev_for_neutral, prev_level, 0);
          bidi_record_type_for_neutral (&next_for_neutral, prev_level, 1);
@@ -2919,14 +2925,14 @@ bidi_resolve_neutral (struct bidi_it *bidi_it)
            /* Skip level runs excluded from this isolating run sequence.  */
            new_sidx = bidi_it->stack_idx;
            if (bidi_it->level_stack[new_sidx].level > current_level
-               && (bidi_it->level_stack[new_sidx].isolate_status
+               && (ISOLATE_STATUS (bidi_it, new_sidx)
                    /* This is for when we have an isolate initiator
                       immediately followed by an embedding or
                       override initiator, in which case we get the
                       level stack pushed twice by the single call to
                       bidi_resolve_weak above.  */
                    || (new_sidx > old_sidx + 1
-                       && bidi_it->level_stack[new_sidx - 1].isolate_status)))
+                       && ISOLATE_STATUS (bidi_it, new_sidx - 1))))
              {
                while (bidi_it->level_stack[bidi_it->stack_idx].level
                       > current_level)
diff --git a/src/dispextern.h b/src/dispextern.h
index 0ee5fd6..5510a1f 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1908,7 +1908,7 @@ typedef enum {
 } bidi_bracket_type_t;
 
 /* The basic directionality data type.  */
-typedef enum { NEUTRAL_DIR, L2R, R2L } bidi_dir_t;
+typedef enum { NEUTRAL_DIR = 0, L2R, R2L } bidi_dir_t;
 
 /* Data type for storing information about characters we need to
    remember.  */
@@ -1920,15 +1920,16 @@ struct bidi_saved_info {
 
 /* Data type for keeping track of information about saved embedding
    levels, override status, isolate status, and isolating sequence
-   runs.  */
+   runs.  This should be as tightly packed as possible, because there
+   are 127 such entries in each iterator state, and so the size of
+   cache is directly affected by the size of this struct.  */
 struct bidi_stack {
-  struct bidi_saved_info last_strong;
-  struct bidi_saved_info next_for_neutral;
-  struct bidi_saved_info prev_for_neutral;
-  unsigned level : 7;
-  bool_bf isolate_status : 1;
-  unsigned override : 2;
-  unsigned sos : 2;
+  ptrdiff_t next_for_neutral_pos;
+  unsigned next_for_neutral_type : 3;
+  unsigned last_strong_type : 3;
+  unsigned prev_for_neutral_type : 3;
+  unsigned char level;
+  unsigned char flags;         /* sos, override, isolate_status */
 };
 
 /* Data type for storing information about a string being iterated on.  */



reply via email to

[Prev in Thread] Current Thread [Next in Thread]