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.
This commit is contained in:
parent
96e6fd3c15
commit
fcc4da3e52
3 changed files with 63 additions and 38 deletions
|
@ -1,3 +1,21 @@
|
|||
2014-12-05 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* 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 <monnier@iro.umontreal.ca>
|
||||
|
||||
* eval.c (backtrace_eval_unrewind): Rewind also the excursions.
|
||||
|
|
64
src/bidi.c
64
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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Add table
Reference in a new issue