Skip to content
Permalink
Browse files
Support efficient offstack allocations optionally.
  • Loading branch information
postwait authored and HeinrichHartmann committed Jun 2, 2016
1 parent 76f742a commit 480c2c2
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 8 deletions.
32 lpcap.c
@@ -534,4 +534,34 @@ int getcaptures (lua_State *L, const char *s, const char *r, int ptop) {
return n;
}


#ifdef NO_ONSTACK_LIGHTUSERDATA
#include <stdlib.h>
#include <pthread.h>

#if !defined(INITBACK)
#define INITBACK MAXBACK
#endif

static pthread_mutex_t stack_on_heap_for_lp_match_init_lock = PTHREAD_MUTEX_INITIALIZER;
static int stack_on_heap_for_lp_match_initialized;
static pthread_key_t stack_on_heap_for_lp_match;
struct tls_heap_compensator *lpcap_get_offstack_compenstor() {
struct tls_heap_compensator *comp;
comp = pthread_getspecific(stack_on_heap_for_lp_match);
if(comp == NULL) {
comp = calloc(1, sizeof(*comp) + INITCAPSIZE + INITBACK);
comp->alloc_capsize = (unsigned char *)comp + sizeof(*comp);
comp->alloc_back = (unsigned char *)comp->alloc_capsize + INITCAPSIZE;
pthread_setspecific(stack_on_heap_for_lp_match, comp);
}
return comp;
}
void lpcap_initiailize_offstack_compensator() {
pthread_mutex_lock(&stack_on_heap_for_lp_match_init_lock);
if(!stack_on_heap_for_lp_match_initialized) {
stack_on_heap_for_lp_match_initialized = 1;
pthread_key_create(&stack_on_heap_for_lp_match, free);
}
pthread_mutex_unlock(&stack_on_heap_for_lp_match_init_lock);
}
#endif
11 lpcap.h
@@ -33,11 +33,20 @@ typedef struct CapState {
int valuecached; /* value stored in cache slot */
} CapState;


int runtimecap (CapState *cs, Capture *close, const char *s, int *rem);
int getcaptures (lua_State *L, const char *s, const char *r, int ptop);
int finddyncap (Capture *cap, Capture *last);

#ifdef NO_ONSTACK_LIGHTUSERDATA
struct tls_heap_compensator {
void *alloc_capsize;
void *alloc_back;
};

struct tls_heap_compensator *lpcap_get_offstack_compenstor(void);
void lpcap_initiailize_offstack_compensator(void);
#endif

#endif


@@ -1148,7 +1148,12 @@ static size_t initposition (lua_State *L, size_t len) {
** Main match function
*/
static int lp_match (lua_State *L) {
Capture *capture = calloc(INITCAPSIZE, sizeof(Capture));
#ifdef NO_ONSTACK_LIGHTUSERDATA
struct tls_heap_compensator *comp = lpcap_get_offstack_compenstor();
Capture *capture = comp->alloc_capsize;
#else
Capture capture[INITCAPSIZE];
#endif
const char *r;
size_t l;
int rv;
@@ -1166,7 +1171,6 @@ static int lp_match (lua_State *L) {
return 1;
}
rv = getcaptures(L, s, r, ptop);
free(capture);
return rv;
}

@@ -1287,6 +1291,9 @@ static struct luaL_Reg metareg[] = {

int luaopen_lpeg (lua_State *L);
int luaopen_lpeg (lua_State *L) {
#ifdef NO_ONSTACK_LIGHTUSERDATA
lpcap_initiailize_offstack_compensator();
#endif
luaL_newmetatable(L, PATTERN_T);
lua_pushnumber(L, MAXBACK); /* initialize maximum backtracking */
lua_setfield(L, LUA_REGISTRYINDEX, MAXSTACKIDX);
11 lpvm.c
@@ -147,7 +147,12 @@ static int removedyncap (lua_State *L, Capture *capture,
*/
const char *match (lua_State *L, const char *o, const char *s, const char *e,
Instruction *op, Capture *capture, int ptop) {
Stack *stackbase = calloc(INITBACK, sizeof(Stack));
#ifdef NO_ONSTACK_LIGHTUSERDATA
struct tls_heap_compensator *comp = lpcap_get_offstack_compenstor();
Stack *stackbase = comp->alloc_back;
#else
Stack stackbase[INITBACK];
#endif
Stack *stacklimit = stackbase + INITBACK;
Stack *stack = stackbase; /* point to first empty slot in stack */
int capsize = INITCAPSIZE;
@@ -169,12 +174,10 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
assert(stack == getstackbase(L, ptop) + 1);
capture[captop].kind = Cclose;
capture[captop].s = NULL;
free(stackbase);
return s;
}
case IGiveup: {
assert(stack == getstackbase(L, ptop));
free(stackbase);
return NULL;
}
case IRet: {
@@ -348,7 +351,7 @@ const char *match (lua_State *L, const char *o, const char *s, const char *e,
p++;
continue;
}
default: assert(0); free(stackbase); return NULL;
default: assert(0); return NULL;
}
}
}

2 comments on commit 480c2c2

@HeinrichHartmann
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@postwait This branch avoids the circlpeg rename. No functional changes.

The test suite fails for me:

gmake CC="gcc -m64 -DNO_ONSTACK_LIGHTUSERDATA" LUADIR=/opt/circonus/include/amd64/luajit-2.0

$ luajit test.lua
General tests for LPeg library
version 1.0.0
luajit: test.lua:24: assertion failed!
stack traceback:
        [C]: in function 'assert'
        test.lua:24: in function 'checkeq'
        test.lua:27: in function 'checkeq'
        test.lua:163: in main chunk
        [C]: at 0x00402d50

@HeinrichHartmann
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect that lp_match is called recursively. In this case one global allocation is not enough.

Please sign in to comment.