Avoid linearly searched per function string and number tables.
Unified · Split
| @@ -110,34 +110,6 @@ static int addfunction(JF, js_Function *value) · 109 unmodified lines | ||
| 110 | 110 | return F->funlen++; |
| 111 | 111 | } |
| 112 | 112 | |
| 113 | −static int addnumber(JF, double value) | |
| 114 | −{ | |
| 115 | − int i; | |
| 116 | − for (i = 0; i < F->numlen; ++i) | |
| 117 | − if (F->numtab[i] == value) | |
| 118 | − return i; | |
| 119 | − if (F->numlen >= F->numcap) { | |
| 120 | − F->numcap = F->numcap ? F->numcap * 2 : 16; | |
| 121 | − F->numtab = js_realloc(J, F->numtab, F->numcap * sizeof *F->numtab); | |
| 122 | − } | |
| 123 | − F->numtab[F->numlen] = value; | |
| 124 | − return F->numlen++; | |
| 125 | −} | |
| 126 | − | |
| 127 | −static int addstring(JF, const char *value) | |
| 128 | −{ | |
| 129 | − int i; | |
| 130 | − for (i = 0; i < F->strlen; ++i) | |
| 131 | − if (!strcmp(F->strtab[i], value)) | |
| 132 | − return i; | |
| 133 | − if (F->strlen >= F->strcap) { | |
| 134 | − F->strcap = F->strcap ? F->strcap * 2 : 16; | |
| 135 | − F->strtab = js_realloc(J, F->strtab, F->strcap * sizeof *F->strtab); | |
| 136 | − } | |
| 137 | − F->strtab[F->strlen] = value; | |
| 138 | − return F->strlen++; | |
| 139 | −} | |
| 140 | − | |
| 141 | 113 | static int addlocal(JF, js_Ast *ident, int reuse) |
| 142 | 114 | { |
| 143 | 115 | const char *name = ident->string; |
| @@ -196,15 +168,27 @@ static void emitnumber(JF, double num) · 52 unmodified lines | ||
| 196 | 168 | emit(J, F, OP_INTEGER); |
| 197 | 169 | emitarg(J, F, num + 32768); |
| 198 | 170 | } else { |
| 171 | +#define N (sizeof(num) / sizeof(js_Instruction)) | |
| 172 | + js_Instruction x[N]; | |
| 173 | + size_t i; | |
| 199 | 174 | emit(J, F, OP_NUMBER); |
| 200 | − emitarg(J, F, addnumber(J, F, num)); | |
| 175 | + memcpy(x, &num, sizeof(num)); | |
| 176 | + for (i = 0; i < N; ++i) | |
| 177 | + emitarg(J, F, x[i]); | |
| 178 | +#undef N | |
| 201 | 179 | } |
| 202 | 180 | } |
| 203 | 181 | |
| 204 | 182 | static void emitstring(JF, int opcode, const char *str) |
| 205 | 183 | { |
| 184 | +#define N (sizeof(str) / sizeof(js_Instruction)) | |
| 185 | + js_Instruction x[N]; | |
| 186 | + size_t i; | |
| 206 | 187 | emit(J, F, opcode); |
| 207 | − emitarg(J, F, addstring(J, F, str)); | |
| 188 | + memcpy(x, &str, sizeof(str)); | |
| 189 | + for (i = 0; i < N; ++i) | |
| 190 | + emitarg(J, F, x[i]); | |
| 191 | +#undef N | |
| 208 | 192 | } |
| 209 | 193 | |
| 210 | 194 | static void emitlocal(JF, int oploc, int opvar, js_Ast *ident) |
| @@ -623,8 +607,7 @@ static void cexp(JF, js_Ast *exp) · 412 unmodified lines | ||
| 623 | 607 | |
| 624 | 608 | case EXP_REGEXP: |
| 625 | 609 | emitline(J, F, exp); |
| 626 | − emit(J, F, OP_NEWREGEXP); | |
| 627 | − emitarg(J, F, addstring(J, F, exp->string)); | |
| 610 | + emitstring(J, F, OP_NEWREGEXP, exp->string); | |
| 628 | 611 | emitarg(J, F, exp->number); |
| 629 | 612 | break; |
| 630 | 613 | |
| @@ -123,12 +123,6 @@ struct js_Function · 122 unmodified lines | ||
| 123 | 123 | js_Function **funtab; |
| 124 | 124 | int funcap, funlen; |
| 125 | 125 | |
| 126 | − double *numtab; | |
| 127 | − int numcap, numlen; | |
| 128 | − | |
| 129 | − const char **strtab; | |
| 130 | − int strcap, strlen; | |
| 131 | − | |
| 132 | 126 | const char **vartab; |
| 133 | 127 | int varcap, varlen; |
| 134 | 128 | |
| @@ -781,6 +781,8 @@ void jsC_dumpfunction(js_State *J, js_Function *F) · 780 unmodified lines | ||
| 781 | 781 | { |
| 782 | 782 | js_Instruction *p = F->code; |
| 783 | 783 | js_Instruction *end = F->code + F->codelen; |
| 784 | + char *s; | |
| 785 | + double n; | |
| 784 | 786 | int i; |
| 785 | 787 | |
| 786 | 788 | minify = 0; |
| @@ -807,16 +809,21 @@ void jsC_dumpfunction(js_State *J, js_Function *F) · 20 unmodified lines | ||
| 807 | 809 | printf(" %ld", (long)((*p++) - 32768)); |
| 808 | 810 | break; |
| 809 | 811 | case OP_NUMBER: |
| 810 | − printf(" %.9g", F->numtab[*p++]); | |
| 812 | + memcpy(&n, p, sizeof(n)); | |
| 813 | + p += sizeof(n) / sizeof(*p); | |
| 814 | + printf(" %.9g", n); | |
| 811 | 815 | break; |
| 812 | 816 | case OP_STRING: |
| 817 | + memcpy(&s, p, sizeof(s)); | |
| 818 | + p += sizeof(s) / sizeof(*p); | |
| 813 | 819 | pc(' '); |
| 814 | − pstr(F->strtab[*p++]); | |
| 820 | + pstr(s); | |
| 815 | 821 | break; |
| 816 | 822 | case OP_NEWREGEXP: |
| 817 | 823 | pc(' '); |
| 818 | − pregexp(F->strtab[p[0]], p[1]); | |
| 819 | − p += 2; | |
| 824 | + memcpy(&s, p, sizeof(s)); | |
| 825 | + p += sizeof(s) / sizeof(*p); | |
| 826 | + pregexp(s, *p++); | |
| 820 | 827 | break; |
| 821 | 828 | |
| 822 | 829 | case OP_GETVAR: |
| @@ -827,8 +834,10 @@ void jsC_dumpfunction(js_State *J, js_Function *F) · 4 unmodified lines | ||
| 827 | 834 | case OP_SETPROP_S: |
| 828 | 835 | case OP_DELPROP_S: |
| 829 | 836 | case OP_CATCH: |
| 837 | + memcpy(&s, p, sizeof(s)); | |
| 838 | + p += sizeof(s) / sizeof(*p); | |
| 830 | 839 | pc(' '); |
| 831 | − ps(F->strtab[*p++]); | |
| 840 | + ps(s); | |
| 832 | 841 | break; |
| 833 | 842 | |
| 834 | 843 | case OP_GETLOCAL: |
| @@ -13,8 +13,6 @@ static void jsG_freeenvironment(js_State *J, js_Environment *env) · 12 unmodified lines | ||
| 13 | 13 | static void jsG_freefunction(js_State *J, js_Function *fun) |
| 14 | 14 | { |
| 15 | 15 | js_free(J, fun->funtab); |
| 16 | − js_free(J, fun->numtab); | |
| 17 | − js_free(J, fun->strtab); | |
| 18 | 16 | js_free(J, fun->vartab); |
| 19 | 17 | js_free(J, fun->code); |
| 20 | 18 | js_free(J, fun); |
| @@ -1314,8 +1314,6 @@ void js_trap(js_State *J, int pc) · 1313 unmodified lines | ||
| 1314 | 1314 | static void jsR_run(js_State *J, js_Function *F) |
| 1315 | 1315 | { |
| 1316 | 1316 | js_Function **FT = F->funtab; |
| 1317 | − double *NT = F->numtab; | |
| 1318 | − const char **ST = F->strtab; | |
| 1319 | 1317 | const char **VT = F->vartab-1; |
| 1320 | 1318 | int lightweight = F->lightweight; |
| 1321 | 1319 | js_Instruction *pcstart = F->code; |
| @@ -1335,6 +1333,10 @@ static void jsR_run(js_State *J, js_Function *F) · 13 unmodified lines | ||
| 1335 | 1333 | savestrict = J->strict; |
| 1336 | 1334 | J->strict = F->strict; |
| 1337 | 1335 | |
| 1336 | +#define READSTRING() \ | |
| 1337 | + memcpy(&str, pc, sizeof(str)); \ | |
| 1338 | + pc += sizeof(str) / sizeof(*pc) | |
| 1339 | + | |
| 1338 | 1340 | while (1) { |
| 1339 | 1341 | if (J->gccounter > J->gcthresh) |
| 1340 | 1342 | js_gc(J, 0); |
| @@ -1351,14 +1353,28 @@ static void jsR_run(js_State *J, js_Function *F) · 10 unmodified lines | ||
| 1351 | 1353 | case OP_ROT3: js_rot3(J); break; |
| 1352 | 1354 | case OP_ROT4: js_rot4(J); break; |
| 1353 | 1355 | |
| 1354 | − case OP_INTEGER: js_pushnumber(J, *pc++ - 32768); break; | |
| 1355 | − case OP_NUMBER: js_pushnumber(J, NT[*pc++]); break; | |
| 1356 | − case OP_STRING: js_pushliteral(J, ST[*pc++]); break; | |
| 1356 | + case OP_INTEGER: | |
| 1357 | + js_pushnumber(J, *pc++ - 32768); | |
| 1358 | + break; | |
| 1359 | + | |
| 1360 | + case OP_NUMBER: | |
| 1361 | + memcpy(&x, pc, sizeof(x)); | |
| 1362 | + pc += sizeof(x) / sizeof(*pc); | |
| 1363 | + js_pushnumber(J, x); | |
| 1364 | + break; | |
| 1365 | + | |
| 1366 | + case OP_STRING: | |
| 1367 | + READSTRING(); | |
| 1368 | + js_pushliteral(J, str); | |
| 1369 | + break; | |
| 1357 | 1370 | |
| 1358 | 1371 | case OP_CLOSURE: js_newfunction(J, FT[*pc++], J->E); break; |
| 1359 | 1372 | case OP_NEWOBJECT: js_newobject(J); break; |
| 1360 | 1373 | case OP_NEWARRAY: js_newarray(J); break; |
| 1361 | − case OP_NEWREGEXP: js_newregexp(J, ST[pc[0]], pc[1]); pc += 2; break; | |
| 1374 | + case OP_NEWREGEXP: | |
| 1375 | + READSTRING(); | |
| 1376 | + js_newregexp(J, str, *pc++); | |
| 1377 | + break; | |
| 1362 | 1378 | |
| 1363 | 1379 | case OP_UNDEF: js_pushundefined(J); break; |
| 1364 | 1380 | case OP_NULL: js_pushnull(J); break; |
| @@ -1410,22 +1426,25 @@ static void jsR_run(js_State *J, js_Function *F) · 45 unmodified lines | ||
| 1410 | 1426 | break; |
| 1411 | 1427 | |
| 1412 | 1428 | case OP_GETVAR: |
| 1413 | − str = ST[*pc++]; | |
| 1429 | + READSTRING(); | |
| 1414 | 1430 | if (!js_hasvar(J, str)) |
| 1415 | 1431 | js_referenceerror(J, "'%s' is not defined", str); |
| 1416 | 1432 | break; |
| 1417 | 1433 | |
| 1418 | 1434 | case OP_HASVAR: |
| 1419 | − if (!js_hasvar(J, ST[*pc++])) | |
| 1435 | + READSTRING(); | |
| 1436 | + if (!js_hasvar(J, str)) | |
| 1420 | 1437 | js_pushundefined(J); |
| 1421 | 1438 | break; |
| 1422 | 1439 | |
| 1423 | 1440 | case OP_SETVAR: |
| 1424 | − js_setvar(J, ST[*pc++]); | |
| 1441 | + READSTRING(); | |
| 1442 | + js_setvar(J, str); | |
| 1425 | 1443 | break; |
| 1426 | 1444 | |
| 1427 | 1445 | case OP_DELVAR: |
| 1428 | − b = js_delvar(J, ST[*pc++]); | |
| 1446 | + READSTRING(); | |
| 1447 | + b = js_delvar(J, str); | |
| 1429 | 1448 | js_pushboolean(J, b); |
| 1430 | 1449 | break; |
| 1431 | 1450 | |
| @@ -1471,7 +1490,7 @@ static void jsR_run(js_State *J, js_Function *F) · 39 unmodified lines | ||
| 1471 | 1490 | break; |
| 1472 | 1491 | |
| 1473 | 1492 | case OP_GETPROP_S: |
| 1474 | − str = ST[*pc++]; | |
| 1493 | + READSTRING(); | |
| 1475 | 1494 | obj = js_toobject(J, -1); |
| 1476 | 1495 | jsR_getproperty(J, obj, str); |
| 1477 | 1496 | js_rot2pop1(J); |
| @@ -1486,7 +1505,7 @@ static void jsR_run(js_State *J, js_Function *F) · 8 unmodified lines | ||
| 1486 | 1505 | break; |
| 1487 | 1506 | |
| 1488 | 1507 | case OP_SETPROP_S: |
| 1489 | − str = ST[*pc++]; | |
| 1508 | + READSTRING(); | |
| 1490 | 1509 | obj = js_toobject(J, -2); |
| 1491 | 1510 | transient = !js_isobject(J, -2); |
| 1492 | 1511 | jsR_setproperty(J, obj, str, transient); |
| @@ -1502,7 +1521,7 @@ static void jsR_run(js_State *J, js_Function *F) · 9 unmodified lines | ||
| 1502 | 1521 | break; |
| 1503 | 1522 | |
| 1504 | 1523 | case OP_DELPROP_S: |
| 1505 | − str = ST[*pc++]; | |
| 1524 | + READSTRING(); | |
| 1506 | 1525 | obj = js_toobject(J, -1); |
| 1507 | 1526 | b = jsR_delproperty(J, obj, str); |
| 1508 | 1527 | js_pop(J, 1); |
| @@ -1738,7 +1757,7 @@ static void jsR_run(js_State *J, js_Function *F) · 229 unmodified lines | ||
| 1738 | 1757 | break; |
| 1739 | 1758 | |
| 1740 | 1759 | case OP_CATCH: |
| 1741 | − str = ST[*pc++]; | |
| 1760 | + READSTRING(); | |
| 1742 | 1761 | obj = jsV_newobject(J, JS_COBJECT, NULL); |
| 1743 | 1762 | js_pushobject(J, obj); |
| 1744 | 1763 | js_rot2(J); |