use switch for std functions (instead of array, for better performance (?))

This commit is contained in:
ProgramSnail 2025-03-03 01:15:07 +03:00
parent f50e1fe7c5
commit 044b0ccae0
3 changed files with 199 additions and 55 deletions

View file

@ -127,7 +127,7 @@ void LprintfPerror(char *s, ...);
void Bmatch_failure(void *v, char *fname, aint line, aint col); void Bmatch_failure(void *v, char *fname, aint line, aint col);
void * /*Lstrcat*/ Li__Infix_4343(void *a, void *b); extern void * /*Lstrcat*/ Li__Infix_4343(aint *args /* void *a, void *b */);
void *Lsprintf(char *fmt, ...); void *Lsprintf(char *fmt, ...);
void *LgetEnv(char *var); void *LgetEnv(char *var);

View file

@ -37,6 +37,8 @@ static inline void **s_nth(size_t n) {
return (void **)__gc_stack_top + n; return (void **)__gc_stack_top + n;
} }
static inline aint *s_nth_i(size_t n) { return (aint *)s_nth(n); }
static inline void **s_peek() { static inline void **s_peek() {
#ifndef WITH_CHECK #ifndef WITH_CHECK
if ((void **)__gc_stack_top == s_top()) { if ((void **)__gc_stack_top == s_top()) {

View file

@ -440,58 +440,208 @@ BUILTIN id_by_builtin(const char *name) {
} }
void run_stdlib_func(BUILTIN id, size_t args_count) { void run_stdlib_func(BUILTIN id, size_t args_count) {
static const StdFunc std_func[] = { void *ret = NULL;
{.ptr = (void (*)()) & Luppercase, .args_count = 1}, // TODO: deal with right pointers, etc.
{.ptr = (void (*)()) & Llowercase, .args_count = 1}, switch (id) {
{.ptr = (void (*)()) & Lassert, .args_count = 2, .is_vararg = true}, case BUILTIN_Luppercase:
{.ptr = (void (*)()) & Lstring, .args_count = 1, .is_args = true}, ret = (void *)Luppercase(*s_nth(0));
{.ptr = (void (*)()) & Llength, .args_count = 1}, s_popn(1);
{.ptr = (void (*)()) & LstringInt, .args_count = 1}, s_push(ret);
{.ptr = (void (*)()) & Lread, .args_count = 0}, break;
{.ptr = (void (*)()) & Lwrite, .args_count = 1}, case BUILTIN_Llowercase:
{.ptr = (void (*)()) & LmakeArray, .args_count = 1}, ret = (void *)Llowercase(*s_nth(0));
{.ptr = (void (*)()) & LmakeString, .args_count = 1}, s_popn(1);
{.ptr = (void (*)()) & Lstringcat, .args_count = 1, .is_args = true}, s_push(ret);
{.ptr = (void (*)()) & LmatchSubString, .args_count = 3}, break;
{.ptr = (void (*)()) & Lsprintf, .args_count = 1, .is_vararg = true}, case BUILTIN_Lassert:
{.ptr = (void (*)()) & Lsubstring, .args_count = 3, .is_args = true}, // .args_count = 2, .is_vararg = true
{.ptr = (void (*)()) & Li__Infix_4343, call_anyarg_func<20>((void (*)()) & Lassert, args_count);
.args_count = 2, break;
.is_args = true}, // ++ case BUILTIN_Lstring:
{.ptr = (void (*)()) & Lclone, .args_count = 1, .is_args = true}, ret = Lstring(s_nth_i(0)); // .is_args = true
{.ptr = (void (*)()) & Lhash, .args_count = 1}, s_popn(1);
{.ptr = (void (*)()) & LtagHash, .args_count = 1}, s_push(ret);
{.ptr = (void (*)()) & Lcompare, .args_count = 2}, break;
{.ptr = (void (*)()) & LflatCompare, .args_count = 2}, case BUILTIN_Llength:
{.ptr = (void (*)()) & Lfst, .args_count = 1}, ret = (void *)Llength(*s_nth(0));
{.ptr = (void (*)()) & Lsnd, .args_count = 1}, s_popn(1);
{.ptr = (void (*)()) & Lhd, .args_count = 1}, s_push(ret);
{.ptr = (void (*)()) & Ltl, .args_count = 1}, break;
{.ptr = (void (*)()) & LreadLine, .args_count = 0}, case BUILTIN_LstringInt:
{.ptr = (void (*)()) & Lprintf, .args_count = 1, .is_vararg = true}, ret = (void *)LstringInt((char *)*s_nth(0));
{.ptr = (void (*)()) & Lfopen, .args_count = 2}, s_popn(1);
{.ptr = (void (*)()) & Lfclose, .args_count = 1}, s_push(ret);
{.ptr = (void (*)()) & Lfread, .args_count = 1}, break;
{.ptr = (void (*)()) & Lfwrite, .args_count = 2}, case BUILTIN_Lread:
{.ptr = (void (*)()) & Lfexists, .args_count = 1}, ret = (void *)Lread();
{.ptr = (void (*)()) & Lfprintf, .args_count = 2, .is_vararg = true}, s_push(ret);
{.ptr = (void (*)()) & Lregexp, .args_count = 1}, break;
{.ptr = (void (*)()) & LregexpMatch, .args_count = 3}, case BUILTIN_Lwrite:
{.ptr = (void (*)()) & Lfailure, .args_count = 1, .is_vararg = true}, ret = (void *)Lwrite(*s_nth_i(0));
{.ptr = (void (*)()) & Lsystem, .args_count = 1}, s_popn(1);
{.ptr = (void (*)()) & LgetEnv, .args_count = 1}, s_push(ret);
{.ptr = (void (*)()) & Lrandom, .args_count = 1}, break;
{.ptr = (void (*)()) & Ltime, .args_count = 0}, case BUILTIN_LmakeArray:
}; ret = (void *)LmakeArray(*s_nth_i(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_LmakeString:
ret = (void *)LmakeString(*s_nth_i(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_Lstringcat:
ret = (void *)Lstringcat(s_nth_i(0)); // .is_args = true;
s_popn(1);
s_push(ret);
break;
case BUILTIN_LmatchSubString:
ret = (void *)LmatchSubString((char *)*s_nth(0), (char *)*s_nth(1),
*s_nth_i(2));
s_popn(3);
s_push(ret);
break;
case BUILTIN_Lsprintf:
// .args_count = 1, .is_vararg = true
call_anyarg_func<20>((void (*)()) & Lsprintf, args_count);
break;
case BUILTIN_Lsubstring:
ret = (void *)Lsubstring(s_nth_i(0)); // .is_args = true;
s_popn(3);
s_push(ret);
break;
case BUILTIN_Li__Infix_4343:
ret = (void *)Li__Infix_4343(s_nth_i(0)); // .is_args = true
s_popn(2);
s_push(ret);
break; // ++
case BUILTIN_Lclone:
ret = (void *)Lclone(s_nth_i(0)); // .is_args = true;
s_popn(1);
s_push(ret);
break;
case BUILTIN_Lhash:
ret = (void *)Lhash(*s_nth(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_LtagHash:
ret = (void *)LtagHash((char *)*s_nth(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_Lcompare:
ret = (void *)Lcompare(*s_nth(0), *s_nth(1));
s_popn(2);
s_push(ret);
break;
case BUILTIN_LflatCompare:
ret = (void *)LflatCompare(*s_nth(0), *s_nth(1));
s_popn(2);
s_push(ret);
break;
case BUILTIN_Lfst:
ret = (void *)Lfst(*s_nth(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_Lsnd:
ret = (void *)Lsnd(*s_nth(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_Lhd:
ret = (void *)Lhd(*s_nth(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_Ltl:
ret = (void *)Ltl(*s_nth(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_LreadLine:
ret = (void *)LreadLine();
s_push(ret);
break;
case BUILTIN_Lprintf:
// .args_count = 1, .is_vararg = true
call_anyarg_func<20>((void (*)()) & Lprintf, args_count);
break;
case BUILTIN_Lfopen:
ret = (void *)Lfopen((char *)*s_nth(0), (char *)*s_nth(1));
s_popn(2);
s_push(ret);
break;
case BUILTIN_Lfclose:
/*ret = (void *)*/ Lfclose((FILE *)*s_nth(0));
s_popn(1);
// s_push(ret); // NOTE: ??
break;
case BUILTIN_Lfread:
ret = (void *)Lfread((char *)*s_nth(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_Lfwrite:
/*ret = (void *)*/ Lfwrite((char *)*s_nth(0), (char *)*s_nth(1));
s_popn(2);
// s_push(ret); // NOTE: ??
break;
case BUILTIN_Lfexists:
ret = (void *)Lfexists((char *)*s_nth(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_Lfprintf:
// .args_count = 2, .is_vararg = true
call_anyarg_func<20>((void (*)()) & Lfprintf, args_count);
break;
case BUILTIN_Lregexp:
ret = (void *)Lregexp((char *)*s_nth(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_LregexpMatch:
ret = (void *)LregexpMatch((struct re_pattern_buffer *)*s_nth(0),
(char *)*s_nth(1), *s_nth_i(2));
s_popn(2);
s_push(ret);
break;
case BUILTIN_Lfailure:
// .args_count = 1, .is_vararg = true
call_anyarg_func<20>((void (*)()) & Lfailure, args_count);
break;
case BUILTIN_Lsystem:
ret = (void *)Lsystem((char *)*s_nth(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_LgetEnv:
ret = (void *)LgetEnv((char *)*s_nth(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_Lrandom:
ret = (void *)Lrandom(*s_nth_i(0));
s_popn(1);
s_push(ret);
break;
case BUILTIN_Ltime:
ret = (void *)Ltime();
s_push(ret);
break;
default:
failure("RUNTIME ERROR: stdlib function <%u> not found\n", id);
break;
}
// some functions do use on args pointer // some functions do use on args pointer
// // NOTE: is checked on subst // // NOTE: is checked on subst
// if (id > sizeof(std_func) / sizeof(StdFunc)) { // if (id > sizeof(std_func) / sizeof(StdFunc)) {
// failure("RUNTIME ERROR: stdlib function <%u> not found\n", id); // failure("RUNTIME ERROR: stdlib function <%u> not found\n", id);
// } // }
const auto &func = std_func[id];
// // TODO: move to bytecode verifier // // TODO: move to bytecode verifier
// if ((!func.is_vararg && func.args_count != args_count) || // if ((!func.is_vararg && func.args_count != args_count) ||
// func.args_count > args_count) { // func.args_count > args_count) {
@ -500,12 +650,4 @@ void run_stdlib_func(BUILTIN id, size_t args_count) {
// "expected (expected is <%s%zu>)\n", // "expected (expected is <%s%zu>)\n",
// id, func.args_count, func.is_vararg ? ">=" : "=", args_count); // id, func.args_count, func.is_vararg ? ">=" : "=", args_count);
// } // }
if (func.is_args) {
void *ret = ((void *(*)(aint *))func.ptr)((aint *)s_peek());
s_popn(func.args_count);
s_push(ret);
} else {
call_anyarg_func<20>(func.ptr, args_count);
}
} }