<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><pre style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class="">Yes, mainly to keep fragmentation low, but also to keep the code of the garbage collector reasonably simple. </span><span style="white-space: pre-wrap;" class="">See ch. 8.2., p. 105, of the book "Project Oberon "at</span></pre><pre style="background-color: rgb(255, 255, 255);" class=""><br class=""></pre><pre style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class=""><a href="https://www.inf.ethz.ch/personal/wirth/ProjectOberon/PO.System.pdf" class="">https://www.inf.ethz.ch/personal/wirth/ProjectOberon/PO.System.pdf</a></span></pre><pre style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class=""><br class=""></span></pre><pre style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class="">for a description of the properties of the heuristics used (i.e. using 4 lists instead of 1). Another benefit of the choice of values for the sizes of heap records (32, 64, 128, n*256) is that it permits the easy merging of any two contiguous elements into an element of the next list. This of course also helps keeping fragmentation low.</span></pre><pre style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class=""><br class=""></span></pre><pre style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class="">As for “holes": In Oberon there are no holes per se in the memory area between Kernel.heapOrg and Kernel.heapLim (the “heap”) - </span><span style="white-space: pre-wrap;" class="">in the sense that *each and every* block in that space is either (i) “free” (mark < 0), </span><span style="white-space: pre-wrap;" class="">(ii), allocated and unmarked (mark = 0), or </span><span style="white-space: pre-wrap;" class="">(iii) allocated and marked (mark > 0). By convention, f</span><span style="white-space: pre-wrap;" class="">or each block p, Mem[p+4] is *defined* to be the mark field, which allows the scan phase of the garbage collector to actually recognize the free blocks as such. Heap blocks can become *fragmented* though - in the sense that the both free and allocated blocks can be "spread out" throughout the heap space.</span></pre><pre style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class=""><br class=""></span></pre><pre style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class="">------------------------------------
<br class=""></span></pre><pre style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class="">Tomas Kral thomas.kral at email.cz Wed Apr 19 16:38:11 CEST 2017</span></pre><pre style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class="">Hi,</span></pre><pre style="background-color: rgb(255, 255, 255);" class=""><span style="white-space: pre-wrap;" class="">Yes, I can see now.

Oberon maintains distinct chains of 32,64,128, and multiple 256 byte
blocks. With the idea to prevent holes and fragmentation?

Many thanks
Tomas

On Wed, 19 Apr 2017 15:48:27 +0200
Andreas Pirklbauer <</span><a href="https://lists.inf.ethz.ch/mailman/listinfo/oberon" style="white-space: pre-wrap;" class="">andreas_pirklbauer at yahoo.com</a><span style="white-space: pre-wrap;" class="">> wrote:

></span><i style="white-space: pre-wrap;" class=""> Tomas,
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> 
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> The "size" of the heap record, as specified in the type descriptor,
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> needs to satisfy certain criteria, in order for Kernel.New to work:
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> a) it must include 8 bytes for the two hidden fields 'mk' and 'tag'
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> b) the total must be 32, 64, 128 or n*256 bytes long.
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> 
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> 
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> See module Memory.Mod on 
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> 
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> <a href="https://github.com/andreaspirklbauer/Oberon-generic-heap-allocation" class="">https://github.com/andreaspirklbauer/Oberon-generic-heap-allocation</a>
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> 
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> to see how this can be done (first three lines of procedures
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> Memory.New).
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> 
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> It's essential (!) to set size correctly, otherwise the garbage
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> collector gets confused, as becomes evident when studying the code
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> for procedures Kernel.Mark and Kernel.Scan (which obtains the size if
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> a heap record by inspecting the size field in the type descriptor).
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> If it's not a valid size, Kernel.Scan will insert it in the "n*256"
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> list without the record actually being a multiple of 256. Bad!
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> 
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> 
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> [Oberon] Fw: FPGA - Bitmaps.Mod
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> 
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> Tomas Kral thomas.kral at email.cz 
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> Wed Apr 19 12:53:09 CEST 2017
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> Previous message: [Oberon] Fw: FPGA - Bitmaps.Mod
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> Next message: [Oberon] FPGA - Naming Conventions
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> Hi Andreas, Joerg, I have tried both methods suggested here. (a)
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> without tag declaration, simply calling Kernel.New(b.base,
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> SYSTEM.ADR(b.size)); (b) with tag declaration and persistence
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> tag.size := <size of your object to be allocated>; tag.ext[0] := 0;
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> tag.ext[1] := 0; tag.ext[2] := 0; tag.ptr := -1; Kernel.New(b.base,
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> SYSTEM.ADR(tag.size)) They both seem to allocate a block of requested
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> size, however when GC is run, sometimes heap is inconsistent and
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> `System.Watch' reports strange
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> 
</i><span style="white-space: pre-wrap;" class="">></span><i style="white-space: pre-wrap;" class=""> Sent from my iPhone
</i></pre><div class=""><i class=""><br class=""></i></div></body></html>