commit 3b7ccfa7feacf8ec38c73b41acc00df5502c15fd
parent f3f139a7e21d3659afae9765aacb56fbb10bcadd
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Wed, 24 May 2023 15:34:50 -0400
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.
Diffstat:
6 files changed, 34 insertions(+), 28 deletions(-)
diff --git a/fs/doc/arch.txt b/fs/doc/arch.txt
@@ -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.
diff --git a/fs/lib/meta.fs b/fs/lib/meta.fs
@@ -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 ;
diff --git a/fs/xcomp/bootlo.fs b/fs/xcomp/bootlo.fs
@@ -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
diff --git a/fs/xcomp/i386/kernel.fs b/fs/xcomp/i386/kernel.fs
@@ -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,
diff --git a/fs/xcomp/tools.fs b/fs/xcomp/tools.fs
@@ -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 )
diff --git a/posix/vm.c b/posix/vm.c
@@ -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