From 33ffe6efebf477ee1f73c27670af460ffd6cc08d Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Fri, 26 Mar 2021 12:58:34 +0100 Subject: [PATCH] Inline doubles and interned string pointers in the byte code. Avoid linearly searched per function string and number tables. --- jscompile.c | 47 +++++++++++++++-------------------------------- jscompile.h | 6 ------ jsdump.c | 19 ++++++++++++++----- jsgc.c | 2 -- jsrun.c | 47 +++++++++++++++++++++++++++++++++-------------- 5 files changed, 62 insertions(+), 59 deletions(-) diff --git a/jscompile.c b/jscompile.c index 333dffa..dcdee05 100644 --- a/jscompile.c +++ b/jscompile.c @@ -110,34 +110,6 @@ static int addfunction(JF, js_Function *value) return F->funlen++; } -static int addnumber(JF, double value) -{ - int i; - for (i = 0; i < F->numlen; ++i) - if (F->numtab[i] == value) - return i; - if (F->numlen >= F->numcap) { - F->numcap = F->numcap ? F->numcap * 2 : 16; - F->numtab = js_realloc(J, F->numtab, F->numcap * sizeof *F->numtab); - } - F->numtab[F->numlen] = value; - return F->numlen++; -} - -static int addstring(JF, const char *value) -{ - int i; - for (i = 0; i < F->strlen; ++i) - if (!strcmp(F->strtab[i], value)) - return i; - if (F->strlen >= F->strcap) { - F->strcap = F->strcap ? F->strcap * 2 : 16; - F->strtab = js_realloc(J, F->strtab, F->strcap * sizeof *F->strtab); - } - F->strtab[F->strlen] = value; - return F->strlen++; -} - static int addlocal(JF, js_Ast *ident, int reuse) { const char *name = ident->string; @@ -196,15 +168,27 @@ static void emitnumber(JF, double num) emit(J, F, OP_INTEGER); emitarg(J, F, num + 32768); } else { +#define N (sizeof(num) / sizeof(js_Instruction)) + js_Instruction x[N]; + size_t i; emit(J, F, OP_NUMBER); - emitarg(J, F, addnumber(J, F, num)); + memcpy(x, &num, sizeof(num)); + for (i = 0; i < N; ++i) + emitarg(J, F, x[i]); +#undef N } } static void emitstring(JF, int opcode, const char *str) { +#define N (sizeof(str) / sizeof(js_Instruction)) + js_Instruction x[N]; + size_t i; emit(J, F, opcode); - emitarg(J, F, addstring(J, F, str)); + memcpy(x, &str, sizeof(str)); + for (i = 0; i < N; ++i) + emitarg(J, F, x[i]); +#undef N } static void emitlocal(JF, int oploc, int opvar, js_Ast *ident) @@ -623,8 +607,7 @@ static void cexp(JF, js_Ast *exp) case EXP_REGEXP: emitline(J, F, exp); - emit(J, F, OP_NEWREGEXP); - emitarg(J, F, addstring(J, F, exp->string)); + emitstring(J, F, OP_NEWREGEXP, exp->string); emitarg(J, F, exp->number); break; diff --git a/jscompile.h b/jscompile.h index 5338322..716a98f 100644 --- a/jscompile.h +++ b/jscompile.h @@ -123,12 +123,6 @@ struct js_Function js_Function **funtab; int funcap, funlen; - double *numtab; - int numcap, numlen; - - const char **strtab; - int strcap, strlen; - const char **vartab; int varcap, varlen; diff --git a/jsdump.c b/jsdump.c index fe3defc..af5ed3b 100644 --- a/jsdump.c +++ b/jsdump.c @@ -781,6 +781,8 @@ void jsC_dumpfunction(js_State *J, js_Function *F) { js_Instruction *p = F->code; js_Instruction *end = F->code + F->codelen; + char *s; + double n; int i; minify = 0; @@ -807,16 +809,21 @@ void jsC_dumpfunction(js_State *J, js_Function *F) printf(" %ld", (long)((*p++) - 32768)); break; case OP_NUMBER: - printf(" %.9g", F->numtab[*p++]); + memcpy(&n, p, sizeof(n)); + p += sizeof(n) / sizeof(*p); + printf(" %.9g", n); break; case OP_STRING: + memcpy(&s, p, sizeof(s)); + p += sizeof(s) / sizeof(*p); pc(' '); - pstr(F->strtab[*p++]); + pstr(s); break; case OP_NEWREGEXP: pc(' '); - pregexp(F->strtab[p[0]], p[1]); - p += 2; + memcpy(&s, p, sizeof(s)); + p += sizeof(s) / sizeof(*p); + pregexp(s, *p++); break; case OP_GETVAR: @@ -827,8 +834,10 @@ void jsC_dumpfunction(js_State *J, js_Function *F) case OP_SETPROP_S: case OP_DELPROP_S: case OP_CATCH: + memcpy(&s, p, sizeof(s)); + p += sizeof(s) / sizeof(*p); pc(' '); - ps(F->strtab[*p++]); + ps(s); break; case OP_GETLOCAL: diff --git a/jsgc.c b/jsgc.c index 079b8a6..3b65bdf 100644 --- a/jsgc.c +++ b/jsgc.c @@ -13,8 +13,6 @@ static void jsG_freeenvironment(js_State *J, js_Environment *env) static void jsG_freefunction(js_State *J, js_Function *fun) { js_free(J, fun->funtab); - js_free(J, fun->numtab); - js_free(J, fun->strtab); js_free(J, fun->vartab); js_free(J, fun->code); js_free(J, fun); diff --git a/jsrun.c b/jsrun.c index c418e39..49ab5b6 100644 --- a/jsrun.c +++ b/jsrun.c @@ -1314,8 +1314,6 @@ void js_trap(js_State *J, int pc) static void jsR_run(js_State *J, js_Function *F) { js_Function **FT = F->funtab; - double *NT = F->numtab; - const char **ST = F->strtab; const char **VT = F->vartab-1; int lightweight = F->lightweight; js_Instruction *pcstart = F->code; @@ -1335,6 +1333,10 @@ static void jsR_run(js_State *J, js_Function *F) savestrict = J->strict; J->strict = F->strict; +#define READSTRING() \ + memcpy(&str, pc, sizeof(str)); \ + pc += sizeof(str) / sizeof(*pc) + while (1) { if (J->gccounter > J->gcthresh) js_gc(J, 0); @@ -1351,14 +1353,28 @@ static void jsR_run(js_State *J, js_Function *F) case OP_ROT3: js_rot3(J); break; case OP_ROT4: js_rot4(J); break; - case OP_INTEGER: js_pushnumber(J, *pc++ - 32768); break; - case OP_NUMBER: js_pushnumber(J, NT[*pc++]); break; - case OP_STRING: js_pushliteral(J, ST[*pc++]); break; + case OP_INTEGER: + js_pushnumber(J, *pc++ - 32768); + break; + + case OP_NUMBER: + memcpy(&x, pc, sizeof(x)); + pc += sizeof(x) / sizeof(*pc); + js_pushnumber(J, x); + break; + + case OP_STRING: + READSTRING(); + js_pushliteral(J, str); + break; case OP_CLOSURE: js_newfunction(J, FT[*pc++], J->E); break; case OP_NEWOBJECT: js_newobject(J); break; case OP_NEWARRAY: js_newarray(J); break; - case OP_NEWREGEXP: js_newregexp(J, ST[pc[0]], pc[1]); pc += 2; break; + case OP_NEWREGEXP: + READSTRING(); + js_newregexp(J, str, *pc++); + break; case OP_UNDEF: js_pushundefined(J); break; case OP_NULL: js_pushnull(J); break; @@ -1410,22 +1426,25 @@ static void jsR_run(js_State *J, js_Function *F) break; case OP_GETVAR: - str = ST[*pc++]; + READSTRING(); if (!js_hasvar(J, str)) js_referenceerror(J, "'%s' is not defined", str); break; case OP_HASVAR: - if (!js_hasvar(J, ST[*pc++])) + READSTRING(); + if (!js_hasvar(J, str)) js_pushundefined(J); break; case OP_SETVAR: - js_setvar(J, ST[*pc++]); + READSTRING(); + js_setvar(J, str); break; case OP_DELVAR: - b = js_delvar(J, ST[*pc++]); + READSTRING(); + b = js_delvar(J, str); js_pushboolean(J, b); break; @@ -1471,7 +1490,7 @@ static void jsR_run(js_State *J, js_Function *F) break; case OP_GETPROP_S: - str = ST[*pc++]; + READSTRING(); obj = js_toobject(J, -1); jsR_getproperty(J, obj, str); js_rot2pop1(J); @@ -1486,7 +1505,7 @@ static void jsR_run(js_State *J, js_Function *F) break; case OP_SETPROP_S: - str = ST[*pc++]; + READSTRING(); obj = js_toobject(J, -2); transient = !js_isobject(J, -2); jsR_setproperty(J, obj, str, transient); @@ -1502,7 +1521,7 @@ static void jsR_run(js_State *J, js_Function *F) break; case OP_DELPROP_S: - str = ST[*pc++]; + READSTRING(); obj = js_toobject(J, -1); b = jsR_delproperty(J, obj, str); js_pop(J, 1); @@ -1738,7 +1757,7 @@ static void jsR_run(js_State *J, js_Function *F) break; case OP_CATCH: - str = ST[*pc++]; + READSTRING(); obj = jsV_newobject(J, JS_COBJECT, NULL); js_pushobject(J, obj); js_rot2(J);