From 0a6f8ac72b99e5f0a008f7010d84d9d833cb6524 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Thu, 17 Jul 2025 18:46:57 -0700 Subject: [PATCH 01/17] Replaces scaling factor 2 for array length offsets by DLWORDSPER_CELL as that is what it represents. --- src/gcfinal.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/gcfinal.c b/src/gcfinal.c index 0d10de9..568b99e 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -69,7 +69,7 @@ #endif /* NEVER */ #define min(a, b) (((a) > (b)) ? (b) : (a)) -#define Trailer(ldatum, datum68) ((ldatum) + 2 * ((datum68)->arlen - ARRAYBLOCKTRAILERCELLS)) +#define Trailer(ldatum, datum68) ((ldatum) + DLWORDSPER_CELL * ((datum68)->arlen - ARRAYBLOCKTRAILERCELLS)) #define BucketIndex(n) min(integerlength(n), MAXBUCKETINDEX) #define FreeBlockChainN(n) ((POINTERMASK & *FreeBlockBuckets_word) + 2 * BucketIndex(n)) @@ -367,7 +367,7 @@ LispPTR arrayblockmerger(LispPTR base, LispPTR nbase) { * (3) creating a max size block leaves a non-viable leftover block * move the boundary to make a big block and a minimum size leftover block */ - if (base + (2 * arlens) != nbase) { + if (base + (DLWORDSPER_CELL * arlens) != nbase) { error("Attempt to merge non-adjacent blocks in array space\n"); } if (narlens > secondbite) { /* (2) or (3) */ @@ -381,7 +381,7 @@ LispPTR arrayblockmerger(LispPTR base, LispPTR nbase) { arlens += shaveback; secondbite += shaveback; } - linkblock(makefreearrayblock(nbase + 2 * secondbite, narlens)); + linkblock(makefreearrayblock(nbase + DLWORDSPER_CELL * secondbite, narlens)); narlens = 0; } return (linkblock(makefreearrayblock(base, arlens + narlens))); @@ -405,7 +405,7 @@ LispPTR mergebackward(LispPTR base) { if ((*ArrayMerging_word == NIL) || ((base == *ArraySpace_word) || ((base == *ArraySpace2_word) || (ptrailer->inuse == T)))) return (linkblock(base)); - pbase = base - 2 * ptrailer->arlen; + pbase = base - DLWORDSPER_CELL * ptrailer->arlen; checkarrayblock(pbase, T, NIL); deleteblock(pbase); return (arrayblockmerger(pbase, base)); @@ -427,7 +427,7 @@ LispPTR mergeforward(LispPTR base) { if (checkarrayblock(base, T, T)) return NIL; bbase = (struct arrayblock *)NativeAligned4FromLAddr(base); - nbase = base + 2 * (bbase->arlen); + nbase = base + DLWORDSPER_CELL * (bbase->arlen); if (nbase == *ArrayFrLst_word || nbase == *ArrayFrLst2_word) return NIL; bnbase = (struct arrayblock *)NativeAligned4FromLAddr(nbase); @@ -487,7 +487,7 @@ LispPTR reclaimarrayblock(LispPTR ptr) { switch (base->gctype) { case PTRBLOCK_GCT: { - btrailer = (ptr - 2) + 2 * (base->arlen - ARRAYBLOCKTRAILERCELLS); + btrailer = (ptr - 2) + DLWORDSPER_CELL * (base->arlen - ARRAYBLOCKTRAILERCELLS); tmpptr = ptr; do { tmpp = (LispPTR *)NativeAligned4FromLAddr(tmpptr); @@ -545,8 +545,8 @@ void printarrayblock(LispPTR base) { btrailer = (struct arrayblock *)NativeAligned4FromLAddr(Trailer(base, bbase)); ptrailer = (struct arrayblock *)NativeAligned4FromLAddr(base - ARRAYBLOCKTRAILERWORDS); - nbase = base + 2 * bbase->arlen; - pbase = base - 2 * ptrailer->arlen; + nbase = base + DLWORDSPER_CELL * bbase->arlen; + pbase = base - DLWORDSPER_CELL * ptrailer->arlen; printf("This array block: 0x%x. Previous: 0x%x. Next: 0x%x.\n", base, pbase, nbase); printf(" Length: %d cells.\n\n", bbase->arlen); From 1ffd1ba7cb463abcd148abd608bebd2ab086ef76 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Thu, 17 Jul 2025 18:52:15 -0700 Subject: [PATCH 02/17] Replaces integerlength(n) implementation with call to fls(n) and makes it static --- inc/gcfinaldefs.h | 1 - src/gcfinal.c | 19 +++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/inc/gcfinaldefs.h b/inc/gcfinaldefs.h index 88945e3..fa6d0a0 100644 --- a/inc/gcfinaldefs.h +++ b/inc/gcfinaldefs.h @@ -2,7 +2,6 @@ #define GCFINALDEFS_H 1 #include "lispemul.h" /* for LispPTR, DLword */ void printarrayblock(LispPTR base); -int integerlength(unsigned int n); LispPTR findptrsbuffer(LispPTR ptr); LispPTR releasingvmempage(LispPTR ptr); LispPTR checkarrayblock(LispPTR base, LispPTR free, LispPTR onfreelist); diff --git a/src/gcfinal.c b/src/gcfinal.c index 568b99e..1d44336 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -43,6 +43,7 @@ /*************************************************************************/ #include // for printf +#include // for fls #include "address.h" // for HILOC #include "adr68k.h" // for NativeAligned4FromLAddr, LAddrFromNative #include "array.h" // for arrayblock, ARRAYBLOCKTRAILERCELLS, MAXBUCK... @@ -123,24 +124,10 @@ struct buf { #endif /* BIGVM */ #endif /* BYTESWAP */ -/************* The following procedure is common !! **************************/ - -int integerlength(unsigned int n) { - int cnt; - if (n <= 2) - return (n); - else { - cnt = 1; - do { - cnt++; - n = (n >> 1); - } while (n != 1); - return (cnt); - } +static int integerlength(unsigned int n) { + return (fls(n)); } -/************* The above procedure is common !! **************************/ - /************************************************************************/ /* */ /* f i n d p t r s b u f f e r */ From 357336b5f1fdbb3a0b570ae18ec17adf16be4a53 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Fri, 18 Jul 2025 09:12:43 -0700 Subject: [PATCH 03/17] Rewrites (and makes static) findptrsbuffer to avoid multiple conversions between Lisp and native pointers --- inc/gcfinaldefs.h | 1 - src/gcfinal.c | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/inc/gcfinaldefs.h b/inc/gcfinaldefs.h index fa6d0a0..7918e1c 100644 --- a/inc/gcfinaldefs.h +++ b/inc/gcfinaldefs.h @@ -2,7 +2,6 @@ #define GCFINALDEFS_H 1 #include "lispemul.h" /* for LispPTR, DLword */ void printarrayblock(LispPTR base); -LispPTR findptrsbuffer(LispPTR ptr); LispPTR releasingvmempage(LispPTR ptr); LispPTR checkarrayblock(LispPTR base, LispPTR free, LispPTR onfreelist); LispPTR deleteblock(LispPTR base); diff --git a/src/gcfinal.c b/src/gcfinal.c index 1d44336..2d75968 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -138,14 +138,16 @@ static int integerlength(unsigned int n) { /* */ /************************************************************************/ -LispPTR findptrsbuffer(LispPTR ptr) { - struct buf *bptr; - bptr = (struct buf *)NativeAligned4FromLAddr(*System_Buffer_List_word); - while (LAddrFromNative(bptr) != NIL) { - if (ptr == bptr->vmempage) - return (LAddrFromNative(bptr)); - else - bptr = (struct buf *)NativeAligned4FromLAddr(bptr->sysnext); +static LispPTR findptrsbuffer(LispPTR ptr) { + LispPTR buf; + struct buf *buf_np; + buf = *System_Buffer_List_word; + while (buf != NIL) { + buf_np = (struct buf *)NativeAligned4FromLAddr(buf); + if (ptr == buf_np->vmempage) { + return (buf); + } + buf = buf_np->sysnext; } return (NIL); } From 1f18779eb8ffe75bf61cd97a9d7483a3fc4f5bf3 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Fri, 18 Jul 2025 10:09:41 -0700 Subject: [PATCH 04/17] Cleans up deleteblock implementation to increase clarity Procedure can be static void as there was only an unused constant result. Uses consistent naming (_np) for native pointer equivalents of Lisp addresses, and better matches Lisp implementation naming of variables. Adds comments with a little explanation of what the code is doing. --- inc/gcfinaldefs.h | 1 - src/gcfinal.c | 54 ++++++++++++++++++++++++++--------------------- 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/inc/gcfinaldefs.h b/inc/gcfinaldefs.h index 7918e1c..2072fee 100644 --- a/inc/gcfinaldefs.h +++ b/inc/gcfinaldefs.h @@ -4,7 +4,6 @@ void printarrayblock(LispPTR base); LispPTR releasingvmempage(LispPTR ptr); LispPTR checkarrayblock(LispPTR base, LispPTR free, LispPTR onfreelist); -LispPTR deleteblock(LispPTR base); LispPTR linkblock(LispPTR base); LispPTR makefreearrayblock(LispPTR block, DLword length); LispPTR arrayblockmerger(LispPTR base, LispPTR nbase); diff --git a/src/gcfinal.c b/src/gcfinal.c index 2d75968..efffd8d 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -51,7 +51,7 @@ #include "gccodedefs.h" // for reclaimcodeblock #include "gcdata.h" // for DELREF, REC_GCLOOKUP #include "gchtfinddefs.h" // for htfind, rec_htfind -#include "gcfinaldefs.h" // for arrayblockmerger, checkarrayblock, deleteblock +#include "gcfinaldefs.h" // for arrayblockmerger, checkarrayblock #include "lispemul.h" // for LispPTR, NIL, T, POINTERMASK, DLword, ATOM_T #include "llstkdefs.h" // for decusecount68k #include "lspglob.h" // for FreeBlockBuckets_word, ArrayMerging_word @@ -243,32 +243,38 @@ LispPTR checkarrayblock(LispPTR base, LispPTR free, LispPTR onfreelist) { /* */ /* */ /************************************************************************/ - -LispPTR deleteblock(LispPTR base) { - struct arrayblock *bbase, *fbbase, *bbbase; - LispPTR fwd, bkwd, fbl, freeblocklsp; - LispPTR *freeblock; - bbase = (struct arrayblock *)NativeAligned4FromLAddr(base); - if ((bbase->arlen >= MINARRAYBLOCKSIZE) && (bbase->fwd != NIL)) { - fwd = bbase->fwd; - fbbase = (struct arrayblock *)NativeAligned4FromLAddr(fwd); - bkwd = bbase->bkwd; - bbbase = (struct arrayblock *)NativeAligned4FromLAddr(bkwd); - fbl = FreeBlockChainN(bbase->arlen); - freeblock = (LispPTR *)NativeAligned4FromLAddr(fbl); - freeblocklsp = POINTERMASK & *freeblock; - if (base == fwd) { - if (base == freeblocklsp) - *freeblock = NIL; +/* + * Removes "base", a block from the free list and + * adjusts the forward and backward pointers of the blocks behind and + * ahead of the deleted block. + * The forward and backward pointers of this deleted block are left + * dangling - as in the Lisp implementation. Also does not affect the + * inuse bit in header and trailer. + */ +static void deleteblock(LispPTR base) { + struct arrayblock *base_np, *f_np, *b_np; + LispPTR f, b, fbl, freeblock; + LispPTR *fbl_np; + base_np = (struct arrayblock *)NativeAligned4FromLAddr(base); + if ((base_np->arlen >= MINARRAYBLOCKSIZE) && (base_np->fwd != NIL)) { + f = base_np->fwd; + f_np = (struct arrayblock *)NativeAligned4FromLAddr(f); + b = base_np->bkwd; + b_np = (struct arrayblock *)NativeAligned4FromLAddr(b); + fbl = FreeBlockChainN(base_np->arlen); + fbl_np = (LispPTR *)NativeAligned4FromLAddr(fbl); + freeblock = POINTERMASK & *fbl_np; + if (base == f) { + if (base == freeblock) + *fbl_np = NIL; else error("GC error:deleting last list # FREEBLOCKLIST\n"); - return (NIL); - } else if (base == freeblocklsp) - *freeblock = fwd; - fbbase->bkwd = bkwd; - bbbase->fwd = fwd; + return; + } else if (base == freeblock) + *fbl_np = f; + f_np->bkwd = b; + b_np->fwd = f; } - return (NIL); } /************************************************************************/ From 31fcfb36cafe9c9de8cd6bd69ebdfb29bf4e2429 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Fri, 18 Jul 2025 10:19:36 -0700 Subject: [PATCH 05/17] Cleans up linkblock implementation to increase clarity Procedure can be static as it is only used within this file Uses consistent naming (_np) for native pointer equivalents of Lisp addresses, and better matches Lisp implementation naming of variables. Improve readability by reducing if/else nesting with early outs in exceptional cases. Still equivalent to the original Lisp version. Adds comments with a little explanation of what the code is doing. --- inc/gcfinaldefs.h | 1 - src/gcfinal.c | 71 ++++++++++++++++++++++++++++++----------------- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/inc/gcfinaldefs.h b/inc/gcfinaldefs.h index 2072fee..257a095 100644 --- a/inc/gcfinaldefs.h +++ b/inc/gcfinaldefs.h @@ -4,7 +4,6 @@ void printarrayblock(LispPTR base); LispPTR releasingvmempage(LispPTR ptr); LispPTR checkarrayblock(LispPTR base, LispPTR free, LispPTR onfreelist); -LispPTR linkblock(LispPTR base); LispPTR makefreearrayblock(LispPTR block, DLword length); LispPTR arrayblockmerger(LispPTR base, LispPTR nbase); LispPTR mergebackward(LispPTR base); diff --git a/src/gcfinal.c b/src/gcfinal.c index efffd8d..e30d35d 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -284,34 +284,53 @@ static void deleteblock(LispPTR base) { /* */ /* */ /************************************************************************/ +/* + * Links a block onto the free list for a particular size range. + * The free list is maintained as a doubly linked circular list accessed + * from the block pointed to by the free list bucket for the size. + * If there are no blocks in the free list bucket then the forward and + * backward pointers of the newly added block point to the block itself. + */ +static LispPTR linkblock(LispPTR base) { + struct arrayblock *base_np, *freeblock_np, *tail_np; + LispPTR fbl, freeblock; + LispPTR *fbl_np; -LispPTR linkblock(LispPTR base) { - struct arrayblock *bbase, *fbbase, *tmpbase; - LispPTR fbl, freeblocklsp; - LispPTR *freeblock; - if (*FreeBlockBuckets_word != NIL) { - bbase = (struct arrayblock *)NativeAligned4FromLAddr(base); - if (bbase->arlen < MINARRAYBLOCKSIZE) - checkarrayblock(base, T, NIL); - else { - fbl = FreeBlockChainN(bbase->arlen); - freeblock = (LispPTR *)NativeAligned4FromLAddr(POINTERMASK & fbl); - freeblocklsp = POINTERMASK & (*freeblock); - if (freeblocklsp == NIL) { - bbase->fwd = base; - bbase->bkwd = base; - } else { - fbbase = (struct arrayblock *)NativeAligned4FromLAddr(freeblocklsp); - bbase->fwd = freeblocklsp; - bbase->bkwd = fbbase->bkwd; - tmpbase = (struct arrayblock *)NativeAligned4FromLAddr(fbbase->bkwd); - tmpbase->fwd = base; - fbbase->bkwd = base; - } - *freeblock = base; - checkarrayblock(base, T, T); - } + if (*FreeBlockBuckets_word == NIL) + return (base); + + base_np = (struct arrayblock *)NativeAligned4FromLAddr(base); + if (base_np->arlen < MINARRAYBLOCKSIZE) { + checkarrayblock(base, T, NIL); + return (base); } + + /* lisp pointer to bucket for size */ + fbl = FreeBlockChainN(base_np->arlen); + /* native pointer to bucket */ + fbl_np = (LispPTR *)NativeAligned4FromLAddr(POINTERMASK & fbl); + /* lisp pointer to first free block on chain */ + freeblock = POINTERMASK & (*fbl_np); + if (freeblock == NIL) { /* no blocks already in chain */ + base_np->fwd = base; + base_np->bkwd = base; + } else { + /* set up new block to be first free block on the chain */ + freeblock_np = (struct arrayblock *)NativeAligned4FromLAddr(freeblock); + /* link new block forward to free block */ + base_np->fwd = freeblock; + /* new block's backward link becomes free block's backward link */ + base_np->bkwd = freeblock_np->bkwd; + /* get the tail location (backward pointer of freelist head) */ + tail_np = (struct arrayblock *)NativeAligned4FromLAddr(freeblock_np->bkwd); + /* set its forward pointer to new block */ + tail_np->fwd = base; + /* and the update the free block's backward link to new block */ + freeblock_np->bkwd = base; + } + /* new block becomes the head of the free list */ + *fbl_np = base; + checkarrayblock(base, T, T); /* free, and on free list */ return (base); } From 93b3a709c97dc03c96159b483d10a75e103dd8f5 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sat, 19 Jul 2025 12:11:11 -0700 Subject: [PATCH 06/17] Cleans up makefreearrayblock implementation Uses consistent naming (_np) for native pointer equivalents of Lisp addresses Adds comments regarding use of WORDPTR macro to hide BYTESWAP setting --- src/gcfinal.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/gcfinal.c b/src/gcfinal.c index e30d35d..d459b7f 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -344,17 +344,26 @@ static LispPTR linkblock(LispPTR base) { LispPTR makefreearrayblock(LispPTR block, DLword length) { LispPTR trailer; - struct arrayblock *bbase; - struct abdum *dbase; - bbase = (struct arrayblock *)NativeAligned4FromLAddr(block); - dbase = (struct abdum *)WORDPTR(bbase); - dbase->abflags = FREEARRAYFLAGWORD; - bbase->arlen = length; - trailer = Trailer(block, bbase); - bbase = (struct arrayblock *)NativeAligned4FromLAddr(trailer); - dbase = (struct abdum *)WORDPTR(bbase); - dbase->abflags = FREEARRAYFLAGWORD; - bbase->arlen = length; + struct arrayblock *block_np, *trailer_np; + struct abdum *flags_np; + block_np = (struct arrayblock *)NativeAligned4FromLAddr(block); + /* this is an appropriate place to test whether the block that + is about to be freed contains words that look like valid + array header/trailer pairs as data. This may result in + false positives, but could help if there's a real smash happening. + */ + /* struct abdum's abflags is a DLword and does not account for + the BYTESWAP setup (as arrayblock does), so use WORDPTR to + pick the correct word of the cell + */ + flags_np = (struct abdum *)WORDPTR(block_np); + flags_np->abflags = FREEARRAYFLAGWORD; + block_np->arlen = length; + trailer = Trailer(block, block_np); + trailer_np = (struct arrayblock *)NativeAligned4FromLAddr(trailer); + flags_np = (struct abdum *)WORDPTR(trailer_np); + flags_np->abflags = FREEARRAYFLAGWORD; + trailer_np->arlen = length; return (block); } From 2c46a9473a1a303324e09817d3e56528797aa27a Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sat, 19 Jul 2025 12:26:29 -0700 Subject: [PATCH 07/17] Cleans up and makes static arrayblockmerger implementation Uses consistent naming (_np) for native pointer equivalents of Lisp addresses --- inc/gcfinaldefs.h | 1 - src/gcfinal.c | 14 +++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/inc/gcfinaldefs.h b/inc/gcfinaldefs.h index 257a095..198b9bf 100644 --- a/inc/gcfinaldefs.h +++ b/inc/gcfinaldefs.h @@ -5,7 +5,6 @@ void printarrayblock(LispPTR base); LispPTR releasingvmempage(LispPTR ptr); LispPTR checkarrayblock(LispPTR base, LispPTR free, LispPTR onfreelist); LispPTR makefreearrayblock(LispPTR block, DLword length); -LispPTR arrayblockmerger(LispPTR base, LispPTR nbase); LispPTR mergebackward(LispPTR base); LispPTR mergeforward(LispPTR base); LispPTR reclaimarrayblock(LispPTR ptr); diff --git a/src/gcfinal.c b/src/gcfinal.c index d459b7f..763a777 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -51,7 +51,7 @@ #include "gccodedefs.h" // for reclaimcodeblock #include "gcdata.h" // for DELREF, REC_GCLOOKUP #include "gchtfinddefs.h" // for htfind, rec_htfind -#include "gcfinaldefs.h" // for arrayblockmerger, checkarrayblock +#include "gcfinaldefs.h" // for checkarrayblock #include "lispemul.h" // for LispPTR, NIL, T, POINTERMASK, DLword, ATOM_T #include "llstkdefs.h" // for decusecount68k #include "lspglob.h" // for FreeBlockBuckets_word, ArrayMerging_word @@ -374,13 +374,13 @@ LispPTR makefreearrayblock(LispPTR block, DLword length) { /* */ /* */ /************************************************************************/ -LispPTR arrayblockmerger(LispPTR base, LispPTR nbase) { +static LispPTR arrayblockmerger(LispPTR base, LispPTR nbase) { DLword arlens, narlens, secondbite, minblocksize, shaveback; - struct arrayblock *bbase, *bnbase; - bbase = (struct arrayblock *)NativeAligned4FromLAddr(base); - bnbase = (struct arrayblock *)NativeAligned4FromLAddr(nbase); - arlens = bbase->arlen; - narlens = bnbase->arlen; + struct arrayblock *base_np, *nbase_np; + base_np = (struct arrayblock *)NativeAligned4FromLAddr(base); + nbase_np = (struct arrayblock *)NativeAligned4FromLAddr(nbase); + arlens = base_np->arlen; + narlens = nbase_np->arlen; secondbite = MAXARRAYBLOCKSIZE - arlens; /* There are three cases for merging the blocks * (1) the total size of the two blocks is less than max: From f375519dbc9ced7d4e702d9e1872d372b34ee434 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sat, 19 Jul 2025 12:35:02 -0700 Subject: [PATCH 08/17] Cleans up mergebackward implementation Uses consistent naming (_np) for native pointer equivalents of Lisp addresses Adds comments with a little explanation of what the code is doing --- src/gcfinal.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/gcfinal.c b/src/gcfinal.c index 763a777..2f52fdd 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -418,18 +418,34 @@ static LispPTR arrayblockmerger(LispPTR base, LispPTR nbase) { /* */ /************************************************************************/ +/* + * merges this block into the block behind it, unless there are + * disqualifying conditions: + * merging is turned off or + * this is the first block in array space or + * this is the first block in the 2nd array space or + * the block behind it is in use + * in which case it is linked onto the freelist (fwd and backward pointers) + * and added to the free block chain by size. + * If it can be merged, + */ LispPTR mergebackward(LispPTR base) { LispPTR pbase; - struct arrayblock *ptrailer; + struct arrayblock *ptrailer_np; if (base == NIL) return (NIL); - ptrailer = (struct arrayblock *)NativeAligned4FromLAddr(base - ARRAYBLOCKTRAILERWORDS); + /* back up to get the trailer of the previous block */ + ptrailer_np = (struct arrayblock *)NativeAligned4FromLAddr(base - ARRAYBLOCKTRAILERWORDS); + /* check that there are no disqualifying conditions for merging with previous block */ if ((*ArrayMerging_word == NIL) || - ((base == *ArraySpace_word) || ((base == *ArraySpace2_word) || (ptrailer->inuse == T)))) + ((base == *ArraySpace_word) || ((base == *ArraySpace2_word) || (ptrailer_np->inuse == T)))) return (linkblock(base)); - pbase = base - DLWORDSPER_CELL * ptrailer->arlen; + /* back up to the header of the previous block */ + pbase = base - DLWORDSPER_CELL * ptrailer_np->arlen; + /* check that it is free, but skip free list checks */ checkarrayblock(pbase, T, NIL); + /* remove it from the free list */ deleteblock(pbase); return (arrayblockmerger(pbase, base)); } From 7c7da4cd0cdf6068806e7e8f55d506ab3b828773 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sat, 19 Jul 2025 13:19:27 -0700 Subject: [PATCH 09/17] Cleans up mergeforward implementation Uses consistent naming (_np) for native pointer equivalents of Lisp addresses --- src/gcfinal.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gcfinal.c b/src/gcfinal.c index 2f52fdd..c186507 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -460,17 +460,17 @@ LispPTR mergebackward(LispPTR base) { LispPTR mergeforward(LispPTR base) { LispPTR nbase, nbinuse; - struct arrayblock *bbase, *bnbase; + struct arrayblock *base_np, *nbase_np; if (*ArrayMerging_word == NIL) return NIL; if (base == NIL) return NIL; if (checkarrayblock(base, T, T)) return NIL; - bbase = (struct arrayblock *)NativeAligned4FromLAddr(base); - nbase = base + DLWORDSPER_CELL * (bbase->arlen); + base_np = (struct arrayblock *)NativeAligned4FromLAddr(base); + nbase = base + DLWORDSPER_CELL * (base_np->arlen); if (nbase == *ArrayFrLst_word || nbase == *ArrayFrLst2_word) return NIL; - bnbase = (struct arrayblock *)NativeAligned4FromLAddr(nbase); - nbinuse = bnbase->inuse; + nbase_np = (struct arrayblock *)NativeAligned4FromLAddr(nbase); + nbinuse = nbase_np->inuse; if (checkarrayblock(nbase, !nbinuse, NIL)) return NIL; if (nbinuse) return (NIL); deleteblock(nbase); From 812e296fe8595448c21752e0f56d82dc2f7c26c7 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sat, 19 Jul 2025 15:39:36 -0700 Subject: [PATCH 10/17] Cleans up reclaimarrayblock implementation Uses consistent naming (_np) for native pointer equivalents of Lisp addresses Adds comments regarding the parameter passed to reclaimarrayblock --- src/gcfinal.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/gcfinal.c b/src/gcfinal.c index c186507..4b011af 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -485,10 +485,13 @@ LispPTR mergeforward(LispPTR base) { /* Reclaim a block of storage in the array-space heap. */ /* */ /************************************************************************/ - +/* + * The pointer passed is to the data of the block, not the array block + * header. + */ LispPTR reclaimarrayblock(LispPTR ptr) { LispPTR tmpptr, btrailer; - struct arrayblock *base; + struct arrayblock *base_np; LispPTR *tmpp; int reclaim_p; @@ -497,7 +500,7 @@ LispPTR reclaimarrayblock(LispPTR ptr) { checkarrayblock(ptr - ARRAYBLOCKHEADERWORDS, NIL, NIL); #endif /* ARRAYCHECK */ - base = (struct arrayblock *)NativeAligned4FromLAddr(ptr - ARRAYBLOCKHEADERWORDS); + base_np = (struct arrayblock *)NativeAligned4FromLAddr(ptr - ARRAYBLOCKHEADERWORDS); #ifdef ARRAYCHECK if (HILOC(ptr) < FIRSTARRAYSEGMENT) { printarrayblock(ptr - ARRAYBLOCKHEADERWORDS); @@ -505,11 +508,11 @@ LispPTR reclaimarrayblock(LispPTR ptr) { "Bad array block reclaimed [not in array space].\nContinue with 'q' but save state ASAP. " "\n"); return (T); - } else if (ARRAYBLOCKPASSWORD != base->password) { + } else if (ARRAYBLOCKPASSWORD != base_np->password) { printarrayblock(ptr - ARRAYBLOCKHEADERWORDS); error("Bad array block reclaimed [password wrong].\nContinue with 'q' but save state ASAP. \n"); return (T); - } else if (base->inuse == NIL) { + } else if (base_np->inuse == NIL) { printarrayblock(ptr - ARRAYBLOCKHEADERWORDS); error( "Bad array block reclaimed [block not in use].\nContinue with 'q' but save state ASAP. \n"); @@ -518,15 +521,15 @@ LispPTR reclaimarrayblock(LispPTR ptr) { #else /* Normal case, just tell the guy something's wrong: */ if ((HILOC(ptr) < FIRSTARRAYSEGMENT) || - ((ARRAYBLOCKPASSWORD != base->password) || (base->inuse == NIL))) { + ((ARRAYBLOCKPASSWORD != base_np->password) || (base_np->inuse == NIL))) { error("Bad array block reclaimed--continue with 'q' but save state ASAP. \n"); return (T); } #endif /* ARRAYCHECK */ - switch (base->gctype) { + switch (base_np->gctype) { case PTRBLOCK_GCT: { - btrailer = (ptr - 2) + DLWORDSPER_CELL * (base->arlen - ARRAYBLOCKTRAILERCELLS); + btrailer = (ptr - 2) + DLWORDSPER_CELL * (base_np->arlen - ARRAYBLOCKTRAILERCELLS); tmpptr = ptr; do { tmpp = (LispPTR *)NativeAligned4FromLAddr(tmpptr); @@ -543,7 +546,7 @@ LispPTR reclaimarrayblock(LispPTR ptr) { /* default: No Action */ } if (reclaim_p == T) - mergeforward(mergebackward(makefreearrayblock(ptr - ARRAYBLOCKHEADERWORDS, base->arlen))); + mergeforward(mergebackward(makefreearrayblock(ptr - ARRAYBLOCKHEADERWORDS, base_np->arlen))); return (T); } From 3fad090a6c4f9b9372816a7a07d2119220a12eb3 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sat, 19 Jul 2025 17:34:52 -0700 Subject: [PATCH 11/17] Cleans up printarrayblock implementation Uses consistent naming (_np) for native pointer equivalents of Lisp addresses --- src/gcfinal.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/gcfinal.c b/src/gcfinal.c index 4b011af..67e288b 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -578,31 +578,35 @@ LispPTR reclaimstackp(LispPTR ptr) /* This is the entry function */ /************************************************************************/ void printarrayblock(LispPTR base) { - struct arrayblock *bbase, *btrailer, *ptrailer; + struct arrayblock *base_np, *trailer_np, *ptrailer_np; LispPTR *addr; - LispPTR pbase, nbase; - bbase = (struct arrayblock *)NativeAligned4FromLAddr(base); - btrailer = (struct arrayblock *)NativeAligned4FromLAddr(Trailer(base, bbase)); - ptrailer = (struct arrayblock *)NativeAligned4FromLAddr(base - ARRAYBLOCKTRAILERWORDS); + base_np = (struct arrayblock *)NativeAligned4FromLAddr(base); + trailer_np = (struct arrayblock *)NativeAligned4FromLAddr(Trailer(base, base_np)); + ptrailer_np = (struct arrayblock *)NativeAligned4FromLAddr(base - ARRAYBLOCKTRAILERWORDS); - nbase = base + DLWORDSPER_CELL * bbase->arlen; - pbase = base - DLWORDSPER_CELL * ptrailer->arlen; + nbase = base + DLWORDSPER_CELL * base_np->arlen; + pbase = base - DLWORDSPER_CELL * ptrailer_np->arlen; printf("This array block: 0x%x. Previous: 0x%x. Next: 0x%x.\n", base, pbase, nbase); - printf(" Length: %d cells.\n\n", bbase->arlen); + printf(" password: 0x%x gctype: 0x%x in use: %d\n", base_np->password, + base_np->gctype, base_np->inuse); + if (!base_np->inuse) + printf(" Free list: fwd 0x%x bkwd 0x%x\n", base_np->fwd, base_np->bkwd); + printf(" Header Length: %d cells.\n\n", base_np->arlen); + printf(" Trailer Length: %d cells.\n\n", trailer_np->arlen); - addr = ((LispPTR *)bbase) - 20; - for (; addr < (LispPTR *)bbase; addr++) printf("%16p %8x\n", (void *)addr, *addr); - printf("%16p %8x <- array header\n", (void *)addr, *addr); + addr = ((LispPTR *)base_np) - 20; + for (; addr < (LispPTR *)base_np; addr++) printf("%16p (0x%8x) %8x\n", (void *)addr, LAddrFromNative(addr), *addr); + printf("%16p (0x%8x) %8x <- array header\n", (void *)addr, LAddrFromNative(addr), *addr); addr++; - for (; addr < (LispPTR *)bbase + 20; addr++) printf("%16p %8x\n", (void *)addr, *addr); + for (; addr < (LispPTR *)base_np + 20; addr++) printf("%16p (0x%8x) %8x\n", (void *)addr, LAddrFromNative(addr), *addr); printf(". . .\n"); - addr = ((LispPTR *)btrailer) - 20; - for (; addr < (LispPTR *)btrailer; addr++) printf("%16p %8x\n", (void *)addr, *addr); - printf("%16p %8x <- array trailer\n", (void *)addr, *addr); + addr = ((LispPTR *)trailer_np) - 20; + for (; addr < (LispPTR *)trailer_np; addr++) printf("%16p (0x%8x) %8x\n", (void *)addr, LAddrFromNative(addr), *addr); + printf("%16p (0x%8x) %8x <- array trailer\n", (void *)addr, LAddrFromNative(addr), *addr); addr++; - for (; addr < (LispPTR *)btrailer + 20; addr++) printf("%16p %8x\n", (void *)addr, *addr); + for (; addr < (LispPTR *)trailer_np + 20; addr++) printf("%16p (0x%8x) %8x\n", (void *)addr, LAddrFromNative(addr), *addr); } From f2bf026b07c92aa96f97aa8b719e9ea0b9a0721e Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sat, 19 Jul 2025 17:50:55 -0700 Subject: [PATCH 12/17] Adds URaid F command to print array block free list heads --- inc/gcfinaldefs.h | 1 + src/gcfinal.c | 27 +++++++++++++++++++++++++++ src/uraid.c | 22 ++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/inc/gcfinaldefs.h b/inc/gcfinaldefs.h index 198b9bf..26d409f 100644 --- a/inc/gcfinaldefs.h +++ b/inc/gcfinaldefs.h @@ -2,6 +2,7 @@ #define GCFINALDEFS_H 1 #include "lispemul.h" /* for LispPTR, DLword */ void printarrayblock(LispPTR base); +void printfreeblockchainn(int arlen); LispPTR releasingvmempage(LispPTR ptr); LispPTR checkarrayblock(LispPTR base, LispPTR free, LispPTR onfreelist); LispPTR makefreearrayblock(LispPTR block, DLword length); diff --git a/src/gcfinal.c b/src/gcfinal.c index 67e288b..97825e5 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -610,3 +610,30 @@ void printarrayblock(LispPTR base) { addr++; for (; addr < (LispPTR *)trailer_np + 20; addr++) printf("%16p (0x%8x) %8x\n", (void *)addr, LAddrFromNative(addr), *addr); } + +static void printfreeblockchainhead(int index) +{ + LispPTR fbl, freeblock; + LispPTR *fbl_np; + + fbl = POINTERMASK & ((*FreeBlockBuckets_word) + (DLWORDSPER_CELL * index)); + fbl_np = (LispPTR *)NativeAligned4FromLAddr(fbl); + /* lisp pointer to free block on chain */ + freeblock = POINTERMASK & (*fbl_np); + if (freeblock == NIL) { /* no blocks in chain */ + printf("Free block chain (bucket %d): NIL\n", index); + } else { + printf("Free block chain(bucket %d): 0x%x\n", index, freeblock); + } +} + +void printfreeblockchainn(int arlen) +{ + if (arlen >= 0) { + printfreeblockchainhead(BucketIndex(arlen)); + return; + } else + for (int i = 0; i <= MAXBUCKETINDEX; i++) { + printfreeblockchainhead(i); + } +} diff --git a/src/uraid.c b/src/uraid.c index 31ea76d..fda8717 100644 --- a/src/uraid.c +++ b/src/uraid.c @@ -168,6 +168,7 @@ static const char *URaid_summary2 = "\n-- Memory display commands\n\ a litatom\t\tDisplays the top-level value of the litatom\n\ B Xaddress\t\tPrint the contents of the arrayblock at that address.\n\ +F [size]\t\tPrint the head of the array free list chain for given size, or all\n\ d litatom\t\tDisplays the definition cell for the litatom\n\ M\t\t\tDisplays TOS,CSP,PVAR,IVAR,PC\n\ m func1 func2\t\tMOVD func1 to func2\n\ @@ -201,6 +202,7 @@ l [type]\t\tDisplays backtrace for specified type of stack. (k|m|r|g|p|u|) \n-- Memory display commands\n\ a litatom\t\tDisplays the top-level value of the litatom\n\ B Xaddress\t\tDisplays the contents of the arrayblock at that address.\n\ +F [size]\t\tPrint the head of the array free list chain for given size, or all\n\ d litatom\t\tDisplays the definition cell of the litatom\n\ M\t\t\tDisplays TOS,CSP,PVAR,IVAR,PC\n\ m func1 func2\t\tMoves definition of func1 to func2 (MOVD)\n\ @@ -467,6 +469,26 @@ LispPTR uraid_commands(void) { } break; + case 'F': { /* print array block free list head(s) */ + long size; + if (URaid_argnum != 1 && URaid_argnum != 2) { + printf("FREE-BLOCK-CHAIN: F [block-size (cells)]\n"); + return (T); + } + if (URaid_argnum == 1) { + size = -1; + } else { + errno = 0; + size = (LispPTR)strtol(URaid_arg1, &endpointer, 0); + if (errno != 0 || *endpointer != '\0') { + printf("Arg not number\n"); + return (T); + } + } + printfreeblockchainn(size); + } + break; + case 'd': /* DEFCELL */ if (URaid_argnum != 2) { printf("GETD: d litatom\n"); From c58336f81344bb1ce8d9b5451a13d45469c1757f Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sat, 19 Jul 2025 18:11:43 -0700 Subject: [PATCH 13/17] Cleans up checkarrayblock implementation Uses consistent naming (_np) for native pointer equivalents of Lisp addresses Ensures non-zero return value if arrayblock fails check --- src/gcfinal.c | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/gcfinal.c b/src/gcfinal.c index 97825e5..7a0e177 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -181,10 +181,9 @@ LispPTR releasingvmempage(LispPTR ptr) { /* Given an array block, do consistency checks on it. */ /* */ /************************************************************************/ - LispPTR checkarrayblock(LispPTR base, LispPTR free, LispPTR onfreelist) { - struct arrayblock *bbase, *btrailer; - struct arrayblock *bfwd, *bbwd, *rbase; + struct arrayblock *base_np, *trailer_np; + struct arrayblock *fwd_np, *bkwd_np, *rbase; LispPTR fbl; LispPTR *rover, *tmprover; #ifdef ARRAYCHECK @@ -193,38 +192,51 @@ LispPTR checkarrayblock(LispPTR base, LispPTR free, LispPTR onfreelist) { if (*Array_Block_Checking_word != NIL) #endif { - bbase = (struct arrayblock *)NativeAligned4FromLAddr(base); - btrailer = (struct arrayblock *)NativeAligned4FromLAddr(Trailer(base, bbase)); - if (bbase->password != ARRAYBLOCKPASSWORD) { + base_np = (struct arrayblock *)NativeAligned4FromLAddr(base); + trailer_np = (struct arrayblock *)NativeAligned4FromLAddr(Trailer(base, base_np)); +#if 0 + printf("cblock: 0x%x free: %x onfreelist: %x pw: %x arlen %d\n", + base, free, onfreelist, base_np->password, base_np->arlen); +#endif + if (base_np->password != ARRAYBLOCKPASSWORD) { printarrayblock(base); error("ARRAYBLOCK password wrong\n"); - } else if (bbase->inuse == free) { + return(T); + } else if (base_np->inuse == free) { printarrayblock(base); error("ARRAYBLOCK INUSE bit set wrong\n"); - } else if (btrailer->password != ARRAYBLOCKPASSWORD) { + return(T); + } else if (trailer_np->password != ARRAYBLOCKPASSWORD) { printarrayblock(base); error("ARRAYBLOCK trailer password wrong\n"); - } else if (bbase->arlen != btrailer->arlen) { + return(T); + } else if (base_np->arlen != trailer_np->arlen) { printarrayblock(base); error("ARRAYBLOCK Header and Trailer length don't match\n"); - } else if (btrailer->inuse == free) + return(T); + } else if (trailer_np->inuse == free) /* This is not original source.(in original, - btrailer -> bbase) maybe, this is correction. */ + trailer_np -> base_np) maybe, this is correction. */ { printarrayblock(base); error("ARRAYBLOCK Trailer INUSE bit set wrong\n"); - } else if (!onfreelist || (bbase->arlen < MINARRAYBLOCKSIZE)) + return(T); + } else if (!onfreelist || (base_np->arlen < MINARRAYBLOCKSIZE)) return (NIL); /* Remaining tests only for free list. */ - bfwd = (struct arrayblock *)NativeAligned4FromLAddr(bbase->fwd); - bbwd = (struct arrayblock *)NativeAligned4FromLAddr(bbase->bkwd); - if ((bbwd->fwd != base) || (bfwd->bkwd != base)) { + fwd_np = (struct arrayblock *)NativeAligned4FromLAddr(base_np->fwd); + bkwd_np = (struct arrayblock *)NativeAligned4FromLAddr(base_np->bkwd); + if ((bkwd_np->fwd != base) || (fwd_np->bkwd != base)) { error("ARRAYBLOCK links fouled\n"); + return(T); } else { - fbl = FreeBlockChainN(bbase->arlen); + fbl = FreeBlockChainN(base_np->arlen); rover = tmprover = (LispPTR *)NativeAligned4FromLAddr(fbl); /* GETBASEPTR */ - if ((*rover & POINTERMASK) == NIL) error("Free Block's bucket empty\n"); + if ((*rover & POINTERMASK) == NIL) { + error("Free Block's bucket empty\n"); + return(T); + } do { if ((*rover & POINTERMASK) == base) return (NIL); checkarrayblock((*rover & POINTERMASK), T, NIL); From 0e2cda2328ffd2c70e92afaeae8ff095cc29a49b Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sat, 19 Jul 2025 22:44:27 -0700 Subject: [PATCH 14/17] Cleans up releasingvmempage implementation Uses consistent naming (_np) for native pointer equivalents of Lisp addresses --- src/gcfinal.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gcfinal.c b/src/gcfinal.c index 7a0e177..ec4d1cf 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -164,13 +164,13 @@ static LispPTR findptrsbuffer(LispPTR ptr) { /************************************************************************/ LispPTR releasingvmempage(LispPTR ptr) { - struct buf *bptr; - LispPTR bufferptr = findptrsbuffer(ptr); + LispPTR buffer = findptrsbuffer(ptr); + struct buf *buffer_np; - if (bufferptr == NIL) return (NIL); /* Not in use, OK to reclaim it */ + if (buffer == NIL) return (NIL); /* Not in use, OK to reclaim it */ - bptr = (struct buf *)NativeAligned4FromLAddr(bufferptr); - bptr->noreference = T; /* Mark the buffer free to use ?? */ + buffer_np = (struct buf *)NativeAligned4FromLAddr(buffer); + buffer_np->noreference = T; /* Mark the buffer free to use ?? */ return (ATOM_T); } From b75e66d91cef9d96e65dc37d16bb15587206a59f Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sat, 19 Jul 2025 23:19:19 -0700 Subject: [PATCH 15/17] Renames struct buf to struct buffer to match corresponding Lisp datatype name --- src/gcfinal.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/gcfinal.c b/src/gcfinal.c index ec4d1cf..5a4ad85 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -74,9 +74,12 @@ #define BucketIndex(n) min(integerlength(n), MAXBUCKETINDEX) #define FreeBlockChainN(n) ((POINTERMASK & *FreeBlockBuckets_word) + 2 * BucketIndex(n)) +/* + * Declaration of buffer must be identical layout to Lisp BUFFER datatype in PMAP. + */ #ifndef BYTESWAP #ifdef BIGVM -struct buf { +struct buffer { LispPTR filepage; LispPTR vmempage; LispPTR buffernext; @@ -87,7 +90,7 @@ struct buf { unsigned sysnext : 28; }; #else -struct buf { +struct buffer { LispPTR filepage; LispPTR vmempage; LispPTR buffernext; @@ -100,7 +103,7 @@ struct buf { #endif /* BIGVM */ #else #ifdef BIGVM -struct buf { +struct buffer { LispPTR filepage; LispPTR vmempage; LispPTR buffernext; @@ -111,7 +114,7 @@ struct buf { unsigned noreference : 1; }; #else -struct buf { +struct buffer { LispPTR filepage; LispPTR vmempage; LispPTR buffernext; @@ -140,10 +143,10 @@ static int integerlength(unsigned int n) { static LispPTR findptrsbuffer(LispPTR ptr) { LispPTR buf; - struct buf *buf_np; + struct buffer *buf_np; buf = *System_Buffer_List_word; while (buf != NIL) { - buf_np = (struct buf *)NativeAligned4FromLAddr(buf); + buf_np = (struct buffer *)NativeAligned4FromLAddr(buf); if (ptr == buf_np->vmempage) { return (buf); } @@ -165,11 +168,11 @@ static LispPTR findptrsbuffer(LispPTR ptr) { LispPTR releasingvmempage(LispPTR ptr) { LispPTR buffer = findptrsbuffer(ptr); - struct buf *buffer_np; + struct buffer *buffer_np; if (buffer == NIL) return (NIL); /* Not in use, OK to reclaim it */ - buffer_np = (struct buf *)NativeAligned4FromLAddr(buffer); + buffer_np = (struct buffer *)NativeAligned4FromLAddr(buffer); buffer_np->noreference = T; /* Mark the buffer free to use ?? */ return (ATOM_T); } From 3569e54524538387ae98a05e4899ccfda894b015 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Sun, 20 Jul 2025 10:48:20 -0700 Subject: [PATCH 16/17] Uses consistent naming (_np) for native pointer equivalents of Lisp addresses in GC aref1 --- src/gcarray.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/gcarray.c b/src/gcarray.c index 9135f0e..8e68124 100644 --- a/src/gcarray.c +++ b/src/gcarray.c @@ -99,35 +99,35 @@ struct hashtable { LispPTR aref1(LispPTR array, int index) { LispPTR retval = 0; LispPTR base; - short typenumber; - struct arrayheader *actarray; + struct arrayheader *array_np; - actarray = (struct arrayheader *)NativeAligned4FromLAddr(array); - if (index >= actarray->totalsize) { + array_np = (struct arrayheader *)NativeAligned4FromLAddr(array); + if (index >= array_np->totalsize) { printf("Invalid index in GC's AREF1: 0x%x\n", index); - printf(" Array size limit: 0x%x\n", actarray->totalsize); + printf(" Array size limit: 0x%x\n", array_np->totalsize); printf(" Array ptr: 0x%x\n", array); - printf(" Array 68K ptr: %p\n", (void *)actarray); - printf("base: 0x%x\n", actarray->base); - printf("offset: 0x%x\n", actarray->offset); - printf("type #: 0x%x\n", actarray->typenumber); - printf("fill ptr: 0x%x\n", actarray->fillpointer); + printf(" Array native ptr: %p\n", (void *)array_np); + printf("base: 0x%x\n", array_np->base); + printf("offset: 0x%x\n", array_np->offset); + printf("type #: 0x%x\n", array_np->typenumber); + printf("fill ptr: 0x%x\n", array_np->fillpointer); error("index out of range in GC's AREF1."); } - index += actarray->offset; - typenumber = actarray->typenumber; - base = actarray->base; - switch (typenumber) { - case 3: /* unsigned 8bits */ - retval = (GETBYTE(((char *)NativeAligned2FromLAddr(base)) + index)) & 0x0ff; - retval |= S_POSITIVE; - break; - case 4: /* unsigned 16bits */ - retval = (GETWORD(((DLword *)NativeAligned2FromLAddr(base)) + index)) & 0x0ffff; - retval |= S_POSITIVE; - break; - case 38: retval = (*(((LispPTR *)NativeAligned4FromLAddr(base)) + index)); break; - default: error("Not Implemented in gc's aref1 (other types)"); + index += array_np->offset; + base = array_np->base; + switch (array_np->typenumber) { + case 3: /* unsigned 8 bits */ + retval = (GETBYTE(((char *)NativeAligned2FromLAddr(base)) + index)) & 0x0ff; + retval |= S_POSITIVE; + break; + case 4: /* unsigned 16 bits */ + retval = (GETWORD(((DLword *)NativeAligned2FromLAddr(base)) + index)) & 0x0ffff; + retval |= S_POSITIVE; + break; + case 38: /* pointer 32 bits */ + retval = (*(((LispPTR *)NativeAligned4FromLAddr(base)) + index)); + break; + default: error("Not Implemented in gc's aref1 (other types)"); } return (retval); } From 01d21b0a448d07d4b63583a296f34771267df8c9 Mon Sep 17 00:00:00 2001 From: Nick Briggs Date: Tue, 22 Jul 2025 09:43:49 -0700 Subject: [PATCH 17/17] Revert integerlength() to pure (but more efficient) C as glibc does not provide fls() --- src/gcfinal.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/gcfinal.c b/src/gcfinal.c index 5a4ad85..b5a4244 100644 --- a/src/gcfinal.c +++ b/src/gcfinal.c @@ -43,7 +43,6 @@ /*************************************************************************/ #include // for printf -#include // for fls #include "address.h" // for HILOC #include "adr68k.h" // for NativeAligned4FromLAddr, LAddrFromNative #include "array.h" // for arrayblock, ARRAYBLOCKTRAILERCELLS, MAXBUCK... @@ -128,7 +127,29 @@ struct buffer { #endif /* BYTESWAP */ static int integerlength(unsigned int n) { - return (fls(n)); + int p = 0; + + if (n <= 2) return (n); /* easy case */ + if (n >= 65536) { + n >>= 16; + p += 16; + } + if (n >= 256) { + n >>= 8; + p += 8; + } + if (n >= 16) { + n >>= 4; + p += 4; + } + if (n >= 4) { + n >>= 2; + p += 2; + } + if (n >= 2) { + p += 1; + } + return (p + 1); } /************************************************************************/