~dexter/parrot-pkg/maverick

« back to all changes in this revision

Viewing changes to src/gc/gc_ms.c

  • Committer: Piotr Roszatycki
  • Date: 2011-01-11 14:34:28 UTC
  • mfrom: (1.1.13 upstream)
  • Revision ID: piotr.roszatycki@gmail.com-20110111143428-s7pa7qz38m61o4tw
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
Copyright (C) 2001-2010, Parrot Foundation.
3
 
$Id: gc_ms.c 49093 2010-09-17 23:39:13Z mikehh $
4
3
 
5
4
=head1 NAME
6
5
 
16
15
 
17
16
#include "parrot/parrot.h"
18
17
#include "gc_private.h"
 
18
#include "parrot/list.h"
19
19
 
20
20
#define DEBUG_FREE_LIST 0
21
21
 
43
43
static int gc_ms_active_sized_buffers(ARGIN(const Memory_Pools *mem_pools))
44
44
        __attribute__nonnull__(1);
45
45
 
46
 
static void gc_ms_add_free_object(SHIM_INTERP,
47
 
    ARGMOD(Memory_Pools *mem_pools),
 
46
static void gc_ms_add_free_object(PARROT_INTERP,
 
47
    SHIM(Memory_Pools *mem_pools),
48
48
    ARGMOD(Fixed_Size_Pool *pool),
49
49
    ARGIN(void *to_add))
50
 
        __attribute__nonnull__(2)
 
50
        __attribute__nonnull__(1)
51
51
        __attribute__nonnull__(3)
52
52
        __attribute__nonnull__(4)
53
 
        FUNC_MODIFIES(*mem_pools)
54
53
        FUNC_MODIFIES(*pool);
55
54
 
56
55
static void gc_ms_alloc_objects(PARROT_INTERP,
67
66
        __attribute__nonnull__(1);
68
67
 
69
68
PARROT_MALLOC
70
 
PARROT_CANNOT_RETURN_NULL
 
69
PARROT_CAN_RETURN_NULL
71
70
static void * gc_ms_allocate_memory_chunk(SHIM_INTERP, size_t size);
72
71
 
73
72
PARROT_MALLOC
74
 
PARROT_CANNOT_RETURN_NULL
 
73
PARROT_CAN_RETURN_NULL
75
74
static void * gc_ms_allocate_memory_chunk_zeroed(SHIM_INTERP, size_t size);
76
75
 
77
76
PARROT_CANNOT_RETURN_NULL
84
83
static PMC* gc_ms_allocate_pmc_header(PARROT_INTERP, UINTVAL flags)
85
84
        __attribute__nonnull__(1);
86
85
 
 
86
PARROT_WARN_UNUSED_RESULT
87
87
PARROT_CAN_RETURN_NULL
88
88
static STRING* gc_ms_allocate_string_header(PARROT_INTERP, UINTVAL flags)
89
89
        __attribute__nonnull__(1);
155
155
static unsigned int gc_ms_is_blocked_GC_sweep(PARROT_INTERP)
156
156
        __attribute__nonnull__(1);
157
157
 
 
158
PARROT_WARN_UNUSED_RESULT
 
159
static int gc_ms_is_pmc_ptr(PARROT_INTERP, ARGIN_NULLOK(void *ptr))
 
160
        __attribute__nonnull__(1);
 
161
 
 
162
PARROT_WARN_UNUSED_RESULT
 
163
static int gc_ms_is_string_ptr(PARROT_INTERP, ARGIN_NULLOK(void *ptr))
 
164
        __attribute__nonnull__(1);
 
165
 
158
166
static void gc_ms_iterate_live_strings(PARROT_INTERP,
159
167
    string_iterator_callback callback,
160
168
    ARGIN_NULLOK(void *data))
163
171
static void gc_ms_mark_and_sweep(PARROT_INTERP, UINTVAL flags)
164
172
        __attribute__nonnull__(1);
165
173
 
 
174
static void gc_ms_mark_pobj_header(SHIM_INTERP, ARGMOD_NULLOK(PObj *obj))
 
175
        FUNC_MODIFIES(*obj);
 
176
 
166
177
static void gc_ms_mark_special(PARROT_INTERP, ARGIN(PMC *pmc))
167
178
        __attribute__nonnull__(1)
168
179
        __attribute__nonnull__(2);
169
180
 
170
181
static void gc_ms_more_traceable_objects(PARROT_INTERP,
171
 
    ARGIN(Memory_Pools *mem_pools),
 
182
    SHIM(Memory_Pools *mem_pools),
172
183
    ARGMOD(Fixed_Size_Pool *pool))
173
184
        __attribute__nonnull__(1)
174
 
        __attribute__nonnull__(2)
175
185
        __attribute__nonnull__(3)
176
186
        FUNC_MODIFIES(*pool);
177
187
 
180
190
        FUNC_MODIFIES(*pool);
181
191
 
182
192
PARROT_MALLOC
183
 
PARROT_CANNOT_RETURN_NULL
 
193
PARROT_CAN_RETURN_NULL
184
194
static void * gc_ms_reallocate_memory_chunk(SHIM_INTERP,
185
195
    ARGFREE(void *from),
186
196
    size_t size);
252
262
#define ASSERT_ARGS_gc_ms_active_sized_buffers __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
253
263
       PARROT_ASSERT_ARG(mem_pools))
254
264
#define ASSERT_ARGS_gc_ms_add_free_object __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
255
 
       PARROT_ASSERT_ARG(mem_pools) \
 
265
       PARROT_ASSERT_ARG(interp) \
256
266
    , PARROT_ASSERT_ARG(pool) \
257
267
    , PARROT_ASSERT_ARG(to_add))
258
268
#define ASSERT_ARGS_gc_ms_alloc_objects __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
308
318
       PARROT_ASSERT_ARG(interp))
309
319
#define ASSERT_ARGS_gc_ms_is_blocked_GC_sweep __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
310
320
       PARROT_ASSERT_ARG(interp))
 
321
#define ASSERT_ARGS_gc_ms_is_pmc_ptr __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
 
322
       PARROT_ASSERT_ARG(interp))
 
323
#define ASSERT_ARGS_gc_ms_is_string_ptr __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
 
324
       PARROT_ASSERT_ARG(interp))
311
325
#define ASSERT_ARGS_gc_ms_iterate_live_strings __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
312
326
       PARROT_ASSERT_ARG(interp))
313
327
#define ASSERT_ARGS_gc_ms_mark_and_sweep __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
314
328
       PARROT_ASSERT_ARG(interp))
 
329
#define ASSERT_ARGS_gc_ms_mark_pobj_header __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
315
330
#define ASSERT_ARGS_gc_ms_mark_special __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
316
331
       PARROT_ASSERT_ARG(interp) \
317
332
    , PARROT_ASSERT_ARG(pmc))
318
333
#define ASSERT_ARGS_gc_ms_more_traceable_objects __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
319
334
       PARROT_ASSERT_ARG(interp) \
320
 
    , PARROT_ASSERT_ARG(mem_pools) \
321
335
    , PARROT_ASSERT_ARG(pool))
322
336
#define ASSERT_ARGS_gc_ms_pool_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
323
337
       PARROT_ASSERT_ARG(pool))
400
414
    interp->gc_sys->allocate_bufferlike_header  = gc_ms_allocate_bufferlike_header;
401
415
    interp->gc_sys->free_bufferlike_header      = gc_ms_free_bufferlike_header;
402
416
 
 
417
    interp->gc_sys->is_pmc_ptr              = gc_ms_is_pmc_ptr;
 
418
    interp->gc_sys->is_string_ptr           = gc_ms_is_string_ptr;
 
419
    interp->gc_sys->mark_pmc_header         = gc_ms_mark_pmc_header;
 
420
    interp->gc_sys->mark_pobj_header        = gc_ms_mark_pobj_header;
 
421
 
403
422
    interp->gc_sys->allocate_pmc_attributes = gc_ms_allocate_pmc_attributes;
404
423
    interp->gc_sys->free_pmc_attributes     = gc_ms_free_pmc_attributes;
405
424
 
433
452
 
434
453
    interp->gc_sys->iterate_live_strings = gc_ms_iterate_live_strings;
435
454
 
 
455
    /* gc_private is @objects */
 
456
    interp->gc_sys->gc_private       = Parrot_list_new(interp);
 
457
 
 
458
 
436
459
    Parrot_gc_str_initialize(interp, &interp->mem_pools->string_gc);
437
460
    initialize_fixed_size_pools(interp, interp->mem_pools);
438
461
    Parrot_gc_initialize_fixed_size_pools(interp, interp->mem_pools,
504
527
 
505
528
*/
506
529
 
 
530
PARROT_WARN_UNUSED_RESULT
 
531
PARROT_PURE_FUNCTION
507
532
int
508
533
Parrot_gc_ms_needed(PARROT_INTERP)
509
534
{
510
535
    ASSERT_ARGS(Parrot_gc_ms_needed)
511
536
 
512
 
    const Memory_Pools * const mem_pools = interp->mem_pools;
513
537
    size_t dynamic_threshold;
514
538
 
515
539
    /* new_mem is the additional amount of memory used since the last GC */
516
 
    size_t new_mem = mem_pools->memory_used
517
 
                   - mem_pools->mem_used_last_collect;
 
540
    size_t new_mem = interp->gc_sys->stats.memory_used
 
541
                   - interp->gc_sys->stats.mem_used_last_collect;
518
542
 
519
543
    /* Never run a GC if new_mem is below static GC_SIZE_THRESHOLD */
520
544
    if (new_mem <= GC_SIZE_THRESHOLD)
522
546
 
523
547
    /* The dynamic threshold is a configurable percentage of the amount of
524
548
       memory used after the last GC */
525
 
    dynamic_threshold = (size_t)(mem_pools->mem_used_last_collect *
 
549
    dynamic_threshold = (size_t)(interp->gc_sys->stats.mem_used_last_collect *
526
550
                                 (0.01 * interp->gc_threshold));
527
551
 
528
552
    return new_mem > dynamic_threshold;
581
605
 
582
606
    }
583
607
    else {
584
 
        ++mem_pools->gc_lazy_mark_runs;
 
608
        ++interp->gc_sys->stats.gc_lazy_mark_runs;
585
609
 
586
610
        Parrot_gc_clear_live_bits(interp, mem_pools->pmc_pool);
587
611
    }
592
616
    pt_gc_stop_mark(interp);
593
617
 
594
618
    /* Note it */
595
 
    ++mem_pools->gc_mark_runs;
 
619
    ++interp->gc_sys->stats.gc_mark_runs;
 
620
    interp->gc_sys->stats.header_allocs_since_last_collect = 0;
 
621
 
596
622
    --mem_pools->gc_mark_block_level;
597
 
    mem_pools->header_allocs_since_last_collect = 0;
598
 
    mem_pools->mem_used_last_collect = mem_pools->memory_used;
 
623
    interp->gc_sys->stats.header_allocs_since_last_collect = 0;
 
624
    interp->gc_sys->stats.mem_used_last_collect = interp->gc_sys->stats.memory_used;
599
625
 
600
626
    return;
601
627
}
777
803
 
778
804
/*
779
805
 
 
806
=item C<void gc_ms_mark_pmc_header(PARROT_INTERP, PMC *obj)>
 
807
 
 
808
Mark the PMC *obj as live and attach PMCs and/or buffers
 
809
 
 
810
=cut
 
811
 
 
812
*/
 
813
 
 
814
void
 
815
gc_ms_mark_pmc_header(PARROT_INTERP, ARGMOD_NULLOK(PMC *obj))
 
816
{
 
817
    ASSERT_ARGS(gc_ms_mark_pmc_header)
 
818
    if (!PMC_IS_NULL(obj)) {
 
819
        PARROT_ASSERT(PObj_is_PMC_TEST(obj));
 
820
 
 
821
        if (PObj_is_live_or_free_TESTALL(obj))
 
822
            return;
 
823
 
 
824
        /* mark it live */
 
825
        PObj_live_SET(obj);
 
826
 
 
827
        /* if object is a PMC and contains buffers or PMCs, then attach the PMC
 
828
         * to the chained mark list. */
 
829
        if (PObj_is_special_PMC_TEST(obj)) {
 
830
            if (PObj_custom_mark_TEST(obj))
 
831
                VTABLE_mark(interp, obj);
 
832
        }
 
833
 
 
834
        if (PMC_metadata(obj))
 
835
            Parrot_gc_mark_PMC_alive(interp, PMC_metadata(obj));
 
836
    }
 
837
}
 
838
 
 
839
/*
 
840
 
 
841
=item C<static int gc_ms_is_pmc_ptr(PARROT_INTERP, void *ptr)>
 
842
 
 
843
return True if *ptr is contained in the pool
 
844
 
 
845
=cut
 
846
 
 
847
*/
 
848
 
 
849
PARROT_WARN_UNUSED_RESULT
 
850
static int
 
851
gc_ms_is_pmc_ptr(PARROT_INTERP, ARGIN_NULLOK(void *ptr))
 
852
{
 
853
    ASSERT_ARGS(gc_ms_is_pmc_ptr)
 
854
    return contained_in_pool(interp->mem_pools->pmc_pool, ptr);
 
855
}
 
856
 
 
857
/*
 
858
 
 
859
=item C<static int gc_ms_is_string_ptr(PARROT_INTERP, void *ptr)>
 
860
 
 
861
establish if string *ptr is owned
 
862
 
 
863
=cut
 
864
 
 
865
*/
 
866
 
 
867
PARROT_WARN_UNUSED_RESULT
 
868
static int
 
869
gc_ms_is_string_ptr(PARROT_INTERP, ARGIN_NULLOK(void *ptr))
 
870
{
 
871
    ASSERT_ARGS(gc_ms_is_string_ptr)
 
872
    UINTVAL        i;
 
873
 
 
874
    for (i = 0; i < interp->mem_pools->num_sized; ++i) {
 
875
        if (interp->mem_pools->sized_header_pools[i]
 
876
            &&  contained_in_pool(interp->mem_pools->sized_header_pools[i], ptr))
 
877
            return 1;
 
878
    }
 
879
 
 
880
    return 0;
 
881
}
 
882
 
 
883
/*
 
884
 
780
885
=item C<static STRING* gc_ms_allocate_string_header(PARROT_INTERP, UINTVAL
781
886
flags)>
782
887
 
785
890
=cut
786
891
 
787
892
*/
 
893
 
 
894
PARROT_WARN_UNUSED_RESULT
788
895
PARROT_CAN_RETURN_NULL
789
896
static STRING*
790
897
gc_ms_allocate_string_header(PARROT_INTERP, UINTVAL flags)
795
902
            ? interp->mem_pools->constant_string_header_pool
796
903
            : interp->mem_pools->string_header_pool;
797
904
 
798
 
    STRING *s = (STRING *)pool->get_free_object(interp, interp->mem_pools, pool);
 
905
    STRING * const s = (STRING *)pool->get_free_object(interp, interp->mem_pools, pool);
799
906
    memset(s, 0, sizeof (STRING));
800
907
    return s;
801
908
}
824
931
 
825
932
/*
826
933
 
 
934
=item C<static void gc_ms_mark_pobj_header(PARROT_INTERP, PObj *obj)>
 
935
 
 
936
mark *obj as live
 
937
 
 
938
=cut
 
939
 
 
940
*/
 
941
 
 
942
static void
 
943
gc_ms_mark_pobj_header(SHIM_INTERP, ARGMOD_NULLOK(PObj *obj))
 
944
{
 
945
    ASSERT_ARGS(gc_ms_mark_pobj_header)
 
946
    if (obj) {
 
947
        /* mark it live */
 
948
        PObj_live_SET(obj);
 
949
    }
 
950
}
 
951
 
 
952
/*
 
953
 
827
954
=item C<static Buffer * gc_ms_allocate_bufferlike_header(PARROT_INTERP, size_t
828
955
size)>
829
956
 
1209
1336
*/
1210
1337
 
1211
1338
PARROT_MALLOC
1212
 
PARROT_CANNOT_RETURN_NULL
 
1339
PARROT_CAN_RETURN_NULL
1213
1340
static void *
1214
1341
gc_ms_allocate_memory_chunk(SHIM_INTERP, size_t size)
1215
1342
{
1218
1345
#ifdef DETAIL_MEMORY_DEBUG
1219
1346
    fprintf(stderr, "Allocated %i at %p\n", size, ptr);
1220
1347
#endif
1221
 
    if (!ptr)
 
1348
    if (!ptr && size)
1222
1349
        PANIC_OUT_OF_MEM(size);
1223
1350
    return ptr;
1224
1351
}
1225
1352
 
1226
1353
PARROT_MALLOC
1227
 
PARROT_CANNOT_RETURN_NULL
 
1354
PARROT_CAN_RETURN_NULL
1228
1355
static void *
1229
1356
gc_ms_reallocate_memory_chunk(SHIM_INTERP, ARGFREE(void *from), size_t size)
1230
1357
{
1240
1367
#ifdef DETAIL_MEMORY_DEBUG
1241
1368
    fprintf(stderr, "Allocated %i at %p\n", size, ptr);
1242
1369
#endif
1243
 
    if (!ptr)
 
1370
    if (!ptr && size)
1244
1371
        PANIC_OUT_OF_MEM(size);
1245
1372
    return ptr;
1246
1373
}
1247
1374
 
1248
1375
PARROT_MALLOC
1249
 
PARROT_CANNOT_RETURN_NULL
 
1376
PARROT_CAN_RETURN_NULL
1250
1377
static void *
1251
1378
gc_ms_allocate_memory_chunk_zeroed(SHIM_INTERP, size_t size)
1252
1379
{
1255
1382
#ifdef DETAIL_MEMORY_DEBUG
1256
1383
    fprintf(stderr, "Allocated %i at %p\n", size, ptr);
1257
1384
#endif
1258
 
    if (!ptr)
 
1385
    if (!ptr && size)
1259
1386
        PANIC_OUT_OF_MEM(size);
1260
1387
    return ptr;
1261
1388
}
1383
1510
 
1384
1511
static void
1385
1512
gc_ms_more_traceable_objects(PARROT_INTERP,
1386
 
        ARGIN(Memory_Pools *mem_pools),
 
1513
        SHIM(Memory_Pools *mem_pools),
1387
1514
        ARGMOD(Fixed_Size_Pool *pool))
1388
1515
{
1389
1516
    ASSERT_ARGS(gc_ms_more_traceable_objects)
1415
1542
*/
1416
1543
 
1417
1544
static void
1418
 
gc_ms_add_free_object(SHIM_INTERP,
1419
 
        ARGMOD(Memory_Pools *mem_pools),
 
1545
gc_ms_add_free_object(PARROT_INTERP,
 
1546
        SHIM(Memory_Pools *mem_pools),
1420
1547
        ARGMOD(Fixed_Size_Pool *pool),
1421
1548
        ARGIN(void *to_add))
1422
1549
{
1431
1558
 
1432
1559
    object->next_ptr = pool->free_list;
1433
1560
    pool->free_list  = object;
1434
 
    mem_pools->memory_used -= pool->object_size;
 
1561
    interp->gc_sys->stats.memory_used -= pool->object_size;
1435
1562
}
1436
1563
 
1437
1564
/*
1482
1609
    }
1483
1610
 
1484
1611
    --pool->num_free_objects;
1485
 
    mem_pools->memory_used += pool->object_size;
 
1612
    interp->gc_sys->stats.memory_used += pool->object_size;
1486
1613
 
1487
1614
    return ptr;
1488
1615
}
1632
1759
 
1633
1760
    Memory_Pools * const mem_pools = interp->mem_pools;
1634
1761
    switch (which) {
1635
 
        case TOTAL_MEM_ALLOC:
1636
 
            return mem_pools->memory_allocated;
1637
 
        case GC_MARK_RUNS:
1638
 
            return mem_pools->gc_mark_runs;
1639
 
        case GC_COLLECT_RUNS:
1640
 
            return mem_pools->gc_collect_runs;
1641
1762
        case ACTIVE_PMCS:
1642
1763
            return mem_pools->pmc_pool->total_objects -
1643
1764
                   mem_pools->pmc_pool->num_free_objects;
1647
1768
            return mem_pools->pmc_pool->total_objects;
1648
1769
        case TOTAL_BUFFERS:
1649
1770
            return gc_ms_total_sized_buffers(mem_pools);
 
1771
        case IMPATIENT_PMCS:
 
1772
            return mem_pools->num_early_gc_PMCs;
 
1773
        default:
 
1774
            return Parrot_gc_get_info(interp, which, &interp->gc_sys->stats);
 
1775
            break;
 
1776
    }
 
1777
    return 0;
 
1778
}
 
1779
 
 
1780
/*
 
1781
TODO Move it somewhere.
 
1782
*/
 
1783
 
 
1784
/*
 
1785
 
 
1786
=item C<size_t Parrot_gc_get_info(PARROT_INTERP, Interpinfo_enum which,
 
1787
GC_Statistics *stats)>
 
1788
 
 
1789
returns stats as required by enum which
 
1790
 
 
1791
=cut
 
1792
 
 
1793
*/
 
1794
 
 
1795
PARROT_WARN_UNUSED_RESULT
 
1796
PARROT_PURE_FUNCTION
 
1797
size_t
 
1798
Parrot_gc_get_info(SHIM_INTERP, Interpinfo_enum which, ARGIN(GC_Statistics *stats))
 
1799
{
 
1800
    ASSERT_ARGS(Parrot_gc_get_info)
 
1801
 
 
1802
    switch (which) {
 
1803
        case TOTAL_MEM_ALLOC:
 
1804
            return stats->memory_allocated;
 
1805
        case GC_MARK_RUNS:
 
1806
            return stats->gc_mark_runs;
 
1807
        case GC_COLLECT_RUNS:
 
1808
            return stats->gc_collect_runs;
1650
1809
        case HEADER_ALLOCS_SINCE_COLLECT:
1651
 
            return mem_pools->header_allocs_since_last_collect;
 
1810
            return stats->header_allocs_since_last_collect;
1652
1811
        case MEM_ALLOCS_SINCE_COLLECT:
1653
 
            return mem_pools->mem_allocs_since_last_collect;
 
1812
            return stats->mem_allocs_since_last_collect;
1654
1813
        case TOTAL_COPIED:
1655
 
            return mem_pools->memory_collected;
1656
 
        case IMPATIENT_PMCS:
1657
 
            return mem_pools->num_early_gc_PMCs;
 
1814
            return stats->memory_collected;
1658
1815
        case GC_LAZY_MARK_RUNS:
1659
 
            return mem_pools->gc_lazy_mark_runs;
1660
 
        case EXTENDED_PMCS:
 
1816
            return stats->gc_lazy_mark_runs;
1661
1817
        default:
1662
1818
            break;
1663
1819
    }
1775
1931
 * Local variables:
1776
1932
 *   c-file-style: "parrot"
1777
1933
 * End:
1778
 
 * vim: expandtab shiftwidth=4:
 
1934
 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
1779
1935
 */