summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/luapplib/ppheap.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luapplib/ppheap.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/luapplib/ppheap.c424
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
+
+
+}
+
+