diff options
| author | Paul Eggert | 2013-06-21 13:11:44 -0700 |
|---|---|---|
| committer | Paul Eggert | 2013-06-21 13:11:44 -0700 |
| commit | fbe9e0b9fb6a250674e7619e9ba794e74ff5f0bc (patch) | |
| tree | 7b1836faca02f39413afec531c2ae467898523f5 /src/alloc.c | |
| parent | cad5d1cb5af7210154814b60825576d14740158f (diff) | |
| download | emacs-fbe9e0b9fb6a250674e7619e9ba794e74ff5f0bc.tar.gz emacs-fbe9e0b9fb6a250674e7619e9ba794e74ff5f0bc.zip | |
Use C99-style flexible array members if available.
This avoids some subtle aliasing issues, which typically
aren't a problem with GCC but may be a problem elsewhere.
* lib-src/ebrowse.c (struct member, struct alias, struct sym):
Use FLEXIBLE_ARRAY_MEMBER.
(add_sym, add_member, make_namespace, register_namespace_alias):
Use offsetof (struct, flex_array_member), not sizeof (struct), as
that ports better to pre-C99 non-GCC.
* src/alloc.c (sdata): New typedef, replacing the old struct sdata.
It is a struct if GC_CHECK_STRING_BYTES, a union otherwise.
In either case, it uses a flexible array member rather than
the old struct hack. All uses changed.
(SDATA_NBYTES, sweep_strings) [!GC_CHECK_STRING_BYTES]:
Adjust to sdata reorganization.
* src/alloc.c (VBLOCK_BYTES_MIN, allocate_vectorlike, Fgarbage_collect):
Use offsetof (struct, flex_array_member), not sizeof (struct), as
that ports better to pre-C99 non-GCC.
* src/chartab.c (Fmake_char_table, make_sub_char_table, copy_char_table):
Use CHAR_TABLE_STANDARD_SLOTS rather than its definition,
as the latter has changed.
* src/conf_post.h (FLEXIBLE_ARRAY_MEMBER): Move here from w32.c,
and port better to pre-C99 GCC.
* src/image.c (struct xpm_cached_color):
* src/lisp.h (struct Lisp_Vector, struct Lisp_Bool_Vector)
(struct Lisp_Char_Table, struct Lisp_Sub_Char_Table):
Use FLEXIBLE_ARRAY_MEMBER.
* src/lisp.h (string_bytes) [GC_CHECK_STRING_BYTES]:
Move decl to top level so it gets checked against implementation.
(CHAR_TABLE_STANDARD_SLOTS): Adjust to struct Lisp_Char_Table change.
* src/w32.c (FLEXIBLE_ARRAY_MEMBER): Move to conf_post.h.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 80 |
1 files changed, 46 insertions, 34 deletions
diff --git a/src/alloc.c b/src/alloc.c index d277dd2419b..eaef0d4b797 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -1260,7 +1260,7 @@ mark_interval (register INTERVAL i, Lisp_Object dummy) | |||
| 1260 | When a Lisp_String is freed during GC, it is put back on | 1260 | When a Lisp_String is freed during GC, it is put back on |
| 1261 | string_free_list, and its `data' member and its sdata's `string' | 1261 | string_free_list, and its `data' member and its sdata's `string' |
| 1262 | pointer is set to null. The size of the string is recorded in the | 1262 | pointer is set to null. The size of the string is recorded in the |
| 1263 | `u.nbytes' member of the sdata. So, sdata structures that are no | 1263 | `n.nbytes' member of the sdata. So, sdata structures that are no |
| 1264 | longer used, can be easily recognized, and it's easy to compact the | 1264 | longer used, can be easily recognized, and it's easy to compact the |
| 1265 | sblocks of small strings which we do in compact_small_strings. */ | 1265 | sblocks of small strings which we do in compact_small_strings. */ |
| 1266 | 1266 | ||
| @@ -1274,10 +1274,12 @@ mark_interval (register INTERVAL i, Lisp_Object dummy) | |||
| 1274 | 1274 | ||
| 1275 | #define LARGE_STRING_BYTES 1024 | 1275 | #define LARGE_STRING_BYTES 1024 |
| 1276 | 1276 | ||
| 1277 | /* Structure describing string memory sub-allocated from an sblock. | 1277 | /* Struct or union describing string memory sub-allocated from an sblock. |
| 1278 | This is where the contents of Lisp strings are stored. */ | 1278 | This is where the contents of Lisp strings are stored. */ |
| 1279 | 1279 | ||
| 1280 | struct sdata | 1280 | #ifdef GC_CHECK_STRING_BYTES |
| 1281 | |||
| 1282 | typedef struct | ||
| 1281 | { | 1283 | { |
| 1282 | /* Back-pointer to the string this sdata belongs to. If null, this | 1284 | /* Back-pointer to the string this sdata belongs to. If null, this |
| 1283 | structure is free, and the NBYTES member of the union below | 1285 | structure is free, and the NBYTES member of the union below |
| @@ -1287,34 +1289,42 @@ struct sdata | |||
| 1287 | contents. */ | 1289 | contents. */ |
| 1288 | struct Lisp_String *string; | 1290 | struct Lisp_String *string; |
| 1289 | 1291 | ||
| 1290 | #ifdef GC_CHECK_STRING_BYTES | ||
| 1291 | |||
| 1292 | ptrdiff_t nbytes; | 1292 | ptrdiff_t nbytes; |
| 1293 | unsigned char data[1]; | 1293 | unsigned char data[FLEXIBLE_ARRAY_MEMBER]; |
| 1294 | } sdata; | ||
| 1294 | 1295 | ||
| 1295 | #define SDATA_NBYTES(S) (S)->nbytes | 1296 | #define SDATA_NBYTES(S) (S)->nbytes |
| 1296 | #define SDATA_DATA(S) (S)->data | 1297 | #define SDATA_DATA(S) (S)->data |
| 1297 | #define SDATA_SELECTOR(member) member | 1298 | #define SDATA_SELECTOR(member) member |
| 1298 | 1299 | ||
| 1299 | #else /* not GC_CHECK_STRING_BYTES */ | 1300 | #else |
| 1300 | 1301 | ||
| 1301 | union | 1302 | typedef union |
| 1303 | { | ||
| 1304 | struct Lisp_String *string; | ||
| 1305 | |||
| 1306 | /* When STRING is non-null. */ | ||
| 1307 | struct | ||
| 1302 | { | 1308 | { |
| 1303 | /* When STRING is non-null. */ | 1309 | struct Lisp_String *string; |
| 1304 | unsigned char data[1]; | 1310 | unsigned char data[FLEXIBLE_ARRAY_MEMBER]; |
| 1311 | } u; | ||
| 1305 | 1312 | ||
| 1306 | /* When STRING is null. */ | 1313 | /* When STRING is null. */ |
| 1314 | struct | ||
| 1315 | { | ||
| 1316 | struct Lisp_String *string; | ||
| 1307 | ptrdiff_t nbytes; | 1317 | ptrdiff_t nbytes; |
| 1308 | } u; | 1318 | } n; |
| 1319 | } sdata; | ||
| 1309 | 1320 | ||
| 1310 | #define SDATA_NBYTES(S) (S)->u.nbytes | 1321 | #define SDATA_NBYTES(S) (S)->n.nbytes |
| 1311 | #define SDATA_DATA(S) (S)->u.data | 1322 | #define SDATA_DATA(S) (S)->u.data |
| 1312 | #define SDATA_SELECTOR(member) u.member | 1323 | #define SDATA_SELECTOR(member) u.member |
| 1313 | 1324 | ||
| 1314 | #endif /* not GC_CHECK_STRING_BYTES */ | 1325 | #endif /* not GC_CHECK_STRING_BYTES */ |
| 1315 | 1326 | ||
| 1316 | #define SDATA_DATA_OFFSET offsetof (struct sdata, SDATA_SELECTOR (data)) | 1327 | #define SDATA_DATA_OFFSET offsetof (sdata, SDATA_SELECTOR (data)) |
| 1317 | }; | ||
| 1318 | 1328 | ||
| 1319 | 1329 | ||
| 1320 | /* Structure describing a block of memory which is sub-allocated to | 1330 | /* Structure describing a block of memory which is sub-allocated to |
| @@ -1329,10 +1339,10 @@ struct sblock | |||
| 1329 | 1339 | ||
| 1330 | /* Pointer to the next free sdata block. This points past the end | 1340 | /* Pointer to the next free sdata block. This points past the end |
| 1331 | of the sblock if there isn't any space left in this block. */ | 1341 | of the sblock if there isn't any space left in this block. */ |
| 1332 | struct sdata *next_free; | 1342 | sdata *next_free; |
| 1333 | 1343 | ||
| 1334 | /* Start of data. */ | 1344 | /* Start of data. */ |
| 1335 | struct sdata first_data; | 1345 | sdata first_data; |
| 1336 | }; | 1346 | }; |
| 1337 | 1347 | ||
| 1338 | /* Number of Lisp strings in a string_block structure. The 1020 is | 1348 | /* Number of Lisp strings in a string_block structure. The 1020 is |
| @@ -1388,7 +1398,7 @@ static EMACS_INT total_string_bytes; | |||
| 1388 | a pointer to the `u.data' member of its sdata structure; the | 1398 | a pointer to the `u.data' member of its sdata structure; the |
| 1389 | structure starts at a constant offset in front of that. */ | 1399 | structure starts at a constant offset in front of that. */ |
| 1390 | 1400 | ||
| 1391 | #define SDATA_OF_STRING(S) ((struct sdata *) ((S)->data - SDATA_DATA_OFFSET)) | 1401 | #define SDATA_OF_STRING(S) ((sdata *) ((S)->data - SDATA_DATA_OFFSET)) |
| 1392 | 1402 | ||
| 1393 | 1403 | ||
| 1394 | #ifdef GC_CHECK_STRING_OVERRUN | 1404 | #ifdef GC_CHECK_STRING_OVERRUN |
| @@ -1487,7 +1497,7 @@ string_bytes (struct Lisp_String *s) | |||
| 1487 | static void | 1497 | static void |
| 1488 | check_sblock (struct sblock *b) | 1498 | check_sblock (struct sblock *b) |
| 1489 | { | 1499 | { |
| 1490 | struct sdata *from, *end, *from_end; | 1500 | sdata *from, *end, *from_end; |
| 1491 | 1501 | ||
| 1492 | end = b->next_free; | 1502 | end = b->next_free; |
| 1493 | 1503 | ||
| @@ -1501,7 +1511,7 @@ check_sblock (struct sblock *b) | |||
| 1501 | same as the one recorded in the sdata structure. */ | 1511 | same as the one recorded in the sdata structure. */ |
| 1502 | nbytes = SDATA_SIZE (from->string ? string_bytes (from->string) | 1512 | nbytes = SDATA_SIZE (from->string ? string_bytes (from->string) |
| 1503 | : SDATA_NBYTES (from)); | 1513 | : SDATA_NBYTES (from)); |
| 1504 | from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); | 1514 | from_end = (sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); |
| 1505 | } | 1515 | } |
| 1506 | } | 1516 | } |
| 1507 | 1517 | ||
| @@ -1631,7 +1641,7 @@ void | |||
| 1631 | allocate_string_data (struct Lisp_String *s, | 1641 | allocate_string_data (struct Lisp_String *s, |
| 1632 | EMACS_INT nchars, EMACS_INT nbytes) | 1642 | EMACS_INT nchars, EMACS_INT nbytes) |
| 1633 | { | 1643 | { |
| 1634 | struct sdata *data, *old_data; | 1644 | sdata *data, *old_data; |
| 1635 | struct sblock *b; | 1645 | struct sblock *b; |
| 1636 | ptrdiff_t needed, old_nbytes; | 1646 | ptrdiff_t needed, old_nbytes; |
| 1637 | 1647 | ||
| @@ -1701,7 +1711,7 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1701 | b = current_sblock; | 1711 | b = current_sblock; |
| 1702 | 1712 | ||
| 1703 | data = b->next_free; | 1713 | data = b->next_free; |
| 1704 | b->next_free = (struct sdata *) ((char *) data + needed + GC_STRING_EXTRA); | 1714 | b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA); |
| 1705 | 1715 | ||
| 1706 | MALLOC_UNBLOCK_INPUT; | 1716 | MALLOC_UNBLOCK_INPUT; |
| 1707 | 1717 | ||
| @@ -1772,7 +1782,7 @@ sweep_strings (void) | |||
| 1772 | else | 1782 | else |
| 1773 | { | 1783 | { |
| 1774 | /* String is dead. Put it on the free-list. */ | 1784 | /* String is dead. Put it on the free-list. */ |
| 1775 | struct sdata *data = SDATA_OF_STRING (s); | 1785 | sdata *data = SDATA_OF_STRING (s); |
| 1776 | 1786 | ||
| 1777 | /* Save the size of S in its sdata so that we know | 1787 | /* Save the size of S in its sdata so that we know |
| 1778 | how large that is. Reset the sdata's string | 1788 | how large that is. Reset the sdata's string |
| @@ -1781,7 +1791,7 @@ sweep_strings (void) | |||
| 1781 | if (string_bytes (s) != SDATA_NBYTES (data)) | 1791 | if (string_bytes (s) != SDATA_NBYTES (data)) |
| 1782 | emacs_abort (); | 1792 | emacs_abort (); |
| 1783 | #else | 1793 | #else |
| 1784 | data->u.nbytes = STRING_BYTES (s); | 1794 | data->n.nbytes = STRING_BYTES (s); |
| 1785 | #endif | 1795 | #endif |
| 1786 | data->string = NULL; | 1796 | data->string = NULL; |
| 1787 | 1797 | ||
| @@ -1862,13 +1872,13 @@ static void | |||
| 1862 | compact_small_strings (void) | 1872 | compact_small_strings (void) |
| 1863 | { | 1873 | { |
| 1864 | struct sblock *b, *tb, *next; | 1874 | struct sblock *b, *tb, *next; |
| 1865 | struct sdata *from, *to, *end, *tb_end; | 1875 | sdata *from, *to, *end, *tb_end; |
| 1866 | struct sdata *to_end, *from_end; | 1876 | sdata *to_end, *from_end; |
| 1867 | 1877 | ||
| 1868 | /* TB is the sblock we copy to, TO is the sdata within TB we copy | 1878 | /* TB is the sblock we copy to, TO is the sdata within TB we copy |
| 1869 | to, and TB_END is the end of TB. */ | 1879 | to, and TB_END is the end of TB. */ |
| 1870 | tb = oldest_sblock; | 1880 | tb = oldest_sblock; |
| 1871 | tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); | 1881 | tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE); |
| 1872 | to = &tb->first_data; | 1882 | to = &tb->first_data; |
| 1873 | 1883 | ||
| 1874 | /* Step through the blocks from the oldest to the youngest. We | 1884 | /* Step through the blocks from the oldest to the youngest. We |
| @@ -1897,7 +1907,7 @@ compact_small_strings (void) | |||
| 1897 | eassert (nbytes <= LARGE_STRING_BYTES); | 1907 | eassert (nbytes <= LARGE_STRING_BYTES); |
| 1898 | 1908 | ||
| 1899 | nbytes = SDATA_SIZE (nbytes); | 1909 | nbytes = SDATA_SIZE (nbytes); |
| 1900 | from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); | 1910 | from_end = (sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); |
| 1901 | 1911 | ||
| 1902 | #ifdef GC_CHECK_STRING_OVERRUN | 1912 | #ifdef GC_CHECK_STRING_OVERRUN |
| 1903 | if (memcmp (string_overrun_cookie, | 1913 | if (memcmp (string_overrun_cookie, |
| @@ -1910,14 +1920,14 @@ compact_small_strings (void) | |||
| 1910 | if (s) | 1920 | if (s) |
| 1911 | { | 1921 | { |
| 1912 | /* If TB is full, proceed with the next sblock. */ | 1922 | /* If TB is full, proceed with the next sblock. */ |
| 1913 | to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); | 1923 | to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); |
| 1914 | if (to_end > tb_end) | 1924 | if (to_end > tb_end) |
| 1915 | { | 1925 | { |
| 1916 | tb->next_free = to; | 1926 | tb->next_free = to; |
| 1917 | tb = tb->next; | 1927 | tb = tb->next; |
| 1918 | tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); | 1928 | tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE); |
| 1919 | to = &tb->first_data; | 1929 | to = &tb->first_data; |
| 1920 | to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); | 1930 | to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); |
| 1921 | } | 1931 | } |
| 1922 | 1932 | ||
| 1923 | /* Copy, and update the string's `data' pointer. */ | 1933 | /* Copy, and update the string's `data' pointer. */ |
| @@ -2581,7 +2591,7 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); | |||
| 2581 | 2591 | ||
| 2582 | /* Size of the minimal vector allocated from block. */ | 2592 | /* Size of the minimal vector allocated from block. */ |
| 2583 | 2593 | ||
| 2584 | #define VBLOCK_BYTES_MIN vroundup (sizeof (struct Lisp_Vector)) | 2594 | #define VBLOCK_BYTES_MIN vroundup (header_size + sizeof (Lisp_Object)) |
| 2585 | 2595 | ||
| 2586 | /* Size of the largest vector allocated from block. */ | 2596 | /* Size of the largest vector allocated from block. */ |
| 2587 | 2597 | ||
| @@ -2938,7 +2948,8 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 2938 | else | 2948 | else |
| 2939 | { | 2949 | { |
| 2940 | struct large_vector *lv | 2950 | struct large_vector *lv |
| 2941 | = lisp_malloc (sizeof (*lv) + (len - 1) * word_size, | 2951 | = lisp_malloc ((offsetof (struct large_vector, v.contents) |
| 2952 | + len * word_size), | ||
| 2942 | MEM_TYPE_VECTORLIKE); | 2953 | MEM_TYPE_VECTORLIKE); |
| 2943 | lv->next.vector = large_vectors; | 2954 | lv->next.vector = large_vectors; |
| 2944 | large_vectors = lv; | 2955 | large_vectors = lv; |
| @@ -5416,7 +5427,8 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5416 | total[4] = list3 (Qstring_bytes, make_number (1), | 5427 | total[4] = list3 (Qstring_bytes, make_number (1), |
| 5417 | bounded_number (total_string_bytes)); | 5428 | bounded_number (total_string_bytes)); |
| 5418 | 5429 | ||
| 5419 | total[5] = list3 (Qvectors, make_number (sizeof (struct Lisp_Vector)), | 5430 | total[5] = list3 (Qvectors, |
| 5431 | make_number (header_size + sizeof (Lisp_Object)), | ||
| 5420 | bounded_number (total_vectors)); | 5432 | bounded_number (total_vectors)); |
| 5421 | 5433 | ||
| 5422 | total[6] = list4 (Qvector_slots, make_number (word_size), | 5434 | total[6] = list4 (Qvector_slots, make_number (word_size), |