[Oberon] Fw: FPGA - Bitmaps.Mod
andreas_pirklbauer at yahoo.com
Fri Apr 7 17:32:46 CEST 2017
a couple of comments on your code:
1. It is normal that you see only a single reference to procedure Kernel.New in the Oberon 2013 system, namely in procedure System.Trap - which is the system's trap handler. This is because in Oberon 2013, the operator NEW is *implemented* using the trap mechanism (in order to avoid any reference to module Kernel in the compiler). So, when the programmer writes NEW (p), the compiler generates code that first assigns the address of p to register R0 (which will then appear as variable 'a' in procedure System.Trap), and the type tag (=the address of the type descriptor) to register R1 (which will then appears as variable 'b' in procedure System.Trap), following by an unconditional branch instruction via the R12 (the module table MT), using trap number 0. So, at runtime, this generates trap 0 which in turn lands you in procedure System.Trap which then simply calls Kernel.New(a, b).
2. In your code you allocate the bitmap (VAR b: Bitmap) as a *local* variable. Make it global. This is necessary because the garbage collector *expects* the type tag to be there. The Oberon garbage collector uses a mark-scan scheme. In the mark phase (Kernel.Mark) all dynamic objects reachable from all currently loaded modules (mod.ptr in the module table) are marked. In the scan phase (Kernel.Scan), all non-reachable objects are collected. In both cases, the garbage collector dereferences p to obtain its size (p.tag points to the type descriptor, which in turn has the size of the record in its first slot).
3. Instead of just storing the *size* of the allocated object, you may in fact want to exactly replicate the *full* Oberon type descriptor, and make it globally available in your program. See chapter 8.2., page 109, of the book Project Oberon, for a detailed description of the fields of an Oberon type descriptor. But in essence, it consists of a) the size of the allocated object, b) 3 entries for the so-called extensions, and c) a list of pointer field offsets needed for the garbage collector (terminated by a sentinel value of -1).
You don't really need b) and c), so you could write something like:
TYPE TypeTag = RECORD size: LONGINT; ext: ARRAY 3 OF LONGINT; ptr: LONGINT; <other fields that you may want to add> END ;
Then create the "type tag" by writing:
VAR tag: TypeTag;
and initialise it with:
tag.size := <size of your object to be allocated>; tag.ext := 0; tag.ext := 0; tag.ext := 0; tag.ptr := -1;
4. If you want your objects to be automatically collected by the Oberon garbage collector, you must make it globally reachable via a global pointer. Then they will appear in mod.ptr in the module block which are used as roots for the garbage collector. (Oberon uses all named pointer variables in existence as roots for the mark phase of the garbage collector. See Oberon.GC for the details. It simply calls Kernel.Mark(mod.ptr) for each loaded module mod.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Oberon