~vdupras/duskos

3b7ccfa7feacf8ec38c73b41acc00df5502c15fd — Virgil Dupras 6 days ago f3f139a
Change dictionary entry structure

As I'm about to implement it on ARM, which makes me alignment-aware a little bit
more, I'm thinking that it's a good time to improve this structure.

The idea is to make the link and meta fields 4b-aligned. With the old structure,
those fields could never be aligned because the length field would displace them
by one.
6 files changed, 34 insertions(+), 28 deletions(-)

M fs/doc/arch.txt
M fs/lib/meta.fs
M fs/xcomp/bootlo.fs
M fs/xcomp/i386/kernel.fs
M fs/xcomp/tools.fs
M posix/vm.c
M fs/doc/arch.txt => fs/doc/arch.txt +7 -1
@@ 21,10 21,12 @@ Dictionaries are a form of linked list.

The structure of each entry is:

Xb of padding to align the structure to 4b
Xb name
1b name length + immediate
4b pointer to metadata
4b pointer to previous entry --> this is where we link
1b name length + immediate
... payload ...

The "previous entry" field in an entry refers to this same place.



@@ 33,6 35,10 @@ The link to "metadata" is a linked list, initialized to 0.
The "name length" field is a 7 bit length with the 8th bit reserved for the
"immediate" flag (1=immediate).

The whole structure is aligned to 4 bytes, with zero padding in front of the
name to enforce that alignment. This means that the payload is also always
aligned to 4b.

When we refer to a "word" in Dusk OS, we always refer to its first executable
byte, right after the name length field. When what you have is a word, you can
call it.

M fs/lib/meta.fs => fs/lib/meta.fs +1 -1
@@ 2,7 2,7 @@

\ Dictionary
9 const ENTRYSZ
: wordlen ( w -- len ) 1- c@ $3f and ;
: wordlen ( w -- len ) w>e e>wlen c@ $3f and ;
: wordname[] ( w -- sa sl )
  bi wordlen | 9 - over - ( sl sa ) swap ;
: .word ( w -- ) wordname[] rtype ;

M fs/xcomp/bootlo.fs => fs/xcomp/bootlo.fs +5 -4
@@ 57,12 57,13 @@ code8b W>A, drop, A) 8b) [!], 1 A) [+n], drop, exit,
code + PSP) +, nip, exit,
code - -W, PSP) +, nip, exit,
: -^ swap - ;
: e>w 5 + ;
: w>e 5 - ;
: e>w 4 + ;
: e>wlen 5 - ;
: w>e 4 - ;
: current sysdict @ e>w ;
code 1+ 1 W+n, exit,
code 1- -1 W+n, exit,
: immediate current 1- dup c@ $80 or swap c! ;
: immediate sysdict @ e>wlen dup c@ $80 or swap c! ;
: EMETA_16B $11 ; : EMETA_8B $10 ;
: 16b EMETA_16B MOD ! ; immediate
: 8b EMETA_8B MOD ! ; immediate


@@ 329,7 330,7 @@ code move ( src dst u -- )
  word" SZ" code _cur e>w structsz' litn W) @, exit,
does> ( 'struct )
    _structfind
    dup 1- c@ $80 and not compiling and \ compile only if not immediate
    dup w>e e>wlen c@ $80 and not compiling and \ compile only if not immediate
    if execute, else execute then ;
: ]struct
  \ break the chain at the root of the struct

M fs/xcomp/i386/kernel.fs => fs/xcomp/i386/kernel.fs +6 -6
@@ 492,20 492,20 @@ pc to lblfind \ ax=str dx='dict
  ax inc,
  di push, si push,
pc ( loop )
  bl dx 4 d) mov,   \ entry len
  bl dx -5 d) mov,   \ entry len
  bl $3f i) and,    \ 3f instead of 7f? we reserve space for another flag.
  bl cl cmp,
  forward jnz, to L1 ( skip1 )
  \ same length
  di dx mov,
  di 4 i) sub,
  di 5 i) sub,
  di cx sub,        \ beginning of name range
  si ax mov,
  repz, cmpsb,
  forward jnz, to L2 ( skip2 )
  \ same contents
  si pop, di pop,
  dx 5 i) add,      \ word
  dx 4 i) add,      \ word
  ax dx mov,
  ret,
L2 forward! ( skip2 )


@@ 643,7 643,7 @@ xcode findmod ( w -- w )
  lblmod m) -1 i) test,
  lblret abs>rel jz,
  dx ax mov,
  ax ax -9 d) mov,
  ax ax -8 d) mov,
  bx lblmod m) mov,
  L1 abscall, \ findmeta
  ax ax test,


@@ 675,7 675,7 @@ xcode compword ( str -- )
  xwordlbl litn abs>rel jnz, \ literal: jump to litn
  \ not a literal, find and compile
  L2 abscall, \ ax=w
  ax -1 d) 8b) $80 i) test,
  ax -9 d) 8b) $80 i) test,
  L1 abs>rel jnz, \ immediate? execute
  \ compile word
  wcall, findmod


@@ 711,13 711,13 @@ xcode entry ( 'dict s -- )
  ax inc,
  wcall, align4 \ ( 'dict -- )
  cx push, lblwriterange abscall, cx pop,
  cl cwrite,
  bx lblnextmeta m) mov, bx dwrite,
  lblnextmeta m) 0 i) mov,
  bx ax 0 d) mov, \ ax='dict bx=dict
  dx lblhere m) mov,
  ax 0 d) dx mov, xdrop, ( -- )
  bx dwrite,
  cl cwrite,
  lbl[rcnt] m) 0 i) mov,
  ret,


M fs/xcomp/tools.fs => fs/xcomp/tools.fs +1 -1
@@ 10,7 10,7 @@ create xbindict 0 ,

: xoffset binstart org - ;
: xcode xbindict word entry ;
: ximm xbindict @ e>w 1- dup c@ $80 or swap c! ;
: ximm xbindict @ e>wlen dup c@ $80 or swap c! ;

\ Usage: xwordlbl foo call, "foo" being a word name in xbindict
: xwordlbl ( "name" -- pc )

M posix/vm.c => posix/vm.c +14 -15
@@ 168,9 168,9 @@ static dword _find(dword dict, byte *name, byte slen) {
	dword a = dict;
	byte len;
	while (memchk(a)) {
		len = gb(a+4) & 0x3f;
		if ((len == slen) && (memcmp(name, &vm.mem[a-4-len], len)==0)) {
			return a+5;
		len = gb(a-5) & 0x3f;
		if ((len == slen) && (memcmp(name, &vm.mem[a-5-len], len)==0)) {
			return a+4;
		}
		a = gd(a);
	}


@@ 227,13 227,18 @@ static void compbinopwr(byte binopidx) { litwr(binopidx); cwrite(0x45); }
static void storewr() { cwrite(0x0e); dropwr(); wstorewr(OPA); dropwr(); }

static void callword(dword addr); // forward declaration
static void align4(dword n) {
	n = (here() + n) % 4;
	if (n) { allot(4-n); }
}
static void _entry(dword dict, byte *name, byte slen) {
	align4(slen+1);
	memcpy(&vm.mem[here()], name, slen);
	allot(slen);
	cwrite(slen);
	dwrite(gd(NEXTMETA));
	dwrite(gd(dict));
	cwrite(slen);
	sd(dict, here()-5);
	sd(dict, here()-4);
	sd(NEXTMETA, 0);
}
static void entry(char *name) {


@@ 470,7 475,7 @@ static void WNF() {
static void FINDMOD() {
	dword a;
	if (gd(MOD)) {
		if ((a = findmeta(gd(MOD), gd(vm.W-9)))) {
		if ((a = findmeta(gd(MOD), gd(vm.W-8)))) {
			vm.W = a + 8;
			sd(MOD, 0);
		}


@@ 493,7 498,7 @@ static void COMPWORD() {
		ppush(sysdict());
		FIND();
		if (!vm.W) { WNF(); return; }
		if ((gb(vm.W-1) & 0x80) /* immediate */) {
		if ((gb(vm.W-9) & 0x80) /* immediate */) {
			FINDMOD();
			callword(ppop());
			STACKCHK();


@@ 532,18 537,12 @@ static void RSADDWR() {
static void COMPOP() {
	dword opcode = ppop(); dword operand = ppop(); wopwr(opcode, operand); }

static void ALIGN4() { // 0x40
	dword n = ppop();
	n = (here() + n) % 4;
	if (n) { allot(4-n); }
}
static void ALIGN4() { align4(ppop()); } // 0x40
// ( 'dict s -- )
static void ENTRY() {
	dword s = ppop();
	dword dict = ppop();
	byte len = gb(s++);
	ppush(len+1);
	ALIGN4();
	_entry(dict, &vm.mem[s], len);
	sd(_RCNT_, 0);
}


@@ 935,7 934,7 @@ static void callword(dword addr) {
static void wentry(char *name, byte op) { entry(name); cwrite(op); retwr(); }
static void sysconst(char *name, dword val) { entry(name); litwr(val); retwr(); }
static void sysalias(char *name, char *target) { entry(name); brwr(find(target)); }
static void makeimm() { dword a = sysdict()+4; sb(a, gb(a)|0x80); }
static void makeimm() { dword a = sysdict()-5; sb(a, gb(a)|0x80); }
static void compileop(byte op) { litwr(op); cwritewr(); }

// Names for simple word-to-code mappings