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 /************************************************************************/