From 39c37c2517bbab96123632eb7288bbfbd7b8ad88 Mon Sep 17 00:00:00 2001 From: Martin Haye Date: Tue, 18 Aug 2015 09:39:05 -0700 Subject: [PATCH] Made API for garbage collector (now called heap system) --- Platform/Apple/virtual/src/core/mem.s | 32 ++++---- Platform/Apple/virtual/src/include/mem.i | 94 +++++++++++++++++++++--- 2 files changed, 97 insertions(+), 29 deletions(-) diff --git a/Platform/Apple/virtual/src/core/mem.s b/Platform/Apple/virtual/src/core/mem.s index f29e775e..7eaa3295 100644 --- a/Platform/Apple/virtual/src/core/mem.s +++ b/Platform/Apple/virtual/src/core/mem.s @@ -50,10 +50,6 @@ gcHash_link = $5300 gcHash_dstLo = $5400 gcHash_dstHi = $5500 -; Heap area -heapStart = $F000 ; must be page aligned -heapEnd = $F800 ; must be page aligned - ; Other equates prodosMemMap = $BF58 @@ -651,6 +647,8 @@ typeTblL !fill MAX_TYPES typeTblH !fill MAX_TYPES typeLen !fill MAX_TYPES ; length does not include type byte +heapStartPg !byte 0 +heapEndPg !byte 0 heapTop !word 0 gcHash_top !byte 0 nHeapBlks !byte 0 @@ -682,12 +680,11 @@ setTypeTbl: !zone ; Clear the heap heapReset: !zone - lda #heapStart - sta heapTop lda #0 + sta heapTop sta nHeapBlks + lda heapStartPg + sta heapTop ; fall through to: ; Zero memory heapTop.heapEnd heapClr: !zone @@ -699,7 +696,7 @@ heapClr: !zone inx bne .st iny - cpy #>heapEnd + cpy heapEndPg bne .pg rts @@ -722,7 +719,7 @@ heapAlloc: !zone adc pTmp bcc + iny - cpy #>heapEnd + cpy heapEndPg bcs .needgc + sta heapTop sty heapTop+1 @@ -790,7 +787,7 @@ heapCheck: !zone bcc .blklup inc pTmp+1 lda pTmp+1 - cmp #>heapEnd + cmp heapEndPg bcc .blklup bcs heapCorrupt .isobj and #$7F @@ -814,9 +811,9 @@ heapCheck: !zone bcs heapCorrupt ; but beyond end is not ok + lda (pTmp),y ; get hi byte of ptr beq .tscan ; null is ok - cmp #>heapStart ; else check if < start of heap + cmp heapStartPg ; else check if < start of heap bcc heapCorrupt - cmp #>heapEnd ; or >= than end of heap + cmp heapEndPg ; or >= than end of heap bcc .tscan heapCorrupt: ldx pTmp @@ -832,9 +829,8 @@ gc1_mark: !zone - sta gcHash_first,x inx bne - - lda #heapEnd + stx pSrc ; X is zero'd from loop above + lda heapStartPg sta pSrc+1 sec ; sec means add if not found jsr gcHash_chk ; seed the hash, and thus our queue, with the global block @@ -897,10 +893,10 @@ gc3_fix: ; Phase 2 of Garbage Collection: sweep all accessible blocks together gc2_sweep: !zone - lda #heapStart + lda heapStartPg sta pSrc+1 sta pDst+1 .outer clc ; clc = do not add to hash diff --git a/Platform/Apple/virtual/src/include/mem.i b/Platform/Apple/virtual/src/include/mem.i index 84621098..48f10462 100644 --- a/Platform/Apple/virtual/src/include/mem.i +++ b/Platform/Apple/virtual/src/include/mem.i @@ -248,20 +248,14 @@ DEBUG_MEM = $1A ; Print out the currently allocated memory blocks and their states. ;------------------------------------------------------------------------------ -CHAIN_LOADER = $1E - ; Input: X-reg / Y-reg - pointer to loader (X=lo, Y=hi) to add to chain +CHECK_MEM = $1E + ; Input: None ; ; Output: None ; - ; Add a loader to the chain just after this loader. The current next - ; loader (if there is one) will be passed to the new loader with another - ; CHAIN_LOADER command. - ; - ; The purpose of a loader chain is to insert faster devices between the - ; main/aux loader (fastest) and the disk loader (slowest). Note that the - ; main mem and aux mem loaders are conceptually one; a chained loader will - ; always be inserted after them, not between them. - + ; Check that memory manager structures (and heap structures, if a heap + ; has been set) are all intact. + ;------------------------------------------------------------------------------ FATAL_ERROR = $1F ; Input: X-reg(lo) / Y-reg(hi): message pointer @@ -274,6 +268,84 @@ FATAL_ERROR = $1F ; ; This command halts and thus never returns. +;------------------------------------------------------------------------------ +HEAP_SET = $20 + ; Input: X-reg(lo) / Y-reg(hi): pointer to allocated block for heap + ; + ; Output: None + ; + ; Establishes a block of memory to use as a garbage collected small-object + ; heap. The block must be page-aligned and sized in whole pages, and + ; generally should be locked first. + +;------------------------------------------------------------------------------ +HEAP_TYPE = $21 + ; Input: X-reg(lo) / Y-reg(hi): pointer to type table + ; + ; Output: None + ; + ; Adds a type to the list of known heap types. Each type will be assigned + ; a number starting at $80 and going up to $81, $82, etc. By convention + ; type $80 should be the single "Global" object from which all others live + ; objects can be traced. + ; + ; The type table for the type should be laid out as follows: + ; byte 0: length byte (1 to 127) + ; byte 1: offset of first pointer (1 to 127) + ; byte 2: offset of second pointer + ; ... + ; byte n: zero (0) value marks end of table + +;------------------------------------------------------------------------------ +HEAP_ALLOC = $22 + ; Input: X-reg: string length $01-7F, or type code $80-FF + ; + ; Output: X-reg(lo) / Y-reg(hi): pointer to allocated object space + ; + ; Allocates an object on the heap. If X <= $7F, it's a string object + ; (no internal pointers). If X >= $80, it's a typed object corresponding + ; to the types added with HEAP_TYPE. + ; + ; The first byte of the returned block will be the length or type code, + ; (which you must never change), and subsequent bytes are initialized to + ; all zero. + ; + ; By convention, the very first block allocated should be of the "Global" + ; type ($80) and all other live objects must be traceable from there. + +;------------------------------------------------------------------------------ +HEAP_COLLECT = $23 + ; Input: None. + ; + ; Output: X-reg(lo) / Y-reg(hi): free space in heap after collection + ; + ; Traces objects in the heap to determine which ones are "live", that is, + ; reachable from the very first object allocated. By convention, that first + ; object should be of the "Global" type, i.e. $80, and everything reachable + ; from pointers there is considered live. + ; + ; Live objects are then coalesced together in contiguous memory, squeezing + ; out any objects that can no longer be reached. + ; + ; NOTE: The main memory area from $4000.5FFF is used during the collection + ; process. Therefore, HEAP_COLLECT should not be run during a + ; START_LOAD..FINISH_LOAD sequence, nor when hi-res page 2 is being shown. + +;------------------------------------------------------------------------------ +CHAIN_LOADER = $30 + ; Input: X-reg / Y-reg - pointer to loader (X=lo, Y=hi) to add to chain + ; + ; Output: None + ; + ; Add a loader to the chain just after this loader. The current next + ; loader (if there is one) will be passed to the new loader with another + ; CHAIN_LOADER command. + ; + ; The purpose of a loader chain is to insert faster devices between the + ; main/aux loader (fastest) and the disk loader (slowest). Note that the + ; main mem and aux mem loaders are conceptually one; a chained loader will + ; always be inserted after them, not between them. + ;------------------------------------------------------------------------------ ; Convenience for writing assembly routines in PLASMA source ; Macro param: number of parameters passed from PLASMA to the asm routine