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 | return F->funlen++; | 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 | static int addlocal(JF, js_Ast *ident, int reuse) | 113 | static int addlocal(JF, js_Ast *ident, int reuse) |
| 142 | { | 114 | { |
| 143 | const char *name = ident->string; | 115 | const char *name = ident->string; |
| @@ -196,15 +168,27 @@ static void emitnumber(JF, double num) · 52 unmodified lines | |||
| 196 | emit(J, F, OP_INTEGER); | 168 | emit(J, F, OP_INTEGER); |
| 197 | emitarg(J, F, num + 32768); | 169 | emitarg(J, F, num + 32768); |
| 198 | } else { | 170 | } else { |
| 171 | #define N (sizeof(num) / sizeof(js_Instruction)) | ||
| 172 | js_Instruction x[N]; | ||
| 173 | size_t i; | ||
| 199 | emit(J, F, OP_NUMBER); | 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 | static void emitstring(JF, int opcode, const char *str) | 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 | emit(J, F, opcode); | 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 | static void emitlocal(JF, int oploc, int opvar, js_Ast *ident) | 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 | case EXP_REGEXP: | 608 | case EXP_REGEXP: |
| 625 | emitline(J, F, exp); | 609 | emitline(J, F, exp); |
| 626 | emit(J, F, OP_NEWREGEXP); | 610 | emitstring(J, F, OP_NEWREGEXP, exp->string); |
| 627 | emitarg(J, F, addstring(J, F, exp->string)); | ||
| 628 | emitarg(J, F, exp->number); | 611 | emitarg(J, F, exp->number); |
| 629 | break; | 612 | break; |
| 630 | 613 | ||
| @@ -123,12 +123,6 @@ struct js_Function · 122 unmodified lines | |||
| 123 | js_Function **funtab; | 123 | js_Function **funtab; |
| 124 | int funcap, funlen; | 124 | int funcap, funlen; |
| 125 | 125 | ||
| 126 | double *numtab; | ||
| 127 | int numcap, numlen; | ||
| 128 | |||
| 129 | const char **strtab; | ||
| 130 | int strcap, strlen; | ||
| 131 | |||
| 132 | const char **vartab; | 126 | const char **vartab; |
| 133 | int varcap, varlen; | 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 | js_Instruction *p = F->code; | 782 | js_Instruction *p = F->code; |
| 783 | js_Instruction *end = F->code + F->codelen; | 783 | js_Instruction *end = F->code + F->codelen; |
| 784 | char *s; | ||
| 785 | double n; | ||
| 784 | int i; | 786 | int i; |
| 785 | 787 | ||
| 786 | minify = 0; | 788 | minify = 0; |
| @@ -807,16 +809,21 @@ void jsC_dumpfunction(js_State *J, js_Function *F) · 20 unmodified lines | |||
| 807 | printf(" %ld", (long)((*p++) - 32768)); | 809 | printf(" %ld", (long)((*p++) - 32768)); |
| 808 | break; | 810 | break; |
| 809 | case OP_NUMBER: | 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 | break; | 815 | break; |
| 812 | case OP_STRING: | 816 | case OP_STRING: |
| 817 | memcpy(&s, p, sizeof(s)); | ||
| 818 | p += sizeof(s) / sizeof(*p); | ||
| 813 | pc(' '); | 819 | pc(' '); |
| 814 | pstr(F->strtab[*p++]); | 820 | pstr(s); |
| 815 | break; | 821 | break; |
| 816 | case OP_NEWREGEXP: | 822 | case OP_NEWREGEXP: |
| 817 | pc(' '); | 823 | pc(' '); |
| 818 | pregexp(F->strtab[p[0]], p[1]); | 824 | memcpy(&s, p, sizeof(s)); |
| 819 | p += 2; | 825 | p += sizeof(s) / sizeof(*p); |
| 826 | pregexp(s, *p++); | ||
| 820 | break; | 827 | break; |
| 821 | 828 | ||
| 822 | case OP_GETVAR: | 829 | case OP_GETVAR: |
| @@ -827,8 +834,10 @@ void jsC_dumpfunction(js_State *J, js_Function *F) · 4 unmodified lines | |||
| 827 | case OP_SETPROP_S: | 834 | case OP_SETPROP_S: |
| 828 | case OP_DELPROP_S: | 835 | case OP_DELPROP_S: |
| 829 | case OP_CATCH: | 836 | case OP_CATCH: |
| 837 | memcpy(&s, p, sizeof(s)); | ||
| 838 | p += sizeof(s) / sizeof(*p); | ||
| 830 | pc(' '); | 839 | pc(' '); |
| 831 | ps(F->strtab[*p++]); | 840 | ps(s); |
| 832 | break; | 841 | break; |
| 833 | 842 | ||
| 834 | case OP_GETLOCAL: | 843 | case OP_GETLOCAL: |
| @@ -13,8 +13,6 @@ static void jsG_freeenvironment(js_State *J, js_Environment *env) · 12 unmodified lines | |||
| 13 | static void jsG_freefunction(js_State *J, js_Function *fun) | 13 | static void jsG_freefunction(js_State *J, js_Function *fun) |
| 14 | { | 14 | { |
| 15 | js_free(J, fun->funtab); | 15 | js_free(J, fun->funtab); |
| 16 | js_free(J, fun->numtab); | ||
| 17 | js_free(J, fun->strtab); | ||
| 18 | js_free(J, fun->vartab); | 16 | js_free(J, fun->vartab); |
| 19 | js_free(J, fun->code); | 17 | js_free(J, fun->code); |
| 20 | js_free(J, fun); | 18 | js_free(J, fun); |
| @@ -1314,8 +1314,6 @@ void js_trap(js_State *J, int pc) · 1313 unmodified lines | |||
| 1314 | static void jsR_run(js_State *J, js_Function *F) | 1314 | static void jsR_run(js_State *J, js_Function *F) |
| 1315 | { | 1315 | { |
| 1316 | js_Function **FT = F->funtab; | 1316 | js_Function **FT = F->funtab; |
| 1317 | double *NT = F->numtab; | ||
| 1318 | const char **ST = F->strtab; | ||
| 1319 | const char **VT = F->vartab-1; | 1317 | const char **VT = F->vartab-1; |
| 1320 | int lightweight = F->lightweight; | 1318 | int lightweight = F->lightweight; |
| 1321 | js_Instruction *pcstart = F->code; | 1319 | js_Instruction *pcstart = F->code; |
| @@ -1335,6 +1333,10 @@ static void jsR_run(js_State *J, js_Function *F) · 13 unmodified lines | |||
| 1335 | savestrict = J->strict; | 1333 | savestrict = J->strict; |
| 1336 | J->strict = F->strict; | 1334 | J->strict = F->strict; |
| 1337 | 1335 | ||
| 1336 | #define READSTRING() \ | ||
| 1337 | memcpy(&str, pc, sizeof(str)); \ | ||
| 1338 | pc += sizeof(str) / sizeof(*pc) | ||
| 1339 | |||
| 1338 | while (1) { | 1340 | while (1) { |
| 1339 | if (J->gccounter > J->gcthresh) | 1341 | if (J->gccounter > J->gcthresh) |
| 1340 | js_gc(J, 0); | 1342 | js_gc(J, 0); |
| @@ -1351,14 +1353,28 @@ static void jsR_run(js_State *J, js_Function *F) · 10 unmodified lines | |||
| 1351 | case OP_ROT3: js_rot3(J); break; | 1353 | case OP_ROT3: js_rot3(J); break; |
| 1352 | case OP_ROT4: js_rot4(J); break; | 1354 | case OP_ROT4: js_rot4(J); break; |
| 1353 | 1355 | ||
| 1354 | case OP_INTEGER: js_pushnumber(J, *pc++ - 32768); break; | 1356 | case OP_INTEGER: |
| 1355 | case OP_NUMBER: js_pushnumber(J, NT[*pc++]); break; | 1357 | js_pushnumber(J, *pc++ - 32768); |
| 1356 | case OP_STRING: js_pushliteral(J, ST[*pc++]); break; | 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 | case OP_CLOSURE: js_newfunction(J, FT[*pc++], J->E); break; | 1371 | case OP_CLOSURE: js_newfunction(J, FT[*pc++], J->E); break; |
| 1359 | case OP_NEWOBJECT: js_newobject(J); break; | 1372 | case OP_NEWOBJECT: js_newobject(J); break; |
| 1360 | case OP_NEWARRAY: js_newarray(J); break; | 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 | case OP_UNDEF: js_pushundefined(J); break; | 1379 | case OP_UNDEF: js_pushundefined(J); break; |
| 1364 | case OP_NULL: js_pushnull(J); break; | 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 | break; | 1426 | break; |
| 1411 | 1427 | ||
| 1412 | case OP_GETVAR: | 1428 | case OP_GETVAR: |
| 1413 | str = ST[*pc++]; | 1429 | READSTRING(); |
| 1414 | if (!js_hasvar(J, str)) | 1430 | if (!js_hasvar(J, str)) |
| 1415 | js_referenceerror(J, "'%s' is not defined", str); | 1431 | js_referenceerror(J, "'%s' is not defined", str); |
| 1416 | break; | 1432 | break; |
| 1417 | 1433 | ||
| 1418 | case OP_HASVAR: | 1434 | case OP_HASVAR: |
| 1419 | if (!js_hasvar(J, ST[*pc++])) | 1435 | READSTRING(); |
| 1436 | if (!js_hasvar(J, str)) | ||
| 1420 | js_pushundefined(J); | 1437 | js_pushundefined(J); |
| 1421 | break; | 1438 | break; |
| 1422 | 1439 | ||
| 1423 | case OP_SETVAR: | 1440 | case OP_SETVAR: |
| 1424 | js_setvar(J, ST[*pc++]); | 1441 | READSTRING(); |
| 1442 | js_setvar(J, str); | ||
| 1425 | break; | 1443 | break; |
| 1426 | 1444 | ||
| 1427 | case OP_DELVAR: | 1445 | case OP_DELVAR: |
| 1428 | b = js_delvar(J, ST[*pc++]); | 1446 | READSTRING(); |
| 1447 | b = js_delvar(J, str); | ||
| 1429 | js_pushboolean(J, b); | 1448 | js_pushboolean(J, b); |
| 1430 | break; | 1449 | break; |
| 1431 | 1450 | ||
| @@ -1471,7 +1490,7 @@ static void jsR_run(js_State *J, js_Function *F) · 39 unmodified lines | |||
| 1471 | break; | 1490 | break; |
| 1472 | 1491 | ||
| 1473 | case OP_GETPROP_S: | 1492 | case OP_GETPROP_S: |
| 1474 | str = ST[*pc++]; | 1493 | READSTRING(); |
| 1475 | obj = js_toobject(J, -1); | 1494 | obj = js_toobject(J, -1); |
| 1476 | jsR_getproperty(J, obj, str); | 1495 | jsR_getproperty(J, obj, str); |
| 1477 | js_rot2pop1(J); | 1496 | js_rot2pop1(J); |
| @@ -1486,7 +1505,7 @@ static void jsR_run(js_State *J, js_Function *F) · 8 unmodified lines | |||
| 1486 | break; | 1505 | break; |
| 1487 | 1506 | ||
| 1488 | case OP_SETPROP_S: | 1507 | case OP_SETPROP_S: |
| 1489 | str = ST[*pc++]; | 1508 | READSTRING(); |
| 1490 | obj = js_toobject(J, -2); | 1509 | obj = js_toobject(J, -2); |
| 1491 | transient = !js_isobject(J, -2); | 1510 | transient = !js_isobject(J, -2); |
| 1492 | jsR_setproperty(J, obj, str, transient); | 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 | break; | 1521 | break; |
| 1503 | 1522 | ||
| 1504 | case OP_DELPROP_S: | 1523 | case OP_DELPROP_S: |
| 1505 | str = ST[*pc++]; | 1524 | READSTRING(); |
| 1506 | obj = js_toobject(J, -1); | 1525 | obj = js_toobject(J, -1); |
| 1507 | b = jsR_delproperty(J, obj, str); | 1526 | b = jsR_delproperty(J, obj, str); |
| 1508 | js_pop(J, 1); | 1527 | js_pop(J, 1); |
| @@ -1738,7 +1757,7 @@ static void jsR_run(js_State *J, js_Function *F) · 229 unmodified lines | |||
| 1738 | break; | 1757 | break; |
| 1739 | 1758 | ||
| 1740 | case OP_CATCH: | 1759 | case OP_CATCH: |
| 1741 | str = ST[*pc++]; | 1760 | READSTRING(); |
| 1742 | obj = jsV_newobject(J, JS_COBJECT, NULL); | 1761 | obj = jsV_newobject(J, JS_COBJECT, NULL); |
| 1743 | js_pushobject(J, obj); | 1762 | js_pushobject(J, obj); |
| 1744 | js_rot2(J); | 1763 | js_rot2(J); |