** Main match function
*/
static int lp_match (lua_State *L) {
-#ifdef LPEG_LUD_WORKAROUND
- Capture *capture = lpeg_allocate_mem_low(sizeof(Capture) * INITCAPSIZE);
-#else
Capture capture[INITCAPSIZE];
-#endif
const char *r;
size_t l;
const char *s;
else if (lua_type (L, SUBJIDX) == LUA_TUSERDATA) {
struct rspamd_lua_text *t = lua_check_text (L, SUBJIDX);
if (!t) {
-#ifdef LPEG_LUD_WORKAROUND
- lpeg_free_mem_low (capture);
-#endif
return luaL_error (L, "invalid argument (not a text)");
}
s = t->start;
if (s == NULL) {
lua_pushnil(L);
-#ifdef LPEG_LUD_WORKAROUND
- lpeg_free_mem_low (capture);
-#endif
return 1;
}
}
else {
-#ifdef LPEG_LUD_WORKAROUND
- lpeg_free_mem_low (capture);
-#endif
return luaL_error (L, "invalid argument: %s",
lua_typename (L, lua_type (L, SUBJIDX)));
}
r = match(L, s, s + i, s + l, code, capture, ptop);
if (r == NULL) {
lua_pushnil(L);
-#ifdef LPEG_LUD_WORKAROUND
- lpeg_free_mem_low (capture);
-#endif
return 1;
}
rs = getcaptures(L, s, r, ptop);
-#ifdef LPEG_LUD_WORKAROUND
- lpeg_free_mem_low (capture);
-#endif
return rs;
}
#include "lpvm.h"
#include "lpprint.h"
-#ifdef LPEG_LUD_WORKAROUND
-#include <sys/mman.h>
-
-#define MAX_PIECES (1u << 2u)
-
-/* 64 bytes, 1 cache line */
-struct poor_slab {
- struct slab_piece {
- unsigned char *ptr;
- uint32_t sz;
- uint32_t occupied;
- } pieces[MAX_PIECES];
-};
-
-/* Used to optimize pages allocation */
-RSPAMD_ALIGNED (64) struct poor_slab slabs;
-
-static uint64_t xorshifto_seed[2] = {0xdeadbabe, 0xdeadbeef};
-
-static inline uint64_t
-xoroshiro_rotl (const uint64_t x, int k) {
- return (x << k) | (x >> (64 - k));
-}
-
-void *
-lpeg_allocate_mem_low (size_t sz)
-{
- unsigned char *cp;
- unsigned flags = MAP_PRIVATE | MAP_ANON;
- void *base_addr = NULL;
-
- /* Check slabs */
- for (unsigned i = 0; i < MAX_PIECES; i ++) {
- if (!slabs.pieces[i].occupied && slabs.pieces[i].sz == sz) {
- /* Reuse, short path */
- slabs.pieces[i].occupied = 1;
- return slabs.pieces[i].ptr + sizeof (size_t);
- }
- }
-
-#ifdef MAP_32BIT
- flags |= MAP_32BIT;
-#else
- const uint64_t s0 = xorshifto_seed[0];
- uint64_t s1 = xorshifto_seed[1];
-
- s1 ^= s0;
- xorshifto_seed[0] = xoroshiro_rotl (s0, 55) ^ s1 ^ (s1 << 14);
- xorshifto_seed[1] = xoroshiro_rotl (s1, 36);
- flags |= MAP_FIXED;
- /* Get 46 bits */
- base_addr = (void *)((xorshifto_seed[0] + xorshifto_seed[1]) & 0x7FFFFFFFF000ULL);
-#endif
-
- cp = mmap (base_addr, sz + sizeof (sz), PROT_WRITE | PROT_READ,
- flags, -1, 0);
- assert (cp != MAP_FAILED);
- memcpy (cp, &sz, sizeof (sz));
-
- for (unsigned i = 0; i < MAX_PIECES; i ++) {
- if (slabs.pieces[i].occupied == 0) {
- /* Store piece */
- slabs.pieces[i].sz = sz;
- slabs.pieces[i].ptr = cp;
- slabs.pieces[i].occupied = 1;
-
- return cp + sizeof (sz);
- }
- }
-
- /* Not enough free pieces, pop some */
- unsigned sel = ((uintptr_t)cp) & ((MAX_PIECES * 2) - 1);
- /* Here we free memory in fact */
- munmap (slabs.pieces[sel].ptr, slabs.pieces[sel].sz + sizeof (sz));
- slabs.pieces[sel].sz = sz;
- slabs.pieces[sel].ptr = cp;
- slabs.pieces[sel].occupied = 1;
-
- return cp + sizeof (sz);
-}
-
-void
-lpeg_free_mem_low(void *p)
-{
- unsigned char *cp = (unsigned char *)p;
- size_t sz;
-
- /* Base address */
- cp -= sizeof (sz);
- memcpy (&sz, cp, sizeof (sz));
-
- for (unsigned i = 0; i < MAX_PIECES; i ++) {
- if (slabs.pieces[i].occupied && slabs.pieces[i].ptr == cp) {
- /* Return back */
- slabs.pieces[i].occupied = 0;
-
- return;
- }
- }
-
- /* No match, unmapped by allocation */
-}
-
-#endif
-
/* initial size for call/backtrack stack */
#if !defined(INITBACK)
#define INITBACK MAXBACK
*/
const char *match (lua_State *L, const char *o, const char *s, const char *e,
Instruction *op, Capture *capture, int ptop) {
-#ifdef LPEG_LUD_WORKAROUND
- Stack *stackbase = lpeg_allocate_mem_low(sizeof (Stack) * INITBACK);
-#else
Stack stackbase[INITBACK];
-#endif
Stack *stacklimit = stackbase + INITBACK;
Stack *stack = stackbase; /* point to first empty slot in stack */
int capsize = INITCAPSIZE;
assert(stack == getstackbase(L, ptop) + 1);
capture[captop].kind = Cclose;
capture[captop].s = NULL;
-#ifdef LPEG_LUD_WORKAROUND
- lpeg_free_mem_low(stackbase);
-#endif
return s;
}
case IGiveup: {
assert(stack == getstackbase(L, ptop));
-#ifdef LPEG_LUD_WORKAROUND
- lpeg_free_mem_low(stackbase);
-#endif
return NULL;
}
case IRet: {