~ubuntu-branches/ubuntu/raring/parrot/raring-proposed

« back to all changes in this revision

Viewing changes to src/gc/gc_gms.c

  • Committer: Bazaar Package Importer
  • Author(s): Allison Randal
  • Date: 2011-07-30 18:45:03 UTC
  • mfrom: (1.1.13 upstream)
  • Revision ID: james.westby@ubuntu.com-20110730184503-34d4mprtfx6pt5h3
Tags: 3.6.0-1
* New upstream release
* debian/watch:
  - Modified regular expression to capture numbered directory name
    (patch from Dominique Dumont).
* debian/rules:
  - Split build-arch and build-indep, resolving lintian warning.
  - Update path to pbc_disassemble for manpage generation (patch
    from Dominique Dumont).
* debian/patches:
  - Added patch 02_fix_perl_interpreter_path.patch, resolving
    lintian warnings.
* debian/control:
  - Added DM-Upload-Allowed field.

Show diffs side-by-side

added added

removed removed

Lines of Context:
117
117
 *  1. Maximum number is 8 due limit number of bits in PMC.flags.
118
118
 *  2. Don't forget to update gc_gms_select_generation_to_collect after changing it!
119
119
 */
120
 
#define MAX_GENERATIONS     8
 
120
#define MAX_GENERATIONS     4
121
121
 
122
122
/* We allocate additional space in front of PObj* to store additional pointer */
123
123
typedef struct pmc_alloc_struct {
210
210
 
211
211
PARROT_MALLOC
212
212
PARROT_CAN_RETURN_NULL
213
 
static Buffer* gc_gms_allocate_buffer_header(PARROT_INTERP,
214
 
    SHIM(size_t size))
 
213
static Buffer* gc_gms_allocate_buffer_header(PARROT_INTERP, size_t size)
215
214
        __attribute__nonnull__(1);
216
215
 
217
216
static void gc_gms_allocate_buffer_storage(PARROT_INTERP,
226
225
 
227
226
PARROT_MALLOC
228
227
PARROT_CAN_RETURN_NULL
229
 
static void * gc_gms_allocate_memory_chunk(SHIM_INTERP, size_t size);
 
228
static void * gc_gms_allocate_memory_chunk(PARROT_INTERP, size_t size);
230
229
 
231
230
PARROT_MALLOC
232
231
PARROT_CAN_RETURN_NULL
233
 
static void * gc_gms_allocate_memory_chunk_zeroed(SHIM_INTERP, size_t size);
 
232
static void * gc_gms_allocate_memory_chunk_zeroed(PARROT_INTERP,
 
233
    size_t size);
234
234
 
235
235
PARROT_MALLOC
236
236
PARROT_CAN_RETURN_NULL
246
246
 
247
247
PARROT_MALLOC
248
248
PARROT_CAN_RETURN_NULL
249
 
static STRING* gc_gms_allocate_string_header(PARROT_INTERP,
250
 
    SHIM(UINTVAL flags))
 
249
static STRING* gc_gms_allocate_string_header(PARROT_INTERP, UINTVAL flags)
251
250
        __attribute__nonnull__(1);
252
251
 
253
252
static void gc_gms_allocate_string_storage(PARROT_INTERP,
290
289
 
291
290
static void gc_gms_free_buffer_header(PARROT_INTERP,
292
291
    ARGFREE(Buffer *s),
293
 
    SHIM(size_t size))
 
292
    size_t size)
294
293
        __attribute__nonnull__(1);
295
294
 
296
295
static void gc_gms_free_fixed_size_storage(PARROT_INTERP,
300
299
        __attribute__nonnull__(3)
301
300
        FUNC_MODIFIES(*data);
302
301
 
303
 
static void gc_gms_free_memory_chunk(SHIM_INTERP, ARGFREE(void *data));
 
302
static void gc_gms_free_memory_chunk(PARROT_INTERP, ARGFREE(void *data));
304
303
static void gc_gms_free_pmc_attributes(PARROT_INTERP, ARGMOD(PMC *pmc))
305
304
        __attribute__nonnull__(1)
306
305
        __attribute__nonnull__(2)
361
360
        __attribute__nonnull__(2)
362
361
        FUNC_MODIFIES(*str);
363
362
 
364
 
static void gc_gms_maybe_mark_and_sweep(PARROT_INTERP)
365
 
        __attribute__nonnull__(1);
366
 
 
367
363
static void gc_gms_pmc_get_youngest_generation(PARROT_INTERP,
368
364
    ARGIN(PMC *pmc))
369
365
        __attribute__nonnull__(1)
401
397
 
402
398
PARROT_MALLOC
403
399
PARROT_CAN_RETURN_NULL
404
 
static void * gc_gms_reallocate_memory_chunk(SHIM_INTERP,
 
400
static void * gc_gms_reallocate_memory_chunk(PARROT_INTERP,
405
401
    ARGFREE(void *from),
406
402
    size_t size);
407
403
 
408
404
PARROT_MALLOC
409
405
PARROT_CAN_RETURN_NULL
410
 
static void * gc_gms_reallocate_memory_chunk_zeroed(SHIM_INTERP,
 
406
static void * gc_gms_reallocate_memory_chunk_zeroed(PARROT_INTERP,
411
407
    ARGFREE(void *data),
412
408
    size_t newsize,
413
409
    size_t oldsize);
425
421
static size_t gc_gms_select_generation_to_collect(PARROT_INTERP)
426
422
        __attribute__nonnull__(1);
427
423
 
428
 
static void gc_gms_soil_pmc(PARROT_INTERP, ARGIN(PMC *pmc))
429
 
        __attribute__nonnull__(1)
430
 
        __attribute__nonnull__(2);
431
 
 
432
 
static void gc_gms_soil_roots(PARROT_INTERP, ARGIN(MarkSweep_GC *self))
433
 
        __attribute__nonnull__(1)
434
 
        __attribute__nonnull__(2);
435
 
 
436
424
static void gc_gms_str_get_youngest_generation(PARROT_INTERP,
437
425
    ARGIN(STRING *str))
438
426
        __attribute__nonnull__(1)
439
427
        __attribute__nonnull__(2);
440
428
 
441
 
static void gc_gms_sweep_pmc_cb(PARROT_INTERP, ARGIN(PObj *obj))
442
 
        __attribute__nonnull__(1)
443
 
        __attribute__nonnull__(2);
444
 
 
445
429
static void gc_gms_sweep_pools(PARROT_INTERP, ARGMOD(MarkSweep_GC *self))
446
430
        __attribute__nonnull__(1)
447
431
        __attribute__nonnull__(2)
448
432
        FUNC_MODIFIES(*self);
449
433
 
450
 
static void gc_gms_sweep_string_cb(PARROT_INTERP, ARGIN(PObj *obj))
451
 
        __attribute__nonnull__(1)
452
 
        __attribute__nonnull__(2);
453
 
 
454
434
static void gc_gms_unblock_GC_mark(PARROT_INTERP)
455
435
        __attribute__nonnull__(1);
456
436
 
468
448
        __attribute__nonnull__(1)
469
449
        __attribute__nonnull__(2);
470
450
 
471
 
static void gc_gms_validate_str(SHIM_INTERP, ARGIN(STRING *str))
 
451
static void gc_gms_validate_str(PARROT_INTERP, ARGIN(STRING *str))
472
452
        __attribute__nonnull__(2);
473
453
 
474
454
static void gc_gms_write_barrier(PARROT_INTERP, ARGMOD(PMC *pmc))
565
545
#define ASSERT_ARGS_gc_gms_mark_str_header __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
566
546
       PARROT_ASSERT_ARG(interp) \
567
547
    , PARROT_ASSERT_ARG(str))
568
 
#define ASSERT_ARGS_gc_gms_maybe_mark_and_sweep __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
569
 
       PARROT_ASSERT_ARG(interp))
570
548
#define ASSERT_ARGS_gc_gms_pmc_get_youngest_generation \
571
549
     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
572
550
       PARROT_ASSERT_ARG(interp) \
604
582
#define ASSERT_ARGS_gc_gms_select_generation_to_collect \
605
583
     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
606
584
       PARROT_ASSERT_ARG(interp))
607
 
#define ASSERT_ARGS_gc_gms_soil_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
608
 
       PARROT_ASSERT_ARG(interp) \
609
 
    , PARROT_ASSERT_ARG(pmc))
610
 
#define ASSERT_ARGS_gc_gms_soil_roots __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
611
 
       PARROT_ASSERT_ARG(interp) \
612
 
    , PARROT_ASSERT_ARG(self))
613
585
#define ASSERT_ARGS_gc_gms_str_get_youngest_generation \
614
586
     __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
615
587
       PARROT_ASSERT_ARG(interp) \
616
588
    , PARROT_ASSERT_ARG(str))
617
 
#define ASSERT_ARGS_gc_gms_sweep_pmc_cb __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
618
 
       PARROT_ASSERT_ARG(interp) \
619
 
    , PARROT_ASSERT_ARG(obj))
620
589
#define ASSERT_ARGS_gc_gms_sweep_pools __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
621
590
       PARROT_ASSERT_ARG(interp) \
622
591
    , PARROT_ASSERT_ARG(self))
623
 
#define ASSERT_ARGS_gc_gms_sweep_string_cb __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
624
 
       PARROT_ASSERT_ARG(interp) \
625
 
    , PARROT_ASSERT_ARG(obj))
626
592
#define ASSERT_ARGS_gc_gms_unblock_GC_mark __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
627
593
       PARROT_ASSERT_ARG(interp))
628
594
#define ASSERT_ARGS_gc_gms_unblock_GC_sweep __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
680
646
{
681
647
    ASSERT_ARGS(Parrot_gc_gms_init)
682
648
    struct MarkSweep_GC *self;
 
649
    const Parrot_Float4 nursery_size = (args->nursery_size > 0)
 
650
                        ? args->nursery_size
 
651
                        : GC_DEFAULT_NURSERY_SIZE;
683
652
 
684
653
    /* We have to transfer ownership of memory to parent interp in threaded parrot */
685
654
    interp->gc_sys->finalize_gc_system = NULL; /* gc_gms_finalize; */
772
741
        self->fixed_size_allocator = Parrot_gc_fixed_allocator_new(interp);
773
742
 
774
743
        /*
775
 
         * Collect every 1/100 of avaliable memory.
 
744
         * Collect every nursery_size/100 of system memory.
776
745
         *
777
 
         * Will be configured/dynamically adjusted in future. For now it gives
778
 
         * good performance overrall.
 
746
         * Configured by runtime parameter (default 2%).
779
747
         */
780
 
        self->gc_threshold = Parrot_sysmem_amount(interp) / 100;
 
748
        self->gc_threshold = Parrot_sysmem_amount(interp) * nursery_size / 100;
781
749
 
782
750
        Parrot_gc_str_initialize(interp, &self->string_gc);
783
751
    }
793
761
    MarkSweep_GC * const self = (MarkSweep_GC *)interp->gc_sys->gc_private;
794
762
    int gen = -1;
795
763
 
796
 
    UNUSED(flags);
797
 
 
798
764
    /* GC is blocked */
799
765
    if (self->gc_mark_block_level)
800
766
        return;
817
783
 
818
784
    gc_gms_check_sanity(interp);
819
785
    /*
820
 
    2. Choose K - how many collections we want to collect. Collections [0..K] will
821
 
    be collected. Remember K in C<self->gen_to_collect>.
 
786
    2. Choose K - how many collections we want to collect. Collections [0..K]
 
787
    will be collected. Remember K in C<self->gen_to_collect>.
822
788
    */
823
789
    self->gen_to_collect = gen = gc_gms_select_generation_to_collect(interp);
824
790
 
837
803
    */
838
804
    gc_gms_mark_pmc_header(interp, PMCNULL);
839
805
    Parrot_gc_trace_root(interp, NULL, GC_TRACE_FULL);
840
 
    if (interp->pdb && interp->pdb->debugger) {
 
806
 
 
807
    if (interp->pdb && interp->pdb->debugger)
841
808
        Parrot_gc_trace_root(interp->pdb->debugger, NULL, GC_TRACE_FULL);
842
 
    }
 
809
 
843
810
    gc_gms_print_stats(interp, "After trace_roots");
844
811
    gc_gms_check_sanity(interp);
845
812
 
859
826
    gc_gms_check_sanity(interp);
860
827
 
861
828
    /*
862
 
     * Before sweeping pools move all _root_ objects from Gen0 into dirty_list.
863
 
     *
864
 
     * Main reason for it:
865
 
     *   PMC *res = Parrot_pmc_new(interp);
866
 
     *   <do something to fill a lot of guts. E.g. Hash.clone>
867
 
     *   return *res;
868
 
     *
869
 
     * C<Hash.clone> can trigger GC. C<res> _will_ not be sealed by any automatic
870
 
     * methods (e.g. pmc2c vtable overrides).
871
 
     *
872
 
     * We will soil objects only from C stack.
873
 
     */
874
 
    gc_gms_soil_roots(interp, self);
875
 
 
876
 
    /*
877
829
    7. Sweep generations starting from K:
878
830
        - Destroy all dead objects
879
831
        - Move live objects into generation max(K+1, N)
882
834
    gc_gms_sweep_pools(interp, self);
883
835
    gc_gms_check_sanity(interp);
884
836
 
885
 
 
886
837
    /* Update some stats */
887
838
    interp->gc_sys->stats.header_allocs_since_last_collect  = 0;
888
839
    interp->gc_sys->stats.mem_used_last_collect             = 0;
922
873
    /* TODO Use less naive approach. E.g. count amount of allocated memory in
923
874
     * older generations */
924
875
    size_t runs = interp->gc_sys->stats.gc_mark_runs;
 
876
/*
925
877
    if (runs % 100000000 == 0)
926
878
        return 8;
927
879
    if (runs % 10000000 == 0)
932
884
        return 5;
933
885
    if (runs % 10000 == 0)
934
886
        return 4;
 
887
*/
935
888
    if (runs % 1000 == 0)
936
889
        return 3;
937
890
    if (runs % 100 == 0)
988
941
        }
989
942
        else {
990
943
            /* Survival */
991
 
            if ((gen <= self->gen_to_collect) && (gen < MAX_GENERATIONS - 1)) {
 
944
            /* This check used to be
 
945
             * if ((gen <= self->gen_to_collect) && (gen < MAX_GENERATIONS - 1))
 
946
             * Unfortunatelly it's wrong.
 
947
             * Consider this:
 
948
             * A1* -> B1* -> C0. (Object in generation notation. Star denotes "dirt
 
949
             * During gen0 collecting will "sink" A object, but not B. This picture
 
950
             * A2 -> B1* -> C1
 
951
             * After collecting gen1 we'll sink all of them:
 
952
             * A3 -> B2 -> C2.
 
953
             * And after collecting of gen2 we'll collect B and C incorrectly.
 
954
             * Because A(3) will be in older generation than B and C.
 
955
             */
 
956
            if (gen < MAX_GENERATIONS - 1) {
992
957
                SET_GEN_FLAGS(pmc, gen + 1);
993
958
            }
994
959
        };);
1068
1033
 
1069
1034
/*
1070
1035
 
1071
 
=item C<static void gc_gms_soil_pmc(PARROT_INTERP, PMC *pmc)>
1072
 
 
1073
 
Mark single nursery PMC as dirty. Part of Step 7.
1074
 
 
1075
 
=cut
1076
 
 
1077
 
*/
1078
 
 
1079
 
static void
1080
 
gc_gms_soil_pmc(PARROT_INTERP, ARGIN(PMC *pmc))
1081
 
{
1082
 
    ASSERT_ARGS(gc_gms_soil_pmc)
1083
 
    MarkSweep_GC      *self = (MarkSweep_GC *)interp->gc_sys->gc_private;
1084
 
    pmc_alloc_struct  *item = PMC2PAC(pmc);
1085
 
    size_t             gen  = POBJ2GEN(pmc);
1086
 
 
1087
 
    /* If object is dirty already */
1088
 
    if (PObj_GC_on_dirty_list_TEST(pmc))
1089
 
        return;
1090
 
 
1091
 
    /* Older objects are covered by other steps */
1092
 
    if (gen)
1093
 
        return;
1094
 
 
1095
 
    Parrot_pa_remove(interp, self->objects[0], item->ptr);
1096
 
    item->ptr = Parrot_pa_insert(interp, self->dirty_list, item);
1097
 
 
1098
 
    /* Move to next generation */
1099
 
    SET_GEN_FLAGS(pmc, 1);
1100
 
    PObj_GC_on_dirty_list_SET(pmc);
1101
 
    PObj_live_CLEAR(pmc);
1102
 
}
1103
 
 
1104
 
/*
1105
 
 
1106
 
=item C<static void gc_gms_soil_roots(PARROT_INTERP, MarkSweep_GC *self)>
1107
 
 
1108
 
Mark all nursery PMCs on C-stack as durty. Part of Step 7.
1109
 
 
1110
 
*/
1111
 
 
1112
 
static void
1113
 
gc_gms_soil_roots(PARROT_INTERP, ARGIN(MarkSweep_GC *self))
1114
 
{
1115
 
    ASSERT_ARGS(gc_gms_soil_roots)
1116
 
    interp->gc_sys->mark_pmc_header = gc_gms_soil_pmc;
1117
 
    Parrot_gc_trace_root(interp, NULL, GC_TRACE_SYSTEM_ONLY);
1118
 
    interp->gc_sys->mark_pmc_header = gc_gms_mark_pmc_header;
1119
 
}
1120
 
 
1121
 
/*
1122
 
 
1123
1036
=item C<static void gc_gms_sweep_pools(PARROT_INTERP, MarkSweep_GC *self)>
1124
1037
 
1125
1038
Sweep generations starting from K:
1145
1058
            pmc_alloc_struct *item = (pmc_alloc_struct *)ptr;
1146
1059
            PMC              *pmc  = &(item->pmc);
1147
1060
 
1148
 
            PARROT_ASSERT(PObj_constant_TEST(pmc) || POBJ2GEN(pmc) == i);
 
1061
            PARROT_ASSERT(PObj_constant_TEST(pmc) || (int)POBJ2GEN(pmc) == i);
1149
1062
 
1150
1063
            /* Paint live objects white */
1151
1064
            if (PObj_live_TEST(pmc) || PObj_constant_TEST(pmc)) {
1152
1065
                PObj_live_CLEAR(pmc);
1153
1066
 
1154
1067
                if (move_to_old) {
 
1068
                    SET_GEN_FLAGS(pmc, i + 1);
 
1069
 
1155
1070
                    Parrot_pa_remove(interp, self->objects[i], item->ptr);
1156
 
                    item->ptr = Parrot_pa_insert(interp, self->objects[i + 1], item);
1157
 
                    SET_GEN_FLAGS(pmc, i + 1);
1158
 
                    gc_gms_seal_object(interp, pmc);
 
1071
                    /* If this was freshly allocated object in C stack - move it to dirty list */
 
1072
                    if (PObj_GC_soil_root_TEST(pmc)) {
 
1073
                        item->ptr = Parrot_pa_insert(interp, self->dirty_list, item);
 
1074
                        PObj_GC_soil_root_CLEAR(pmc);
 
1075
                        PObj_GC_on_dirty_list_SET(pmc);
 
1076
                    }
 
1077
                    else {
 
1078
                        item->ptr = Parrot_pa_insert(interp, self->objects[i + 1], item);
 
1079
                        gc_gms_seal_object(interp, pmc);
 
1080
                    }
1159
1081
                }
1160
1082
            }
1161
1083
            else if (!PObj_constant_TEST(pmc)) {
1440
1362
    Parrot_gc_str_finalize(interp, &self->string_gc);
1441
1363
 
1442
1364
    for (i = 0; i < MAX_GENERATIONS; i++) {
1443
 
        Parrot_pa_destroy(interp, self->objects[0]);
1444
 
        Parrot_pa_destroy(interp, self->strings[0]);
 
1365
        Parrot_pa_destroy(interp, self->objects[i]);
 
1366
        Parrot_pa_destroy(interp, self->strings[i]);
1445
1367
    }
1446
1368
 
1447
1369
    Parrot_gc_pool_destroy(interp, self->pmc_allocator);
1449
1371
    Parrot_gc_fixed_allocator_destroy(interp, self->fixed_size_allocator);
1450
1372
}
1451
1373
 
 
1374
/*
 
1375
 
 
1376
=item C<gc_gms_maybe_mark_and_sweep(PARROT_INTERP)>
 
1377
 
 
1378
Maybe M&S. Depends on total allocated memory, memory allocated since last alloc
 
1379
and phase of the Moon.
 
1380
 
 
1381
=cut
 
1382
 
 
1383
*/
 
1384
 
 
1385
#define gc_gms_maybe_mark_and_sweep(i) \
 
1386
    do { \
 
1387
        MarkSweep_GC * const self = (MarkSweep_GC *)(i)->gc_sys->gc_private; \
 
1388
    \
 
1389
        /* Collect every gc_threshold. */ \
 
1390
        if (!self->gc_mark_block_level \
 
1391
        &&  (i)->gc_sys->stats.mem_used_last_collect > self->gc_threshold) \
 
1392
            gc_gms_mark_and_sweep(interp, 0); \
 
1393
    } while (0)
 
1394
 
1452
1395
PARROT_MALLOC
1453
1396
PARROT_CAN_RETURN_NULL
1454
1397
static PMC*
1518
1461
    MarkSweep_GC     * const self = (MarkSweep_GC *)interp->gc_sys->gc_private;
1519
1462
    PObj             * const obj  = (PObj *)ptr;
1520
1463
    pmc_alloc_struct * const item = PMC2PAC(ptr);
1521
 
    size_t            i;
1522
1464
 
1523
 
    if (!obj || !item)
 
1465
    /* Not aligned pointers aren't pointers */
 
1466
    if (!obj || !item || ((size_t)obj & 3) || ((size_t)item & 3))
1524
1467
        return 0;
1525
1468
 
1526
1469
    if (!Parrot_gc_pool_is_owned(interp, self->pmc_allocator, item))
1531
1474
        return 0;
1532
1475
 
1533
1476
    /* If object too old - skip it */
1534
 
    if (POBJ2GEN(&item->pmc) > self->gen_to_collect)
 
1477
    if (POBJ2GEN(obj) > self->gen_to_collect)
1535
1478
        return 0;
1536
1479
 
1537
1480
    /* Object is on dirty_list. */
1538
 
    if (PObj_GC_on_dirty_list_TEST(&item->pmc))
 
1481
    if (PObj_GC_on_dirty_list_TEST(obj))
1539
1482
        return 0;
1540
1483
 
1541
 
    for (i = 0; i < MAX_GENERATIONS; i++) {
1542
 
        /* Pool.is_owned isn't precise enough (yet) */
1543
 
        if (Parrot_pa_is_owned(interp, self->objects[i], item, item->ptr))
1544
 
            return 1;
 
1484
    /* Pool.is_owned isn't precise enough (yet) */
 
1485
    if (Parrot_pa_is_owned(interp, self->objects[POBJ2GEN(obj)], item, item->ptr)) {
 
1486
        if (POBJ2GEN(obj) == 0)
 
1487
            PObj_GC_soil_root_SET(obj);
 
1488
        return 1;
1545
1489
    }
1546
1490
 
1547
1491
    return 0;
1549
1493
 
1550
1494
/*
1551
1495
 
1552
 
=item C<static void gc_gms_sweep_pmc_cb(PARROT_INTERP, PObj *obj)>
1553
 
 
1554
 
destroy pmc *obj
1555
 
 
1556
 
=cut
1557
 
 
1558
 
*/
1559
 
 
1560
 
static void
1561
 
gc_gms_sweep_pmc_cb(PARROT_INTERP, ARGIN(PObj *obj))
1562
 
{
1563
 
    ASSERT_ARGS(gc_gms_sweep_pmc_cb)
1564
 
    PMC *pmc = (PMC *)obj;
1565
 
    Parrot_pmc_destroy(interp, pmc);
1566
 
}
1567
 
 
1568
 
/*
1569
 
 
1570
1496
=item C<gc_gms_allocate_string_header(PARROT_INTERP, STRING *str)>
1571
1497
 
1572
1498
=item C<gc_gms_free_string_header(PARROT_INTERP, STRING *s)>
1590
1516
    MarkSweep_GC     * const self = (MarkSweep_GC *)interp->gc_sys->gc_private;
1591
1517
    Pool_Allocator   * const pool = self->string_allocator;
1592
1518
    string_alloc_struct *item;
1593
 
    STRING           *ret;
 
1519
    STRING              *ret;
1594
1520
 
1595
1521
    gc_gms_maybe_mark_and_sweep(interp);
1596
1522
 
1597
 
    /* Increase used memory. Not precisely accurate due Pool_Allocator paging */
 
1523
    /* Increase used memory.
 
1524
     * Not precisely accurate due to Pool_Allocator paging.  */
1598
1525
    ++interp->gc_sys->stats.header_allocs_since_last_collect;
1599
1526
    interp->gc_sys->stats.memory_used           += sizeof (STRING);
1600
1527
    interp->gc_sys->stats.mem_used_last_collect += sizeof (STRING);
1665
1592
    MarkSweep_GC     * const self = (MarkSweep_GC *)interp->gc_sys->gc_private;
1666
1593
    PObj             * const obj  = (PObj *)ptr;
1667
1594
    string_alloc_struct * const item = STR2PAC(ptr);
1668
 
    size_t            i;
1669
1595
 
1670
 
    if (!obj || !item)
 
1596
    /* Not aligned pointers aren't pointers */
 
1597
    if (!obj || !item || ((size_t)obj & 3) || ((size_t)item & 3))
1671
1598
        return 0;
1672
1599
 
1673
1600
    if (!Parrot_gc_pool_is_owned(interp, self->string_allocator, item))
1681
1608
    if (POBJ2GEN(&item->str) > self->gen_to_collect)
1682
1609
        return 0;
1683
1610
 
1684
 
    /* Pool.is_owned isn't precise enough (yet) */
1685
 
    for (i = 0; i < MAX_GENERATIONS; i++) {
1686
 
        if (Parrot_pa_is_owned(interp, self->strings[i], item, item->ptr))
1687
 
            return 1;
1688
 
    }
 
1611
    if (Parrot_pa_is_owned(interp, self->strings[POBJ2GEN(obj)], item, item->ptr))
 
1612
        return 1;
 
1613
 
1689
1614
    return 0;
1690
1615
}
1691
1616
 
1750
1675
 
1751
1676
/*
1752
1677
 
1753
 
=item C<static void gc_gms_sweep_string_cb(PARROT_INTERP, PObj *obj)>
1754
 
 
1755
 
destroy string *obj
1756
 
 
1757
 
=cut
1758
 
 
1759
 
*/
1760
 
 
1761
 
static void
1762
 
gc_gms_sweep_string_cb(PARROT_INTERP, ARGIN(PObj *obj))
1763
 
{
1764
 
    ASSERT_ARGS(gc_gms_sweep_string_cb)
1765
 
    MarkSweep_GC * const self = (MarkSweep_GC *)interp->gc_sys->gc_private;
1766
 
    Buffer       * const str  = (Buffer *)obj;
1767
 
    /* Compact string pool here. Or get rid of "shared buffers" and just free storage */
1768
 
    if (Buffer_bufstart(str) && !PObj_external_TEST(str))
1769
 
        Parrot_gc_str_free_buffer_storage(interp, &self->string_gc, str);
1770
 
}
1771
 
 
1772
 
 
1773
 
/*
1774
 
 
1775
1678
=item C<static void gc_gms_iterate_live_strings(PARROT_INTERP,
1776
1679
string_iterator_callback callback, void *data)>
1777
1680
 
2010
1913
}
2011
1914
 
2012
1915
/*
2013
 
 
2014
 
=item C<static void gc_gms_maybe_mark_and_sweep(PARROT_INTERP)>
2015
 
 
2016
 
Maybe M&S. Depends on total allocated memory, memory allocated since last alloc
2017
 
and phase of the Moon.
2018
 
 
2019
 
=cut
2020
 
 
2021
 
*/
2022
 
static void
2023
 
gc_gms_maybe_mark_and_sweep(PARROT_INTERP)
2024
 
{
2025
 
    ASSERT_ARGS(gc_gms_maybe_mark_and_sweep)
2026
 
 
2027
 
    MarkSweep_GC * const self = (MarkSweep_GC *)interp->gc_sys->gc_private;
2028
 
 
2029
 
    /* Collect every gc_threshold. */
2030
 
    if (interp->gc_sys->stats.mem_used_last_collect > self->gc_threshold) {
2031
 
        gc_gms_mark_and_sweep(interp, 0);
2032
 
    }
2033
 
}
2034
 
 
2035
 
/*
2036
1916
=item C<static void gc_gms_write_barrier(PARROT_INTERP, PMC *pmc)>
2037
1917
 
2038
1918
WriteBarrier for PMC. Add to root_objects list for mandatory next collecting.