When the compiled JIT code runs, it needs a block of memory to
use as a stack. By default, it uses 32K on the machine stack.
However, some large or complicated patterns need more than this.
The error PCRE_ERROR_JIT_STACKLIMIT is given when there is not
enough stack. Three functions are provided for managing blocks of
memory for use as JIT stacks. There is further discussion about
the use of JIT stacks in the section entitled "JIT stack FAQ"
below.
The pcre_jit_stack_alloc()
function creates a JIT stack. Its
arguments are a starting size and a maximum size, and it returns
a pointer to an opaque structure of type pcre_jit_stack
, or NULL
if there is an error. The pcre_jit_stack_free()
function can be
used to free a stack that is no longer needed. (For the
technically minded: the address space is allocated by mmap or
VirtualAlloc.)
JIT uses far less memory for recursion than the interpretive
code, and a maximum stack size of 512K to 1M should be more than
enough for any pattern.
The pcre_assign_jit_stack()
function specifies which stack JIT
code should use. Its arguments are as follows:
pcre_extra *extra
pcre_jit_callback callback
void *data
The extra argument must be the result of studying a pattern with
PCRE_STUDY_JIT_COMPILE etc. There are three cases for the values
of the other two options:
(1) If callback is NULL and data is NULL, an internal 32K block
on the machine stack is used.
(2) If callback is NULL and data is not NULL, data must be
a valid JIT stack, the result of calling
pcre_jit_stack_alloc()
.
(3) If callback is not NULL, it must point to a function that
is
called with data as an argument at the start of matching,
in
order to set up a JIT stack. If the return from the
callback
function is NULL, the internal 32K stack is used; otherwise
the
return value must be a valid JIT stack, the result of
calling
pcre_jit_stack_alloc()
.
A callback function is obeyed whenever JIT code is about to be
run; it is not obeyed when pcre_exec()
is called with options
that are incompatible for JIT execution. A callback function can
therefore be used to determine whether a match operation was
executed by JIT or by the interpreter.
You may safely use the same JIT stack for more than one pattern
(either by assigning directly or by callback), as long as the
patterns are all matched sequentially in the same thread. In a
multithread application, if you do not specify a JIT stack, or if
you assign or pass back NULL from a callback, that is thread-
safe, because each thread has its own machine stack. However, if
you assign or pass back a non-NULL JIT stack, this must be a
different stack for each thread so that the application is
thread-safe.
Strictly speaking, even more is allowed. You can assign the same
non-NULL stack to any number of patterns as long as they are not
used for matching by multiple threads at the same time. For
example, you can assign the same stack to all compiled patterns,
and use a global mutex in the callback to wait until the stack is
available for use. However, this is an inefficient solution, and
not recommended.
This is a suggestion for how a multithreaded program that needs
to set up non-default JIT stacks might operate:
During thread initialization
thread_local_var = pcre_jit_stack_alloc(...)
During thread exit
pcre_jit_stack_free(thread_local_var)
Use a one-line callback function
return thread_local_var
All the functions described in this section do nothing if JIT is
not available, and pcre_assign_jit_stack()
does nothing unless
the extra
argument is non-NULL and points to a pcre_extra
block
that is the result of a successful study with
PCRE_STUDY_JIT_COMPILE etc.