2015-06-07 21:56:23 -04:00
|
|
|
/* picoc heap memory allocation. */
|
2015-06-07 00:40:08 -04:00
|
|
|
|
2009-02-23 21:14:07 -05:00
|
|
|
/* stack grows up from the bottom and heap grows down from the top of heap space */
|
2011-02-17 02:11:20 -05:00
|
|
|
#include "interpreter.h"
|
2009-02-23 21:14:07 -05:00
|
|
|
|
2009-04-10 05:35:10 -04:00
|
|
|
#ifdef DEBUG_HEAP
|
2012-09-22 01:11:44 -04:00
|
|
|
void ShowBigList(Picoc *pc)
|
2009-04-10 05:35:10 -04:00
|
|
|
{
|
|
|
|
struct AllocNode *LPos;
|
2015-06-07 00:40:08 -04:00
|
|
|
|
2015-06-07 02:28:10 -04:00
|
|
|
printf("Heap: bottom=0x%lx 0x%lx-0x%lx, big freelist=", (long)pc->HeapBottom,
|
|
|
|
(long)&(pc->HeapMemory)[0], (long)&(pc->HeapMemory)[HEAP_SIZE]);
|
2012-09-22 01:11:44 -04:00
|
|
|
for (LPos = pc->FreeListBig; LPos != NULL; LPos = LPos->NextFree)
|
2009-04-10 05:35:10 -04:00
|
|
|
printf("0x%lx:%d ", (long)LPos, LPos->Size);
|
2015-06-07 00:40:08 -04:00
|
|
|
|
2009-04-10 05:35:10 -04:00
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-02-23 21:14:07 -05:00
|
|
|
/* initialise the stack and heap storage */
|
2012-09-22 01:11:44 -04:00
|
|
|
void HeapInit(Picoc *pc, int StackOrHeapSize)
|
2009-02-23 21:14:07 -05:00
|
|
|
{
|
|
|
|
int Count;
|
2009-11-07 12:47:25 -05:00
|
|
|
int AlignOffset = 0;
|
2015-06-07 00:40:08 -04:00
|
|
|
|
2012-09-22 01:11:44 -04:00
|
|
|
pc->HeapMemory = malloc(StackOrHeapSize);
|
2015-06-07 02:28:10 -04:00
|
|
|
pc->HeapBottom = NULL; /* the bottom of the (downward-growing) heap */
|
|
|
|
pc->StackFrame = NULL; /* the current stack frame */
|
|
|
|
pc->HeapStackTop = NULL; /* the top of the stack */
|
2010-07-27 10:03:06 -04:00
|
|
|
|
2012-09-22 01:11:44 -04:00
|
|
|
while (((unsigned long)&pc->HeapMemory[AlignOffset] & (sizeof(ALIGN_TYPE)-1)) != 0)
|
2009-11-07 12:47:25 -05:00
|
|
|
AlignOffset++;
|
2015-06-07 00:40:08 -04:00
|
|
|
|
2012-09-22 01:11:44 -04:00
|
|
|
pc->StackFrame = &(pc->HeapMemory)[AlignOffset];
|
|
|
|
pc->HeapStackTop = &(pc->HeapMemory)[AlignOffset];
|
|
|
|
*(void **)(pc->StackFrame) = NULL;
|
|
|
|
pc->HeapBottom = &(pc->HeapMemory)[StackOrHeapSize-sizeof(ALIGN_TYPE)+AlignOffset];
|
|
|
|
pc->FreeListBig = NULL;
|
2009-02-23 21:14:07 -05:00
|
|
|
for (Count = 0; Count < FREELIST_BUCKETS; Count++)
|
2012-09-22 01:11:44 -04:00
|
|
|
pc->FreeListBucket[Count] = NULL;
|
2009-02-23 21:14:07 -05:00
|
|
|
}
|
|
|
|
|
2012-09-22 01:11:44 -04:00
|
|
|
void HeapCleanup(Picoc *pc)
|
2010-07-27 10:03:06 -04:00
|
|
|
{
|
2012-09-22 01:11:44 -04:00
|
|
|
free(pc->HeapMemory);
|
2010-07-27 10:03:06 -04:00
|
|
|
}
|
|
|
|
|
2009-02-23 21:14:07 -05:00
|
|
|
/* allocate some space on the stack, in the current stack frame
|
|
|
|
* clears memory. can return NULL if out of stack space */
|
2012-09-22 01:11:44 -04:00
|
|
|
void *HeapAllocStack(Picoc *pc, int Size)
|
2009-02-23 21:14:07 -05:00
|
|
|
{
|
2012-09-22 01:11:44 -04:00
|
|
|
char *NewMem = pc->HeapStackTop;
|
2015-06-09 03:45:00 -04:00
|
|
|
char *NewTop = (char*)pc->HeapStackTop + MEM_ALIGN(Size);
|
2009-06-02 01:51:51 -04:00
|
|
|
#ifdef DEBUG_HEAP
|
2012-09-22 01:11:44 -04:00
|
|
|
printf("HeapAllocStack(%ld) at 0x%lx\n", (unsigned long)MEM_ALIGN(Size), (unsigned long)pc->HeapStackTop);
|
2009-06-02 01:51:51 -04:00
|
|
|
#endif
|
2015-06-09 03:45:00 -04:00
|
|
|
if (NewTop > (char*)pc->HeapBottom)
|
2009-02-23 21:14:07 -05:00
|
|
|
return NULL;
|
2015-06-07 00:40:08 -04:00
|
|
|
|
2015-06-09 03:45:00 -04:00
|
|
|
pc->HeapStackTop = (void*)NewTop;
|
|
|
|
memset((void*)NewMem, '\0', Size);
|
2009-02-23 21:14:07 -05:00
|
|
|
return NewMem;
|
2009-01-26 03:57:32 -05:00
|
|
|
}
|
|
|
|
|
2009-06-02 01:51:51 -04:00
|
|
|
/* allocate some space on the stack, in the current stack frame */
|
2012-09-22 01:11:44 -04:00
|
|
|
void HeapUnpopStack(Picoc *pc, int Size)
|
2009-06-02 01:51:51 -04:00
|
|
|
{
|
|
|
|
#ifdef DEBUG_HEAP
|
2012-09-22 01:11:44 -04:00
|
|
|
printf("HeapUnpopStack(%ld) at 0x%lx\n", (unsigned long)MEM_ALIGN(Size), (unsigned long)pc->HeapStackTop);
|
2009-06-02 01:51:51 -04:00
|
|
|
#endif
|
2015-06-09 03:45:00 -04:00
|
|
|
pc->HeapStackTop = (void*)((char*)pc->HeapStackTop + MEM_ALIGN(Size));
|
2009-06-02 01:51:51 -04:00
|
|
|
}
|
|
|
|
|
2009-01-26 03:57:32 -05:00
|
|
|
/* free some space at the top of the stack */
|
2012-09-22 01:11:44 -04:00
|
|
|
int HeapPopStack(Picoc *pc, void *Addr, int Size)
|
2009-01-26 03:57:32 -05:00
|
|
|
{
|
|
|
|
int ToLose = MEM_ALIGN(Size);
|
2015-06-09 03:45:00 -04:00
|
|
|
if (ToLose > ((char*)pc->HeapStackTop - (char*)&(pc->HeapMemory)[0]))
|
2009-01-26 03:57:32 -05:00
|
|
|
return FALSE;
|
2015-06-07 00:40:08 -04:00
|
|
|
|
2009-06-02 01:51:51 -04:00
|
|
|
#ifdef DEBUG_HEAP
|
2015-06-07 02:28:10 -04:00
|
|
|
printf("HeapPopStack(0x%lx, %ld) back to 0x%lx\n", (unsigned long)Addr,
|
|
|
|
(unsigned long)MEM_ALIGN(Size), (unsigned long)pc->HeapStackTop - ToLose);
|
2009-06-02 01:51:51 -04:00
|
|
|
#endif
|
2015-06-09 03:45:00 -04:00
|
|
|
pc->HeapStackTop = (void*)((char*)pc->HeapStackTop - ToLose);
|
2012-09-22 01:11:44 -04:00
|
|
|
assert(Addr == NULL || pc->HeapStackTop == Addr);
|
2015-06-07 00:40:08 -04:00
|
|
|
|
2009-01-26 03:57:32 -05:00
|
|
|
return TRUE;
|
2009-02-23 21:14:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* push a new stack frame on to the stack */
|
2012-09-22 01:11:44 -04:00
|
|
|
void HeapPushStackFrame(Picoc *pc)
|
2009-02-23 21:14:07 -05:00
|
|
|
{
|
|
|
|
#ifdef DEBUG_HEAP
|
2012-09-22 01:11:44 -04:00
|
|
|
printf("Adding stack frame at 0x%lx\n", (unsigned long)pc->HeapStackTop);
|
2009-02-23 21:14:07 -05:00
|
|
|
#endif
|
2012-09-22 01:11:44 -04:00
|
|
|
*(void **)pc->HeapStackTop = pc->StackFrame;
|
|
|
|
pc->StackFrame = pc->HeapStackTop;
|
2015-06-09 03:45:00 -04:00
|
|
|
pc->HeapStackTop = (void*)((char*)pc->HeapStackTop + MEM_ALIGN(sizeof(ALIGN_TYPE)));
|
2009-02-23 21:14:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* pop the current stack frame, freeing all memory in the frame. can return NULL */
|
2012-09-22 01:11:44 -04:00
|
|
|
int HeapPopStackFrame(Picoc *pc)
|
2009-02-23 21:14:07 -05:00
|
|
|
{
|
2015-06-07 00:40:08 -04:00
|
|
|
if (*(void **)pc->StackFrame != NULL) {
|
2012-09-22 01:11:44 -04:00
|
|
|
pc->HeapStackTop = pc->StackFrame;
|
2015-06-09 03:45:00 -04:00
|
|
|
pc->StackFrame = *(void**)pc->StackFrame;
|
2009-02-23 21:14:07 -05:00
|
|
|
#ifdef DEBUG_HEAP
|
2012-09-22 01:11:44 -04:00
|
|
|
printf("Popping stack frame back to 0x%lx\n", (unsigned long)pc->HeapStackTop);
|
2009-02-23 21:14:07 -05:00
|
|
|
#endif
|
|
|
|
return TRUE;
|
2015-06-07 00:40:08 -04:00
|
|
|
} else
|
2009-02-23 21:14:07 -05:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* allocate some dynamically allocated memory. memory is cleared. can return NULL if out of memory */
|
2012-09-22 01:11:44 -04:00
|
|
|
void *HeapAllocMem(Picoc *pc, int Size)
|
2009-02-23 21:14:07 -05:00
|
|
|
{
|
2009-03-10 22:19:18 -04:00
|
|
|
return calloc(Size, 1);
|
2009-02-23 21:14:07 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* free some dynamically allocated memory */
|
2012-09-22 01:11:44 -04:00
|
|
|
void HeapFreeMem(Picoc *pc, void *Mem)
|
2009-02-23 21:14:07 -05:00
|
|
|
{
|
2010-06-13 07:31:19 -04:00
|
|
|
free(Mem);
|
2009-01-23 06:34:12 -05:00
|
|
|
}
|
2009-11-06 13:08:11 -05:00
|
|
|
|