Idris-dev/rts/idris_heap.h
XeFias d2a81f50a9 part 2 of FORCE_ALIGNMENT fix for arduino targets.
When FORCE_ALIGNMENT was introduced for pointer aligment on 8-bit arduino targets (See idris-lang@47cd264) it was not applied to the initialization of the cheney algorithm during garbage collection. The fix modifies the start of the heap location in the same way the FORCE_ALIGNMENT-define does for the initialization of the FP-heap in alloc_heap(...) in file idris_heap.c.

To prevent duplicate code this logic has been put in the function aligned_heap_pointer(...).
2017-01-09 21:41:58 +01:00

112 lines
3.1 KiB
C

#ifndef _IDRIS_HEAP_H
#define _IDRIS_HEAP_H
#include <stdbool.h>
#include <stddef.h>
/* *** C heap ***
* Objects with finalizers. Mark&sweep-collected.
*
* The C heap is implemented as a doubly linked list
* of pointers coupled with their finalizers.
*/
struct VM;
#define C_HEAP_GC_TRIGGER_SIZE(heap_size) \
(heap_size < 2048 \
? 4096 \
: 2 * heap_size \
)
typedef void CDataFinalizer(void *);
typedef struct CHeapItem {
/// Payload.
void * data;
/// Size of the item, in bytes.
/// This does not have to be a precise size. It is used to assess
/// whether the heap needs garbage collection.
size_t size;
/// Finalizer that will be called on the payload pointer.
/// Its job is to deallocate all associated resources,
/// including the memory pointed to by `data` (if any).
CDataFinalizer * finalizer;
/// The mark bit set by the FP heap traversal,
/// cleared by C heap sweep.
bool is_used;
/// Next item in the C heap.
struct CHeapItem * next;
/// Pointer to the previous next-pointer.
struct CHeapItem ** prev_next;
} CHeapItem;
typedef struct CHeap {
/// The first item in the heap. NULL if the heap is empty.
CHeapItem * first;
/// Total size of the heap. (Sum of sizes of items.)
/// This may not be a precise size since individual items'
/// sizes may be just estimates.
size_t size;
/// When heap reaches this size, GC will be triggered.
size_t gc_trigger_size;
} CHeap;
/// Create a C heap.
void c_heap_init(CHeap * c_heap);
/// Destroy the given C heap. Will not deallocate the given pointer.
/// Will call finalizers & deallocate all blocks in the heap.
void c_heap_destroy(CHeap * c_heap);
/// Insert the given item into the heap if it's not there yet.
/// The VM pointer is needed because this operation may trigger GC.
void c_heap_insert_if_needed(struct VM * vm, CHeap * c_heap, CHeapItem * item);
/// Mark the given item as used.
void c_heap_mark_item(CHeapItem * item);
/// Sweep the C heap, finalizing and freeing unused blocks.
void c_heap_sweep(CHeap * c_heap);
/// Create a C heap item from its payload, size estimate, and finalizer.
/// The size does not have to be precise but it should roughly reflect
/// how big the item is for GC to work effectively.
CHeapItem * c_heap_create_item(void * data, size_t size, CDataFinalizer * finalizer);
/* *** Idris heap **
* Objects without finalizers. Cheney-collected.
*/
typedef struct {
char* next; // Next allocated chunk. Should always (heap <= next < end).
char* heap; // Point to bottom of heap
char* end; // Point to top of heap
size_t size; // Size of _next_ heap. Size of current heap is /end - heap/.
size_t growth; // Quantity of heap growth in bytes.
char* old;
} Heap;
void alloc_heap(Heap * heap, size_t heap_size, size_t growth, char * old);
void free_heap(Heap * heap);
char* aligned_heap_pointer(char * heap);
#ifdef IDRIS_DEBUG
void heap_check_all(Heap * heap);
// Should be used _between_ gc's.
#define HEAP_CHECK(vm) heap_check_all(&(vm->heap));
#else
#define HEAP_CHECK(vm)
#endif // IDRIS_DEBUG
#endif // _IDRIS_HEAP_H