mirror of
https://github.com/ccxvii/mujs.git
synced 2026-02-05 17:29:43 +08:00
Inline doubles and interned string pointers in the byte code.
Avoid linearly searched per function string and number tables.
This commit is contained in:
47
jscompile.c
47
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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
19
jsdump.c
19
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:
|
||||
|
||||
2
jsgc.c
2
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);
|
||||
|
||||
47
jsrun.c
47
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);
|
||||
|
||||
Reference in New Issue
Block a user