Ticket #1605: PCA-patch-001.patch

File PCA-patch-001.patch, 22.7 KB (added by Paul C. Anagnostopoulos, 4 years ago)
  • src/gc/alloc_resources.c

     
    281281- reduce alignment to a reasonable value i.e. MALLOC_ALIGNMENT 
    282282  aka 2*sizeof (size_t) or just 8 (TODO make a config hint) 
    283283 
    284 Buffer memory layout: 
     284See pobj.h for a discussion of the Buffer descriptor and the buffer itself, 
     285including its header. 
    285286 
    286                     +-------------------+ 
    287                     | flags # GC header | 
    288   obj->bufstart  -> +-------------------+ 
    289                     |  data             | 
    290                     v                   v 
    291  
    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 above 
    295  * obj->buflen is the usable length excluding the optional GC part. 
    296  
    297287=cut 
    298288 
    299289*/ 
     
    612602    /* we can't perform the math all the time, because 
    613603        * strstart might be in unallocated memory */ 
    614604    if (PObj_is_COWable_TEST(old_buf)) { 
    615         flags = Buffer_bufrefcountptr(old_buf); 
     605        flags = Buffer_bufflagsptr(old_buf); 
    616606        old_block = Buffer_pool(old_buf); 
    617607 
    618608        if (PObj_is_string_TEST(old_buf)) { 
     
    631621 
    632622        /* Make sure they know that we own it too */ 
    633623        /* Set Buffer_shared_FLAG in new buffer */ 
    634         *Buffer_bufrefcountptr(hdr) |= Buffer_shared_FLAG; 
     624        *Buffer_bufflagsptr(hdr) |= Buffer_shared_FLAG; 
    635625 
    636626        /* Now make sure we point to where the other guy does */ 
    637627        Buffer_bufstart(old_buf) = Buffer_bufstart(hdr); 
  • src/gc/gc_ms.c

     
    12561256    PARROT_ASSERT(PObj_is_movable_TESTALL(str)); 
    12571257 
    12581258    /* We must not reallocate shared buffers! */ 
    1259     PARROT_ASSERT(!(*Buffer_bufrefcountptr(str) & Buffer_shared_FLAG)); 
     1259    PARROT_ASSERT(!(*Buffer_bufflagsptr(str) & Buffer_shared_FLAG)); 
    12601260 
    12611261    /* Decrease usage */ 
    12621262    PARROT_ASSERT(Buffer_pool(str)); 
  • src/gc/gc_private.h

     
    7777   larger then sizeof(PObj), thus creating overflow. However PObjs are never 
    7878   used by themselves, things like PMCs and STRINGs are cast to PObj in the 
    7979   GC, so we should have plenty of space. */ 
     80 
    8081typedef struct GC_MS_PObj_Wrapper { 
    8182    size_t flags; 
    8283    struct GC_MS_PObj_Wrapper * next_ptr; 
     
    164165     */ 
    165166} GC_Subsystem; 
    166167 
     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 
    167171typedef 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 */ 
    177180} Memory_Block; 
    178181 
     182/* This structure describes a variable-size memory pool. Various such pools 
     183   hang off the Memory_Pools root structure. */ 
     184 
    179185typedef 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. */ 
    188197} Variable_Size_Pool; 
    189198 
     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 
    190203typedef 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. */ 
    196209} Fixed_Size_Arena; 
    197210 
     211/* This simple header structure describes a free PMC attribute object. 
     212   A list of them hang off the PMC attribute pool. */ 
     213 
    198214typedef struct PMC_Attribute_Free_List { 
    199     struct PMC_Attribute_Free_List * next; 
     215    struct PMC_Attribute_Free_List * next; /* Pointer to next free object. */ 
    200216} PMC_Attribute_Free_List; 
    201217 
     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 
    202222typedef 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. */ 
    205225} PMC_Attribute_Arena; 
    206226 
     227/* This structure describes a PMC attribute pool. A vector of them hang 
     228   off the Memory_Pools root structure. */ 
     229 
    207230typedef 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 
    214238#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. */ 
    217244#endif 
    218245} PMC_Attribute_Pool; 
    219246 
    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 
    221250typedef struct Fixed_Size_Pool { 
    222251 
    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. */ 
    227257 
    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. */ 
    230260 
    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. */ 
    235265 
    236     PARROT_OBSERVER const char *name; 
     266    PARROT_OBSERVER const char *name;   /* Name of pool. */ 
    237267 
    238     size_t objects_per_alloc; 
     268    size_t objects_per_alloc;           /* Number of object slots to allocate. */ 
    239269 
    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. */ 
    242274 
    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. */ 
    251282 
    252283    /* Contains GC system-specific data structures ... unused at the moment, 
    253284     * but this is where it should go when we need it ... 
     
    256287    */ 
    257288 
    258289#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. */ 
    261295#endif 
    262296 
    263297} Fixed_Size_Pool; 
    264298 
     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 
    265303typedef 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. */ 
    274313 
    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. */ 
    277317 
    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 */ 
    279323    size_t  gc_mark_runs;       /* Number of times we've done a mark run */ 
    280324    size_t  gc_lazy_mark_runs;  /* Number of successful lazy mark runs */ 
    281325    size_t  gc_collect_runs;    /* Number of times we've done a memory 
     
    288332                                                 * blocks allocated from 
    289333                                                 * the system since the last 
    290334                                                 * 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 
    296338                                   * anything */ 
    297339    UINTVAL memory_collected;     /* Total amount of memory copied 
    298340                                     during collection */ 
     
    311353                                     requests are there? */ 
    312354 
    313355    /* private data for the GC subsystem */ 
    314     void *gc_private;           /* gc subsystem data */ 
     356    void *gc_private;             /* GC subsystem data */ 
    315357} Memory_Pools; 
    316358 
    317359/* HEADERIZER BEGIN: src/gc/system.c */ 
  • src/gc/mark_sweep.c

     
    681681    if (mem_pool) { 
    682682        /* Update Memory_Block usage */ 
    683683        if (PObj_is_movable_TESTALL(b)) { 
    684             INTVAL *buffer_flags = Buffer_bufrefcountptr(b); 
     684            INTVAL *buffer_flags = Buffer_bufflagsptr(b); 
    685685 
    686686            /* Mask low 2 bits used for flags */ 
    687687            Memory_Block * block = Buffer_pool(b); 
  • src/string/api.c

     
    395395    /* Now check that buffer allocated from pool and affected by compacting */ 
    396396    if (is_movable && Buffer_bufstart(s)) { 
    397397        /* If so, mark it as shared */ 
    398         INTVAL * const buffer_flags = Buffer_bufrefcountptr(d); 
     398        INTVAL * const buffer_flags = Buffer_bufflagsptr(d); 
    399399        *buffer_flags |= Buffer_shared_FLAG; 
    400400    } 
    401401 
  • CREDITS

     
    810810D: Pynie 
    811811E: pmichaud@pobox.com 
    812812 
     813N: Paul C. Anagnostopoulos 
     814U: Paul C. Anagnostopoulos 
     815E: paul@windfall.com 
     816D: Improving memory management documentation 
     817 
    813818N: Paul Cochrane 
    814819U: paultcochrane 
    815820D: Changing the newspaper in the parrot cage 
  • include/parrot/pobj.h

     
    77 *  Data Structure and Algorithms: 
    88 *  History: 
    99 *  Notes: 
    10  *  References: memory_internals.pod 
     10 *  References: memory_internals.pod (out of date as of 8/2010). 
    1111 */ 
    1212 
    1313#ifndef PARROT_POBJ_H_GUARD 
     
    1515 
    1616#include "parrot/config.h" 
    1717 
    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 
    1921typedef struct pobj_t { 
    20     Parrot_UInt flags; 
     22    Parrot_UInt flags;                  /* Lots of flags (see below). */ 
    2123} PObj; 
    2224 
     25/* This is a buffer header object, "inheriting" from PObj. */ 
     26 
    2327typedef struct buffer_t { 
    2428    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. */ 
    2732} Buffer; 
    2833 
     34/* Use these macros to access the two buffer header slots. */ 
     35 
    2936#define Buffer_bufstart(buffer)    (buffer)->_bufstart 
    3037#define Buffer_buflen(buffer)      (buffer)->_buflen 
    3138 
    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: 
    3942 
    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                                         +------------------------+ 
    4554 
    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. 
    5360*/ 
    5461 
    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. */ 
    6363 
     64#define Buffer_prolog_offset (sizeof (void*)) 
     65#define Buffer_bufprolog(b) ((char *)Buffer_bufstart(b) - Buffer_prolog_offset)  
    6466 
     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 
    6579typedef enum { 
    6680    enum_stringrep_unknown = 0, 
    6781    enum_stringrep_one     = 1, 
     
    6983    enum_stringrep_four    = 4 
    7084} parrot_string_representation_t; 
    7185 
     86/* Here is the Parrot string header object, "inheriting" from Buffer. */ 
     87 
    7288struct parrot_string_t { 
    7389    Parrot_UInt flags; 
    7490    void *     _bufstart; 
    7591    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. */ 
    8097 
    8198    /*    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. */ 
    84101}; 
    85102 
    86 /* note that cache and flags are isomorphic with Buffer and PObj */ 
     103/* Here is the Parrot PMC object, "inheriting" from PObj. */ 
     104 
    87105struct 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. */ 
    93110}; 
    94111 
     112/* Use these macros to access the data and metadata. */ 
     113 
    95114#define PMC_data(pmc)                   (pmc)->data 
    96115#define PMC_data_typed(pmc, type) (type)(pmc)->data 
    97116#define PMC_metadata(pmc)         ((pmc)->_metadata)