From 550050d9c373afe12c421f82a5e2632517c7ec89 Mon Sep 17 00:00:00 2001 From: Brad Nelson Date: Tue, 12 Jul 2022 21:25:14 -0700 Subject: [PATCH] Refining asm.js version. --- common/core.h | 33 +++++---- common/opcodes.h | 2 +- web/dump_web_opcodes.c | 6 +- web/web.template.js | 156 ++++++++++++++++++++++++++++++----------- 4 files changed, 137 insertions(+), 60 deletions(-) diff --git a/common/core.h b/common/core.h index b42cd2c..3366d96 100644 --- a/common/core.h +++ b/common/core.h @@ -143,14 +143,13 @@ static void finish(void) { static void create(const char *name, cell_t nlength, cell_t flags, void *op) { finish(); g_sys->heap = (cell_t *) CELL_ALIGNED(g_sys->heap); - char *pos = (char *) g_sys->heap; - for (cell_t n = nlength; n; --n) { *pos++ = *name++; } // name - g_sys->heap += CELL_LEN(nlength); - *g_sys->heap++ = (cell_t) *g_sys->current; // link - *g_sys->heap++ = (nlength << 8) | flags; // flags & length + for (cell_t n = nlength; n; --n) { CCOMMA(*name++); } // name + g_sys->heap = (cell_t *) CELL_ALIGNED(g_sys->heap); + COMMA(*g_sys->current); // link + COMMA((nlength << 8) | flags); // flags & length *g_sys->current = g_sys->heap; g_sys->latestxt = g_sys->heap; - *g_sys->heap++ = (cell_t) op; // code + COMMA(op); // code } static int match(char sep, char ch) { @@ -181,7 +180,7 @@ static cell_t *evaluate1(cell_t *rp) { cell_t xt = find((const char *) name, len); if (xt) { if (g_sys->state && !(((cell_t *) xt)[-1] & IMMEDIATE)) { - *g_sys->heap++ = xt; + COMMA(xt); } else { call = xt; } @@ -189,8 +188,8 @@ static cell_t *evaluate1(cell_t *rp) { cell_t n; if (convert((const char *) name, len, g_sys->base, &n)) { if (g_sys->state) { - *g_sys->heap++ = g_sys->DOLIT_XT; - *g_sys->heap++ = n; + COMMA(g_sys->DOLIT_XT); + COMMA(n); } else { PUSH n; } @@ -198,7 +197,7 @@ static cell_t *evaluate1(cell_t *rp) { float f; if (fconvert((const char *) name, len, &f)) { if (g_sys->state) { - *g_sys->heap++ = g_sys->DOFLIT_XT; + COMMA(g_sys->DOFLIT_XT); *(float *) g_sys->heap++ = f; } else { *++fp = f; @@ -243,13 +242,13 @@ static void forth_init(int argc, char *argv[], // FORTH worldlist (relocated when vocabularies added). cell_t *forth_wordlist = g_sys->heap; - *g_sys->heap++ = 0; + COMMA(0); // Vocabulary stack. g_sys->current = (cell_t **) forth_wordlist; g_sys->context = (cell_t ***) g_sys->heap; g_sys->latestxt = 0; - *g_sys->heap++ = (cell_t) forth_wordlist; - for (int i = 0; i < VOCABULARY_DEPTH; ++i) { *g_sys->heap++ = 0; } + COMMA(forth_wordlist); + for (int i = 0; i < VOCABULARY_DEPTH; ++i) { COMMA(0); } // Setup boot text. g_sys->boot = src; @@ -259,7 +258,7 @@ static void forth_init(int argc, char *argv[], #define V(name) \ create(#name "-builtins", sizeof(#name "-builtins") - 1, \ BUILTIN_FORK, g_sys->DOCREATE_OP); \ - *g_sys->heap++ = VOC_ ## name; + COMMA(VOC_ ## name); VOCABULARY_LIST #undef V g_sys->latestxt = 0; // So last builtin doesn't get wrong size. @@ -271,9 +270,9 @@ static void forth_init(int argc, char *argv[], // Init code. cell_t *start = g_sys->heap; - *g_sys->heap++ = FIND("EVALUATE1"); - *g_sys->heap++ = FIND("BRANCH"); - *g_sys->heap++ = (cell_t) start; + COMMA(FIND("EVALUATE1")); + COMMA(FIND("BRANCH")); + COMMA(start); g_sys->argc = argc; g_sys->argv = argv; diff --git a/common/opcodes.h b/common/opcodes.h index 346c556..06fc55e 100644 --- a/common/opcodes.h +++ b/common/opcodes.h @@ -46,7 +46,7 @@ typedef uintptr_t ucell_t; (void *) *((cell_t *) xt) == ADDROF(DODOES) ? 2 : 1)) #ifndef COMMA -# define COMMA(n) *g_sys->heap++ = (n) +# define COMMA(n) *g_sys->heap++ = (cell_t) (n) # define CCOMMA(n) *(uint8_t *) g_sys->heap = (n); \ g_sys->heap = (cell_t *) (1 + ((cell_t) g_sys->heap)); # define DOES(ip) **g_sys->current = (cell_t) ADDROF(DODOES); (*g_sys->current)[1] = (cell_t) ip diff --git a/web/dump_web_opcodes.c b/web/dump_web_opcodes.c index 2113eaf..30965f0 100644 --- a/web/dump_web_opcodes.c +++ b/web/dump_web_opcodes.c @@ -58,12 +58,12 @@ int main(int argc, char *argv[]) { #undef Z } else if (argc == 2 && strcmp(argv[1], "dict") == 0) { #define V(name) \ - printf(" create(\"" #name "-builtins\", %d);\n", BUILTIN_FORK, OP_DOCREATE); \ - printf(" comma(%d);\n", VOC_ ## name); + printf(" Create(\"" #name "-builtins\", %d);\n", BUILTIN_FORK, OP_DOCREATE); \ + printf(" COMMA(%d);\n", VOC_ ## name); VOCABULARY_LIST #undef V #define Z(flags, name, op, code) \ - printf(" builtin(" #name ", %d, %d, %d);\n", \ + printf(" Builtin(" #name ", %d, %d, %d);\n", \ ((VOC_ ## flags >> 8) & 0xff) | BUILTIN_MARK, \ (VOC_ ## flags & 0xff), OP_ ## op); PLATFORM_OPCODE_LIST diff --git a/web/web.template.js b/web/web.template.js index 16331ed..56c67f8 100644 --- a/web/web.template.js +++ b/web/web.template.js @@ -20,11 +20,18 @@ const HEAP_SIZE = (1024 * 1024); const STACK_CELLS = 4096; const VOCABULARY_DEPTH = 16; +const IMMEDIATE = 1; +const SMUDGE = 2; +const BUILTIN_FORK = 4; +const BUILTIN_MARK = 8; + {{boot}} var heap = new ArrayBuffer(HEAP_SIZE); var i32 = new Int32Array(heap); +var u16 = new Uint16Array(heap); var u8 = new Uint8Array(heap); +var builtins = []; var objects = [SetEval]; {{sys}} @@ -68,55 +75,126 @@ function Same(a, b) { return true; } -function GetName(xt) { - var clen = i32[(xt - 3*4)>>2]; +function GetString(a, n) { var ret = ''; - for (var i = 0; i < clen; ++i) { - ret += String.fromCharCode(u8[xt - 3 * 4 - clen + i]); + for (var i = 0; i < n; ++i) { + ret += String.fromCharCode(u8[a + i]); } return ret; } + +function CELL_ALIGNED(n) { return (n + 3) & ~3; } + +function TOFLAGS(xt) { return xt - 4; } +function TONAMELEN(xt) { return xt + 1; } +function TOPARAMS(xt) { return TOFLAGS(xt) + 2; } +function TOSIZE(xt) { return CELL_ALIGNED(u8[TONAMELEN(xt)>>2]) + 4 * i32[TOPARAMS(xt)>>2]; } +function TOLINK(xt) { return xt - 2; } +function TONAME(xt) { + return (i32[TOFLAGS(xt)] & BUILTIN_MARK) + ? u8[TOLINK(xt)] : TOLINK(xt) - CELL_ALIGNED(u8[TONAMELEN(xt)]); +} +function TOBODY(xt) { + return xt + (i32[xt>>2] === OP_DOCREATE || i32[xt>>2] === OP_DODOES ? 2 : 1); +} + +function BUILTIN_ITEM(i) { + return i32[g_sys_builtins>>2] + 4 * 3 * i; +} +function BUILTIN_NAME(i) { + return i32[(BUILTIN_ITEM(i) + 0 * 4)>>2]; +} +function BUILTIN_FLAGS(i) { + return u8[BUILTIN_ITEM(i) + 1 * 4 + 0]; +} +function BUILTIN_NAMELEN(i) { + return i32[BUILTIN_ITEM(i) + 1 * 4 + 1]; +} +function BUILTIN_VOCAB(i) { + return u16[(BUILTIN_ITEM(i) + 1 * 4 + 2)>>1]; +} +function BUILTIN_CODE(i) { + return BUILTIN_ITEM(i) + 2 * 4; +} + function Find(name) { - var pos = i32[i32[g_sys_context>>2]>>2]; - while (pos) { - if (Same(GetName(pos), name)) { - return pos; + for (var voc = i32[g_sys_context>>2]; i32[voc>>2]; voc += 4) { + var xt = i32[i32[voc>>2]>>2]; + while (xt) { + if (u8[TOFLAGS(xt)] & BUILTIN_FORK) { + var vocab = i32[(TOLINK(xt) + 4 * 3)>>2]; + for (var i = 0; BUILTIN_NAME(i); ++i) { + if (BUILTIN_VOCAB(i) === vocab && + name.length === BUILTIN_NAMELEN(i) && + name === GetString(BUILTIN_NAME(i), name.length)) { + return BUILTIN_CODE(i); + } + } + } + if (!(u8[TOFLAGS(xt)] & SMUDGE) && + name.length === u8[TONAMELEN(xt)] && + name === GetString(TONAME(xt), name.length)) { + return xt; + } + xt = i32[TOLINK(xt)>>2]; } - pos = i32[(pos - 2*4)>>2]; } return 0; } -function comma(value) { +function COMMA(value) { i32[i32[g_sys_heap>>2]>>2] = value; - i32[g_sys_heap>>2] = (i32[g_sys_heap>>2] + 4) | 0; + i32[g_sys_heap>>2] += 4; } -function create(name, flags, opcode) { +function CCOMMA(value) { + u8[i32[g_sys_heap>>2]>>2] = value; + i32[g_sys_heap>>2]++; +} + +function Finish() { + // TODO +} + +function Create(name, flags, op) { + Finish(); + i32[g_sys_heap>>2] = CELL_ALIGNED(i32[g_sys_heap>>2]); i32[g_sys_heap>>2] = Load(i32[g_sys_heap>>2], name); // name - i32[g_sys_heap>>2] = (i32[g_sys_heap>>2] + 3) & ~3; - - i32[i32[g_sys_heap>>2]>>2] = name.length; // length - i32[g_sys_heap>>2] += 4; - - i32[i32[g_sys_heap>>2]>>2] = i32[i32[i32[g_sys_current]>>2]>>2]; // link - i32[g_sys_heap>>2] += 4; - - i32[i32[g_sys_heap>>2]>>2] = 0; // flags - i32[g_sys_heap>>2] += 4; - + i32[g_sys_heap>>2] = CELL_ALIGNED(i32[g_sys_heap>>2]); + COMMA(i32[i32[g_sys_current>>2]>>2]); // link + COMMA((name.length << 8) | flags); // flags & length i32[i32[g_sys_current>>2]>>2] = i32[g_sys_heap>>2]; - - i32[i32[i32[g_sys_current>>2]>>2]>>2] = opcode; // code - i32[g_sys_heap>>2] += 4; + i32[g_sys_latestxt>>2] = i32[g_sys_heap>>2]; + COMMA(op); } -function builtin(name, flags, vocab, opcode) { +function Builtin(name, flags, vocab, opcode) { + builtins.push([name, flags | BUILTIN_MARK, vocab, opcode]); +} + +function SetupBuiltins() { + for (var i = 0; i < builtins.length; ++i) { + var name = builtins[i][0]; + builtins[i][0] = i32[g_sys_heap>>2]; + i32[g_sys_heap>>2] = Load(i32[g_sys_heap>>2], name); // name + i32[g_sys_heap>>2] = CELL_ALIGNED(i32[g_sys_heap>>2]); + builtins[i][1] |= (name.length << 8); + } + i32[g_sys_builtins>>2] = i32[g_sys_heap>>2]; + for (var i = 0; i < builtins.length; ++i) { + COMMA(builtins[i][0]); + COMMA(builtins[i][1] | (builtins[i][2] << 16)); + COMMA(builtins[i][3]); + } + COMMA(0); + COMMA(0); + COMMA(0); } function InitDictionary() { {{dict}} + SetupBuiltins(); } function Init() { @@ -135,13 +213,13 @@ function Init() { // FORTH worldlist (relocated when vocabularies added). var forth_wordlist = i32[g_sys_heap>>2]; - comma(0); + COMMA(0); // Vocabulary stack. i32[g_sys_current>>2] = forth_wordlist; i32[g_sys_context>>2] = i32[g_sys_heap>>2]; i32[g_sys_latestxt>>2] = 0; - comma(forth_wordlist); - for (var i = 0; i < VOCABULARY_DEPTH; ++i) { comma(0); } + COMMA(forth_wordlist); + for (var i = 0; i < VOCABULARY_DEPTH; ++i) { COMMA(0); } // setup boot text. var source = g_sys_heap; @@ -160,9 +238,9 @@ function Init() { // Init code. var start = i32[g_sys_heap>>2]; - comma(Find("EVALUATE1")); - comma(Find("BRANCH")); - comma(start); + COMMA(Find("EVALUATE1")); + COMMA(Find("BRANCH")); + COMMA(start); i32[g_sys_argc>>2] = 0; i32[g_sys_argv>>2] = 0; @@ -170,10 +248,10 @@ function Init() { i32[g_sys_tib>>2] = source; i32[g_sys_ntib>>2] = source_len; - i32[rp>>2] = fp; rp += 4; - i32[rp>>2] = sp; rp += 4; - i32[rp>>2] = start; rp += 4; - i32[g_sys_rp] = rp; + rp += 4; i32[rp>>2] = fp; + rp += 4; i32[rp>>2] = sp; + rp += 4; i32[rp>>2] = start; + i32[g_sys_rp>>2] = rp; } function VM(stdlib, foreign, heap) { @@ -257,8 +335,8 @@ var ffi = { Call: Call, create: function() { console.log('create'); }, parse: function() { console.log('parse'); }, - COMMA: function(n) { i32[i32[g_sys_heap>>2]] = n; i32[g_sys_heap>>2] += 4; console.log('comma'); }, - CCOMMA: function(n) { u8[i32[g_sys_heap>>2]] = n; i32[g_sys_heap>>2] += 1; console.log('ccomma'); }, + COMMA: function(n) { COMMA(n); }, + CCOMMA: function(n) { COMMA(n); }, SSMOD: function() { console.log('ssmod'); }, DOES: function() { console.log('does'); }, DOIMMEDIATE: function() { console.log('immediate'); },