diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-05-29 09:39:03 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-05-29 09:39:03 -0300 |
commit | 44fab2a44d06a956c3121ceba2b39ca7b00dc428 (patch) | |
tree | 9f492ba2ebaa4fb3cf6554fcb63f3fe026d43a5d /lpcode.c | |
parent | 460a35cbcb33fbc56f5a658b96a793b9bb8963e9 (diff) | |
download | lpeg-44fab2a44d06a956c3121ceba2b39ca7b00dc428.tar.gz lpeg-44fab2a44d06a956c3121ceba2b39ca7b00dc428.tar.bz2 lpeg-44fab2a44d06a956c3121ceba2b39ca7b00dc428.zip |
Code size stored in code itself
Most patterns do not have code, as they are not directly used for
a match; they are created only to compose larger patterns. So, we
shouldn't waste space to store the size of their code, as a NULL
pointer already indicates that the size is zero.
Diffstat (limited to 'lpcode.c')
-rw-r--r-- | lpcode.c | 67 |
1 files changed, 51 insertions, 16 deletions
@@ -392,29 +392,63 @@ static void codegen (CompileState *compst, TTree *tree, int opt, int tt, | |||
392 | const Charset *fl); | 392 | const Charset *fl); |
393 | 393 | ||
394 | 394 | ||
395 | void realloccode (lua_State *L, Pattern *p, int nsize) { | 395 | static void finishrelcode (lua_State *L, Pattern *p, Instruction *block, |
396 | int size) { | ||
397 | if (block == NULL) | ||
398 | luaL_error(L, "not enough memory"); | ||
399 | block->codesize = size; | ||
400 | p->code = (Instruction *)block + 1; | ||
401 | } | ||
402 | |||
403 | |||
404 | /* | ||
405 | ** Initialize array 'p->code' | ||
406 | */ | ||
407 | static void newcode (lua_State *L, Pattern *p, int size) { | ||
396 | void *ud; | 408 | void *ud; |
409 | Instruction *block; | ||
397 | lua_Alloc f = lua_getallocf(L, &ud); | 410 | lua_Alloc f = lua_getallocf(L, &ud); |
398 | void *newblock = f(ud, p->code, p->codesize * sizeof(Instruction), | 411 | size++; /* slot for 'codesize' */ |
399 | nsize * sizeof(Instruction)); | 412 | block = (Instruction*) f(ud, NULL, 0, size * sizeof(Instruction)); |
400 | if (newblock == NULL && nsize > 0) | 413 | finishrelcode(L, p, block, size); |
401 | luaL_error(L, "not enough memory"); | 414 | } |
402 | p->code = (Instruction *)newblock; | 415 | |
403 | p->codesize = nsize; | 416 | |
417 | void freecode (lua_State *L, Pattern *p) { | ||
418 | if (p->code != NULL) { | ||
419 | void *ud; | ||
420 | lua_Alloc f = lua_getallocf(L, &ud); | ||
421 | uint osize = p->code[-1].codesize; | ||
422 | f(ud, p->code - 1, osize * sizeof(Instruction), 0); /* free block */ | ||
423 | } | ||
424 | } | ||
425 | |||
426 | |||
427 | /* | ||
428 | ** Assume that 'nsize' is not zero and that 'p->code' already exists. | ||
429 | */ | ||
430 | static void realloccode (lua_State *L, Pattern *p, int nsize) { | ||
431 | void *ud; | ||
432 | lua_Alloc f = lua_getallocf(L, &ud); | ||
433 | Instruction *block = p->code - 1; | ||
434 | uint osize = block->codesize; | ||
435 | nsize++; /* add the 'codesize' slot to size */ | ||
436 | block = (Instruction*) f(ud, block, osize * sizeof(Instruction), | ||
437 | nsize * sizeof(Instruction)); | ||
438 | finishrelcode(L, p, block, nsize); | ||
404 | } | 439 | } |
405 | 440 | ||
406 | 441 | ||
407 | /* | 442 | /* |
408 | ** Add space for 'n' more instructions and return the index of | 443 | ** Add space for an instruction with 'n' slots and return its index. |
409 | ** the first one. | ||
410 | */ | 444 | */ |
411 | static int nextinstruction (CompileState *compst, int n) { | 445 | static int nextinstruction (CompileState *compst, int n) { |
412 | int size = compst->p->codesize; | 446 | int size = compst->p->code[-1].codesize - 1; |
413 | int ncode = compst->ncode; | 447 | int ncode = compst->ncode; |
414 | if (ncode >= size - n) { | 448 | if (ncode > size - n) { |
415 | uint nsize = size + (size >> 1) + n; | 449 | uint nsize = size + (size >> 1) + n; |
416 | if (nsize > INT_MAX) | 450 | if (nsize >= INT_MAX) |
417 | luaL_error(compst->L, "code too large"); | 451 | luaL_error(compst->L, "pattern code too large"); |
418 | realloccode(compst->L, compst->p, nsize); | 452 | realloccode(compst->L, compst->p, nsize); |
419 | } | 453 | } |
420 | compst->ncode = ncode + n; | 454 | compst->ncode = ncode + n; |
@@ -998,12 +1032,13 @@ static void peephole (CompileState *compst) { | |||
998 | 1032 | ||
999 | 1033 | ||
1000 | /* | 1034 | /* |
1001 | ** Compile a pattern | 1035 | ** Compile a pattern. 'size' is the size of the pattern's tree, |
1036 | ** which gives a hint for the size of the final code. | ||
1002 | */ | 1037 | */ |
1003 | Instruction *compile (lua_State *L, Pattern *p) { | 1038 | Instruction *compile (lua_State *L, Pattern *p, uint size) { |
1004 | CompileState compst; | 1039 | CompileState compst; |
1005 | compst.p = p; compst.ncode = 0; compst.L = L; | 1040 | compst.p = p; compst.ncode = 0; compst.L = L; |
1006 | realloccode(L, p, 4); /* minimum initial size */ | 1041 | newcode(L, p, size/2u + 2); /* set initial size */ |
1007 | codegen(&compst, p->tree, 0, NOINST, fullset); | 1042 | codegen(&compst, p->tree, 0, NOINST, fullset); |
1008 | addinstruction(&compst, IEnd, 0); | 1043 | addinstruction(&compst, IEnd, 0); |
1009 | realloccode(L, p, compst.ncode); /* set final size */ | 1044 | realloccode(L, p, compst.ncode); /* set final size */ |