>  トップ  >  archive  >  gccompact.c

gccompact.c

#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <inttypes.h>

union variant_s {
    struct cell_s *p;
    intptr_t i;
};

struct cell_s {
    intptr_t n;
    struct cell_s *p;
    union variant_s e[];
};

/*
 *  root                   heap            heaptop
 *  |32|NULL|e[0] ... e[31]|      ...      |
 *                         freeptr
 */
struct memory_s {
    struct cell_s *space;
    struct cell_s *root;
    struct cell_s *heap;
    struct cell_s *heaptop;
    struct cell_s *freeptr;
};

static inline struct cell_s *
forwarding_cell (struct cell_s const *const x, intptr_t const n)
{
    return (struct cell_s *)(x->e + n);
}

struct memory_s *
memory_initialize (struct memory_s *const vm)
{
    enum { ROOTSIZE = 32, SPACESIZE = 126 };

    vm->space = malloc ((SPACESIZE + 2) * sizeof (vm->space->e[0]));
    if (vm->space == NULL) return NULL;

    vm->root = vm->space;
    vm->root->n = ROOTSIZE;
    vm->root->p = NULL;
    for (intptr_t i = 0; i < vm->root->n; i++)
        vm->root->e[i].p = NULL;

    vm->heap = forwarding_cell (vm->root, vm->root->n);
    vm->heaptop = forwarding_cell (vm->space, SPACESIZE);
    vm->freeptr = vm->heap;

    return vm;
}

int
variant_ispointer (union variant_s const x)
{
    return (x.i & 7) == 0; 
}

int
memory_isheap_pointer (struct memory_s *const vm, union variant_s const x)
{
    return variant_ispointer (x) && vm->heap <= x.p && x.p < vm->freeptr;
}

void
memory_print_variant (struct memory_s *const vm, union variant_s const x)
{
    if (! variant_ispointer (x))
        printf ("%10"PRIdPTR, x.i);
    else if (NULL == x.p)
        printf ("      NULL");
    else if (memory_isheap_pointer (vm, x))
        printf (" #%07td#", x.p - vm->space);
    else
        printf ("%10p", x.p);
}

void
memory_print (struct memory_s *const vm)
{
    struct cell_s const *p = vm->space;
    while (p < vm->freeptr) {
        printf ("#%07td={%10"PRIdPTR, p - vm->space, p->n);
        if (p->p == NULL) printf ("       NULL");
        else printf ("  #%07td#", p->p - vm->space);
        for (intptr_t i = 0; i < p->n; i++) {
            if (i % 4 == 2) printf ("          ");
            else printf (" ");
            memory_print_variant (vm, p->e[i]);
            if (i % 4 == 1 && i + 1 < p->n) printf ("\n");
        }
        printf ("}\n");
        p = forwarding_cell (p, p->n);
    }
}

void
memory_mark (struct memory_s *const vm)
{
    vm->root->p = vm->heaptop;
    struct cell_s *top = vm->root;
    while (top != vm->heaptop) {
        struct cell_s *const cell = top;
        top = cell->p;
        for (intptr_t i = 0; i < cell->n; i++)
            if (memory_isheap_pointer (vm, cell->e[i]) && cell->e[i].p->p == NULL) {
                cell->e[i].p->p = top;
                top = cell->e[i].p;
            }
    }
}

void
memory_calculate_address (struct memory_s *const vm)
{
    struct cell_s *dst = vm->heap;
    struct cell_s *src = vm->heap;
    while (src < vm->freeptr) {
        struct cell_s *forw = forwarding_cell (src, src->n);
        if (src->p != NULL) {
            src->p = dst;
            dst = forwarding_cell (dst, src->n);
        } else {
            while (forw < vm->freeptr && forw->p == NULL) {
                src->n += 2 + forw->n;
                forw = forwarding_cell (src, src->n);
            }
        }
        src = forw;
    }
}

void
memory_update_pointer (struct memory_s *const vm)
{
    struct cell_s *cell = vm->space;
    while (cell < vm->freeptr) {
        if (cell->p != NULL)
            for (intptr_t i = 0; i < cell->n; i++)
                if (memory_isheap_pointer (vm, cell->e[i]))
                    cell->e[i].p = cell->e[i].p->p;
        cell = forwarding_cell (cell, cell->n);
    }
}

void
memory_relocate (struct memory_s *const vm)
{
    struct cell_s *dst = vm->heap;
    struct cell_s *src = vm->heap;
    while (src < vm->freeptr) {
        if (src->p) {
            src->p = NULL;
            if (dst < src) {
                dst->n = src->n;
                dst->p = src->p;
                for (intptr_t i = 0; i < dst->n; i++)
                    dst->e[i] = src->e[i];
            }
            dst = forwarding_cell (dst, dst->n);
        }
        src = forwarding_cell (src, src->n);
    }
    vm->freeptr = dst;
    vm->root->p = NULL;
}

void
memory_mark_compact_lisp2 (struct memory_s *const vm)
{
    memory_mark (vm);
    memory_calculate_address (vm);
    memory_update_pointer (vm);
    memory_relocate (vm);
}

struct cell_s *
memory_alloc (struct memory_s *const vm, intptr_t const n)
{
    if (forwarding_cell (vm->freeptr, n) > vm->heaptop) {
        memory_mark_compact_lisp2 (vm);
        if (forwarding_cell (vm->freeptr, n) > vm->heaptop)
            return NULL;
    }
    struct cell_s *const cell = vm->freeptr;
    cell->n = n;
    cell->p = NULL;
    for (intptr_t i = 0; i < n; i++)
        cell->e[i].p = NULL;
    vm->freeptr = forwarding_cell (vm->freeptr, n);
    return cell;
}

int
main (int argc, char *argv[])
{
    int i, c;
    struct cell_s *p;
    struct memory_s vm_store;
    struct memory_s *vm = memory_initialize (&vm_store);
    
    c = 0;
    if ((p = memory_alloc (vm, 2)) != NULL) {
        vm->root->e[1].p = p;
        vm->root->e[1].p->e[0].p = NULL;
        vm->root->e[1].p->e[1].i = (c++ << 1) | 1;
    }
    for (i = 0; i < 8 && (p = memory_alloc (vm, 2)) != NULL; i++) {
        vm->root->e[3].p = p;
        vm->root->e[3].p->e[0] = vm->root->e[1];
        vm->root->e[3].p->e[1].i = (c++ << 1) | 1;
    }
    for (i = 0; i < 8 && (p = memory_alloc (vm, 2)) != NULL; i++) {
        vm->root->e[5].p = p;
        vm->root->e[5].p->e[0] = vm->root->e[3];
        vm->root->e[5].p->e[1].i = (c++ << 1) | 1;
    }
    for (i = 0; i < 32 && (p = memory_alloc (vm, 2)) != NULL; i++) {
        vm->root->e[6].p = p;
        vm->root->e[6].p->e[0] = vm->root->e[6];
        vm->root->e[6].p->e[1].i = (c++ << 1) | 1;
    }
    vm->root->e[1].p = vm->root->e[3].p = NULL;
    memory_print (vm);
    free (vm->space);

    return EXIT_SUCCESS;
}
MIZUTANI Tociyuki at Kanagawa-Ku, Yokohama-City, Japan