First time free-and-collect works right.

This commit is contained in:
Martin Haye 2015-09-06 11:06:01 -07:00
parent 1f324ea547
commit 6d61a0073f
2 changed files with 88 additions and 43 deletions

View File

@ -19,7 +19,7 @@ MAX_SEGS = 96
DO_COMP_CHECKSUMS = 0 ; during compression debugging DO_COMP_CHECKSUMS = 0 ; during compression debugging
DEBUG_DECOMP = 0 DEBUG_DECOMP = 0
DEBUG = 0 DEBUG = 1
SANITY_CHECK = 0 ; also prints out request data SANITY_CHECK = 0 ; also prints out request data
; Zero page temporary variables ; Zero page temporary variables
@ -943,8 +943,15 @@ gcHash_chk: !zone
rts rts
.corrup jmp heapCorrupt .corrup jmp heapCorrupt
!if DEBUG = 0 {
debugOnly:
jsr inlineFatal : !text "DebugOnly",0
}
; Verify integrity of memory manager structures ; Verify integrity of memory manager structures
memCheck: !zone memCheck: !zone
!if DEBUG = 0 { jmp debugOnly }
!if DEBUG {
jsr heapCheck ; heap check (if there is one) jsr heapCheck ; heap check (if there is one)
ldx #0 ; check main bank ldx #0 ; check main bank
jsr .chk jsr .chk
@ -1017,6 +1024,7 @@ heapCheck: !zone
tay tay
iny ; not much we can do to validate lo byte, so skip it iny ; not much we can do to validate lo byte, so skip it
cpy tmp ; ensure offset is within type length cpy tmp ; ensure offset is within type length
beq + ; very end is ok
bcs heapCorrupt ; beyond end is not ok bcs heapCorrupt ; beyond end is not ok
+ lda (pTmp),y ; get hi byte of ptr + lda (pTmp),y ; get hi byte of ptr
beq .tscan ; null is ok beq .tscan ; null is ok
@ -1024,6 +1032,8 @@ heapCheck: !zone
bcc heapCorrupt bcc heapCorrupt
cmp heapEndPg ; or >= than end of heap cmp heapEndPg ; or >= than end of heap
bcc .tscan bcc .tscan
}
heapCorrupt: heapCorrupt:
ldx pTmp ldx pTmp
lda pTmp+1 lda pTmp+1
@ -1117,12 +1127,6 @@ gc2_sweep: !zone
jsr gcHash_chk ; is this block in hash? jsr gcHash_chk ; is this block in hash?
; note: next 20 lines or so *must* preserve the carry flag ; note: next 20 lines or so *must* preserve the carry flag
bcc + ; if not in hash, don't set any dest addr bcc + ; if not in hash, don't set any dest addr
+prWord pSrc
+prStr : !text "->",0
+prWord pDst
+crout
lda pDst lda pDst
sta gcHash_dstLo,y ; record new address sta gcHash_dstLo,y ; record new address
eor pSrc eor pSrc
@ -1143,6 +1147,12 @@ gc2_sweep: !zone
tax ; and in index for byte-copy count tax ; and in index for byte-copy count
lda tmp ; check for pSrc == pDst lda tmp ; check for pSrc == pDst
beq .advDst ; if equal, no need to copy beq .advDst ; if equal, no need to copy
+prWord pSrc
+prStr : !text "->",0
+prWord pDst
+crout
inx ; set up to copy type/len byte as well inx ; set up to copy type/len byte as well
.cplup lda (pSrc),y .cplup lda (pSrc),y
sta (pDst),y sta (pDst),y

View File

@ -808,7 +808,10 @@ end
// Get a keystroke and convert it to upper case // Get a keystroke and convert it to upper case
def getUpperKey() def getUpperKey()
byte key byte key
word oldSeed
oldSeed = *seed // for now, make the seed stay consistent, for randomized heap testing
key = rdkey() key = rdkey()
*seed = oldSeed
if key >= $60 if key >= $60
key = key - $20 key = key - $20
fin fin
@ -1500,11 +1503,12 @@ end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
def freeObj(ptr) def freeObj(ptr)
byte typeNum byte typeNum
printf2(" freeObj ptr=$%x", ptr)
if ptr == NULL; return; fin if ptr == NULL; return; fin
typeNum = ^ptr typeNum = ^ptr
typeCounts[typeNum] = typeCounts[typeNum] - 1 typeCounts[typeNum] = typeCounts[typeNum] - 1
when type printf3(" freeObj p=$%x t=$%x newCt=%d\n", ptr, typeNum, typeCounts[typeNum])
if typeNum >= $80
when typeNum
is TYPE_GLOBAL is TYPE_GLOBAL
fatal("can't free global obj") fatal("can't free global obj")
is TYPE_PLAYER is TYPE_PLAYER
@ -1516,7 +1520,10 @@ def freeObj(ptr)
freeObj(ptr=>nextObj) freeObj(ptr=>nextObj)
freeObj(ptr=>name) freeObj(ptr=>name)
break break
otherwise
fatal("unknown obj type encountered in heap")
wend wend
fin
end end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
@ -1551,6 +1558,7 @@ def findTestString(len)
while *p while *p
t = ^p t = ^p
if t == len if t == len
printf2(" re-use len %d str @ %x\n", len, p)
return p return p
elsif t < $80 elsif t < $80
p = p + t + 1 p = p + t + 1
@ -1607,7 +1615,13 @@ def checkHeapCounts()
// Then verify the counts // Then verify the counts
bad = 0 bad = 0
for t = 0 to 255 for t = 0 to 127
if (typeCounts[t] > 0) and (checkCounts[t] <> 1)
printf3("Count for type $%x should be 1, got %d\n", t, checkCounts[t])
bad = bad+1
fin
next
for t = 128 to 255
if typeCounts[t] <> checkCounts[t] if typeCounts[t] <> checkCounts[t]
printf3("Count for type $%x should be %d, got %d\n", t, typeCounts[t], checkCounts[t]) printf3("Count for type $%x should be %d, got %d\n", t, typeCounts[t], checkCounts[t])
bad = bad+1 bad = bad+1
@ -1662,56 +1676,77 @@ def addPlayer()
return p return p
end end
def countList(p)
word n
n = 0
while p
n = n+1
p = p=>nextObj
loop
return n
end
def unlinkPlayer(toRemove) def unlinkPlayer(toRemove)
word p word p
word prev word prev
word n, n2
// Count number of players before
n = countList(global=>players)
// Now unlink
prev = NULL prev = NULL
p = global=>players p = global=>players
if p == toRemove if p == toRemove
global=>players = p=>nextObj global=>players = p=>nextObj
p=>nextObj = NULL else
return
fin
while p while p
if p == toRemove if p == toRemove
prev=>nextObj = p=>nextObj prev=>nextObj = p=>nextObj
p=>nextObj = NULL break
return
fin fin
prev = p
p = p=>nextObj p = p=>nextObj
loop loop
fin
if !p
fatal("Obj to unlink not in list") fatal("Obj to unlink not in list")
fin
p=>nextObj = NULL
// Check count after
n2 = countList(global=>players)
if n-1 <> n2
printf2("Info: n before=%d after=%d\n", n, n2)
fatal("Unlink didn't work")
fin
end end
def collect() def collect()
word nFree word nFree
puts("*** NEED TO DO MEM CHECK SOON\n") mmgr(CHECK_MEM, 0)
// memMgr(MEM_CHECK, 0)
puts("Collecting garbage.\n") puts("Collecting garbage.\n")
nFree = mmgr(HEAP_COLLECT, 0) nFree = mmgr(HEAP_COLLECT, 0)
printf1(" heap avail=$%x\n", nFree) printf1(" heap avail=$%x\n", nFree)
getUpperKey() getUpperKey()
puts("Checking heap counts.\n") puts("Checking heap counts.\n")
checkHeapCounts() checkHeapCounts()
puts("*** NEED TO DO MEM CHECK SOON\n") mmgr(CHECK_MEM, 0)
// memMgr(MEM_CHECK, 0)
end end
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
// Test out the heap // Test out the heap
def testHeap() def testHeap()
word p word p
*seed = 0
collect() collect()
addPlayer() addPlayer()
collect() collect()
addPlayer() addPlayer()
collect() collect()
p = global=>players p = global=>players
while p
printf1("A player: $%x\n", p)
p = p=>nextObj
loop
p = global=>players
p = p=>nextObj p = p=>nextObj
printf1("Unlinking player $%x\n", p) printf1("Unlinking player $%x\n", p)
unlinkPlayer(p) unlinkPlayer(p)