Alien-TinyCCx

 view release on metacpan or  search on metacpan

src/tccpp.c  view on Meta::CPAN

#define TAL_DEBUG_PARAMS
#else
#define TAL_DEBUG 1
//#define TAL_INFO 1 /* collect and dump allocators stats */
#define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__)
#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size, __FILE__, __LINE__)
#define TAL_DEBUG_PARAMS , const char *file, int line
#define TAL_DEBUG_FILE_LEN 15
#endif

#define TOKSYM_TAL_SIZE     (768 * 1024) /* allocator for tiny TokenSym in table_ident */
#define TOKSTR_TAL_SIZE     (768 * 1024) /* allocator for tiny TokenString instances */
#define CSTR_TAL_SIZE       (256 * 1024) /* allocator for tiny CString instances */
#define TOKSYM_TAL_LIMIT    256 /* prefer unique limits to distinguish allocators debug msgs */
#define TOKSTR_TAL_LIMIT    128 /* 32 * sizeof(int) */
#define CSTR_TAL_LIMIT      1024

typedef struct TinyAlloc {
    size_t  limit;
    size_t  size;
    uint8_t *buffer;
    uint8_t *p;
    size_t  nb_allocs;
    struct TinyAlloc *next, *top;
#ifdef TAL_INFO
    size_t  nb_peak;
    size_t  nb_total;
    size_t  nb_missed;
    uint8_t *peak_p;
#endif
} TinyAlloc;

typedef struct tal_header_t {
    size_t  size;
#ifdef TAL_DEBUG
    int     line_num; /* negative line_num used for double free check */
    char    file_name[TAL_DEBUG_FILE_LEN + 1];
#endif
} tal_header_t;

/* ------------------------------------------------------------------------- */

ST_FUNC TinyAlloc *tal_new(TinyAlloc **pal, size_t limit, size_t size)
{
    TinyAlloc *al = tcc_mallocz(sizeof(TinyAlloc));
    al->p = al->buffer = tcc_malloc(size);
    al->limit = limit;
    al->size = size;
    if (pal) *pal = al;
    return al;
}

ST_FUNC void tal_delete(TinyAlloc *al)
{
    TinyAlloc *next;

tail_call:
    if (!al)
        return;
#ifdef TAL_INFO
    fprintf(stderr, "limit=%5d, size=%5g MB, nb_peak=%6d, nb_total=%8d, nb_missed=%6d, usage=%5.1f%%\n",
            al->limit, al->size / 1024.0 / 1024.0, al->nb_peak, al->nb_total, al->nb_missed,
            (al->peak_p - al->buffer) * 100.0 / al->size);
#endif
#ifdef TAL_DEBUG
    if (al->nb_allocs > 0) {
        uint8_t *p;
        fprintf(stderr, "TAL_DEBUG: mem leak %d chunks (limit= %d)\n",
                al->nb_allocs, al->limit);
        p = al->buffer;
        while (p < al->p) {
            tal_header_t *header = (tal_header_t *)p;
            if (header->line_num > 0) {
                fprintf(stderr, "  file %s, line %u: %u bytes\n",
                        header->file_name, header->line_num, header->size);
            }
            p += header->size + sizeof(tal_header_t);
        }
    }
#endif
    next = al->next;
    tcc_free(al->buffer);
    tcc_free(al);
    al = next;
    goto tail_call;
}

ST_FUNC void tal_free_impl(TinyAlloc *al, void *p TAL_DEBUG_PARAMS)
{
    if (!p)
        return;
tail_call:
    if (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size) {
#ifdef TAL_DEBUG
        tal_header_t *header = (((tal_header_t *)p) - 1);
        if (header->line_num < 0) {
            fprintf(stderr, "TAL_DEBUG: file %s, line %u double frees chunk from\n",
                    file, line);
            fprintf(stderr, "  file %s, line %u: %u bytes\n",
                    header->file_name, -header->line_num, header->size);
        } else
            header->line_num = -header->line_num;
#endif
        al->nb_allocs--;
        if (!al->nb_allocs)
            al->p = al->buffer;
    } else if (al->next) {
        al = al->next;
        goto tail_call;
    }
    else
        tcc_free(p);
}

ST_FUNC void *tal_realloc_impl(TinyAlloc **pal, void *p, size_t size TAL_DEBUG_PARAMS)
{
    tal_header_t *header;
    void *ret;
    int is_own;
    size_t adj_size = (size + 3) & -4;
    TinyAlloc *al = *pal;

tail_call:
    is_own = (al->buffer <= (uint8_t *)p && (uint8_t *)p < al->buffer + al->size);
    if ((!p || is_own) && size <= al->limit) {
        if (al->p + adj_size + sizeof(tal_header_t) < al->buffer + al->size) {
            header = (tal_header_t *)al->p;
            header->size = adj_size;
#ifdef TAL_DEBUG
            { int ofs = strlen(file) - TAL_DEBUG_FILE_LEN;
            strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), TAL_DEBUG_FILE_LEN);
            header->file_name[TAL_DEBUG_FILE_LEN] = 0;
            header->line_num = line; }
#endif
            ret = al->p + sizeof(tal_header_t);
            al->p += adj_size + sizeof(tal_header_t);
            if (is_own) {
                header = (((tal_header_t *)p) - 1);
                memcpy(ret, p, header->size);
#ifdef TAL_DEBUG
                header->line_num = -header->line_num;
#endif
            } else {
                al->nb_allocs++;
            }
#ifdef TAL_INFO
            if (al->nb_peak < al->nb_allocs)
                al->nb_peak = al->nb_allocs;
            if (al->peak_p < al->p)
                al->peak_p = al->p;
            al->nb_total++;
#endif
            return ret;
        } else if (is_own) {
            al->nb_allocs--;
            ret = tal_realloc(*pal, 0, size);
            header = (((tal_header_t *)p) - 1);
            memcpy(ret, p, header->size);
#ifdef TAL_DEBUG



( run in 0.474 second using v1.01-cache-2.11-cpan-13bb782fe5a )