aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c66
1 files changed, 45 insertions, 21 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 07775391bfb..93146526118 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -349,14 +349,23 @@ static void
349mark_interval_tree (tree) 349mark_interval_tree (tree)
350 register INTERVAL tree; 350 register INTERVAL tree;
351{ 351{
352 if (XMARKBIT (tree->plist)) 352 /* No need to test if this tree has been marked already; this
353 return; 353 function is always called through the MARK_INTERVAL_TREE macro,
354 which takes care of that. */
355
356 /* XMARK expands to an assignment; the LHS of an assignment can't be
357 a cast. */
358 XMARK (* (Lisp_Object *) &tree->parent);
354 359
355 traverse_intervals (tree, 1, 0, mark_interval, Qnil); 360 traverse_intervals (tree, 1, 0, mark_interval, Qnil);
356} 361}
357 362
358#define MARK_INTERVAL_TREE(i) \ 363#define MARK_INTERVAL_TREE(i) \
359 { if (!NULL_INTERVAL_P (i)) mark_interval_tree (i); } 364 do { \
365 if (!NULL_INTERVAL_P (i) \
366 && ! XMARKBIT ((Lisp_Object) i->parent)) \
367 mark_interval_tree (i); \
368 } while (0)
360 369
361/* The oddity in the call to XUNMARK is necessary because XUNMARK 370/* The oddity in the call to XUNMARK is necessary because XUNMARK
362 expands to an assignment to its argument, and most C compilers don't 371 expands to an assignment to its argument, and most C compilers don't
@@ -1957,25 +1966,30 @@ gc_sweep ()
1957 /* Free all "large strings" not marked with ARRAY_MARK_FLAG. */ 1966 /* Free all "large strings" not marked with ARRAY_MARK_FLAG. */
1958 { 1967 {
1959 register struct string_block *sb = large_string_blocks, *prev = 0, *next; 1968 register struct string_block *sb = large_string_blocks, *prev = 0, *next;
1969 struct Lisp_String *s;
1960 1970
1961 while (sb) 1971 while (sb)
1962 if (!(((struct Lisp_String *)(&sb->chars[0]))->size & ARRAY_MARK_FLAG)) 1972 {
1963 { 1973 s = (struct Lisp_String *) &sb->chars[0];
1964 if (prev) 1974 if (s->size & ARRAY_MARK_FLAG)
1965 prev->next = sb->next; 1975 {
1966 else 1976 ((struct Lisp_String *)(&sb->chars[0]))->size
1967 large_string_blocks = sb->next; 1977 &= ~ARRAY_MARK_FLAG & ~MARKBIT;
1968 next = sb->next; 1978 UNMARK_BALANCE_INTERVALS (s->intervals);
1969 xfree (sb); 1979 total_string_size += ((struct Lisp_String *)(&sb->chars[0]))->size;
1970 sb = next; 1980 prev = sb, sb = sb->next;
1971 } 1981 }
1972 else 1982 else
1973 { 1983 {
1974 ((struct Lisp_String *)(&sb->chars[0]))->size 1984 if (prev)
1975 &= ~ARRAY_MARK_FLAG & ~MARKBIT; 1985 prev->next = sb->next;
1976 total_string_size += ((struct Lisp_String *)(&sb->chars[0]))->size; 1986 else
1977 prev = sb, sb = sb->next; 1987 large_string_blocks = sb->next;
1978 } 1988 next = sb->next;
1989 xfree (sb);
1990 sb = next;
1991 }
1992 }
1979 } 1993 }
1980} 1994}
1981 1995
@@ -2067,6 +2081,16 @@ compact_strings ()
2067 } 2081 }
2068 /* Store the actual size in the size field. */ 2082 /* Store the actual size in the size field. */
2069 newaddr->size = size; 2083 newaddr->size = size;
2084
2085 /* Now that the string has been relocated, rebalance its
2086 interval tree, and update the tree's parent pointer. */
2087 if (! NULL_INTERVAL_P (newaddr->intervals))
2088 {
2089 UNMARK_BALANCE_INTERVALS (newaddr->intervals);
2090 XSET (* (Lisp_Object *) &newaddr->intervals->parent,
2091 Lisp_String,
2092 newaddr);
2093 }
2070 } 2094 }
2071 pos += STRING_FULLSIZE (size); 2095 pos += STRING_FULLSIZE (size);
2072 } 2096 }