diff --git a/mem-arena.tal b/mem-arena.tal new file mode 100644 index 0000000..104de7c --- /dev/null +++ b/mem-arena.tal @@ -0,0 +1,78 @@ +( alloc.tal ) +( ) +( simple arena allocator ) +( ) +( the idea here is to pre-allocate a large arena of memory ) +( and then keep a pointer to the first unallocated byte. ) +( memory is released in reverse order of when it was allocated. ) +( ) +( in this example we're preallocating 16,384 bytes (#4000) ) +( located at mem-arena. we're using mem-cursor to point to ) +( the next unallocated byte. ) +( ) +( if mem-cursor ever contains the address of mem-cursor it ) +( means we've reached the limit of what we can allocate. ) +( we raise divide-by-zero errors if we cannot allocate ) +( or release memory as requested. ) +( ) +( memory can be freed by size (number of bytes) or cleared ) +( all at once. ) + +( macro to allocate one byte of memory ) +%mem-alloc-byte { #0001 ;mem-alloc JMP2r } ( -> addr* ) + +( macro to allocate two bytes of memory ) +%mem-alloc-short { #0002 ;mem-alloc JMP2r } ( -> addr* ) + +( macro to allocate an 8-bit count of memory (n) ) +%mem-alloc8 { #00 SWP ;mem-alloc JMP2r } ( n^ -> addr* ) + +( macro to allocate a 16-bit count of memory (n) ) +%mem-alloc16 { ;mem-alloc JMP2r } ( n* -> addr* ) + +|10 @Console [ &vector $2 &read $1 &pad $5 &write $1 ] + +|0100 + ;mem-init JSR2 + ;on-input .Console/vector DEO2 + ;mem-cursor LDA2 ;start STA2 + BRK + +@start $2 + +@on-input + .Console/read DEI DUP ,&continue JCN + ( ;on-complete JSR2 ) POP BRK + &continue ( mem-alloc-byte STA ) BRK + +@on-complete + ;mem-cursor LDA2 STH2 + ;start LDA2 + &loop + DUP2 STH2kr LTH2 ,&continue JCN + ;mem-init JSR2 POP2 POP2r JMP2r + &continue + LDA2k .Console/write DEO + INC2 ,&loop JMP + +( allocate n bytes of memory ) +@mem-alloc ( n* -> addr* ) + ;mem-cursor LDA2 ADD2 DUP2 ( new-addr new-addr ) + ;mem-cursor LTH2 ,&ok JCN DIV2 #0000 ( fail if we reach mem-cursor's own address ) + &ok DUP2 ;mem-cursor STA2 JMP2r + +( initialize memory, release all allocated memory ) +@mem-init ( -> ) + ;mem-arena ;mem-cursor STA2 JMP2r + +( release n bytes of allocated memory ) +@mem-release ( n* -> ) + ;mem-cursor LDA2 SUB2 DUP2 ( new-addr new-addr ) + ;mem-arena LTH2 ,&fail JCN ;mem-cursor STA2 JMP2r + &fail DIV2 #0000 ( fail if we reach beyond mem-arena's own address ) + +( location of the memory to be allocated ) +@mem-arena $4000 + +( pointer to the next free byte, if any ) +@mem-cursor $2