Ticket #1605: PCA-patch-001.patch
| File PCA-patch-001.patch, 22.7 KB (added by Paul C. Anagnostopoulos, 3 years ago) |
|---|
-
src/gc/alloc_resources.c
281 281 - reduce alignment to a reasonable value i.e. MALLOC_ALIGNMENT 282 282 aka 2*sizeof (size_t) or just 8 (TODO make a config hint) 283 283 284 Buffer memory layout: 284 See pobj.h for a discussion of the Buffer descriptor and the buffer itself, 285 including its header. 285 286 286 +-------------------+287 | flags # GC header |288 obj->bufstart -> +-------------------+289 | data |290 v v291 292 * if PObj_is_COWable is set, then we have space for flags.293 294 * if PObj_align_FLAG is set, obj->bufstart is aligned like discussed above295 * obj->buflen is the usable length excluding the optional GC part.296 297 287 =cut 298 288 299 289 */ … … 612 602 /* we can't perform the math all the time, because 613 603 * strstart might be in unallocated memory */ 614 604 if (PObj_is_COWable_TEST(old_buf)) { 615 flags = Buffer_buf refcountptr(old_buf);605 flags = Buffer_bufflagsptr(old_buf); 616 606 old_block = Buffer_pool(old_buf); 617 607 618 608 if (PObj_is_string_TEST(old_buf)) { … … 631 621 632 622 /* Make sure they know that we own it too */ 633 623 /* Set Buffer_shared_FLAG in new buffer */ 634 *Buffer_buf refcountptr(hdr) |= Buffer_shared_FLAG;624 *Buffer_bufflagsptr(hdr) |= Buffer_shared_FLAG; 635 625 636 626 /* Now make sure we point to where the other guy does */ 637 627 Buffer_bufstart(old_buf) = Buffer_bufstart(hdr); -
src/gc/gc_ms.c
1256 1256 PARROT_ASSERT(PObj_is_movable_TESTALL(str)); 1257 1257 1258 1258 /* We must not reallocate shared buffers! */ 1259 PARROT_ASSERT(!(*Buffer_buf refcountptr(str) & Buffer_shared_FLAG));1259 PARROT_ASSERT(!(*Buffer_bufflagsptr(str) & Buffer_shared_FLAG)); 1260 1260 1261 1261 /* Decrease usage */ 1262 1262 PARROT_ASSERT(Buffer_pool(str)); -
src/gc/gc_private.h
77 77 larger then sizeof(PObj), thus creating overflow. However PObjs are never 78 78 used by themselves, things like PMCs and STRINGs are cast to PObj in the 79 79 GC, so we should have plenty of space. */ 80 80 81 typedef struct GC_MS_PObj_Wrapper { 81 82 size_t flags; 82 83 struct GC_MS_PObj_Wrapper * next_ptr; … … 164 165 */ 165 166 } GC_Subsystem; 166 167 168 /* This header structure describes a block of memory that is part of a 169 variable-size pool. The allocatable memory follows the header. */ 170 167 171 typedef struct Memory_Block { 168 size_t free; 169 size_t size; 170 struct Memory_Block *prev; 171 struct Memory_Block *next; 172 char *start; 173 char *top; 174 175 /* Amount of freed memory. Used in compact_pool */ 176 size_t freed; 172 size_t free; /* Remaining free space. */ 173 size_t size; /* Size of memory. */ 174 struct Memory_Block *prev; /* Pointer to previous block. */ 175 struct Memory_Block *next; /* Pointer to next block. */ 176 char *start; /* Pointer to start of memory. */ 177 char *top; /* Pointer to free space in memory. */ 178 size_t freed; /* Amount of freed memory. 179 Used in compact_pool */ 177 180 } Memory_Block; 178 181 182 /* This structure describes a variable-size memory pool. Various such pools 183 hang off the Memory_Pools root structure. */ 184 179 185 typedef struct Variable_Size_Pool { 180 Memory_Block *top_block; 181 void (*compact)(PARROT_INTERP, struct Memory_Pools *, struct Variable_Size_Pool *); 182 size_t minimum_block_size; 183 size_t total_allocated; /* total bytes allocated to this pool */ 184 size_t guaranteed_reclaimable; /* bytes that can definitely be reclaimed*/ 185 size_t possibly_reclaimable; /* bytes that can possibly be reclaimed 186 * (above plus COW-freed bytes) */ 187 FLOATVAL reclaim_factor; /* minimum percentage we will reclaim */ 186 Memory_Block *top_block; /* Pointer to most recent memory block. */ 187 /* Pool compactor, or NULL. */ 188 void (*compact)(PARROT_INTERP, struct Memory_Pools *, 189 struct Variable_Size_Pool *); 190 size_t minimum_block_size; /* Minimum allocation size, to 191 prevent fragmentation. */ 192 size_t total_allocated; /* Total bytes allocated to this pool. */ 193 size_t guaranteed_reclaimable; /* Bytes that can definitely be reclaimed. */ 194 size_t possibly_reclaimable; /* Bytes that can possibly be reclaimed 195 (above plus COW-freed bytes). */ 196 FLOATVAL reclaim_factor; /* Minimum percentage we will reclaim. */ 188 197 } Variable_Size_Pool; 189 198 199 /* This header structure describes an arena: a block of memory that is part of a 200 fixed-sized pool. The arena has enough memory for 'total_objects' objects 201 of a particular size specified in the pool. */ 202 190 203 typedef struct Fixed_Size_Arena { 191 size_t used;192 size_t total_objects;193 struct Fixed_Size_Arena *prev; 194 struct Fixed_Size_Arena *next; 195 void *start_objects;204 size_t used; /* Number of objects slots used. */ 205 size_t total_objects; /* Total number of object slots. */ 206 struct Fixed_Size_Arena *prev; /* Pointer to previous arena. */ 207 struct Fixed_Size_Arena *next; /* Pointer to next arena. */ 208 void *start_objects; /* Pointer to arena memory. */ 196 209 } Fixed_Size_Arena; 197 210 211 /* This simple header structure describes a free PMC attribute object. 212 A list of them hang off the PMC attribute pool. */ 213 198 214 typedef struct PMC_Attribute_Free_List { 199 struct PMC_Attribute_Free_List * next; 215 struct PMC_Attribute_Free_List * next; /* Pointer to next free object. */ 200 216 } PMC_Attribute_Free_List; 201 217 218 /* This header structure describes a PMC attribute arena: A block of memory 219 that is part of a PMC attribute pool. The allocatable memory follows 220 this header. */ 221 202 222 typedef struct PMC_Attribute_Arena { 203 struct PMC_Attribute_Arena * next; 204 struct PMC_Attribute_Arena * prev; 223 struct PMC_Attribute_Arena * next; /* Pointer to next arena. */ 224 struct PMC_Attribute_Arena * prev; /* Pointer to previous arena. */ 205 225 } PMC_Attribute_Arena; 206 226 227 /* This structure describes a PMC attribute pool. A vector of them hang 228 off the Memory_Pools root structure. */ 229 207 230 typedef struct PMC_Attribute_Pool { 208 size_t attr_size; 209 size_t total_objects; 210 size_t objects_per_alloc; 211 size_t num_free_objects; 212 PMC_Attribute_Free_List * free_list; 213 PMC_Attribute_Arena * top_arena; 231 size_t attr_size; /* Size of attribute object. */ 232 size_t total_objects; /* Total objects in the pool. */ 233 size_t objects_per_alloc; /* Number of object slots to allocate. */ 234 size_t num_free_objects; /* Number of objects on the free list. */ 235 PMC_Attribute_Free_List * free_list; /* List of free object slots, or NULL. */ 236 PMC_Attribute_Arena * top_arena; /* Pointer to most recent arena. */ 237 214 238 #if GC_USE_LAZY_ALLOCATOR 215 PMC_Attribute_Free_List * newfree; 216 PMC_Attribute_Free_List * newlast; 239 /* Using lazy allocator: */ 240 PMC_Attribute_Free_List * newfree; /* Pointer to next object slot in 241 latest arena, or NULL (slots weren't 242 put on free list). */ 243 PMC_Attribute_Free_List * newlast; /* High water mark in arena. */ 217 244 #endif 218 245 } PMC_Attribute_Pool; 219 246 220 /* Tracked resource pool */ 247 /* This structure describes a fixed-size memory pool. Various such pools 248 hang off the Memory_Pools root structure. */ 249 221 250 typedef struct Fixed_Size_Pool { 222 251 223 struct Variable_Size_Pool *mem_pool; 224 /* Size in bytes of an individual pool item. This size may include 225 * a GC-system specific GC header. */ 226 size_t object_size; 252 struct Variable_Size_Pool *mem_pool; /* Pointer to associated variable-size 253 pool, or NULL. */ 254 size_t object_size; /* Size in bytes of an individual pool 255 object. This size may include 256 a GC system-specific GC header. */ 227 257 228 size_t start_arena_memory; 229 size_t end_arena_memory; 258 size_t start_arena_memory; /* Address of the lowest arena. */ 259 size_t end_arena_memory; /* And the highest one. */ 230 260 231 Fixed_Size_Arena *last_Arena; 232 GC_MS_PObj_Wrapper * free_list; 233 size_t num_free_objects; /* number of resources in the free pool*/234 size_t total_objects; 261 Fixed_Size_Arena *last_Arena; /* Pointer to most recent arena. */ 262 GC_MS_PObj_Wrapper * free_list; /* List of free object slots, or NULL. */ 263 size_t num_free_objects; /* Number of objects on the free list. */ 264 size_t total_objects; /* Total objects in the pool. */ 235 265 236 PARROT_OBSERVER const char *name; 266 PARROT_OBSERVER const char *name; /* Name of pool. */ 237 267 238 size_t objects_per_alloc; 268 size_t objects_per_alloc; /* Number of object slots to allocate. */ 239 269 240 int skip; 241 size_t replenish_level; 270 int skip; /* How often to skip full GC 271 (see gc_skip_type_enum). */ 272 size_t replenish_level; /* Replenish pool when free object slots 273 goes below this level. */ 242 274 243 add_free_object_fn_type add_free_object; /* adds a free object to 244 the pool's free list */ 245 get_free_object_fn_type get_free_object; /* gets and removes a free 246 object from the pool's 247 free list */ 248 alloc_objects_fn_type alloc_objects; /* allocates more objects */ 249 alloc_objects_fn_type more_objects; 250 gc_object_fn_type gc_object; 275 add_free_object_fn_type add_free_object; /* Adds a free object to 276 the pool's free list */ 277 get_free_object_fn_type get_free_object; /* Gets and removes a free object 278 from the pool's free list. */ 279 alloc_objects_fn_type alloc_objects; /* Allocates an arena for objects. */ 280 alloc_objects_fn_type more_objects; /* Obtain more free objects. */ 281 gc_object_fn_type gc_object; /* GCs object during sweep. */ 251 282 252 283 /* Contains GC system-specific data structures ... unused at the moment, 253 284 * but this is where it should go when we need it ... … … 256 287 */ 257 288 258 289 #if GC_USE_LAZY_ALLOCATOR 259 void *newfree; 260 void *newlast; 290 /* Using lazy allocator: */ 291 void *newfree; /* Pointer to next object slot in 292 latest arena, or NULL (slots weren't 293 put on free list). */ 294 void *newlast; /* High water mark in arena. */ 261 295 #endif 262 296 263 297 } Fixed_Size_Pool; 264 298 299 /* This structure acts as the root for all the various memory pools: 300 variable-sized, fixed-size, and PMC attributes. It also contains 301 various GC-related items. It hangs off the Interp structure. */ 302 265 303 typedef struct Memory_Pools { 266 Variable_Size_Pool *memory_pool; 267 Variable_Size_Pool *constant_string_pool; 268 Fixed_Size_Pool *string_header_pool; 269 Fixed_Size_Pool *pmc_pool; 270 Fixed_Size_Pool *constant_pmc_pool; 271 Fixed_Size_Pool *constant_string_header_pool; 272 Fixed_Size_Pool **sized_header_pools; 273 size_t num_sized; 304 /* Pointers to pools */ 305 Variable_Size_Pool *memory_pool; /* General memory pool. */ 306 Variable_Size_Pool *constant_string_pool; /* Constant string pool (not 307 compacted). */ 308 Fixed_Size_Pool *string_header_pool; /* String header pool. */ 309 Fixed_Size_Pool *pmc_pool; /* PMC object pool. */ 310 Fixed_Size_Pool *constant_pmc_pool; /* And one for constant PMCs. */ 311 Fixed_Size_Pool *constant_string_header_pool; /* And a constant string 312 header pool. */ 274 313 275 PMC_Attribute_Pool **attrib_pools; 276 size_t num_attribs; 314 Fixed_Size_Pool **sized_header_pools; /* Vector of pools for other 315 fixed-size headers. */ 316 size_t num_sized; /* Length of that vector. */ 277 317 278 /** statistics for GC **/ 318 PMC_Attribute_Pool **attrib_pools; /* Vector of pools for PMC 319 attributes. */ 320 size_t num_attribs; /* Length of that vector. */ 321 322 /* statistics for GC */ 279 323 size_t gc_mark_runs; /* Number of times we've done a mark run */ 280 324 size_t gc_lazy_mark_runs; /* Number of successful lazy mark runs */ 281 325 size_t gc_collect_runs; /* Number of times we've done a memory … … 288 332 * blocks allocated from 289 333 * the system since the last 290 334 * GC run */ 291 size_t memory_allocated; /* The total amount of 292 * allocatable memory 293 * allocated. Doesn't count 294 * memory for headers or 295 * internal structures or 335 size_t memory_allocated; /* The total amount of allocatable memory 336 * allocated. Doesn't count memory for 337 * headers or internal structures or 296 338 * anything */ 297 339 UINTVAL memory_collected; /* Total amount of memory copied 298 340 during collection */ … … 311 353 requests are there? */ 312 354 313 355 /* private data for the GC subsystem */ 314 void *gc_private; /* gcsubsystem data */356 void *gc_private; /* GC subsystem data */ 315 357 } Memory_Pools; 316 358 317 359 /* HEADERIZER BEGIN: src/gc/system.c */ -
src/gc/mark_sweep.c
681 681 if (mem_pool) { 682 682 /* Update Memory_Block usage */ 683 683 if (PObj_is_movable_TESTALL(b)) { 684 INTVAL *buffer_flags = Buffer_buf refcountptr(b);684 INTVAL *buffer_flags = Buffer_bufflagsptr(b); 685 685 686 686 /* Mask low 2 bits used for flags */ 687 687 Memory_Block * block = Buffer_pool(b); -
src/string/api.c
395 395 /* Now check that buffer allocated from pool and affected by compacting */ 396 396 if (is_movable && Buffer_bufstart(s)) { 397 397 /* If so, mark it as shared */ 398 INTVAL * const buffer_flags = Buffer_buf refcountptr(d);398 INTVAL * const buffer_flags = Buffer_bufflagsptr(d); 399 399 *buffer_flags |= Buffer_shared_FLAG; 400 400 } 401 401 -
CREDITS
810 810 D: Pynie 811 811 E: pmichaud@pobox.com 812 812 813 N: Paul C. Anagnostopoulos 814 U: Paul C. Anagnostopoulos 815 E: paul@windfall.com 816 D: Improving memory management documentation 817 813 818 N: Paul Cochrane 814 819 U: paultcochrane 815 820 D: Changing the newspaper in the parrot cage -
include/parrot/pobj.h
7 7 * Data Structure and Algorithms: 8 8 * History: 9 9 * Notes: 10 * References: memory_internals.pod 10 * References: memory_internals.pod (out of date as of 8/2010). 11 11 */ 12 12 13 13 #ifndef PARROT_POBJ_H_GUARD … … 15 15 16 16 #include "parrot/config.h" 17 17 18 /* Parrot Object - base class for all others */ 18 /* This is the base Parrot object structure. Every object begins with 19 this slot, then has additional slots as required. */ 20 19 21 typedef struct pobj_t { 20 Parrot_UInt flags; 22 Parrot_UInt flags; /* Lots of flags (see below). */ 21 23 } PObj; 22 24 25 /* This is a buffer header object, "inheriting" from PObj. */ 26 23 27 typedef struct buffer_t { 24 28 Parrot_UInt flags; 25 void * _bufstart; 26 size_t _buflen; 29 void * _bufstart; /* Pointer to start of buffer data 30 (not buffer prolog). */ 31 size_t _buflen; /* Length of buffer data. */ 27 32 } Buffer; 28 33 34 /* Use these macros to access the two buffer header slots. */ 35 29 36 #define Buffer_bufstart(buffer) (buffer)->_bufstart 30 37 #define Buffer_buflen(buffer) (buffer)->_buflen 31 38 32 /* See src/gc/alloc_resources.c. the basic idea is that buffer memory is 33 set up as follows: 34 +-----------------+ 35 | ref_count |f | # GC header 36 obj->bufstart -> +-----------------+ 37 | data | 38 v v 39 /* A buffer header object points to a buffer in a Memory_Block. 40 The buffer includes a prolog, but _bufstart points to the data 41 portion. Here is how it works: 39 42 40 The actual set-up is more involved because of padding. obj->bufstart must 41 be suitably aligned. The start of the memory region (as returned by malloc()) 42 is suitably aligned for any use. If, for example, malloc() returns 43 objects aligned on 8-byte boundaries, and obj->bufstart is also aligned 44 on 8-byte boundaries, then there should be 4 bytes of padding. 43 Buffer header buffer 44 +-------------------+ +------------------------+ 45 | flags | | (possible padding) | } 46 +-------------------+ +---------------------+--+ > prolog 47 | _bufstart | ------+ | *Memory_Block |fl| } 48 +-------------------+ | +---------------------+--+ 49 | _buflen | +-------> | data portion | 50 +-------------------+ | | 51 ~ ~ 52 | | 53 +------------------------+ 45 54 46 ptr from malloc -> +------------------+ 47 [other blocks?] | 48 | INTVAL ref_count | 49 obj->bufstart -> +------------------+ 50 | data | 51 v v 52 55 The buffer prolog consists of possible padding and a pointer to the 56 Memory_Block containing the buffer. There are two flags in the low-order 57 bits of the pointer (see string.h). Padding is only required if the 58 alignment of the data portion is higher than that of a pointer. 59 This was not the case as of 8/2010. 53 60 */ 54 61 55 /* Given a pointer to the buffer, find the ref_count and the actual start of 56 the allocated space. Setting ref_count is clunky because we avoid lvalue 57 casts. */ 58 #define Buffer_alloc_offset sizeof (void*) 59 #define Buffer_bufallocstart(b) ((char *)Buffer_bufstart(b) - Buffer_alloc_offset) 60 #define Buffer_bufrefcountptr(b) ((INTVAL *)Buffer_bufallocstart(b)) 61 #define Buffer_pool(b) ((Memory_Block *)( *(INTVAL*)(Buffer_bufallocstart(b)) & ~3 )) 62 #define Buffer_poolptr(b) ((Memory_Block **)Buffer_bufallocstart(b)) 62 /* These macros let us address the prolog of a buffer. */ 63 63 64 #define Buffer_prolog_offset (sizeof (void*)) 65 #define Buffer_bufprolog(b) ((char *)Buffer_bufstart(b) - Buffer_prolog_offset) 64 66 67 /* This macro gives us the address of the buffer prolog treated as 68 a pointer to the flags. */ 69 70 #define Buffer_bufflagsptr(b) ((INTVAL *)Buffer_bufprolog(b)) 71 72 /* These macros give us the Memory_Block pointer and pointer-pointer, 73 eliminating the flags. */ 74 75 #define Buffer_pool(b) ((Memory_Block *)( *(INTVAL*)(Buffer_bufprolog(b)) & ~3 )) 76 #define Buffer_poolptr(b) ((Memory_Block **)Buffer_bufprolog(b)) 77 78 65 79 typedef enum { 66 80 enum_stringrep_unknown = 0, 67 81 enum_stringrep_one = 1, … … 69 83 enum_stringrep_four = 4 70 84 } parrot_string_representation_t; 71 85 86 /* Here is the Parrot string header object, "inheriting" from Buffer. */ 87 72 88 struct parrot_string_t { 73 89 Parrot_UInt flags; 74 90 void * _bufstart; 75 91 size_t _buflen; 76 char *strstart; 77 UINTVAL bufused; 78 UINTVAL strlen; 79 UINTVAL hashval; /* cached hash value computation */ 92 char *strstart; /* Pointer to start of string 93 (not necessarily at _bufstart). */ 94 UINTVAL bufused; /* Length of string in bytes. */ 95 UINTVAL strlen; /* Length of string in characters. */ 96 UINTVAL hashval; /* Cached hash value. */ 80 97 81 98 /* parrot_string_representation_t representation;*/ 82 const struct _encoding *encoding; 83 const struct _charset *charset; 99 const struct _encoding *encoding; /* Pointer to encoding structure. */ 100 const struct _charset *charset; /* Pointer to charset structure. */ 84 101 }; 85 102 86 /* note that cache and flags are isomorphic with Buffer and PObj */ 103 /* Here is the Parrot PMC object, "inheriting" from PObj. */ 104 87 105 struct PMC { 88 Parrot_UInt flags; 89 VTABLE *vtable; 90 DPOINTER *data; 91 92 PMC *_metadata; /* properties */ 106 Parrot_UInt flags; 107 VTABLE *vtable; /* Pointer to vtable. */ 108 DPOINTER *data; /* Pointer to attribute structure. */ 109 PMC *_metadata; /* Pointer to metadata PMC. */ 93 110 }; 94 111 112 /* Use these macros to access the data and metadata. */ 113 95 114 #define PMC_data(pmc) (pmc)->data 96 115 #define PMC_data_typed(pmc, type) (type)(pmc)->data 97 116 #define PMC_metadata(pmc) ((pmc)->_metadata)
