From ef5864afbc1353901b469f7b4273c5a0ea21db3b Mon Sep 17 00:00:00 2001 From: dzaima Date: Mon, 29 Nov 2021 00:21:41 +0200 Subject: [PATCH] global name list --- src/builtins/fns.c | 32 +++++++++- src/jit/nvm_x86_64.c | 2 +- src/load.c | 13 ++-- src/ns.c | 140 ++++++++++++++++++------------------------- src/ns.h | 17 +++--- src/vm.c | 31 +++++----- src/vm.h | 5 +- 7 files changed, 125 insertions(+), 115 deletions(-) diff --git a/src/builtins/fns.c b/src/builtins/fns.c index 51bd005f..42e8b763 100644 --- a/src/builtins/fns.c +++ b/src/builtins/fns.c @@ -309,7 +309,7 @@ B count_c2(B t, B w, B x) { return c2(rt_count, w, x); } -H_b2i* prevImports; +static H_b2i* prevImports; i32 getPrevImport(B path) { // -1 for unset, -2 for unfinished if (prevImports==NULL) prevImports = m_b2i(16); @@ -322,12 +322,38 @@ void setPrevImport(B path, i32 pos) { bool had; i32 prev = mk_b2i(&prevImports, path, &had); prevImports->a[prev].val = pos; } -void fun_gcFn() { - if (prevImports!=NULL) mm_visitP(prevImports); + +static H_b2i* globalNames; +static B globalNameList; +i32 str2gid(B s) { + if (globalNames==NULL) { + globalNames = m_b2i(32); + globalNameList = emptyHVec(); + } + bool had; + u64 p = mk_b2i(&globalNames, s, &had); + // if(had) print_fmt("str2gid %R → %i\n", s, globalNames->a[p].val); else print_fmt("str2gid %R → %i!!\n", s, a(globalNameList)->ia); + if(had) return globalNames->a[p].val; + + i32 r = a(globalNameList)->ia; + globalNameList = vec_add(globalNameList, inc(s)); + globalNames->a[p].val = r; + return r; +} + +B gid2str(i32 n) { + B r = IGetU(globalNameList, n); + // print_fmt("gid2str %i → %R", n, r); + return r; } +void fun_gcFn() { + if (prevImports!=NULL) mm_visitP(prevImports); + if (globalNames!=NULL) mm_visitP(globalNames); + mm_visit(globalNameList); +} void fns_init() { gc_addFn(fun_gcFn); TIi(t_funBI,print) = print_funBI; diff --git a/src/jit/nvm_x86_64.c b/src/jit/nvm_x86_64.c index 25ec0ebc..26966986 100644 --- a/src/jit/nvm_x86_64.c +++ b/src/jit/nvm_x86_64.c @@ -197,7 +197,7 @@ INS void i_SETMv(B f, B x, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c2(f,v_ge INS void i_SETCv(B f, Scope* sc, u32 p, u32* bc) { POS_UPD; B r = c1(f,v_getI(sc, p, false) ); dec(f); v_setI(sc, p, r, true, false); } INS B i_FLDO(B ns, u32 p, Scope* sc) { if (!isNsp(ns)) thrM("Trying to read a field from non-namespace"); - B r = inc(ns_getU(ns, sc->body->nsDesc->nameList, p)); + B r = inc(ns_getU(ns, p)); dec(ns); return r; } diff --git a/src/load.c b/src/load.c index 0fa292f9..f507df23 100644 --- a/src/load.c +++ b/src/load.c @@ -175,11 +175,14 @@ NOINLINE Block* bqn_compSc(B str, B path, B args, Scope* sc, bool repl) { // con i32 depth = repl? -1 : 0; Scope* csc = sc; while (csc) { - for (u64 i = 0; i < csc->varAm; i++) { - i32 nameID = csc->body->varIDs[i]; - B nl = csc->body->nsDesc->nameList; - vName = vec_add(vName, IGet(nl, nameID)); - vDepth = vec_add(vDepth, m_i32(depth)); + Body* body = csc->body; + if (csc->varAm) { + B nameList = body->bl->comp->nameList; SGetU(nameList); + for (u64 i = 0; i < csc->varAm; i++) { + i32 nameID = body->varData[i + body->varAm]; + vName = vec_add(vName, inc(GetU(nameList, nameID))); + vDepth = vec_add(vDepth, m_i32(depth)); + } } if (csc->ext) for (u64 i = 0; i < csc->ext->varAm; i++) { vName = vec_add(vName, inc(csc->ext->vars[i+csc->ext->varAm])); diff --git a/src/ns.c b/src/ns.c index 0594673b..d6cbbc07 100644 --- a/src/ns.c +++ b/src/ns.c @@ -2,109 +2,91 @@ #include "ns.h" #include "utils/mut.h" -void m_nsDesc(Body* body, bool imm, u8 ty, B nameList, B varIDs, B exported) { // consumes nameList +void m_nsDesc(Body* body, bool imm, u8 ty, i32 actualVam, B nameList, B varIDs, B exported) { // doesn't consume nameList if (!isArr(varIDs) || !isArr(exported)) thrM("Bad namespace description information"); usz ia = a(varIDs)->ia; if (ia!=a(exported)->ia) thrM("Bad namespace description information"); i32 off = (ty==0?0:ty==1?2:3) + (imm?0:3); i32 vam = ia+off; - i32 actualVam = body->varAm; - // if (vam != body->varAm) thrM("Bad namespace description information"); // arg remapping makes body->varAm unrelated to named variable count - NSDesc* r = mm_alloc(fsizeof(NSDesc, expIDs, i32, actualVam), t_nsDesc); - r->nameList = nameList; + NSDesc* r = mm_alloc(fsizeof(NSDesc, expGIDs, i32, actualVam<2?2:actualVam), t_nsDesc); r->varAm = vam; SGetU(varIDs) SGetU(exported) for (i32 i = 0; i < actualVam; i++) { - body->varIDs[i] = -1; - r ->expIDs[i] = -1; + body->varData[i] = -1; + r ->expGIDs[i] = -1; + body->varData[i+actualVam] = -1; } + + SGetU(nameList) for (usz i = 0; i < ia; i++) { i32 cid = o2i(GetU(varIDs, i)); bool cexp = o2b(GetU(exported, i)); - body->varIDs[i+off] = cid; - r->expIDs[i+off] = cexp? cid : -1; + body->varData[i+off + actualVam] = cid; + r->expGIDs[i+off] = cexp? str2gid(GetU(nameList, cid)) : -1; } - // printf("def %p:\n", r); - // for (usz i = 0; i < vam; i++) printf(" %d: %d %d\n", i, body->varIDs[i], r->expIDs[i]); body->nsDesc = r; } B m_ns(Scope* sc, NSDesc* desc) { // consumes both NS* r = mm_alloc(sizeof(NS), t_ns); r->desc = desc; - r->nameList = r->desc->nameList; r->sc = sc; return tag(r,NSP_TAG); } -B ns_getU(B ns, B cNL, i32 nameID) { VTY(ns, t_ns); + +i32 pos2gid(Body* body, i32 pos) { + i32 gid = body->varData[pos]; + if (LIKELY(gid!=-1)) return gid; + + i32 nlIdx = body->varData[pos+body->varAm]; + if (nlIdx==-1) thrM("Cannot use special variable name as namespace key"); + return body->varData[pos] = str2gid(IGetU(body->bl->comp->nameList, nlIdx)); +} + + +B ns_getU(B ns, i32 gid) { VTY(ns, t_ns); NS* n = c(NS, ns); NSDesc* d = n->desc; - i32 dVarAm = d->varAm; - if (nameID<0) thrM("Cannot read key with special name"); - assert((u64)nameID < a(cNL)->ia); - B dNL = d->nameList; - if (cNL.u != dNL.u) { - B cName = IGetU(cNL, nameID); - SGetU(dNL) - for (i32 i = 0; i < dVarAm; i++) { - i32 dID = d->expIDs[i]; - if (dID>=0 && equal(GetU(dNL, dID), cName)) return n->sc->vars[i]; - } - } else { - for (i32 i = 0; i < dVarAm; i++) { - if (d->expIDs[i]==nameID) return n->sc->vars[i]; - } - } + + i32 ia = d->varAm; + for (i32 i = 0; i < ia; i++) if (d->expGIDs[i]==gid) return n->sc->vars[i]; thrM("No key found"); } -B ns_qgetU(B ns, B cNL, i32 nameID) { VTY(ns, t_ns); // TODO somehow merge impl with ns_getU + +B ns_qgetU(B ns, i32 gid) { VTY(ns, t_ns); NS* n = c(NS, ns); NSDesc* d = n->desc; - i32 dVarAm = d->varAm; - if (nameID<0) return bi_N; - assert((u64)nameID < a(cNL)->ia); - B dNL = d->nameList; - if (cNL.u != dNL.u) { - B cName = IGetU(cNL, nameID); - SGetU(dNL) - for (i32 i = 0; i < dVarAm; i++) { - i32 dID = d->expIDs[i]; - if (dID>=0 && equal(GetU(dNL, dID), cName)) return n->sc->vars[i]; - } - } else { - for (i32 i = 0; i < dVarAm; i++) { - if (d->expIDs[i]==nameID) return n->sc->vars[i]; - } - } + + i32 ia = d->varAm; + for (i32 i = 0; i < ia; i++) if (d->expGIDs[i]==gid) return n->sc->vars[i]; return bi_N; } + B ns_getNU(B ns, B name, bool thrEmpty) { VTY(ns, t_ns); NS* n = c(NS, ns); NSDesc* d = n->desc; - i32 dVarAm = d->varAm; - B dNL = d->nameList; - SGetU(dNL) - for (i32 i = 0; i < dVarAm; i++) { - i32 dID = d->expIDs[i]; - if (dID>=0 && equal(GetU(dNL, dID), name)) return n->sc->vars[i]; - } + i32 gid = str2gid(name); + + i32 ia = d->varAm; + for (i32 i = 0; i < ia; i++) if (d->expGIDs[i]==gid) return n->sc->vars[i]; if (thrEmpty) thrM("No key found"); return bi_N; } + void ns_set(B ns, B name, B val) { VTY(ns, t_ns); NS* n = c(NS, ns); + Scope* sc = n->sc; NSDesc* d = n->desc; - i32 dVarAm = d->varAm; - B dNL = d->nameList; - SGetU(dNL) - for (i32 i = 0; i < dVarAm; i++) { - i32 dID = d->expIDs[i]; - if (dID>=0 && equal(GetU(dNL, dID), name)) { - dec(n->sc->vars[i]); - n->sc->vars[i] = val; + i32 gid = str2gid(name); + + i32 ia = d->varAm; + for (i32 i = 0; i < ia; i++) { + if (d->expGIDs[i]==gid) { + dec(sc->vars[i]); + sc->vars[i] = val; return; } } @@ -112,20 +94,18 @@ void ns_set(B ns, B name, B val) { VTY(ns, t_ns); } i32 ns_pos(B ns, B name) { VTY(ns, t_ns); - Body* b = c(NS, ns)->sc->body; - B nameList = c(NS, ns)->desc->nameList; - i32 bVarAm = b->varAm; - SGetU(nameList) - for (i32 i = 0; i < bVarAm; i++) { - i32 id = b->varIDs[i]; - if (id>=0) if (equal(GetU(nameList, id), name)) { dec(name); return i; } + NS* n = c(NS, ns); + Body* body = n->sc->body; + B nameList = body->bl->comp->nameList; SGetU(nameList); + + i32 ia = body->varAm; + for (i32 i = 0; i < ia; i++) { + i32 pos = body->varData[i+ia]; + if (pos>=0 && equal(name, GetU(nameList, pos))) return i; } thrM("No key found"); } -B ns_nameList(NSDesc* d) { - return d->nameList; -} @@ -144,14 +124,13 @@ static void ns_print(B x) { NSDesc* desc = c(NS,x)->desc; Scope* sc = c(NS,x)->sc; i32 am = desc->varAm; - B nl = desc->nameList; SGetU(nl) bool first = true; for (i32 i = 0; i < am; i++) { - i32 id = desc->expIDs[i]; + i32 id = desc->expGIDs[i]; if (id>=0) { if (first) first=false; else printf(" ⋄ "); - printRaw(GetU(nl, id)); + printRaw(gid2str(id)); printf("⇐"); print(sc->vars[i]); } @@ -163,14 +142,13 @@ B nsFmt(B x) { // consumes ACHR('{'); NSDesc* desc = c(NS,x)->desc; i32 am = desc->varAm; - B nl = desc->nameList; SGetU(nl) bool first = true; for (i32 i = 0; i < am; i++) { - i32 id = desc->expIDs[i]; + i32 id = desc->expGIDs[i]; if (id>=0) { if (first) first=false; else ACHR(U'‿'); - AFMT("%R", GetU(nl, id)); + AFMT("%R", gid2str(id)); } } AU("⇐}"); @@ -178,15 +156,13 @@ B nsFmt(B x) { // consumes return s; } -DEF_FREE(nsDesc) { decR(((NSDesc*)x)->nameList); } -static void nsDesc_visit(Value* x) { mm_visit(((NSDesc*)x)->nameList); } static void nsDesc_print(B x) { printf("(namespace description)"); } void ns_init() { - TIi(t_ns,freeO) = ns_freeO; TIi(t_nsDesc,freeO) = nsDesc_freeO; - TIi(t_ns,freeF) = ns_freeF; TIi(t_nsDesc,freeF) = nsDesc_freeF; - TIi(t_ns,visit) = ns_visit; TIi(t_nsDesc,visit) = nsDesc_visit; + TIi(t_ns,freeO) = ns_freeO; + TIi(t_ns,freeF) = ns_freeF; + TIi(t_ns,visit) = ns_visit; TIi(t_nsDesc,visit) = noop_visit; TIi(t_ns,print) = ns_print; TIi(t_nsDesc,print) = nsDesc_print; } diff --git a/src/ns.h b/src/ns.h index b31023e2..7f070081 100644 --- a/src/ns.h +++ b/src/ns.h @@ -3,21 +3,24 @@ typedef struct NSDesc { struct Value; - B nameList; - i32 varAm; // number of items in expIDs (currently equal to sc->varAm/body->varAm) - i32 expIDs[]; // each item is an index in nameList (or -1), and its position is the corresponding position in sc->vars + i32 varAm; // number of items in expGIDs (currently equal to sc->varAm/body->varAm) + i32 expGIDs[]; // for each variable; -1 if not exported, otherwise a gid } NSDesc; typedef struct NS { struct Value; - B nameList; // copy of desc->nameList for quick checking; isn't owned NSDesc* desc; Scope* sc; } NS; -void m_nsDesc(Body* body, bool imm, u8 ty, B nameList, B varIDs, B exported); // consumes nameList +void m_nsDesc(Body* body, bool imm, u8 ty, i32 vam, B nameList, B varIDs, B exported); // doesn't consume nameList B m_ns(Scope* sc, NSDesc* desc); // consumes both -B ns_getU(B ns, B nameList, i32 nameID); // doesn't consume anything, doesn't increment result -B ns_qgetU(B ns, B nameList, i32 nameID); // ns_getU but return bi_N on fail + +B ns_getU(B ns, i32 gid); // doesn't consume, doesn't increment result +B ns_qgetU(B ns, i32 gid); // ns_getU but return bi_N on fail B ns_getNU(B ns, B name, bool thrEmpty); // doesn't consume anything, doesn't increment result; returns bi_N if doesn't exist and !thrEmpty void ns_set(B ns, B name, B val); // consumes val i32 ns_pos(B ns, B name); // consumes name; returns an index in sc->vars for any variable, exported or local + +i32 pos2gid(Body* body, i32 pos); // converts a variable position to a gid; errors on special name variables +i32 str2gid(B s); // doesn't consume +B gid2str(i32 n); // returns unowned object diff --git a/src/vm.c b/src/vm.c index 53f8c044..ebaad598 100644 --- a/src/vm.c +++ b/src/vm.c @@ -86,7 +86,7 @@ void print_gStack() { } static Body* m_body(i32 vam, i32 pos, u32 maxStack, u16 maxPSC) { // leaves varIDs and nsDesc uninitialized - Body* body = mm_alloc(fsizeof(Body,varIDs,i32,vam), t_body); + Body* body = mm_alloc(fsizeof(Body, varData, i32, vam*2), t_body); #if JIT_START != -1 body->nvm = NULL; @@ -309,6 +309,8 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B allBl TSADD(bodyReqs, ((NextRequest){.off = TSSIZE(newBC), .pos1 = pos1, .pos2 = imm? U32_MAX : pos2})); A64(0); if(!imm) A64(0); // to be filled in by later bodyReqs handling break; + case FLDO: TSADD(newBC, FLDO); TSADD(newBC, str2gid(IGetU(nameList, c[1]))); break; + case ALIM: TSADD(newBC, ALIM); TSADD(newBC, str2gid(IGetU(nameList, c[1]))); break; default: { u32* ccpy = c; while (ccpy!=n) TSADD(newBC, *ccpy++); @@ -327,12 +329,13 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, u32* bc, usz bcIA, B allBl if (mpsc>U16_MAX) thrM("VM compiler: Block too deep"); - Body* body = m_body(vam+(remapArgs? argAm : 0), bcStart, (u32)hM, mpsc); + i32 finalVam = vam+(remapArgs? argAm : 0); + Body* body = m_body(finalVam, bcStart, (u32)hM, mpsc); if (boIA>2) { - m_nsDesc(body, imm, ty, inc(nameList), GetU(bodyRepr,2), GetU(bodyRepr,3)); + m_nsDesc(body, imm, ty, finalVam, nameList, GetU(bodyRepr,2), GetU(bodyRepr,3)); } else { body->nsDesc = NULL; - for (u64 i = 0; i < vam; i++) body->varIDs[i] = -1; + for (u64 i = 0; i < vam*2; i++) body->varData[i] = -1; } if (is1) { bodyMap[pos1-1] = body; if (firstM) { firstM=false; startBodies[i ] = body; if(i==0) firstMPos = TSSIZE(bodies); } } @@ -417,6 +420,8 @@ NOINLINE Block* compile(B bcq, B objs, B allBlocks, B allBodies, B indices, B to B t = IGetU(tokenInfo,2); nameList = IGetU(t,0); } + comp->nameList = inc(nameList); + if (!q_N(src) && !q_N(indices)) { if (isAtm(indices) || rnk(indices)!=1 || a(indices)->ia!=2) thrM("VM compiler: Bad indices"); for (i32 i = 0; i < 2; i++) { @@ -456,16 +461,14 @@ NOINLINE void v_setR(Scope* pscs[], B s, B x, bool upd) { B c = sp[i]; if (isVar(c)) { Scope* sc = pscs[(u16)(c.u>>32)]; - i32 nameID = sc->body->varIDs[(u32)c.u]; - v_set(pscs, c, ns_getU(x, sc->body->nsDesc->nameList, nameID), upd, true); + v_set(pscs, c, ns_getU(x, pos2gid(sc->body, (u32)c.u)), upd, true); } else if (isExt(c)) { ScopeExt* ext = pscs[(u16)(c.u>>32)]->ext; v_set(pscs, c, ns_getNU(x, ext->vars[(u32)c.u + ext->varAm], true), upd, true); } else if (isObj(c)) { assert(v(c)->type == t_fldAlias); - Scope* sc = pscs[0]; FldAlias* cf = c(FldAlias,c); - v_set(pscs, cf->obj, ns_getU(x, sc->body->nsDesc->nameList, cf->p), upd, true); + v_set(pscs, cf->obj, ns_getU(x, cf->p), upd, true); } else thrM("Assignment: extracting non-name from namespace"); } return; @@ -486,14 +489,12 @@ NOINLINE bool v_sethR(Scope* pscs[], B s, B x) { B c = sp[i]; if (isVar(c)) { Scope* sc = pscs[(u16)(c.u>>32)]; - i32 nameID = sc->body->varIDs[(u32)c.u]; - B g = ns_qgetU(x, sc->body->nsDesc->nameList, nameID); + B g = ns_qgetU(x, pos2gid(sc->body, (u32)c.u)); if (q_N(g) || !v_seth(pscs, c, g)) return false; } else if (isObj(c) && v(c)->type==t_fldAlias) { assert(v(c)->type == t_fldAlias); - Scope* sc = pscs[0]; FldAlias* cf = c(FldAlias,c); - B g = ns_qgetU(x, sc->body->nsDesc->nameList, cf->p); + B g = ns_qgetU(x, cf->p); if (q_N(g) || !v_seth(pscs, cf->obj, g)) return false; } else return false; } @@ -730,7 +731,7 @@ B evalBC(Block* bl, Body* b, Scope* sc) { // doesn't consume case FLDO: { P(ns) GS_UPD; u32 p = *bc++; POS_UPD; if (!isNsp(ns)) thrM("Trying to read a field from non-namespace"); - ADD(inc(ns_getU(ns, sc->body->nsDesc->nameList, p))); + ADD(inc(ns_getU(ns, p))); dec(ns); break; } @@ -875,7 +876,7 @@ DEF_FREE(block) { i32 am = c->bodyCount; for (i32 i = 0; i < am; i++) ptr_decR(c->bodies[i]); } -DEF_FREE(comp) { Comp* c = (Comp *)x; ptr_decR(c->objs); decR(c->bc); decR(c->src); decR(c->indices); decR(c->path); } +DEF_FREE(comp) { Comp* c = (Comp *)x; ptr_decR(c->objs); decR(c->bc); decR(c->src); decR(c->indices); decR(c->path); decR(c->nameList); } DEF_FREE(funBl) { FunBlock* c = (FunBlock*)x; ptr_dec(c->sc); ptr_decR(c->bl); } DEF_FREE(md1Bl) { Md1Block* c = (Md1Block*)x; ptr_dec(c->sc); ptr_decR(c->bl); } DEF_FREE(md2Bl) { Md2Block* c = (Md2Block*)x; ptr_dec(c->sc); ptr_decR(c->bl); } @@ -908,7 +909,7 @@ void block_visit(Value* x) { i32 am = c->bodyCount; for (i32 i = 0; i < am; i++) mm_visitP(c->bodies[i]); } -void comp_visit(Value* x) { Comp* c = (Comp *)x; mm_visitP(c->objs); mm_visit(c->bc); mm_visit(c->src); mm_visit(c->indices); mm_visit(c->path); } +void comp_visit(Value* x) { Comp* c = (Comp *)x; mm_visitP(c->objs); mm_visit(c->bc); mm_visit(c->src); mm_visit(c->indices); mm_visit(c->path); mm_visit(c->nameList); } void funBl_visit(Value* x) { FunBlock* c = (FunBlock*)x; mm_visitP(c->sc); mm_visitP(c->bl); } void md1Bl_visit(Value* x) { Md1Block* c = (Md1Block*)x; mm_visitP(c->sc); mm_visitP(c->bl); } void md2Bl_visit(Value* x) { Md2Block* c = (Md2Block*)x; mm_visitP(c->sc); mm_visitP(c->bl); } diff --git a/src/vm.h b/src/vm.h index 1d754e3e..fb5abe9c 100644 --- a/src/vm.h +++ b/src/vm.h @@ -75,6 +75,7 @@ typedef struct Comp { B src; B path; B indices; + B nameList; HArr* objs; u32 blockAm; } Comp; @@ -121,13 +122,13 @@ struct Body { Block* bl; // non-owned pointer to corresponding block NSDesc* nsDesc; u16 varAm; - i32 varIDs[]; + i32 varData[]; // length varAm*2; first half is a gid per var (or -1 if not calculated yet), second half is indexes into nameList }; struct ScopeExt { struct Value; u16 varAm; - B vars[]; // vars has length varAm*2; position varAm and onwards are corresponding names to variables at regular indexes + B vars[]; // has length varAm*2; position varAm and onwards are corresponding names to variables at regular indexes }; struct Scope {