summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2011-08-05 13:48:37 +0300
committerEli Zaretskii <eliz@gnu.org>2011-08-05 13:48:37 +0300
commitd736a7c36fca2e768e0cbea832dc6a06ce7a6485 (patch)
tree9a946cd630a0d11c013348f4fade526133b3061c /src
parentba30281389be9f7352e137eae5376fcc06a75522 (diff)
downloademacs-d736a7c36fca2e768e0cbea832dc6a06ce7a6485.tar.gz
Fix bug #9221 with resource allocation under word-wrap.
Add diagnostic facility for monitoring memory allocated for cache shelving. src/xdisp.c (display_line): Release buffer allocated for shelved bidi cache. (Bug#9221) src/bidi.c (bidi_shelve_cache, bidi_unshelve_cache): Track total amount allocated this far in `bidi_cache_total_alloc'. (bidi_unshelve_cache): Accept an additional argument JUST_FREE; if non-zero, only free the data buffer without restoring the cache contents. All callers changed. src/dispextern.h (bidi_unshelve_cache): Update prototype. src/xdisp.c (SAVE_IT, pos_visible_p, move_it_in_display_line_to) (move_it_in_display_line, move_it_to) (move_it_vertically_backward, move_it_by_lines): Replace the call to xfree to an equivalent call to bidi_unshelve_cache. (move_it_in_display_line_to): Fix logic of returning MOVE_POS_MATCH_OR_ZV in the bidi case.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog20
-rw-r--r--src/bidi.c76
-rw-r--r--src/dispextern.h2
-rw-r--r--src/dispnew.c2
-rw-r--r--src/indent.c2
-rw-r--r--src/window.c18
-rw-r--r--src/xdisp.c53
7 files changed, 110 insertions, 63 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 3f01f471abd..cea5da5865b 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,23 @@
+2011-08-05 Eli Zaretskii <eliz@gnu.org>
+
+ *xdisp.c (display_line): Release buffer allocated for shelved bidi
+ cache. (Bug#9221)
+
+ * bidi.c (bidi_shelve_cache, bidi_unshelve_cache): Track total
+ amount allocated this far in `bidi_cache_total_alloc'.
+ (bidi_unshelve_cache): Accept an additional argument JUST_FREE; if
+ non-zero, only free the data buffer without restoring the cache
+ contents. All callers changed.
+
+ * dispextern.h (bidi_unshelve_cache): Update prototype.
+
+ * xdisp.c (SAVE_IT, pos_visible_p, move_it_in_display_line_to)
+ (move_it_in_display_line, move_it_to)
+ (move_it_vertically_backward, move_it_by_lines): Replace the call
+ to xfree to an equivalent call to bidi_unshelve_cache.
+ (move_it_in_display_line_to): Fix logic of returning
+ MOVE_POS_MATCH_OR_ZV in the bidi case.
+
2011-07-24 Eli Zaretskii <eliz@gnu.org>
* xdisp.c (compute_display_string_pos): Fix logic of caching
diff --git a/src/bidi.c b/src/bidi.c
index 77043d9236f..a2ba60a7baf 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -609,12 +609,15 @@ bidi_pop_it (struct bidi_it *bidi_it)
bidi_cache_last_idx = -1;
}
+ptrdiff_t bidi_cache_total_alloc;
+
/* Stash away a copy of the cache and its control variables. */
void *
bidi_shelve_cache (void)
{
unsigned char *databuf;
+ /* Empty cache. */
if (bidi_cache_idx == 0)
return NULL;
@@ -623,6 +626,12 @@ bidi_shelve_cache (void)
+ sizeof (bidi_cache_start_stack)
+ sizeof (bidi_cache_sp) + sizeof (bidi_cache_start)
+ sizeof (bidi_cache_last_idx));
+ bidi_cache_total_alloc +=
+ sizeof (bidi_cache_idx) + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack)
+ + sizeof (bidi_cache_sp) + sizeof (bidi_cache_start)
+ + sizeof (bidi_cache_last_idx);
+
memcpy (databuf, &bidi_cache_idx, sizeof (bidi_cache_idx));
memcpy (databuf + sizeof (bidi_cache_idx),
bidi_cache, bidi_cache_idx * sizeof (struct bidi_it));
@@ -648,7 +657,7 @@ bidi_shelve_cache (void)
/* Restore the cache state from a copy stashed away by bidi_shelve_cache. */
void
-bidi_unshelve_cache (void *databuf)
+bidi_unshelve_cache (void *databuf, int just_free)
{
unsigned char *p = databuf;
@@ -661,30 +670,47 @@ bidi_unshelve_cache (void *databuf)
}
else
{
- memcpy (&bidi_cache_idx, p, sizeof (bidi_cache_idx));
- bidi_cache_ensure_space (bidi_cache_idx);
- memcpy (bidi_cache, p + sizeof (bidi_cache_idx),
- bidi_cache_idx * sizeof (struct bidi_it));
- memcpy (bidi_cache_start_stack,
- p + sizeof (bidi_cache_idx)
- + bidi_cache_idx * sizeof (struct bidi_it),
- sizeof (bidi_cache_start_stack));
- memcpy (&bidi_cache_sp,
- p + sizeof (bidi_cache_idx)
- + bidi_cache_idx * sizeof (struct bidi_it)
- + sizeof (bidi_cache_start_stack),
- sizeof (bidi_cache_sp));
- memcpy (&bidi_cache_start,
- p + sizeof (bidi_cache_idx)
- + bidi_cache_idx * sizeof (struct bidi_it)
- + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp),
- sizeof (bidi_cache_start));
- memcpy (&bidi_cache_last_idx,
- p + sizeof (bidi_cache_idx)
- + bidi_cache_idx * sizeof (struct bidi_it)
- + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
- + sizeof (bidi_cache_start),
- sizeof (bidi_cache_last_idx));
+ if (just_free)
+ {
+ ptrdiff_t idx;
+
+ memcpy (&idx, p, sizeof (bidi_cache_idx));
+ bidi_cache_total_alloc -=
+ sizeof (bidi_cache_idx) + idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
+ + sizeof (bidi_cache_start) + sizeof (bidi_cache_last_idx);
+ }
+ else
+ {
+ memcpy (&bidi_cache_idx, p, sizeof (bidi_cache_idx));
+ bidi_cache_ensure_space (bidi_cache_idx);
+ memcpy (bidi_cache, p + sizeof (bidi_cache_idx),
+ bidi_cache_idx * sizeof (struct bidi_it));
+ memcpy (bidi_cache_start_stack,
+ p + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it),
+ sizeof (bidi_cache_start_stack));
+ memcpy (&bidi_cache_sp,
+ p + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack),
+ sizeof (bidi_cache_sp));
+ memcpy (&bidi_cache_start,
+ p + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp),
+ sizeof (bidi_cache_start));
+ memcpy (&bidi_cache_last_idx,
+ p + sizeof (bidi_cache_idx)
+ + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
+ + sizeof (bidi_cache_start),
+ sizeof (bidi_cache_last_idx));
+ bidi_cache_total_alloc -=
+ sizeof (bidi_cache_idx) + bidi_cache_idx * sizeof (struct bidi_it)
+ + sizeof (bidi_cache_start_stack) + sizeof (bidi_cache_sp)
+ + sizeof (bidi_cache_start) + sizeof (bidi_cache_last_idx);
+ }
xfree (p);
}
diff --git a/src/dispextern.h b/src/dispextern.h
index 5bb72ff7600..32b4bbfab24 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2975,7 +2975,7 @@ extern int bidi_mirror_char (int);
extern void bidi_push_it (struct bidi_it *);
extern void bidi_pop_it (struct bidi_it *);
extern void *bidi_shelve_cache (void);
-extern void bidi_unshelve_cache (void *);
+extern void bidi_unshelve_cache (void *, int);
/* Defined in xdisp.c */
diff --git a/src/dispnew.c b/src/dispnew.c
index 69b32a5cd79..64fa5733741 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -5311,7 +5311,7 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
argument is ZV to prevent move_it_in_display_line from matching
based on buffer positions. */
move_it_in_display_line (&it, ZV, to_x, MOVE_TO_X);
- bidi_unshelve_cache (itdata);
+ bidi_unshelve_cache (itdata, 0);
Fset_buffer (old_current_buffer);
diff --git a/src/indent.c b/src/indent.c
index a73284c6657..3f7b3efe3b8 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -2135,7 +2135,7 @@ whether or not it is currently displayed in some window. */)
}
SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
- bidi_unshelve_cache (itdata);
+ bidi_unshelve_cache (itdata, 0);
}
if (BUFFERP (old_buffer))
diff --git a/src/window.c b/src/window.c
index 094cfcfbda3..d733dea5026 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1190,7 +1190,7 @@ if it isn't already recorded. */)
if (it.current_y < it.last_visible_y)
move_it_past_eol (&it);
value = make_number (IT_CHARPOS (it));
- bidi_unshelve_cache (itdata);
+ bidi_unshelve_cache (itdata, 0);
if (old_buffer)
set_buffer_internal (old_buffer);
@@ -4771,7 +4771,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
}
start = it.current.pos;
- bidi_unshelve_cache (itdata);
+ bidi_unshelve_cache (itdata, 0);
}
else if (auto_window_vscroll_p)
{
@@ -4915,7 +4915,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
}
else
{
- bidi_unshelve_cache (itdata);
+ bidi_unshelve_cache (itdata, 0);
if (noerror)
return;
else if (n < 0) /* could happen with empty buffers */
@@ -4932,7 +4932,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
w->vscroll = 0;
else
{
- bidi_unshelve_cache (itdata);
+ bidi_unshelve_cache (itdata, 0);
if (noerror)
return;
else
@@ -5081,7 +5081,7 @@ window_scroll_pixel_based (Lisp_Object window, int n, int whole, int noerror)
SET_PT_BOTH (charpos, bytepos);
}
}
- bidi_unshelve_cache (itdata);
+ bidi_unshelve_cache (itdata, 0);
}
@@ -5508,7 +5508,7 @@ displayed_window_lines (struct window *w)
start_display (&it, w, start);
move_it_vertically (&it, height);
bottom_y = line_bottom_y (&it);
- bidi_unshelve_cache (itdata);
+ bidi_unshelve_cache (itdata, 0);
/* rms: On a non-window display,
the value of it.vpos at the bottom of the screen
@@ -5614,7 +5614,7 @@ and redisplay normally--don't erase and redraw the frame. */)
move_it_vertically_backward (&it, window_box_height (w) / 2);
charpos = IT_CHARPOS (it);
bytepos = IT_BYTEPOS (it);
- bidi_unshelve_cache (itdata);
+ bidi_unshelve_cache (itdata, 0);
}
else if (iarg < 0)
{
@@ -5662,7 +5662,7 @@ and redisplay normally--don't erase and redraw the frame. */)
}
if (h <= 0)
{
- bidi_unshelve_cache (itdata);
+ bidi_unshelve_cache (itdata, 0);
return Qnil;
}
@@ -5685,7 +5685,7 @@ and redisplay normally--don't erase and redraw the frame. */)
charpos = IT_CHARPOS (it);
bytepos = IT_BYTEPOS (it);
- bidi_unshelve_cache (itdata);
+ bidi_unshelve_cache (itdata, 0);
}
else
{
diff --git a/src/xdisp.c b/src/xdisp.c
index 5f9e80cd11e..77bd4e5ee9a 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -604,7 +604,7 @@ int current_mode_line_height, current_header_line_height;
#define SAVE_IT(ITCOPY,ITORIG,CACHE) \
do { \
if (CACHE) \
- xfree (CACHE); \
+ bidi_unshelve_cache (CACHE, 1); \
ITCOPY = ITORIG; \
CACHE = bidi_shelve_cache(); \
} while (0)
@@ -613,7 +613,7 @@ int current_mode_line_height, current_header_line_height;
do { \
if (pITORIG != pITCOPY) \
*(pITORIG) = *(pITCOPY); \
- bidi_unshelve_cache (CACHE); \
+ bidi_unshelve_cache (CACHE, 0); \
CACHE = NULL; \
} while (0)
@@ -1341,9 +1341,9 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y,
*vpos = it2.vpos;
}
else
- xfree (it2data);
+ bidi_unshelve_cache (it2data, 1);
}
- bidi_unshelve_cache (itdata);
+ bidi_unshelve_cache (itdata, 0);
if (old_buffer)
set_buffer_internal_1 (old_buffer);
@@ -2629,7 +2629,7 @@ init_iterator (struct it *it, struct window *w,
it->paragraph_embedding = R2L;
else
it->paragraph_embedding = NEUTRAL_DIR;
- bidi_unshelve_cache (NULL);
+ bidi_unshelve_cache (NULL, 0);
bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
&it->bidi_it);
}
@@ -5635,7 +5635,7 @@ back_to_previous_visible_line_start (struct it *it)
pos = --IT_CHARPOS (it2);
--IT_BYTEPOS (it2);
it2.sp = 0;
- bidi_unshelve_cache (NULL);
+ bidi_unshelve_cache (NULL, 0);
it2.string_from_display_prop_p = 0;
it2.from_disp_prop_p = 0;
if (handle_display_prop (&it2) == HANDLED_RETURN
@@ -5827,7 +5827,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
{
bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
&it->bidi_it);
- bidi_unshelve_cache (NULL);
+ bidi_unshelve_cache (NULL, 0);
it->bidi_it.paragraph_dir = NEUTRAL_DIR;
it->bidi_it.string.s = NULL;
it->bidi_it.string.lstring = Qnil;
@@ -7995,13 +7995,13 @@ move_it_in_display_line_to (struct it *it,
positions smaller than TO_CHARPOS, return
MOVE_POS_MATCH_OR_ZV, like the unidirectional display
did. */
- if ((op & MOVE_TO_POS) != 0
+ if (it->bidi_p && (op & MOVE_TO_POS) != 0
&& !saw_smaller_pos
&& IT_CHARPOS (*it) > to_charpos)
{
- result = MOVE_POS_MATCH_OR_ZV;
- if (it->bidi_p && IT_CHARPOS (ppos_it) < ZV)
+ if (IT_CHARPOS (ppos_it) < ZV)
RESTORE_IT (it, &ppos_it, ppos_data);
+ goto buffer_pos_reached;
}
else
result = MOVE_NEWLINE_OR_CR;
@@ -8040,14 +8040,13 @@ move_it_in_display_line_to (struct it *it,
character positions smaller than TO_CHARPOS,
return MOVE_POS_MATCH_OR_ZV, like the
unidirectional display did. */
- || ((op & MOVE_TO_POS) != 0
+ || (it->bidi_p && (op & MOVE_TO_POS) != 0
&& !saw_smaller_pos
&& IT_CHARPOS (*it) > to_charpos))
{
- result = MOVE_POS_MATCH_OR_ZV;
- if (it->bidi_p && !at_eob_p && IT_CHARPOS (ppos_it) < ZV)
+ if (!at_eob_p && IT_CHARPOS (ppos_it) < ZV)
RESTORE_IT (it, &ppos_it, ppos_data);
- break;
+ goto buffer_pos_reached;
}
if (ITERATOR_AT_END_OF_LINE_P (it))
{
@@ -8055,14 +8054,13 @@ move_it_in_display_line_to (struct it *it,
break;
}
}
- else if ((op & MOVE_TO_POS) != 0
+ else if (it->bidi_p && (op & MOVE_TO_POS) != 0
&& !saw_smaller_pos
&& IT_CHARPOS (*it) > to_charpos)
{
- result = MOVE_POS_MATCH_OR_ZV;
- if (it->bidi_p && IT_CHARPOS (ppos_it) < ZV)
+ if (IT_CHARPOS (ppos_it) < ZV)
RESTORE_IT (it, &ppos_it, ppos_data);
- break;
+ goto buffer_pos_reached;
}
result = MOVE_LINE_TRUNCATED;
break;
@@ -8082,13 +8080,13 @@ move_it_in_display_line_to (struct it *it,
done:
if (atpos_data)
- xfree (atpos_data);
+ bidi_unshelve_cache (atpos_data, 1);
if (atx_data)
- xfree (atx_data);
+ bidi_unshelve_cache (atx_data, 1);
if (wrap_data)
- xfree (wrap_data);
+ bidi_unshelve_cache (wrap_data, 1);
if (ppos_data)
- xfree (ppos_data);
+ bidi_unshelve_cache (ppos_data, 1);
/* Restore the iterator settings altered at the beginning of this
function. */
@@ -8123,7 +8121,7 @@ move_it_in_display_line (struct it *it,
(it, -1, prev_x, MOVE_TO_X);
}
else
- xfree (save_data);
+ bidi_unshelve_cache (save_data, 1);
}
else
move_it_in_display_line_to (it, to_charpos, to_x, op);
@@ -8382,7 +8380,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos
}
if (backup_data)
- xfree (backup_data);
+ bidi_unshelve_cache (backup_data, 1);
TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
}
@@ -8461,7 +8459,7 @@ move_it_vertically_backward (struct it *it, int dy)
RESTORE_IT (it, it, it2data);
if (nlines > 0)
move_it_by_lines (it, nlines);
- xfree (it3data);
+ bidi_unshelve_cache (it3data, 1);
}
else
{
@@ -8657,7 +8655,7 @@ move_it_by_lines (struct it *it, int dvpos)
if (IT_CHARPOS (*it) >= start_charpos)
RESTORE_IT (it, &it2, it2data);
else
- xfree (it2data);
+ bidi_unshelve_cache (it2data, 1);
}
else
RESTORE_IT (it, it, it2data);
@@ -18764,6 +18762,9 @@ display_line (struct it *it)
}
}
+ if (wrap_data)
+ bidi_unshelve_cache (wrap_data, 1);
+
/* If line is not empty and hscrolled, maybe insert truncation glyphs
at the left window margin. */
if (it->first_visible_x