diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luapplib/ppheap.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/luapplib/ppheap.c | 424 |
1 files changed, 424 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luapplib/ppheap.c b/Build/source/texk/web2c/luatexdir/luapplib/ppheap.c new file mode 100644 index 00000000000..f05e1b7a5df --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luapplib/ppheap.c @@ -0,0 +1,424 @@ + +#include "pplib.h" + +#define PPHEAP_BUFFER 0xFFFF +#define PPHEAP_WASTE 0x00FF + +#define ppheap_head(heap) ((uint8_t *)((heap) + 1)) + + +#if defined __arm__ || defined __ARM__ || defined ARM || defined __ARM || defined __arm || defined __ARM_ARCH ||defined __aarch64__ +# define PPHEAP_ARCH_ARM +# define PPHEAP_NEED_ALIGNMENT +#endif + + + +#ifdef PPHEAP_NEED_ALIGNMENT +/* Tests has shown that long double seems to work: */ +/* for 32bit aligned_data has algn: 64 as ppxref and ppref, */ +/* the other algns divide algn: 64, so it's ok.*/ +/* Hopefully it's ok for aarch64 too */ + +/* These data are stored in ppheap.c.001t.tu */ +/* made with gcc -fdump-tree-all-fdump-tree-all */ + + +/* @2586 identifier_node strg: ppxref lngt: 6 */ +/* @2565 record_type name: @2586 size: @679 algn: 64 */ +/* tag : struct flds: @2587 */ + + +/* @2672 identifier_node strg: ppxsec lngt: 6 */ +/* @2648 type_decl name: @2672 type: @2623 scpe: @221 */ +/* srcp: ppxref.h:16 chain: @2673 */ +/* @2623 record_type name: @2648 unql: @2649 size: @593 */ +/* algn: 32 tag : struct flds: @2650 */ + + +/* @2642 identifier_node strg: ppstream lngt: 8 */ +/* @2615 type_decl name: @2642 type: @2643 scpe: @221 */ +/* srcp: ppapi.h:54 chain: @2644 */ +/* @2643 record_type name: @2615 unql: @2614 size: @634 */ +/* algn: 32 tag : struct flds: @2641 */ + + +/* @2765 identifier_node strg: ppkids lngt: 6 */ +/* @2743 type_decl name: @2765 type: @2766 scpe: @221 */ +/* srcp: ppload.h:16 chain: @2767 */ +/* @2766 record_type name: @2743 unql: @2742 size: @19 */ +/* algn: 32 tag : struct flds: @2764 */ + + +/* @2625 identifier_node strg: ppdoc lngt: 5 */ +/* @2605 record_type name: @2625 size: @2626 algn: 32 */ +/* tag : struct flds: @2627 */ + +/* @2526 identifier_node strg: ppref lngt: 5 */ +/* @2513 record_type name: @2526 size: @662 algn: 64 */ +/* tag : struct flds: @2527 */ + + +/* @2595 identifier_node strg: ppdict lngt: 6 */ +/* @2576 type_decl name: @2595 type: @2596 scpe: @221 */ +/* srcp: ppapi.h:45 chain: @2597 */ +/* @2596 record_type name: @2576 unql: @2575 size: @593 */ +/* algn: 32 tag : struct flds: @2594 */ + + +/* @2769 identifier_node strg: ppcrypt_status lngt: 14 */ +/* @2752 type_decl name: @2769 type: @2770 scpe: @221 */ +/* srcp: ppapi.h:295 chain: @2771 */ +/* @2770 enumeral_type name: @2752 unql: @2655 size: @5 */ +/* algn: 32 prec: 32 sign: signed */ +/* min : @6 max : @7 csts: @2681 */ + + +/* @2558 identifier_node strg: pparray lngt: 7 */ +/* @2541 type_decl name: @2558 type: @2559 scpe: @221 */ +/* srcp: ppapi.h:39 chain: @2560 */ +/* @2559 record_type name: @2541 unql: @2540 size: @19 */ +/* algn: 32 tag : struct flds: @2557 */ + + +/* @2817 identifier_node strg: aligned_data */ +/* @2801 type_decl name: @2817 type: @2818 scpe: @221 */ +/* srcp: ppheap.c:22 chain: @2819 */ +/* @2818 real_type name: @2801 unql: @99 size: @19 */ +/* algn: 64 prec: 64 */ + + +typedef long double aligned_data; + + +#define ALIGN_BUFF_BUCKET_SIZE 0x3000 /* heuristic value, found by running few tests */ +#ifdef __SIZEOF_POINTER__ +#define SIZE_OF_POINTER __SIZEOF_POINTER__ +#else +#define SIZE_OF_POINTER (sizeof(void *)) +#endif + +typedef struct _simplereg { + size_t bucket_pos; + size_t bucket_size; + size_t heap_instance; + aligned_data **align_data_set ; +} simplereg; + +/* By default static vars are initialized to NULL, but to be clear.. */ +static simplereg *align_set = NULL ; + +static void align_init_set(void){ + size_t size ; + + if (align_set) { + align_set->heap_instance++; + return ; + } + + align_set = malloc(sizeof(simplereg)); + if (!align_set) { + fprintf(stderr,"! fatal error: unable to setup master register for aligned pointers\n"); + exit(EXIT_FAILURE); + } + + size = SIZE_OF_POINTER*ALIGN_BUFF_BUCKET_SIZE; + align_set->align_data_set = malloc(size); + if (!align_set->align_data_set) { + fprintf(stderr,"! fatal error: unable to setup register for aligned pointers\n"); + exit(EXIT_FAILURE); + } + + align_set->bucket_pos = 0; + align_set->bucket_size = ALIGN_BUFF_BUCKET_SIZE; + align_set->heap_instance = 1; + memset(align_set->align_data_set, 0UL,size); +} + +static void align_save_into_set(aligned_data *p){ + if (align_set->bucket_pos >= align_set->bucket_size) { + size_t new_size; + aligned_data **align_data_set_new; + + if(!align_set->align_data_set){ + fprintf(stderr,"! fatal error: unable to save aligned pointer,corrupted set\n"); + exit(EXIT_FAILURE); + } + new_size = (ALIGN_BUFF_BUCKET_SIZE+align_set->bucket_size)*SIZE_OF_POINTER; + align_data_set_new = malloc(new_size); + if (!align_data_set_new) { + fprintf(stderr,"! fatal error: unable to save aligned pointer\n"); + exit(EXIT_FAILURE); + } + memset(align_data_set_new,0,new_size); + memcpy(align_data_set_new, align_set->align_data_set, align_set->bucket_size*SIZE_OF_POINTER); + free(align_set->align_data_set); + align_set->align_data_set = align_data_set_new ; + align_set->bucket_size += ALIGN_BUFF_BUCKET_SIZE; + } + if (align_set->bucket_pos>align_set->bucket_size){ + fprintf(stderr,"! fatal error: unable to save aligned pointer, wrong position\n"); + exit(EXIT_FAILURE); + } + align_set->align_data_set[align_set->bucket_pos] = p ; + align_set->bucket_pos++; + +} + +static void align_free_set(void){ + /* We don't know what heap does with its data, so free here is not secure */ + + if(align_set){ + if (align_set->heap_instance>1) { + align_set->heap_instance--; + } else if (align_set->heap_instance ==1) { + if (align_set->align_data_set){ + size_t p; + for(p=1;p<align_set->bucket_pos;p++){ + if (align_set->align_data_set[p]) { + free(align_set->align_data_set[p]); + } + } + free(align_set->align_data_set); + align_set->align_data_set = NULL; + } + align_set->heap_instance=0; + free(align_set); + align_set = NULL ; + } + } +} + +#endif /* PPHEAP_NEED_ALIGNMENT */ + + +static ppheap * ppheap_create (size_t size) +{ + ppheap *heap; + heap = (ppheap *)pp_malloc(sizeof(ppheap) + size * sizeof(uint8_t)); + heap->size = size; + heap->space = size; + heap->data = ppheap_head(heap); + heap->prev = NULL; + return heap; +} + +ppheap * ppheap_new (void) +{ +#ifdef PPHEAP_NEED_ALIGNMENT + align_init_set(); +#endif + return ppheap_create(PPHEAP_BUFFER); +} + +void ppheap_free (ppheap *heap) +{ + ppheap *prev; + do + { + prev = heap->prev; + pp_free(heap); + heap = prev; + } while (heap != NULL); +#ifdef PPHEAP_NEED_ALIGNMENT + align_free_set(); +#endif + +} + +void ppheap_renew (ppheap *heap) +{ // free all but first + ppheap *prev; + if ((prev = heap->prev) != NULL) + { + heap->prev = NULL; + ppheap_free(prev); + } + heap->size = heap->space; + heap->data = ppheap_head(heap); +} + +static ppheap * ppheap_insert_top (ppheap **pheap, size_t size) +{ + ppheap *heap; + heap = ppheap_create(size); + heap->prev = (*pheap); + *pheap = heap; + return heap; +} + +static ppheap * ppheap_insert_sub (ppheap **pheap, size_t size) +{ + ppheap *heap; + heap = ppheap_create(size); + heap->prev = (*pheap)->prev; + (*pheap)->prev = heap; + return heap; +} + +void * ppheap_take (ppheap **pheap, size_t size) +{ + ppheap *heap; + uint8_t *data; +#ifdef PPHEAP_NEED_ALIGNMENT + aligned_data *p_aligned_data; +#endif + heap = *pheap; + if (size <= heap->size) + ; + else if (heap->size <= PPHEAP_WASTE && size <= (PPHEAP_BUFFER >> 1)) + heap = ppheap_insert_top(pheap, PPHEAP_BUFFER); + else + heap = ppheap_insert_sub(pheap, size); + data = heap->data; + heap->data += size; + heap->size -= size; +#ifdef PPHEAP_NEED_ALIGNMENT + /* Todo: only if data%sizeof(aligned_data) != 0 */ + p_aligned_data = malloc(size); + memcpy(p_aligned_data,data,size); + align_save_into_set(p_aligned_data); + return (void *)p_aligned_data; +#else + return (void *)data; +#endif + +} + + +/* iof buffer tied to a heap */ + +static ppheap * ppheap_resize (ppheap **pheap, size_t size) +{ + ppheap *heap; + heap = ppheap_create(size); + heap->prev = (*pheap)->prev; + memcpy(heap->data, (*pheap)->data, (*pheap)->space); // (*pheap)->size is irrelevant + pp_free(*pheap); + *pheap = heap; + return heap; +} + +static size_t ppheap_buffer_handler (iof *O, iof_mode mode) +{ + ppheap **pheap, *heap; + size_t objectsize, buffersize, neededsize; + uint8_t *copyfrom; + switch (mode) + { + case IOFWRITE: + /* apparently more space needed then assumed initsize */ + pheap = (ppheap **)O->link; + heap = *pheap; + objectsize = (size_t)(O->buf - heap->data); + buffersize = (size_t)(O->pos - O->buf); + neededsize = objectsize + (buffersize << 1); + if (ppheap_head(heap) < heap->data) + { + if (heap->size <= PPHEAP_WASTE && neededsize <= (PPHEAP_BUFFER >> 1)) + { + heap = ppheap_insert_top(pheap, PPHEAP_BUFFER); + copyfrom = heap->prev->data; + } + else + { + heap = ppheap_insert_sub(pheap, neededsize); + copyfrom = (*pheap)->data; + O->link = (void *)(&(*pheap)->prev); + } + memcpy(heap->data, copyfrom, objectsize + buffersize); + } + else + { /* the buffer was (re)initialized from a new empty heap and occupies its entire space */ + // ASSERT(ppheap_head(heap) == heap->data); + heap = ppheap_resize(pheap, neededsize); + } + O->buf = heap->data + objectsize; + O->pos = O->buf + buffersize; + O->end = heap->data + heap->size; + return (size_t)(O->end - O->pos); + case IOFFLUSH: + return 0; + case IOFCLOSE: + // O->buf = O->pos = O->end = NULL; + // O->link = NULL; + return 0; + default: + break; + } + return 0; +} + +iof * ppheap_buffer (ppheap **pheap, size_t objectsize, size_t initsize) +{ + static iof ppheap_buffer_iof = IOF_WRITER_STRUCT(ppheap_buffer_handler, NULL, NULL, 0, 0); + ppheap *heap; + size_t size; + size = objectsize + initsize; + heap = *pheap; + if (size <= heap->size) + ; + else if (heap->size <= PPHEAP_WASTE && size <= (PPHEAP_BUFFER >> 1)) + { + heap = ppheap_create(PPHEAP_BUFFER); + heap->prev = (*pheap); + *pheap = heap; + } + else + { + heap = ppheap_create(size); + heap->prev = (*pheap)->prev; + (*pheap)->prev = heap; + pheap = &(*pheap)->prev; // passed to ppheap_buffer_iof.link + } + ppheap_buffer_iof.buf = ppheap_buffer_iof.pos = heap->data + objectsize; + ppheap_buffer_iof.end = heap->data + heap->size; + ppheap_buffer_iof.link = pheap; // ASSERT(*pheap == heap) + return &ppheap_buffer_iof; +} + +/* +void * ppheap_buffer_data (iof *O, size_t *psize) +{ + ppheap *heap; + heap = *((ppheap **)(O->link)); + *psize = ppheap_buffer_size(O, heap); + return heap->data; +} +*/ + +void * ppheap_flush (iof *O, size_t *psize) // not from explicit ppheap ** !!! +{ + ppheap *heap; + uint8_t *data; + size_t size; +#ifdef PPHEAP_NEED_ALIGNMENT + aligned_data *p_aligned_data; +#endif + heap = *((ppheap **)(O->link)); + *psize = ppheap_buffer_size(O, heap); + size = *psize; + data = heap->data; +/* heap->data += *psize; + heap->size -= *psize; +*/ + heap->data += size; + heap->size -= size; + // O->buf = O->pos = O->end = NULL; + // O->link = NULL; + // iof_close(O); +#ifdef PPHEAP_NEED_ALIGNMENT + /* Todo: only if data%sizeof(aligned_data) != 0 */ + p_aligned_data = malloc(size); + memcpy(p_aligned_data,data,size); + align_save_into_set(p_aligned_data); + return (void *)p_aligned_data; +#else + return data; + +#endif + + +} + + |