From f70a8c558c4cbe355899b8df375fa7b507d0040e Mon Sep 17 00:00:00 2001 From: dzaima Date: Fri, 7 May 2021 21:51:54 +0300 Subject: [PATCH] option to not allow reallocating stack with no benefits currently, whatever --- src/h.h | 6 ++-- src/main.c | 3 -- src/mm_2buddy.c | 5 ---- src/mm_buddy.c | 5 ---- src/stuff.c | 9 ++++++ src/vm.c | 75 ++++++++++++++++++++++++++++++++++++------------- 6 files changed, 67 insertions(+), 36 deletions(-) diff --git a/src/h.h b/src/h.h index 8ba02dd9..1ea7b66d 100644 --- a/src/h.h +++ b/src/h.h @@ -85,9 +85,9 @@ enum ElType { // a⌈b shall return the type that can store both, if possible char* format_type(u8 u) { switch(u) { default: return"(unknown type)"; case t_empty:return"empty"; case t_shape:return"shape"; - case t_funBI:return"fun_def"; case t_fun_block:return"fun_block"; - case t_md1BI:return"md1_def"; case t_md1_block:return"md1_block"; - case t_md2BI:return"md2_def"; case t_md2_block:return"md2_block"; + case t_funBI:return"builtin fun"; case t_fun_block:return"fun_block"; + case t_md1BI:return"builtin md1"; case t_md1_block:return"md1_block"; + case t_md2BI:return"builtin md2"; case t_md2_block:return"md2_block"; case t_fork:return"fork"; case t_atop:return"atop"; case t_md1D:return"md1D"; case t_md2D:return"md2D"; case t_md2H:return"md2H"; case t_harr :return"harr" ; case t_i32arr :return"i32arr" ; case t_fillarr :return"fillarr" ; case t_c32arr :return"c32arr" ; case t_f64arr :return"f64arr" ; diff --git a/src/main.c b/src/main.c index c71b9c87..f27b14fb 100644 --- a/src/main.c +++ b/src/main.c @@ -67,9 +67,6 @@ Block* ca3(B x) { return r; } -ssize_t getline(char** line, size_t* n, FILE* stream); - - int main() { hdr_init(); diff --git a/src/mm_2buddy.c b/src/mm_2buddy.c index f6ff4223..0f2a4762 100644 --- a/src/mm_2buddy.c +++ b/src/mm_2buddy.c @@ -1,10 +1,5 @@ #include "h.h" #include "gc.c" -#include - -#ifndef MAP_NORESERVE - #define MAP_NORESERVE 0 // apparently needed for freebsd or something -#endif typedef struct EmptyValue EmptyValue; struct EmptyValue { // needs set: mmInfo; type=t_empty; next; everything else can be garbage diff --git a/src/mm_buddy.c b/src/mm_buddy.c index 46d47987..084c7d72 100644 --- a/src/mm_buddy.c +++ b/src/mm_buddy.c @@ -1,10 +1,5 @@ #include "h.h" #include "gc.c" -#include - -#ifndef MAP_NORESERVE - #define MAP_NORESERVE 0 // apparently needed for freebsd or something -#endif typedef struct EmptyValue EmptyValue; struct EmptyValue { // needs set: mmInfo; type=t_empty; next; everything else can be garbage diff --git a/src/stuff.c b/src/stuff.c index a353f5c7..6336df01 100644 --- a/src/stuff.c +++ b/src/stuff.c @@ -1,6 +1,15 @@ #include "h.h" // a bunch of random things that don't really belong in any other file + +#include +#include + +#ifndef MAP_NORESERVE + #define MAP_NORESERVE 0 // apparently needed for freebsd or something +#endif + + void arr_print(B x) { // should accept refc=0 arguments for debugging purposes ur r = rnk(x); BS2B xgetU = TI(x).getU; diff --git a/src/vm.c b/src/vm.c index 3b435741..5cde5068 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1,5 +1,10 @@ #include "h.h" +// #define GS_REALLOC // whether to dynamically realloc gStack +#ifndef GS_SIZE +#define GS_SIZE 16384 // if !GS_REALLOC, size in number of B objects of the global object stack +#endif + enum { PUSH = 0, // N; push object from objs[N] VARO = 1, // N; push variable with name strs[N] @@ -257,18 +262,29 @@ B* gStackStart; B* gStackEnd; void gsReserve(u64 am) { - u64 left = gStackEnd-gStack; - if (am>left) { - u64 n = gStackEnd-gStackStart + am + 500; - u64 d = gStack-gStackStart; - gStackStart = realloc(gStackStart, n*sizeof(B)); - gStack = gStackStart+d; - gStackEnd = gStackStart+n; - } + #ifdef GS_REALLOC + if (am>gStackEnd-gStack) { + u64 n = gStackEnd-gStackStart + am + 500; + u64 d = gStack-gStackStart; + gStackStart = realloc(gStackStart, n*sizeof(B)); + gStack = gStackStart+d; + gStackEnd = gStackStart+n; + } + #elif DEBUG + if (am>gStackEnd-gStack) err("stack overflow"); + #endif } -NOINLINE void gsReserveR(u64 am) { gsReserve(am); } +#ifdef GS_REALLOC +NOINLINE +#endif +void gsReserveR(u64 am) { gsReserve(am); } + void gsAdd(B x) { - if (gStack==gStackEnd) gsReserveR(1); + #ifdef GS_REALLOC + if (gStack==gStackEnd) gsReserveR(1); + #elif DEBUG + if (gStack==gStackEnd) err("early stack overflow"); + #endif *(gStack++) = x; } B gsPop() { @@ -289,11 +305,18 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume Scope* pscs[b->maxPSC+1]; pscs[0] = sc; for (i32 i = 0; i < b->maxPSC; i++) pscs[i+1] = pscs[i]->psc; - - #define POP (*--gStack) - #define P(N) B N=POP; - #define ADD(X) { B tr=X; *(gStack++) = tr; } // if ordering is needed - // #define ADD(X) *(gStack++) = X; } // if ordering is not needed + #ifdef GS_REALLOC + #define POP (*--gStack) + #define P(N) B N=POP; + #define ADD(X) { B tr=X; *(gStack++) = tr; } + #define GS_UPD + #else + B* lgStack = gStack; + #define POP (*--lgStack) + #define P(N) B N=POP; + #define ADD(X) { *(lgStack++) = X; } + #define GS_UPD { gStack = lgStack; } + #endif while(true) { #ifdef DEBUG_VM @@ -313,18 +336,22 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume break; } case FN1C: { P(f)P(x) + GS_UPD; ADD(c1(f, x); dec(f)); break; } case FN1O: { P(f)P(x) + GS_UPD; ADD(isNothing(x)? x : c1(f, x)); dec(f); break; } case FN2C: { P(w)P(f)P(x) + GS_UPD; ADD(c2(f, w, x); dec(f)); break; } case FN2O: { P(w)P(f)P(x) + GS_UPD; if (isNothing(x)) { dec(w); ADD(x); } else ADD(isNothing(w)? c1(f, x) : c2(f, w, x)); dec(f); @@ -339,6 +366,7 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume break; } case DFND: { + GS_UPD; Block* bl = blocks[*bc++]; switch(bl->ty) { default: UD; case 0: ADD(m_funBlock(bl, sc)); break; @@ -347,11 +375,11 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume } break; } - case OP1D: { P(f)P(m) ADD(m1_d (m,f )); break; } - case OP2D: { P(f)P(m)P(g) ADD(m2_d (m,f,g)); break; } - case OP2H: { P(m)P(g) ADD(m2_h (m, g)); break; } - case TR2D: { P(g)P(h) ADD(m_atop( g,h)); break; } - case TR3D: { P(f)P(g)P(h) ADD(m_fork(f,g,h)); break; } + case OP1D: { P(f)P(m) GS_UPD; ADD(m1_d (m,f )); break; } + case OP2D: { P(f)P(m)P(g) GS_UPD; ADD(m2_d (m,f,g)); break; } + case OP2H: { P(m)P(g) ADD(m2_h (m, g)); break; } + case TR2D: { P(g)P(h) ADD(m_atop( g,h)); break; } + case TR3D: { P(f)P(g)P(h) ADD(m_fork(f,g,h)); break; } case TR3O: { P(f)P(g)P(h) if (isNothing(f)) { ADD(m_atop(g,h)); dec(f); } else ADD(m_fork(f,g,h)); @@ -517,6 +545,13 @@ static inline void comp_init() { ti[t_fun_block].free = funBl_free; ti[t_fun_block].visit = funBl_visit; ti[t_fun_block].print = funBl_print; ti[t_fun_block].decompose = block_decompose; ti[t_md1_block].free = md1Bl_free; ti[t_md1_block].visit = md1Bl_visit; ti[t_md1_block].print = md1Bl_print; ti[t_md1_block].decompose = block_decompose; ti[t_md1_block].m1_d=bl_m1d; ti[t_md2_block].free = md2Bl_free; ti[t_md2_block].visit = md2Bl_visit; ti[t_md2_block].print = md2Bl_print; ti[t_md2_block].decompose = block_decompose; ti[t_md2_block].m2_d=bl_m2d; + #ifndef GS_REALLOC + usz pageSize = sysconf(_SC_PAGESIZE); + u64 sz = (GS_SIZE + pageSize-1)/pageSize * pageSize; + gStack = gStackStart = mmap(NULL, sz*sizeof(B)+pageSize, PROT_READ|PROT_WRITE, MAP_NORESERVE|MAP_PRIVATE|MAP_ANON, -1, 0); + gStackEnd = gStackStart+sz; + mprotect(gStackEnd, pageSize, PROT_NONE); // idk first way i found to force erroring on overflow + #endif } void print_vmStack() {