76 lines
3.2 KiB
C
76 lines
3.2 KiB
C
// Codegen arena: a pool of executable memory that holds compiled
|
|
// sprite routines. Allocator is first-fit with adjacent-hole
|
|
// coalescing on free; manual compaction (codegenArenaCompact)
|
|
// memmoves live slots down to consolidate free space.
|
|
//
|
|
// SpriteT references slots via ArenaSlotT*, never raw function
|
|
// pointers. spriteDraw computes the call address each invocation as
|
|
// `gArenaBase + slot->offset + routineOffsets[shift][op]` so a
|
|
// compaction that moves a slot's bytes is transparent to callers.
|
|
//
|
|
// Allocations go through plain malloc; on every supported port
|
|
// (IIgs ORCA, Amiga libnix, ST mintlib, DJGPP+CWSDPMI) the heap is
|
|
// readable, writable, AND executable. We are not running in a W^X
|
|
// environment.
|
|
//
|
|
// The arena is a process-singleton: codegenArenaInit creates it from
|
|
// JoeyConfigT.codegenBytes during joeyInit; codegenArenaShutdown
|
|
// frees it on joeyShutdown. Most callers should go through the
|
|
// sprite API rather than touching the arena directly.
|
|
|
|
#ifndef JOEYLIB_CODEGEN_ARENA_INTERNAL_H
|
|
#define JOEYLIB_CODEGEN_ARENA_INTERNAL_H
|
|
|
|
#include "joey/types.h"
|
|
|
|
typedef struct ArenaSlotT {
|
|
uint32_t offset; // byte offset within the arena base
|
|
uint32_t size; // bytes occupied by this slot
|
|
bool used; // true = held by a sprite; false = free
|
|
struct ArenaSlotT *next; // linked-list, sorted by offset
|
|
struct ArenaSlotT *prev;
|
|
} ArenaSlotT;
|
|
|
|
|
|
// Lifecycle. Returns false if totalBytes is 0 or the underlying
|
|
// allocation fails. Idempotent: calling Init twice without an
|
|
// intervening Shutdown is a no-op.
|
|
bool codegenArenaInit(uint32_t totalBytes);
|
|
void codegenArenaShutdown(void);
|
|
|
|
// First-fit allocate `bytes` of executable memory. Returns NULL if
|
|
// no free slot is large enough -- the caller should run
|
|
// codegenArenaCompact and retry, or surface the failure.
|
|
ArenaSlotT *codegenArenaAlloc(uint32_t bytes);
|
|
|
|
// Mark the slot free and merge with adjacent free neighbors. The
|
|
// caller must drop its ArenaSlotT* immediately; the struct may be
|
|
// freed (if it coalesced into a neighbor).
|
|
void codegenArenaFree(ArenaSlotT *slot);
|
|
|
|
// Walk live slots in offset order, memmove each down to fill any
|
|
// preceding hole, drop all free slots from the list, and finish with
|
|
// one trailing free slot covering the remaining space. Per-slot
|
|
// `offset` fields are updated atomically with the memmove so any
|
|
// callers indexing through `gArenaBase + slot->offset` see the new
|
|
// value on their next read.
|
|
void codegenArenaCompact(void);
|
|
|
|
// Used for spriteDraw's address computation. The base pointer is
|
|
// stable for the lifetime of the arena; only slot->offset moves.
|
|
uint8_t *codegenArenaBase(void);
|
|
|
|
// Same address as codegenArenaBase() but returned as an integer. The
|
|
// IIgs JSL trampoline needs the 24-bit absolute address as a number
|
|
// it can split into bank/offset bytes; ORCA-C's pointer-to-uint32_t
|
|
// cast has dropped the bank byte in some expressions, so we expose
|
|
// the integer view directly.
|
|
uint32_t codegenArenaBaseAddr(void);
|
|
|
|
// Public-API support: sum of live slot sizes, total arena size.
|
|
// Difference is free space (which may be fragmented across holes
|
|
// until codegenArenaCompact runs).
|
|
uint32_t codegenArenaBytesUsed(void);
|
|
uint32_t codegenArenaBytesTotal(void);
|
|
|
|
#endif
|