Assertion code generator in JIT has been optimized.
This commit is contained in:
parent
d0cf279d87
commit
bccfdcb172
|
@ -1393,6 +1393,9 @@ while (cc < ccend)
|
||||||
case OP_NCLASS:
|
case OP_NCLASS:
|
||||||
case OP_XCLASS:
|
case OP_XCLASS:
|
||||||
|
|
||||||
|
case OP_CALLOUT:
|
||||||
|
case OP_CALLOUT_STR:
|
||||||
|
|
||||||
cc = next_opcode(common, cc);
|
cc = next_opcode(common, cc);
|
||||||
SLJIT_ASSERT(cc != NULL);
|
SLJIT_ASSERT(cc != NULL);
|
||||||
break;
|
break;
|
||||||
|
@ -2092,6 +2095,7 @@ static SLJIT_INLINE void allocate_stack(compiler_common *common, int size)
|
||||||
/* May destroy all locals and registers except TMP2. */
|
/* May destroy all locals and registers except TMP2. */
|
||||||
DEFINE_COMPILER;
|
DEFINE_COMPILER;
|
||||||
|
|
||||||
|
SLJIT_ASSERT(size > 0);
|
||||||
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
|
OP2(SLJIT_ADD, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
|
||||||
#ifdef DESTROY_REGISTERS
|
#ifdef DESTROY_REGISTERS
|
||||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_IMM, 12345);
|
||||||
|
@ -2106,6 +2110,7 @@ add_stub(common, CMP(SLJIT_GREATER, STACK_TOP, 0, STACK_LIMIT, 0));
|
||||||
static SLJIT_INLINE void free_stack(compiler_common *common, int size)
|
static SLJIT_INLINE void free_stack(compiler_common *common, int size)
|
||||||
{
|
{
|
||||||
DEFINE_COMPILER;
|
DEFINE_COMPILER;
|
||||||
|
SLJIT_ASSERT(size > 0);
|
||||||
OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
|
OP2(SLJIT_SUB, STACK_TOP, 0, STACK_TOP, 0, SLJIT_IMM, size * sizeof(sljit_sw));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6401,6 +6406,32 @@ return cc + callout_length;
|
||||||
#undef CALLOUT_ARG_SIZE
|
#undef CALLOUT_ARG_SIZE
|
||||||
#undef CALLOUT_ARG_OFFSET
|
#undef CALLOUT_ARG_OFFSET
|
||||||
|
|
||||||
|
static SLJIT_INLINE BOOL assert_needs_str_ptr_saving(PCRE2_SPTR cc)
|
||||||
|
{
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
switch (*cc)
|
||||||
|
{
|
||||||
|
case OP_CALLOUT_STR:
|
||||||
|
cc += GET(cc, 1 + 2*LINK_SIZE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OP_NOT_WORD_BOUNDARY:
|
||||||
|
case OP_WORD_BOUNDARY:
|
||||||
|
case OP_CALLOUT:
|
||||||
|
case OP_ALT:
|
||||||
|
cc += PRIV(OP_lengths)[*cc];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OP_KET:
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static PCRE2_SPTR compile_assert_matchingpath(compiler_common *common, PCRE2_SPTR cc, assert_backtrack *backtrack, BOOL conditional)
|
static PCRE2_SPTR compile_assert_matchingpath(compiler_common *common, PCRE2_SPTR cc, assert_backtrack *backtrack, BOOL conditional)
|
||||||
{
|
{
|
||||||
DEFINE_COMPILER;
|
DEFINE_COMPILER;
|
||||||
|
@ -6457,15 +6488,28 @@ if (bra == OP_BRAMINZERO)
|
||||||
|
|
||||||
if (framesize < 0)
|
if (framesize < 0)
|
||||||
{
|
{
|
||||||
extrasize = needs_control_head ? 2 : 1;
|
extrasize = 1;
|
||||||
|
if (bra == OP_BRA && !assert_needs_str_ptr_saving(ccbegin + 1 + LINK_SIZE))
|
||||||
|
extrasize = 0;
|
||||||
|
|
||||||
|
if (needs_control_head)
|
||||||
|
extrasize++;
|
||||||
|
|
||||||
if (framesize == no_frame)
|
if (framesize == no_frame)
|
||||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, STACK_TOP, 0);
|
||||||
allocate_stack(common, extrasize);
|
|
||||||
|
if (extrasize > 0)
|
||||||
|
allocate_stack(common, extrasize);
|
||||||
|
|
||||||
if (needs_control_head)
|
if (needs_control_head)
|
||||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
|
||||||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
|
|
||||||
|
if (extrasize > 0)
|
||||||
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
|
||||||
|
|
||||||
if (needs_control_head)
|
if (needs_control_head)
|
||||||
{
|
{
|
||||||
|
SLJIT_ASSERT(extrasize == 2);
|
||||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_IMM, 0);
|
||||||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
|
||||||
}
|
}
|
||||||
|
@ -6474,12 +6518,14 @@ else
|
||||||
{
|
{
|
||||||
extrasize = needs_control_head ? 3 : 2;
|
extrasize = needs_control_head ? 3 : 2;
|
||||||
allocate_stack(common, framesize + extrasize);
|
allocate_stack(common, framesize + extrasize);
|
||||||
|
|
||||||
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
|
OP1(SLJIT_MOV, TMP1, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
|
||||||
OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
|
OP2(SLJIT_SUB, TMP2, 0, STACK_TOP, 0, SLJIT_IMM, (framesize + extrasize) * sizeof(sljit_sw));
|
||||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), private_data_ptr, TMP2, 0);
|
||||||
if (needs_control_head)
|
if (needs_control_head)
|
||||||
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
|
OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr);
|
||||||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0);
|
||||||
|
|
||||||
if (needs_control_head)
|
if (needs_control_head)
|
||||||
{
|
{
|
||||||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(2), TMP1, 0);
|
||||||
|
@ -6488,6 +6534,7 @@ else
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), TMP1, 0);
|
||||||
|
|
||||||
init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize, FALSE);
|
init_frame(common, ccbegin, NULL, framesize + extrasize - 1, extrasize, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6511,7 +6558,7 @@ while (1)
|
||||||
altbacktrack.top = NULL;
|
altbacktrack.top = NULL;
|
||||||
altbacktrack.topbacktracks = NULL;
|
altbacktrack.topbacktracks = NULL;
|
||||||
|
|
||||||
if (*ccbegin == OP_ALT)
|
if (*ccbegin == OP_ALT && extrasize > 0)
|
||||||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
|
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
|
||||||
|
|
||||||
altbacktrack.cc = ccbegin;
|
altbacktrack.cc = ccbegin;
|
||||||
|
@ -6540,8 +6587,9 @@ while (1)
|
||||||
{
|
{
|
||||||
if (framesize == no_frame)
|
if (framesize == no_frame)
|
||||||
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
|
OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(SLJIT_SP), private_data_ptr);
|
||||||
else
|
else if (extrasize > 0)
|
||||||
free_stack(common, extrasize);
|
free_stack(common, extrasize);
|
||||||
|
|
||||||
if (needs_control_head)
|
if (needs_control_head)
|
||||||
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0);
|
OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), 0);
|
||||||
}
|
}
|
||||||
|
@ -6567,7 +6615,10 @@ while (1)
|
||||||
{
|
{
|
||||||
/* We know that STR_PTR was stored on the top of the stack. */
|
/* We know that STR_PTR was stored on the top of the stack. */
|
||||||
if (conditional)
|
if (conditional)
|
||||||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? sizeof(sljit_sw) : 0);
|
{
|
||||||
|
if (extrasize > 0)
|
||||||
|
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), needs_control_head ? sizeof(sljit_sw) : 0);
|
||||||
|
}
|
||||||
else if (bra == OP_BRAZERO)
|
else if (bra == OP_BRAZERO)
|
||||||
{
|
{
|
||||||
if (framesize < 0)
|
if (framesize < 0)
|
||||||
|
@ -6644,7 +6695,7 @@ if (needs_control_head)
|
||||||
if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
|
if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
|
||||||
{
|
{
|
||||||
/* Assert is failed. */
|
/* Assert is failed. */
|
||||||
if (conditional || bra == OP_BRAZERO)
|
if ((conditional && extrasize > 0) || bra == OP_BRAZERO)
|
||||||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
|
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
|
||||||
|
|
||||||
if (framesize < 0)
|
if (framesize < 0)
|
||||||
|
@ -6656,7 +6707,7 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
|
||||||
free_stack(common, 1);
|
free_stack(common, 1);
|
||||||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
|
||||||
}
|
}
|
||||||
else
|
else if (extrasize > 0)
|
||||||
free_stack(common, extrasize);
|
free_stack(common, extrasize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -6681,7 +6732,9 @@ if (opcode == OP_ASSERT || opcode == OP_ASSERTBACK)
|
||||||
if (framesize < 0)
|
if (framesize < 0)
|
||||||
{
|
{
|
||||||
/* We know that STR_PTR was stored on the top of the stack. */
|
/* We know that STR_PTR was stored on the top of the stack. */
|
||||||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw));
|
if (extrasize > 0)
|
||||||
|
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), (extrasize - 1) * sizeof(sljit_sw));
|
||||||
|
|
||||||
/* Keep the STR_PTR on the top of the stack. */
|
/* Keep the STR_PTR on the top of the stack. */
|
||||||
if (bra == OP_BRAZERO)
|
if (bra == OP_BRAZERO)
|
||||||
{
|
{
|
||||||
|
@ -6744,14 +6797,16 @@ else
|
||||||
/* AssertNot is successful. */
|
/* AssertNot is successful. */
|
||||||
if (framesize < 0)
|
if (framesize < 0)
|
||||||
{
|
{
|
||||||
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
|
if (extrasize > 0)
|
||||||
|
OP1(SLJIT_MOV, STR_PTR, 0, SLJIT_MEM1(STACK_TOP), STACK(0));
|
||||||
|
|
||||||
if (bra != OP_BRA)
|
if (bra != OP_BRA)
|
||||||
{
|
{
|
||||||
if (extrasize == 2)
|
if (extrasize == 2)
|
||||||
free_stack(common, 1);
|
free_stack(common, 1);
|
||||||
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
|
OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), SLJIT_IMM, 0);
|
||||||
}
|
}
|
||||||
else
|
else if (extrasize > 0)
|
||||||
free_stack(common, extrasize);
|
free_stack(common, extrasize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -6813,7 +6868,9 @@ if (framesize < 0)
|
||||||
stacksize = needs_control_head ? 1 : 0;
|
stacksize = needs_control_head ? 1 : 0;
|
||||||
if (ket != OP_KET || has_alternatives)
|
if (ket != OP_KET || has_alternatives)
|
||||||
stacksize++;
|
stacksize++;
|
||||||
free_stack(common, stacksize);
|
|
||||||
|
if (stacksize > 0)
|
||||||
|
free_stack(common, stacksize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needs_control_head)
|
if (needs_control_head)
|
||||||
|
@ -9203,7 +9260,9 @@ else if (opcode == OP_ONCE)
|
||||||
/* The STR_PTR must be released. */
|
/* The STR_PTR must be released. */
|
||||||
stacksize++;
|
stacksize++;
|
||||||
}
|
}
|
||||||
free_stack(common, stacksize);
|
|
||||||
|
if (stacksize > 0)
|
||||||
|
free_stack(common, stacksize);
|
||||||
|
|
||||||
JUMPHERE(once);
|
JUMPHERE(once);
|
||||||
/* Restore previous private_data_ptr */
|
/* Restore previous private_data_ptr */
|
||||||
|
|
|
@ -579,6 +579,16 @@ static struct regression_test_case regression_test_cases[] = {
|
||||||
{ MU, A, 0, 0, "(?:(?=.)??[a-c])+m", "abacdcbacacdcaccam" },
|
{ MU, A, 0, 0, "(?:(?=.)??[a-c])+m", "abacdcbacacdcaccam" },
|
||||||
{ MU, A, 0, 0, "((?!a)?(?!([^a]))?)+$", "acbab" },
|
{ MU, A, 0, 0, "((?!a)?(?!([^a]))?)+$", "acbab" },
|
||||||
{ MU, A, 0, 0, "((?!a)?\?(?!([^a]))?\?)+$", "acbab" },
|
{ MU, A, 0, 0, "((?!a)?\?(?!([^a]))?\?)+$", "acbab" },
|
||||||
|
{ MU, A, 0, 0, "a(?=(?C)\\B(?C`x`))b", "ab" },
|
||||||
|
{ MU, A, 0, 0, "a(?!(?C)\\B(?C`x`))bb|ab", "abb" },
|
||||||
|
{ MU, A, 0, 0, "a(?=\\b|(?C)\\B(?C`x`))b", "ab" },
|
||||||
|
{ MU, A, 0, 0, "a(?!\\b|(?C)\\B(?C`x`))bb|ab", "abb" },
|
||||||
|
{ MU, A, 0, 0, "c(?(?=(?C)\\B(?C`x`))ab|a)", "cab" },
|
||||||
|
{ MU, A, 0, 0, "c(?(?!(?C)\\B(?C`x`))ab|a)", "cab" },
|
||||||
|
{ MU, A, 0, 0, "c(?(?=\\b|(?C)\\B(?C`x`))ab|a)", "cab" },
|
||||||
|
{ MU, A, 0, 0, "c(?(?!\\b|(?C)\\B(?C`x`))ab|a)", "cab" },
|
||||||
|
{ MU, A, 0, 0, "a(?=)b", "ab" },
|
||||||
|
{ MU, A, 0, 0 | F_NOMATCH, "a(?!)b", "ab" },
|
||||||
|
|
||||||
/* Not empty, ACCEPT, FAIL */
|
/* Not empty, ACCEPT, FAIL */
|
||||||
{ MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "a*", "bcx" },
|
{ MU, A, PCRE2_NOTEMPTY, 0 | F_NOMATCH, "a*", "bcx" },
|
||||||
|
|
Loading…
Reference in New Issue