Change heap layout for vector delete

This commit is contained in:
drmortalwombat 2023-07-02 13:36:02 +02:00
parent 7858c2135b
commit 291ff890e6
3 changed files with 146 additions and 157 deletions

View File

@ -4118,26 +4118,21 @@ void HeapStart, HeapEnd;
bool HeapInit; bool HeapInit;
struct Heap { struct Heap {
Heap * next; Heap * next, * end;
unsigned size;
} HeapNode; } HeapNode;
#pragma section(heap, 0x0000, HeapStart, HeapEnd) #pragma section(heap, 0x0000, HeapStart, HeapEnd)
__asm malloc __asm malloc
{ {
// round size to be a multiple of four // make room for two additional bytes
// and make room for two additional bytes // to store pointer to end of used memory
// to store size of memory node
clc clc
lda accu + 0 lda accu + 0
sta tmp + 4 adc #2
adc #$05
and #$fc
sta tmp sta tmp
lda accu + 1 lda accu + 1
sta tmp + 5
adc #$00 adc #$00
sta tmp + 1 sta tmp + 1
@ -4166,13 +4161,10 @@ __asm malloc
lda #>HeapStart lda #>HeapStart
sta HeapNode + 1 sta HeapNode + 1
// set size to size of heap // set end of memory block to end of heap
sec
lda #<HeapEnd lda #<HeapEnd
sbc #<HeapStart
sta HeapStart + 2 sta HeapStart + 2
lda #>HeapEnd lda #>HeapEnd
sbc #>HeapStart
sta HeapStart + 3 sta HeapStart + 3
hasHeap: hasHeap:
@ -4181,57 +4173,79 @@ hasHeap:
// perfect fit // perfect fit
lda #<HeapNode lda #<HeapNode
sta accu + 2 ldx #>HeapNode
lda #>HeapNode
sta accu + 3
// Now loop over free nodes, until we find a match // Now loop over free nodes, until we find a match
loop: loop:
sta accu + 2
stx accu + 3
// next heap block // next heap block
// calculate potential end of block
clc
ldy #0 ldy #0
lda (accu + 2), y lda (accu + 2), y
sta accu sta accu + 0
adc tmp
sta tmp + 2
iny iny
lda (accu + 2), y lda (accu + 2), y
sta accu + 1 sta accu + 1
// exit if out of blocks // exit if out of blocks
beq done
beq done adc tmp + 1
// calculate remaining size of heap block
ldy #2
sec
lda (accu), y
sbc tmp
sta tmp + 2
iny
lda (accu), y
sbc tmp + 1
sta tmp + 3 sta tmp + 3
// will fit
// Check if in range of current free block
ldy #2
lda (accu), y
cmp tmp + 2
iny
lda (accu), y
sbc tmp + 3
bcs avail bcs avail
// prev // move current block pointer to prev pointer
lda accu lda accu
sta accu + 2 ldx accu + 1
lda accu + 1
sta accu + 3
jmp loop jmp loop
done: done:
// no more heap blocks // no more heap blocks
rts rts
avail: avail:
// is it a perfect fit? // calculate new end of block
clc
lda tmp + 2 lda tmp + 2
ora tmp + 3 adc #3
and #$fc
sta tmp + 4
lda tmp + 3
adc #0
sta tmp + 5
// compare with end of free block
ldy #2
lda tmp + 4
cmp (accu), y
bne nofit
iny
lda tmp + 5
cmp (accu), y
bne nofit bne nofit
// so adjust previous pointer to point to // perfect fit, so have previous block point to
// next heap block // next free block
ldy #0 ldy #0
lda (accu), y lda (accu), y
sta (accu + 2), y sta (accu + 2), y
@ -4241,42 +4255,42 @@ avail:
jmp found jmp found
nofit: nofit:
// adjust size of remaining heapblock // set next link in new link block
ldy #2
ldy #0
lda (accu), y
sta (tmp + 4), y
lda tmp + 4
sta (accu + 2), y
iny
lda (accu), y
sta (tmp + 4), y
lda tmp + 5
sta (accu + 2), y
// set new end of remaining block
iny
lda (accu), y
sta (tmp + 4), y
iny
lda (accu), y
sta (tmp + 4), y
found:
// remember end of allocated block
ldy #0
lda tmp + 2 lda tmp + 2
sta (accu), y sta (accu), y
iny iny
lda tmp + 3 lda tmp + 3
sta (accu), y sta (accu), y
// advance address to start of next heap block
clc
lda accu
adc tmp + 2
sta accu
lda accu + 1
adc tmp + 3
sta accu + 1
found:
// remember size of heap block for free without size
ldy #0
lda tmp + 4
sta (accu), y
iny
lda tmp + 5
sta (accu), y
// advanve by two bytes to skip size // advanve by two bytes to skip size
clc
lda accu lda accu
adc #2 ora #2
sta accu sta accu
bcc page
inc accu + 1
page:
rts rts
} }
@ -4292,91 +4306,68 @@ __asm inp_malloc
__asm free __asm free
{ {
// check nullptr free
// two bytes back to fix remembered end of block
lda accu lda accu
and #$fc
sta accu
// check nullptr free
ora accu + 1 ora accu + 1
bne notnull bne notnull
rts rts
notnull: notnull:
// two bytes back to fix size
sec
lda accu
sbc #2
sta accu
bcs page
dec accu + 1
page:
// cache size and end of block // cache end of block, rounding to next four byte
// address
clc clc
ldy #0 ldy #0
lda (accu), y lda (accu), y
adc #5 adc #3
and #$fc and #$fc
sta tmp sta accu + 2
iny iny
lda (accu), y lda (accu), y
adc #0 adc #0
sta tmp + 1
clc
lda tmp + 0
adc accu
sta accu + 2
lda tmp + 1
adc accu + 1
sta accu + 3 sta accu + 3
// pointer to heap block, starting with // pointer to heap block, starting with
// dummy block // dummy block
lda #<HeapNode lda #<HeapNode
sta tmp + 2 ldx #>HeapNode
lda #>HeapNode
sta tmp + 3
loop: loop:
sta tmp + 2
stx tmp + 3
// check if end of heap // check if end of heap
ldy #1 ldy #1
lda (tmp + 2), y lda (tmp + 2), y
beq noend beq noend
// Check if behind this block
cmp accu + 1
bcc before
bne after
dey
lda (tmp + 2), y
cmp accu + 0
bcs after
before:
ldy # 1
lda (tmp + 2), y
tax tax
dey dey
lda (tmp + 2), y lda (tmp + 2), y
sta tmp + 2
stx tmp + 3
jmp loop
after:
// Merge with next block // Check if next block is behind the block to free
ldy #1 cpx accu + 3
lda accu + 3 bcc loop
cmp (tmp + 2), y
bne noend bne noend
dey
lda accu + 2 cmp accu + 2
cmp (tmp + 2), y bcc loop
bne noend bne noend
// The end of the block to free matches the
// start of the next free block
// Pointer to next next block // Pointer to next next block
ldy #0 ldy #0
lda (accu + 2), y lda (accu + 2), y
sta (accu), y sta (accu), y
@ -4384,18 +4375,16 @@ after:
lda (accu + 2), y lda (accu + 2), y
sta (accu), y sta (accu), y
// Add size of next block to this // Append free space to new block
iny
clc
lda tmp
adc (accu + 2), y
sta tmp
iny
lda tmp + 1
adc (accu + 2), y
sta tmp + 1
iny
lda (accu + 2), y
sta (accu), y
iny
lda (accu + 2), y
sta (accu), y
jmp start jmp start
noend: noend:
// Link to next block // Link to next block
ldy #0 ldy #0
@ -4405,24 +4394,27 @@ noend:
lda (tmp + 2), y lda (tmp + 2), y
sta (accu), y sta (accu), y
start: // End of new free block
// Calculate end of free block
ldy #2
clc
lda tmp + 2
adc (tmp + 2), y
iny iny
tax lda accu + 2
lda tmp + 3 sta (accu), y
adc (tmp + 2), y iny
lda accu + 3
sta (accu), y
// Matches start of new block start:
// Check if new block matches end of previous block
ldy #2
lda (tmp + 2), y
cmp accu
bne nostart
iny
lda (tmp + 2), y
cmp accu + 1 cmp accu + 1
bne nostart bne nostart
cpx accu
bne nostart
// If so, increase the size and link // If so, increase the size of previous block and link
// to free block after // to free block after
ldy #0 ldy #0
@ -4433,13 +4425,10 @@ start:
sta (tmp + 2), y sta (tmp + 2), y
iny iny
clc lda (accu), y
lda (tmp + 2), y
adc tmp
sta (tmp + 2), y sta (tmp + 2), y
iny iny
lda (tmp + 2), y lda (accu), y
adc tmp + 1
sta (tmp + 2), y sta (tmp + 2), y
rts rts
@ -4453,14 +4442,7 @@ nostart:
iny iny
lda accu + 1 lda accu + 1
sta (tmp + 2), y sta (tmp + 2), y
iny
// Set size of free block
lda tmp
sta (accu), y
iny
lda tmp + 1
sta (accu), y
rts rts
} }

View File

@ -1609,9 +1609,13 @@ void ByteCodeBasicBlock::CallMalloc(InterCodeProcedure* proc, const InterInstruc
} }
ByteCodeInstruction cins(BC_MALLOC); ByteCodeInstruction cins(BC_MALLOC);
mIns.Push(cins); mIns.Push(cins);
ByteCodeInstruction bins(BC_STORE_REG_16);
bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp]; if (ins->mDst.mTemp >= 0)
mIns.Push(bins); {
ByteCodeInstruction bins(BC_STORE_REG_16);
bins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
mIns.Push(bins);
}
} }
void ByteCodeBasicBlock::CallFree(InterCodeProcedure* proc, const InterInstruction* ins) void ByteCodeBasicBlock::CallFree(InterCodeProcedure* proc, const InterInstruction* ins)

View File

@ -7366,10 +7366,13 @@ void NativeCodeBasicBlock::CallMalloc(InterCodeProcedure* proc, const InterInstr
NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("malloc"))); NativeCodeGenerator::Runtime& frt(nproc->mGenerator->ResolveRuntime(Ident::Unique("malloc")));
mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER)); mIns.Push(NativeCodeInstruction(ins, ASMIT_JSR, ASMIM_ABSOLUTE, frt.mOffset, frt.mLinkerObject, NCIF_RUNTIME | NCIF_LOWER | NCIF_UPPER));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0)); if (ins->mDst.mTemp >= 0)
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0)); {
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1)); mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1)); mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, BC_REG_ACCU + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp] + 1));
}
} }
void NativeCodeBasicBlock::CallFree(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc) void NativeCodeBasicBlock::CallFree(InterCodeProcedure* proc, const InterInstruction* ins, NativeCodeProcedure* nproc)