Inline doubles and interned string pointers in the byte code.

Avoid linearly searched per function string and number tables.
This commit is contained in:
Tor Andersson
2021-03-26 12:58:34 +01:00
parent 06a6f9fb11
commit 33ffe6efeb
5 changed files with 62 additions and 59 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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:

2
jsgc.c
View File

@@ -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);

47
jsrun.c
View File

@@ -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);