From 48229571ba953fca38797030eea5e3175072276a Mon Sep 17 00:00:00 2001 From: dzaima Date: Wed, 26 May 2021 16:34:36 +0300 Subject: [PATCH] proper bytecode rewriting --- src/core/stuff.h | 2 +- src/h.h | 1 + src/vm.c | 74 ++++++++++++++++++++++++++++++++---------------- src/vm.h | 4 +-- 4 files changed, 53 insertions(+), 28 deletions(-) diff --git a/src/core/stuff.h b/src/core/stuff.h index 128c8438..a2113163 100644 --- a/src/core/stuff.h +++ b/src/core/stuff.h @@ -45,7 +45,7 @@ typedef struct TStack { usz cap; u8 data[]; } TStack; -#define TSALLOC(T,N) u32 N##_e=sizeof(T); TStack* N##_o = (TStack*)mm_allocN(sizeof(TStack)+N##_e*2, t_temp); N##_o->size=0; N##_o->cap=2; T* N = (T*)N##_o->data; +#define TSALLOC(T,N,I) usz N##_dc=(I); u32 N##_e=sizeof(T); TStack* N##_o = (TStack*)mm_allocN(sizeof(TStack)+N##_e*N##_dc, t_temp); N##_o->size=0; N##_o->cap=N##_dc; T* N = (T*)N##_o->data; #define TSFREE(N) mm_free((Value*)N##_o); #define TSADD(N,X) { if (N##_o->size==N##_o->cap) { N##_o = tstack_ext(N##_o, N##_e); N = (void*)N##_o->data; } N[N##_o->size++] = X; } #define TSSIZE(N) (N##_o->size) diff --git a/src/h.h b/src/h.h index bc18ff2f..7ea1b70e 100644 --- a/src/h.h +++ b/src/h.h @@ -81,6 +81,7 @@ #define AUTO __auto_type #define LIKELY(X) __builtin_expect(X,1) #define RARE(X) __builtin_expect(X,0) +#define RFLD(X,T,F) ((T*)((char*)(X) - offsetof(T,F))) // reverse-read field: `T* x = …; E v = x->f; x == RFLD(v, T, f)` typedef u32 usz; typedef u8 ur; diff --git a/src/vm.c b/src/vm.c index b605ac79..8306048d 100644 --- a/src/vm.c +++ b/src/vm.c @@ -127,53 +127,77 @@ Block* compileBlock(B block, Comp* comp, bool* bDone, i32* bc, usz bcIA, B block bool imm = o2b(bgetU(block,1)); usz idx = o2s(bgetU(block,2)); if (idx>=bcIA) thrM("VM compiler: Bytecode index out of bounds"); usz vam = o2s(bgetU(block,3)); if (vam!=(u16)vam) thrM("VM compiler: >2⋆16 variables not supported"); // TODO any reason for this? 2⋆32 vars should just work, no? - i32* thisBC = bc+idx; i32 h = 0; // stack height i32 hM = 0; // max stack height i32 mpsc = 0; - i32* c = thisBC; - TSALLOC(Block*,nBlT); + TSALLOC(Block*, nBlT, 2); + TSALLOC(i32, nBCT, 20); + TSALLOC(i32, mapT, 20); + i32* c = bc+idx; while (true) { i32* n = nextBC(c); - if (n-thisBC-1 >= bcIA) thrM("VM compiler: No RETN/RETD found before end of bytecode"); + if (n-bc-1 >= bcIA) thrM("VM compiler: No RETN/RETD found before end of bytecode"); + bool ret = false; switch (*c) { case RETN: if(h!=1) thrM("VM compiler: Wrong stack size before RETN"); - goto returned; + TSADD(nBCT, RETN); + ret = true; + break; case RETD: if(h!=1&h!=0) thrM("VM compiler: Wrong stack size before RETD"); - goto returned; - case DFND: + if (h==1) TSADD(nBCT, POPS); + TSADD(nBCT, RETD); + ret = true; + break; + case DFND: { u32 id = c[1]; if ((u32)id >= a(blocks)->ia) thrM("VM compiler: DFND index out-of-bounds"); if (bDone[id]) thrM("VM compiler: DFND of the same block in multiple places"); bDone[id] = true; - c[1] = TSSIZE(nBlT); + TSADD(nBCT, DFND); + TSADD(nBCT, TSSIZE(nBlT)); TSADD(nBlT, compileBlock(TI(blocks).getU(blocks,id), comp, bDone, bc, bcIA, blocks, nameList, sc, depth+1)); break; - case LOCO: case LOCM: case LOCU: + } + case LOCO: case LOCM: case LOCU: { if (c[1]>mpsc) mpsc = c[1]; + TSADD(nBCT, c[0]); + TSADD(nBCT, c[1]); + TSADD(nBCT, c[2]); break; - default: + } + default: { + i32* ccpy = c; + while (ccpy!=n) TSADD(nBCT, *ccpy++); break; + } } + usz nlen = TSSIZE(nBCT)-TSSIZE(mapT); + for (usz i = 0; i < nlen; i++) TSADD(mapT, c-bc); h+= stackDiff(c); if (h<0) thrM("VM compiler: Stack size goes negative"); if (h>hM) hM = h; + if (ret) break; c = n; - } returned:; - u64 blC = TSSIZE(nBlT); + } + + if (mpsc>U16_MAX) thrM("VM compiler: LOC_ too deep"); + + usz blC = TSSIZE(nBlT); BlBlocks* nBl = mm_allocN(fsizeof(BlBlocks,a,Block*,blC), t_blBlocks); nBl->am = blC; memcpy(nBl->a, nBlT, blC*sizeof(Block*)); TSFREE(nBlT); - if (mpsc>U16_MAX) thrM("VM compiler: LOC_ too deep"); + + usz nbcC = TSSIZE(nBCT); i32* nbc; m_i32arrv(&nbc, nbcC); memcpy(nbc, nBCT, nbcC*4); TSFREE(nBCT); + usz mapC = TSSIZE(mapT); i32* map; m_i32arrv(&map, mapC); memcpy(map, mapT, mapC*4); TSFREE(mapT); Body* body = mm_allocN(fsizeof(Body,varIDs,i32,vam), t_body); body->comp = comp; ptr_inc(comp); - body->bc = thisBC; + body->bc = nbc; + body->map = map; body->blocks = nBl; body->maxStack = hM; body->maxPSC = (u16)mpsc; - body->endStack = h; body->varAm = (u16)vam; if (cIA==4) { body->nsDesc = NULL; @@ -292,6 +316,7 @@ i32 bcDepth=-2; i32* vmStack; i32 bcCtr = 0; #endif +#define BCPOS(B,P) (B->map[P-B->bc]) B evalBC(Body* b, Scope* sc) { // doesn't consume #ifdef DEBUG_VM bcDepth+= 2; @@ -329,7 +354,7 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume while(true) { #ifdef DEBUG_VM i32* sbc = bc; - i32 bcPos = sbc-c(I32Arr,b->comp->bc)->a; + i32 bcPos = BCPOS(b,sbc); vmStack[stackNum] = bcPos; for(i32 i = 0; i < bcDepth; i++) printf(" "); printBC(sbc); printf("@%d << ", bcPos); @@ -432,7 +457,6 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume break; } case RETD: { - if (b->endStack) dec(POP); ptr_inc(sc); ptr_inc(b->nsDesc); ADD(m_ns(sc, b->nsDesc)); @@ -456,7 +480,7 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume } #ifdef DEBUG_VM for(i32 i = 0; i < bcDepth; i++) printf(" "); - printBC(sbc); printf("@%ld: ", sbc-c(I32Arr,b->comp->bc)->a); + printBC(sbc); printf("@%ld: ", BCPOS(b, sbc)); for (i32 i = 0; i < b->maxStack; i++) { if(i)printf(" ⋄ "); print(gStack[i]); } putchar('\n'); fflush(stdout); #endif } @@ -546,7 +570,7 @@ void scope_free(Value* x) { for (u32 i = 0; i < am; i++) dec(c->vars[i]); } void comp_free(Value* x) { Comp* c = (Comp *)x; ptr_decR(c->objs); decR(c->bc); decR(c->src); decR(c->indices); } -void body_free(Value* x) { Body* c = (Body *)x; ptr_decR(c->comp); if(c->nsDesc)ptr_decR(c->nsDesc); ptr_decR(c->blocks); } +void body_free(Value* x) { Body* c = (Body *)x; ptr_decR(c->comp); if(c->nsDesc)ptr_decR(c->nsDesc); ptr_decR(c->blocks); ptr_decR(RFLD(c->bc,I32Arr,a)); ptr_decR(RFLD(c->map,I32Arr,a)); } void block_free(Value* x) { Block* c = (Block *)x; ptr_decR(c->body); } void funBl_free(Value* x) { FunBlock* c = (FunBlock*)x; ptr_decR(c->sc); ptr_decR(c->bl); } void md1Bl_free(Value* x) { Md1Block* c = (Md1Block*)x; ptr_decR(c->sc); ptr_decR(c->bl); } @@ -562,7 +586,7 @@ void scope_visit(Value* x) { for (u32 i = 0; i < am; i++) mm_visit(c->vars[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); } -void body_visit(Value* x) { Body* c = (Body *)x; mm_visitP(c->comp); if(c->nsDesc)mm_visitP(c->nsDesc); mm_visitP(c->blocks); } +void body_visit(Value* x) { Body* c = (Body *)x; mm_visitP(c->comp); if(c->nsDesc)mm_visitP(c->nsDesc); mm_visitP(c->blocks); mm_visitP(RFLD(c->bc,I32Arr,a)); mm_visitP(RFLD(c->map,I32Arr,a)); } void block_visit(Value* x) { Block* c = (Block *)x; mm_visitP(c->body); } 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); } @@ -580,9 +604,9 @@ void bBlks_print(B x) { printf("(block list)"); } // void funBl_print(B x) { printf("(%p: function"" block bl=%p sc=%p)",v(x),c(FunBlock,x)->bl,c(FunBlock,x)->sc); } // void md1Bl_print(B x) { printf("(%p: 1-modifier block bl=%p sc=%p)",v(x),c(Md1Block,x)->bl,c(Md1Block,x)->sc); } // void md2Bl_print(B x) { printf("(%p: 2-modifier block bl=%p sc=%p)",v(x),c(Md2Block,x)->bl,c(Md2Block,x)->sc); } -void funBl_print(B x) { printf("(function"" block @%ld)",c(FunBlock,x)->bl->body->bc-c(I32Arr,c(FunBlock,x)->bl->body->comp->bc)->a); } -void md1Bl_print(B x) { printf("(1-modifier block @%ld)",c(Md1Block,x)->bl->body->bc-c(I32Arr,c(Md1Block,x)->bl->body->comp->bc)->a); } -void md2Bl_print(B x) { printf("(2-modifier block @%ld)",c(Md2Block,x)->bl->body->bc-c(I32Arr,c(Md2Block,x)->bl->body->comp->bc)->a); } +void funBl_print(B x) { printf("(function"" block @%d)",c(FunBlock,x)->bl->body->map[0]); } +void md1Bl_print(B x) { printf("(1-modifier block @%d)",c(Md1Block,x)->bl->body->map[0]); } +void md2Bl_print(B x) { printf("(2-modifier block @%d)",c(Md2Block,x)->bl->body->map[0]); } // void funBl_print(B x) { printf("{function""}"); } // void md1Bl_print(B x) { printf("{1-modifier}"); } // void md2Bl_print(B x) { printf("{2-modifier}"); } @@ -697,7 +721,7 @@ NOINLINE void vm_pst(Env* s, Env* e) { i = 10; } Comp* comp = c->sc->body->comp; - i32 bcPos = c>=envStart && cbcL - i32arr_ptr(comp->bc) : c->bcV; + i32 bcPos = c>=envStart && csc->body, c->bcL) : c->bcV; vm_printPos(comp, bcPos, i); i--; } @@ -710,7 +734,7 @@ static void unwindEnv(Env* envNew) { assert(envNew<=envCurr); while (envCurr!=envNew) { envCurr--; - envCurr->bcV = envCurr->bcL - i32arr_ptr(envCurr->sc->body->comp->bc); + envCurr->bcV = BCPOS(envCurr->sc->body, envCurr->bcL); } } diff --git a/src/vm.h b/src/vm.h index 2c1b6389..f154df9e 100644 --- a/src/vm.h +++ b/src/vm.h @@ -34,11 +34,11 @@ struct Body { Comp* comp; BlBlocks* blocks; // B* objs; - i32* bc; // pointer in comp->bc + i32* bc; // pointer in an owned I32Arr + i32* map; // pointer in an owned I32Arr u32 maxStack; u16 maxPSC; u16 varAm; - u32 endStack; NSDesc* nsDesc; i32 varIDs[]; };