Mercurial > hg > xemacs-beta
comparison src/lrecord.h @ 3024:b7f26b2f78bd
[xemacs-hg @ 2005-10-25 08:32:40 by ben]
more mc-alloc-related factoring; make it hard to do the wrong thing
postgresql/postgresql.c, postgresql/postgresql.h: MC-Alloc refactoring.
ldap/eldap.c, ldap/eldap.h: MC-Alloc refactoring.
alloc.c, buffer.c, console.c, emacs.c, file-coding.c, lrecord.h, lstream.c, mule-charset.c, print.c, scrollbar-gtk.c, scrollbar-msw.c, scrollbar-x.c, scrollbar.c, symbols.c, symeval.h, unicode.c, window.c, xemacs.def.in.in: rename `struct lcrecord_header' to `struct old_lcrecord_header';
likewise for `old_basic_alloc_lcrecord', `old_free_lcrecord',
`old_zero_lcrecord', `old_zero_sized_lcrecord', `old_copy_lcrecord',
`old_copy_sized_lcrecord', `old_alloc_lcrecord_type'. Created new
LISPOBJ_STORAGE_SIZE() used only on objects created through allocation
of Lisp-Object memory instead of basic xmalloc()/xfree(). This is
distinguished from malloced_storage_size(), for non-Lisp-Objects.
The definition of LISPOBJ_STORAGE_SIZE() can reduce down to
malloced_storage_size() when not MC-ALLOC, but with MC-ALLOC it's
a different function.
The whole point other than cleaning up the use of LISPOBJ_STORAGE_SIZE
is to make it harder to accidentally use the old kind (lowercase) of
function in new code, since you get a compile error.
author | ben |
---|---|
date | Tue, 25 Oct 2005 08:32:50 +0000 |
parents | 1e7cc382eb16 |
children | 986cd22006a9 |
comparison
equal
deleted
inserted
replaced
3023:d305f4207861 | 3024:b7f26b2f78bd |
---|---|
65 routines in alloc.c to create an object of each such type. | 65 routines in alloc.c to create an object of each such type. |
66 | 66 |
67 Lcrecords are used for less common sorts of objects that don't do | 67 Lcrecords are used for less common sorts of objects that don't do |
68 their own allocation. Each such object is malloc()ed individually, | 68 their own allocation. Each such object is malloc()ed individually, |
69 and the objects are chained together through a `next' pointer. | 69 and the objects are chained together through a `next' pointer. |
70 Lcrecords have a `struct lcrecord_header' at the top, which | 70 Lcrecords have a `struct old_lcrecord_header' at the top, which |
71 contains a `struct lrecord_header' and a `next' pointer, and are | 71 contains a `struct lrecord_header' and a `next' pointer, and are |
72 allocated using alloc_lcrecord_type() or its variants. | 72 allocated using old_alloc_lcrecord_type() or its variants. |
73 | 73 |
74 Creating a new lcrecord type is fairly easy; just follow the | 74 Creating a new lcrecord type is fairly easy; just follow the |
75 lead of some existing type (e.g. hash tables). Note that you | 75 lead of some existing type (e.g. hash tables). Note that you |
76 do not need to supply all the methods (see below); reasonable | 76 do not need to supply all the methods (see below); reasonable |
77 defaults are provided for many of them. Alternatively, if you're | 77 defaults are provided for many of them. Alternatively, if you're |
78 just looking for a way of encapsulating data (which possibly | 78 just looking for a way of encapsulating data (which possibly |
79 could contain Lisp_Objects in it), you may well be able to use | 79 could contain Lisp_Objects in it), you may well be able to use |
80 the opaque type. --ben | 80 the opaque type. --ben |
81 */ | 81 */ |
82 #endif /* not MC_ALLOC */ | 82 #endif /* not MC_ALLOC */ |
83 | |
84 #ifdef MC_ALLOC | |
85 #define ALLOC_LCRECORD_TYPE alloc_lrecord_type | |
86 #define COPY_SIZED_LCRECORD copy_sized_lrecord | |
87 #define COPY_LCRECORD copy_lrecord | |
88 #define LISPOBJ_STORAGE_SIZE(ptr, size, stats) \ | |
89 mc_alloced_storage_size (size, stats) | |
90 #define ZERO_LCRECORD zero_lrecord | |
91 #define LCRECORD_HEADER lrecord_header | |
92 #define BASIC_ALLOC_LCRECORD alloc_lrecord | |
93 #define FREE_LCRECORD free_lrecord | |
94 #else | |
95 #define ALLOC_LCRECORD_TYPE old_alloc_lcrecord_type | |
96 #define COPY_SIZED_LCRECORD old_copy_sized_lcrecord | |
97 #define COPY_LCRECORD old_copy_lcrecord | |
98 #define LISPOBJ_STORAGE_SIZE malloced_storage_size | |
99 #define ZERO_LCRECORD old_zero_lcrecord | |
100 #define LCRECORD_HEADER old_lcrecord_header | |
101 #define BASIC_ALLOC_LCRECORD old_basic_alloc_lcrecord | |
102 #define FREE_LCRECORD old_free_lcrecord | |
103 #endif | |
83 | 104 |
84 BEGIN_C_DECLS | 105 BEGIN_C_DECLS |
85 | 106 |
86 struct lrecord_header | 107 struct lrecord_header |
87 { | 108 { |
143 SLI_header->lisp_readonly = 0; \ | 164 SLI_header->lisp_readonly = 0; \ |
144 } while (0) | 165 } while (0) |
145 #endif /* not MC_ALLOC */ | 166 #endif /* not MC_ALLOC */ |
146 | 167 |
147 #ifndef MC_ALLOC | 168 #ifndef MC_ALLOC |
148 struct lcrecord_header | 169 struct old_lcrecord_header |
149 { | 170 { |
150 struct lrecord_header lheader; | 171 struct lrecord_header lheader; |
151 | 172 |
152 /* The `next' field is normally used to chain all lcrecords together | 173 /* The `next' field is normally used to chain all lcrecords together |
153 so that the GC can find (and free) all of them. | 174 so that the GC can find (and free) all of them. |
154 `basic_alloc_lcrecord' threads lcrecords together. | 175 `old_basic_alloc_lcrecord' threads lcrecords together. |
155 | 176 |
156 The `next' field may be used for other purposes as long as some | 177 The `next' field may be used for other purposes as long as some |
157 other mechanism is provided for letting the GC do its work. | 178 other mechanism is provided for letting the GC do its work. |
158 | 179 |
159 For example, the event and marker object types allocate members | 180 For example, the event and marker object types allocate members |
160 out of memory chunks, and are able to find all unmarked members | 181 out of memory chunks, and are able to find all unmarked members |
161 by sweeping through the elements of the list of chunks. */ | 182 by sweeping through the elements of the list of chunks. */ |
162 struct lcrecord_header *next; | 183 struct old_lcrecord_header *next; |
163 | 184 |
164 /* The `uid' field is just for debugging/printing convenience. | 185 /* The `uid' field is just for debugging/printing convenience. |
165 Having this slot doesn't hurt us much spacewise, since an | 186 Having this slot doesn't hurt us much spacewise, since an |
166 lcrecord already has the above slots plus malloc overhead. */ | 187 lcrecord already has the above slots plus malloc overhead. */ |
167 unsigned int uid :31; | 188 unsigned int uid :31; |
177 }; | 198 }; |
178 | 199 |
179 /* Used for lcrecords in an lcrecord-list. */ | 200 /* Used for lcrecords in an lcrecord-list. */ |
180 struct free_lcrecord_header | 201 struct free_lcrecord_header |
181 { | 202 { |
182 struct lcrecord_header lcheader; | 203 struct old_lcrecord_header lcheader; |
183 Lisp_Object chain; | 204 Lisp_Object chain; |
184 }; | 205 }; |
185 #endif /* not MC_ALLOC */ | 206 #endif /* not MC_ALLOC */ |
186 | 207 |
187 enum lrecord_type | 208 enum lrecord_type |
342 | 363 |
343 #ifdef MC_ALLOC | 364 #ifdef MC_ALLOC |
344 /* Only one of `static_size' and `size_in_bytes_method' is non-0. */ | 365 /* Only one of `static_size' and `size_in_bytes_method' is non-0. */ |
345 #else /* not MC_ALLOC */ | 366 #else /* not MC_ALLOC */ |
346 /* Only one of `static_size' and `size_in_bytes_method' is non-0. | 367 /* Only one of `static_size' and `size_in_bytes_method' is non-0. |
347 If both are 0, this type is not instantiable by basic_alloc_lcrecord(). */ | 368 If both are 0, this type is not instantiable by |
369 old_basic_alloc_lcrecord(). */ | |
348 #endif /* not MC_ALLOC */ | 370 #endif /* not MC_ALLOC */ |
349 Bytecount static_size; | 371 Bytecount static_size; |
350 Bytecount (*size_in_bytes_method) (const void *header); | 372 Bytecount (*size_in_bytes_method) (const void *header); |
351 | 373 |
352 /* The (constant) index into lrecord_implementations_table */ | 374 /* The (constant) index into lrecord_implementations_table */ |
353 enum lrecord_type lrecord_type_index; | 375 enum lrecord_type lrecord_type_index; |
354 | 376 |
355 #ifndef MC_ALLOC | 377 #ifndef MC_ALLOC |
356 /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e. | 378 /* A "basic" lrecord is any lrecord that's not an lcrecord, i.e. |
357 one that does not have an lcrecord_header at the front and which | 379 one that does not have an old_lcrecord_header at the front and which |
358 is (usually) allocated in frob blocks. */ | 380 is (usually) allocated in frob blocks. */ |
359 unsigned int basic_p :1; | 381 unsigned int basic_p :1; |
360 #endif /* not MC_ALLOC */ | 382 #endif /* not MC_ALLOC */ |
361 }; | 383 }; |
362 | 384 |
1494 #ifndef MC_ALLOC | 1516 #ifndef MC_ALLOC |
1495 /*-------------------------- lcrecord-list -----------------------------*/ | 1517 /*-------------------------- lcrecord-list -----------------------------*/ |
1496 | 1518 |
1497 struct lcrecord_list | 1519 struct lcrecord_list |
1498 { | 1520 { |
1499 struct lcrecord_header header; | 1521 struct LCRECORD_HEADER header; |
1500 Lisp_Object free; | 1522 Lisp_Object free; |
1501 Elemcount size; | 1523 Elemcount size; |
1502 const struct lrecord_implementation *implementation; | 1524 const struct lrecord_implementation *implementation; |
1503 }; | 1525 }; |
1504 | 1526 |
1515 | 1537 |
1516 See above for a discussion of the difference between plain lrecords and | 1538 See above for a discussion of the difference between plain lrecords and |
1517 lrecords. lcrecords themselves are divided into three types: (1) | 1539 lrecords. lcrecords themselves are divided into three types: (1) |
1518 auto-managed, (2) hand-managed, and (3) unmanaged. "Managed" refers to | 1540 auto-managed, (2) hand-managed, and (3) unmanaged. "Managed" refers to |
1519 using a special object called an lcrecord-list to keep track of freed | 1541 using a special object called an lcrecord-list to keep track of freed |
1520 lcrecords, which can freed with free_lcrecord() or the like and later be | 1542 lcrecords, which can freed with FREE_LCRECORD() or the like and later be |
1521 recycled when a new lcrecord is required, rather than requiring new | 1543 recycled when a new lcrecord is required, rather than requiring new |
1522 malloc(). Thus, allocation of lcrecords can be very | 1544 malloc(). Thus, allocation of lcrecords can be very |
1523 cheap. (Technically, the lcrecord-list manager could divide up large | 1545 cheap. (Technically, the lcrecord-list manager could divide up large |
1524 chunks of memory and allocate out of that, mimicking what happens with | 1546 chunks of memory and allocate out of that, mimicking what happens with |
1525 lrecords. At that point, however, we'd want to rethink the whole | 1547 lrecords. At that point, however, we'd want to rethink the whole |
1529 they only handle blocks of a particular, fixed size. Thus, objects that | 1551 they only handle blocks of a particular, fixed size. Thus, objects that |
1530 can be of varying sizes need to do various tricks. These considerations | 1552 can be of varying sizes need to do various tricks. These considerations |
1531 in particular dictate the various types of management: | 1553 in particular dictate the various types of management: |
1532 | 1554 |
1533 -- "Auto-managed" means that you just go ahead and allocate the lcrecord | 1555 -- "Auto-managed" means that you just go ahead and allocate the lcrecord |
1534 whenever you want, using alloc_lcrecord_type(), and the appropriate | 1556 whenever you want, using old_alloc_lcrecord_type(), and the appropriate |
1535 lcrecord-list manager is automatically created. To free, you just call | 1557 lcrecord-list manager is automatically created. To free, you just call |
1536 "free_lcrecord()" and the appropriate lcrecord-list manager is | 1558 "FREE_LCRECORD()" and the appropriate lcrecord-list manager is |
1537 automatically located and called. The limitation here of course is that | 1559 automatically located and called. The limitation here of course is that |
1538 all your objects are of the same size. (#### Eventually we should have a | 1560 all your objects are of the same size. (#### Eventually we should have a |
1539 more sophisticated system that tracks the sizes seen and creates one | 1561 more sophisticated system that tracks the sizes seen and creates one |
1540 lcrecord list per size, indexed in a hash table. Usually there are only | 1562 lcrecord list per size, indexed in a hash table. Usually there are only |
1541 a limited number of sizes, so this works well.) | 1563 a limited number of sizes, so this works well.) |
1552 lcrecord-lists, no way to free them. This may be suitable when the | 1574 lcrecord-lists, no way to free them. This may be suitable when the |
1553 lcrecords are variable-sized and (a) you're too lazy to write the code | 1575 lcrecords are variable-sized and (a) you're too lazy to write the code |
1554 to hand-manage them, or (b) the objects you create are always or almost | 1576 to hand-manage them, or (b) the objects you create are always or almost |
1555 always Lisp-visible, and thus there's no point in freeing them (and it | 1577 always Lisp-visible, and thus there's no point in freeing them (and it |
1556 wouldn't be safe to do so). You just create them with | 1578 wouldn't be safe to do so). You just create them with |
1557 basic_alloc_lcrecord(), and that's it. | 1579 BASIC_ALLOC_LCRECORD(), and that's it. |
1558 | 1580 |
1559 --ben | 1581 --ben |
1560 | 1582 |
1561 Here is an in-depth look at the steps required to create a allocate an | 1583 Here is an in-depth look at the steps required to create a allocate an |
1562 lcrecord using the hand-managed style. Since this is the most | 1584 lcrecord using the hand-managed style. Since this is the most |
1565 lcrecord really entails, and what are the precautions: | 1587 lcrecord really entails, and what are the precautions: |
1566 | 1588 |
1567 1) Create an lcrecord-list object using make_lcrecord_list(). This is | 1589 1) Create an lcrecord-list object using make_lcrecord_list(). This is |
1568 often done at initialization. Remember to staticpro_nodump() this | 1590 often done at initialization. Remember to staticpro_nodump() this |
1569 object! The arguments to make_lcrecord_list() are the same as would be | 1591 object! The arguments to make_lcrecord_list() are the same as would be |
1570 passed to basic_alloc_lcrecord(). | 1592 passed to BASIC_ALLOC_LCRECORD(). |
1571 | 1593 |
1572 2) Instead of calling basic_alloc_lcrecord(), call alloc_managed_lcrecord() | 1594 2) Instead of calling BASIC_ALLOC_LCRECORD(), call alloc_managed_lcrecord() |
1573 and pass the lcrecord-list earlier created. | 1595 and pass the lcrecord-list earlier created. |
1574 | 1596 |
1575 3) When done with the lcrecord, call free_managed_lcrecord(). The | 1597 3) When done with the lcrecord, call free_managed_lcrecord(). The |
1576 standard freeing caveats apply: ** make sure there are no pointers to | 1598 standard freeing caveats apply: ** make sure there are no pointers to |
1577 the object anywhere! ** | 1599 the object anywhere! ** |
1578 | 1600 |
1579 4) Calling free_managed_lcrecord() is just like kissing the | 1601 4) Calling free_managed_lcrecord() is just like kissing the |
1580 lcrecord goodbye as if it were garbage-collected. This means: | 1602 lcrecord goodbye as if it were garbage-collected. This means: |
1581 -- the contents of the freed lcrecord are undefined, and the | 1603 -- the contents of the freed lcrecord are undefined, and the |
1582 contents of something produced by alloc_managed_lcrecord() | 1604 contents of something produced by alloc_managed_lcrecord() |
1583 are undefined, just like for basic_alloc_lcrecord(). | 1605 are undefined, just like for BASIC_ALLOC_LCRECORD(). |
1584 -- the mark method for the lcrecord's type will *NEVER* be called | 1606 -- the mark method for the lcrecord's type will *NEVER* be called |
1585 on freed lcrecords. | 1607 on freed lcrecords. |
1586 -- the finalize method for the lcrecord's type will be called | 1608 -- the finalize method for the lcrecord's type will be called |
1587 at the time that free_managed_lcrecord() is called. | 1609 at the time that free_managed_lcrecord() is called. |
1588 */ | 1610 */ |
1589 | 1611 |
1590 /* UNMANAGED MODEL: */ | 1612 /* UNMANAGED MODEL: */ |
1591 void *basic_alloc_lcrecord (Bytecount size, | 1613 void *old_basic_alloc_lcrecord (Bytecount size, |
1592 const struct lrecord_implementation *); | 1614 const struct lrecord_implementation *); |
1593 | 1615 |
1594 /* HAND-MANAGED MODEL: */ | 1616 /* HAND-MANAGED MODEL: */ |
1595 Lisp_Object make_lcrecord_list (Elemcount size, | 1617 Lisp_Object make_lcrecord_list (Elemcount size, |
1596 const struct lrecord_implementation | 1618 const struct lrecord_implementation |
1597 *implementation); | 1619 *implementation); |
1601 /* AUTO-MANAGED MODEL: */ | 1623 /* AUTO-MANAGED MODEL: */ |
1602 MODULE_API void * | 1624 MODULE_API void * |
1603 alloc_automanaged_lcrecord (Bytecount size, | 1625 alloc_automanaged_lcrecord (Bytecount size, |
1604 const struct lrecord_implementation *); | 1626 const struct lrecord_implementation *); |
1605 | 1627 |
1606 #define alloc_lcrecord_type(type, lrecord_implementation) \ | 1628 #define old_alloc_lcrecord_type(type, lrecord_implementation) \ |
1607 ((type *) alloc_automanaged_lcrecord (sizeof (type), lrecord_implementation)) | 1629 ((type *) alloc_automanaged_lcrecord (sizeof (type), lrecord_implementation)) |
1608 | 1630 |
1609 void free_lcrecord (Lisp_Object rec); | 1631 void old_free_lcrecord (Lisp_Object rec); |
1610 | 1632 |
1611 | 1633 |
1612 /* Copy the data from one lcrecord structure into another, but don't | 1634 /* Copy the data from one lcrecord structure into another, but don't |
1613 overwrite the header information. */ | 1635 overwrite the header information. */ |
1614 | 1636 |
1615 #define copy_sized_lcrecord(dst, src, size) \ | 1637 #define old_copy_sized_lcrecord(dst, src, size) \ |
1616 memcpy ((Rawbyte *) (dst) + sizeof (struct lcrecord_header), \ | 1638 memcpy ((Rawbyte *) (dst) + sizeof (struct old_lcrecord_header), \ |
1617 (Rawbyte *) (src) + sizeof (struct lcrecord_header), \ | 1639 (Rawbyte *) (src) + sizeof (struct old_lcrecord_header), \ |
1618 (size) - sizeof (struct lcrecord_header)) | 1640 (size) - sizeof (struct old_lcrecord_header)) |
1619 | 1641 |
1620 #define copy_lcrecord(dst, src) copy_sized_lcrecord (dst, src, sizeof (*(dst))) | 1642 #define old_copy_lcrecord(dst, src) \ |
1621 | 1643 old_copy_sized_lcrecord (dst, src, sizeof (*(dst))) |
1622 #define zero_sized_lcrecord(lcr, size) \ | 1644 |
1623 memset ((Rawbyte *) (lcr) + sizeof (struct lcrecord_header), 0, \ | 1645 #define old_zero_sized_lcrecord(lcr, size) \ |
1624 (size) - sizeof (struct lcrecord_header)) | 1646 memset ((Rawbyte *) (lcr) + sizeof (struct old_lcrecord_header), 0, \ |
1625 | 1647 (size) - sizeof (struct old_lcrecord_header)) |
1626 #define zero_lcrecord(lcr) zero_sized_lcrecord (lcr, sizeof (*(lcr))) | 1648 |
1649 #define old_zero_lcrecord(lcr) old_zero_sized_lcrecord (lcr, sizeof (*(lcr))) | |
1627 | 1650 |
1628 #else /* MC_ALLOC */ | 1651 #else /* MC_ALLOC */ |
1629 | 1652 |
1630 /* How to allocate a lrecord: | 1653 /* How to allocate a lrecord: |
1631 | 1654 |
1691 lisp_object_size (Lisp_Object o) | 1714 lisp_object_size (Lisp_Object o) |
1692 ) | 1715 ) |
1693 { | 1716 { |
1694 return detagged_lisp_object_size (XRECORD_LHEADER (o)); | 1717 return detagged_lisp_object_size (XRECORD_LHEADER (o)); |
1695 } | 1718 } |
1696 | |
1697 #ifdef MC_ALLOC | |
1698 #define ALLOC_LCRECORD_TYPE alloc_lrecord_type | |
1699 #define COPY_SIZED_LCRECORD copy_sized_lrecord | |
1700 #define COPY_LCRECORD copy_lrecord | |
1701 #define MALLOCED_STORAGE_SIZE(ptr, size, stats) \ | |
1702 mc_alloced_storage_size (size, stats) | |
1703 #define ZERO_LCRECORD zero_lrecord | |
1704 #define LCRECORD_HEADER lrecord_header | |
1705 #define BASIC_ALLOC_LCRECORD alloc_lrecord | |
1706 #define FREE_LCRECORD free_lrecord | |
1707 #else | |
1708 #define ALLOC_LCRECORD_TYPE alloc_lcrecord_type | |
1709 #define COPY_SIZED_LCRECORD copy_sized_lcrecord | |
1710 #define COPY_LCRECORD copy_lcrecord | |
1711 #define MALLOCED_STORAGE_SIZE malloced_storage_size | |
1712 #define ZERO_LCRECORD zero_lcrecord | |
1713 #define LCRECORD_HEADER lcrecord_header | |
1714 #define BASIC_ALLOC_LCRECORD basic_alloc_lcrecord | |
1715 #define FREE_LCRECORD free_lcrecord | |
1716 #endif | |
1717 | 1719 |
1718 | 1720 |
1719 /************************************************************************/ | 1721 /************************************************************************/ |
1720 /* Dumping */ | 1722 /* Dumping */ |
1721 /************************************************************************/ | 1723 /************************************************************************/ |