#ifdef DEBUGGING
/*
- dump_trie(trie)
- dump_trie_interim_list(trie,next_alloc)
- dump_trie_interim_table(trie,next_alloc)
+ dump_trie(trie,widecharmap)
+ dump_trie_interim_list(trie,widecharmap,next_alloc)
+ dump_trie_interim_table(trie,widecharmap,next_alloc)
These routines dump out a trie in a somewhat readable format.
The _interim_ variants are used for debugging the interim
*/
/*
- dump_trie(trie)
Dumps the final compressed table form of the trie to Perl_debug_log.
Used for debugging make_trie().
*/
STATIC void
-S_dump_trie(pTHX_ const struct _reg_trie_data *trie,U32 depth)
+S_dump_trie(pTHX_ const struct _reg_trie_data *trie, HV *widecharmap, U32 depth)
{
U32 state;
SV *sv=sv_newmortal();
- int colwidth= trie->widecharmap ? 6 : 4;
+ int colwidth= widecharmap ? 6 : 4;
GET_RE_DEBUG_FLAGS_DECL;
}
}
/*
- dump_trie_interim_list(trie,next_alloc)
Dumps a fully constructed but uncompressed trie in list form.
List tries normally only are used for construction when the number of
possible chars (trie->uniquecharcount) is very high.
Used for debugging make_trie().
*/
STATIC void
-S_dump_trie_interim_list(pTHX_ const struct _reg_trie_data *trie, U32 next_alloc,U32 depth)
+S_dump_trie_interim_list(pTHX_ const struct _reg_trie_data *trie,
+ HV *widecharmap, U32 next_alloc, U32 depth)
{
U32 state;
SV *sv=sv_newmortal();
- int colwidth= trie->widecharmap ? 6 : 4;
+ int colwidth= widecharmap ? 6 : 4;
GET_RE_DEBUG_FLAGS_DECL;
/* print out the table precompression. */
PerlIO_printf( Perl_debug_log, "%*sState :Word | Transition Data\n%*s%s",
}
/*
- dump_trie_interim_table(trie,next_alloc)
Dumps a fully constructed but uncompressed trie in table form.
This is the normal DFA style state transition table, with a few
twists to facilitate compression later.
Used for debugging make_trie().
*/
STATIC void
-S_dump_trie_interim_table(pTHX_ const struct _reg_trie_data *trie, U32 next_alloc, U32 depth)
+S_dump_trie_interim_table(pTHX_ const struct _reg_trie_data *trie,
+ HV *widecharmap, U32 next_alloc, U32 depth)
{
U32 state;
U16 charid;
SV *sv=sv_newmortal();
- int colwidth= trie->widecharmap ? 6 : 4;
+ int colwidth= widecharmap ? 6 : 4;
GET_RE_DEBUG_FLAGS_DECL;
/*
\
if ( noper_next < tail ) { \
if (!trie->jump) \
- Newxz( trie->jump, word_count + 1, U16); \
+ trie->jump = PerlMemShared_calloc( word_count + 1, sizeof(U16) ); \
trie->jump[curword] = (U16)(noper_next - convert); \
if (!jumper) \
jumper = noper_next; \
/* we only allocate the nextword buffer when there */\
/* a dupe, so first time we have to do the allocation */\
if (!trie->nextword) \
- Newxz( trie->nextword, word_count + 1, U16); \
+ trie->nextword = \
+ PerlMemShared_calloc( word_count + 1, sizeof(U16)); \
while ( trie->nextword[dupe] ) \
dupe= trie->nextword[dupe]; \
trie->nextword[dupe]= curword; \
dVAR;
/* first pass, loop through and scan words */
reg_trie_data *trie;
+ HV *widecharmap = NULL;
regnode *cur;
const U32 uniflags = UTF8_ALLOW_DEFAULT;
STRLEN len = 0;
)
);
- const U32 data_slot = add_data( pRExC_state, 1, "t" );
+ const U32 data_slot = add_data( pRExC_state, 2, "tu" );
SV *re_trie_maxbuff;
#ifndef DEBUGGING
/* these are only used during construction but are useful during
PERL_UNUSED_ARG(depth);
#endif
- Newxz( trie, 1, reg_trie_data );
+ trie = PerlMemShared_calloc( 1, sizeof(reg_trie_data) );
trie->refcount = 1;
trie->startstate = 1;
trie->wordcount = word_count;
RExC_rxi->data->data[ data_slot ] = (void*)trie;
- Newxz( trie->charmap, 256, U16 );
+ trie->charmap = PerlMemShared_calloc( 256, sizeof(U16) );
if (!(UTF && folder))
- Newxz( trie->bitmap, ANYOF_BITMAP_SIZE, char );
+ trie->bitmap = PerlMemShared_calloc( ANYOF_BITMAP_SIZE, 1 );
DEBUG_r({
trie->words = newAV();
});
}
} else {
SV** svpp;
- if ( !trie->widecharmap )
- trie->widecharmap = newHV();
+ if ( !widecharmap )
+ widecharmap = newHV();
- svpp = hv_fetch( trie->widecharmap, (char*)&uvc, sizeof( UV ), 1 );
+ svpp = hv_fetch( widecharmap, (char*)&uvc, sizeof( UV ), 1 );
if ( !svpp )
Perl_croak( aTHX_ "error creating/fetching widecharmap entry for 0x%"UVXf, uvc );
DEBUG_TRIE_COMPILE_r(
PerlIO_printf( Perl_debug_log, "%*sTRIE(%s): W:%d C:%d Uq:%d Min:%d Max:%d\n",
(int)depth * 2 + 2,"",
- ( trie->widecharmap ? "UTF8" : "NATIVE" ), (int)word_count,
+ ( widecharmap ? "UTF8" : "NATIVE" ), (int)word_count,
(int)TRIE_CHARCOUNT(trie), trie->uniquecharcount,
(int)trie->minlen, (int)trie->maxlen )
);
- Newxz( trie->wordlen, word_count, U32 );
+ trie->wordlen = PerlMemShared_calloc( word_count, sizeof(U32) );
/*
We now know what we are dealing with in terms of unique chars and
DEBUG_TRIE_COMPILE_MORE_r( PerlIO_printf( Perl_debug_log,
"%*sCompiling trie using list compiler\n",
(int)depth * 2 + 2, ""));
-
- Newxz( trie->states, TRIE_CHARCOUNT(trie) + 2, reg_trie_state );
+
+ trie->states = PerlMemShared_calloc( TRIE_CHARCOUNT(trie) + 2,
+ sizeof(reg_trie_state) );
TRIE_LIST_NEW(1);
next_alloc = 2;
if ( uvc < 256 ) {
charid = trie->charmap[ uvc ];
} else {
- SV** const svpp = hv_fetch( trie->widecharmap, (char*)&uvc, sizeof( UV ), 0);
+ SV** const svpp = hv_fetch( widecharmap, (char*)&uvc, sizeof( UV ), 0);
if ( !svpp ) {
charid = 0;
} else {
/* next alloc is the NEXT state to be allocated */
trie->statecount = next_alloc;
- Renew( trie->states, next_alloc, reg_trie_state );
+ trie->states = PerlMemShared_realloc( trie->states, next_alloc
+ * sizeof(reg_trie_state) );
/* and now dump it out before we compress it */
DEBUG_TRIE_COMPILE_MORE_r(
- dump_trie_interim_list(trie,next_alloc,depth+1)
+ dump_trie_interim_list(trie,widecharmap,next_alloc,depth+1)
);
- Newxz( trie->trans, transcount ,reg_trie_trans );
+ trie->trans
+ = PerlMemShared_calloc( transcount, sizeof(reg_trie_trans) );
{
U32 state;
U32 tp = 0;
}
if ( transcount < tp + maxid - minid + 1) {
transcount *= 2;
- Renew( trie->trans, transcount, reg_trie_trans );
+ trie->trans
+ = PerlMemShared_realloc( trie->trans,
+ transcount
+ * sizeof(reg_trie_trans) );
Zero( trie->trans + (transcount / 2), transcount / 2 , reg_trie_trans );
}
base = trie->uniquecharcount + tp - minid;
"%*sCompiling trie using table compiler\n",
(int)depth * 2 + 2, ""));
- Newxz( trie->trans, ( TRIE_CHARCOUNT(trie) + 1 ) * trie->uniquecharcount + 1,
- reg_trie_trans );
- Newxz( trie->states, TRIE_CHARCOUNT(trie) + 2, reg_trie_state );
+ trie->trans = PerlMemShared_calloc( ( TRIE_CHARCOUNT(trie) + 1 )
+ * trie->uniquecharcount + 1,
+ sizeof(reg_trie_trans) );
+ trie->states = PerlMemShared_calloc( TRIE_CHARCOUNT(trie) + 2,
+ sizeof(reg_trie_state) );
next_alloc = trie->uniquecharcount + 1;
if ( uvc < 256 ) {
charid = trie->charmap[ uvc ];
} else {
- SV* const * const svpp = hv_fetch( trie->widecharmap, (char*)&uvc, sizeof( UV ), 0);
+ SV* const * const svpp = hv_fetch( widecharmap, (char*)&uvc, sizeof( UV ), 0);
charid = svpp ? (U16)SvIV(*svpp) : 0;
}
if ( charid ) {
/* and now dump it out before we compress it */
DEBUG_TRIE_COMPILE_MORE_r(
- dump_trie_interim_table(trie,next_alloc,depth+1)
+ dump_trie_interim_table(trie,widecharmap,next_alloc,depth+1)
);
{
}
}
trie->lasttrans = pos + 1;
- Renew( trie->states, laststate, reg_trie_state);
+ trie->states = PerlMemShared_realloc( trie->states, laststate
+ * sizeof(reg_trie_state) );
DEBUG_TRIE_COMPILE_MORE_r(
PerlIO_printf( Perl_debug_log,
"%*sAlloc: %d Orig: %"IVdf" elements, Final:%"IVdf". Savings of %%%5.2f\n",
(UV)trie->lasttrans)
);
/* resize the trans array to remove unused space */
- Renew( trie->trans, trie->lasttrans, reg_trie_trans);
+ trie->trans = PerlMemShared_realloc( trie->trans, trie->lasttrans
+ * sizeof(reg_trie_trans) );
/* and now dump out the compressed format */
DEBUG_TRIE_COMPILE_r(
- dump_trie(trie,depth+1)
+ dump_trie(trie,widecharmap,depth+1)
);
{ /* Modify the program and insert the new TRIE node*/
/* But first we check to see if there is a common prefix we can
split out as an EXACT and put in front of the TRIE node. */
trie->startstate= 1;
- if ( trie->bitmap && !trie->widecharmap && !trie->jump ) {
+ if ( trie->bitmap && !widecharmap && !trie->jump ) {
U32 state;
for ( state = 1 ; state < trie->statecount-1 ; state++ ) {
U32 ofs = 0;
{
OP( convert ) = TRIEC;
Copy(trie->bitmap, ((struct regnode_charclass *)convert)->bitmap, ANYOF_BITMAP_SIZE, char);
- Safefree(trie->bitmap);
+ PerlMemShared_free(trie->bitmap);
trie->bitmap= NULL;
} else
OP( convert ) = TRIE;
Set_Node_Offset_Length(convert,mjd_offset,mjd_nodelen);
});
} /* end node insert */
+ RExC_rxi->data->data[ data_slot + 1 ] = (void*)widecharmap;
#ifndef DEBUGGING
SvREFCNT_dec(TRIE_REVCHARMAP(trie));
#endif
try 'g' and succeed, prodceding to match 'cdgu'.
*/
/* add a fail transition */
- reg_trie_data *trie=(reg_trie_data *)RExC_rxi->data->data[ARG(source)];
+ const U32 trie_offset = ARG(source);
+ reg_trie_data *trie=(reg_trie_data *)RExC_rxi->data->data[trie_offset];
U32 *q;
const U32 ucharcount = trie->uniquecharcount;
const U32 numstates = trie->statecount;
ARG_SET( stclass, data_slot );
- Newxz( aho, 1, reg_ac_data );
+ aho = PerlMemShared_calloc( 1, sizeof(reg_ac_data) );
RExC_rxi->data->data[ data_slot ] = (void*)aho;
- aho->trie=trie;
- aho->states=(reg_trie_state *)savepvn((const char*)trie->states,
- numstates * sizeof(reg_trie_state));
+ aho->trie=trie_offset;
+ aho->states=(reg_trie_state *)PerlMemShared_malloc( numstates * sizeof(reg_trie_state) );
+ Copy( trie->states, aho->states, numstates, reg_trie_state );
Newxz( q, numstates, U32);
- Newxz( aho->fail, numstates, U32 );
+ aho->fail = PerlMemShared_calloc( numstates, sizeof(U32) );
aho->refcount = 1;
fail = aho->fail;
/* initialize fail[0..1] to be 1 so that we always have
return min < stopmin ? min : stopmin;
}
-STATIC I32
-S_add_data(RExC_state_t *pRExC_state, I32 n, const char *s)
+STATIC U32
+S_add_data(RExC_state_t *pRExC_state, U32 n, const char *s)
{
- if (RExC_rxi->data) {
- const U32 count = RExC_rxi->data->count;
- Renewc(RExC_rxi->data,
- sizeof(*RExC_rxi->data) + sizeof(void*) * (count + n - 1),
- char, struct reg_data);
+ U32 count = RExC_rxi->data ? RExC_rxi->data->count : 0;
+
+ Renewc(RExC_rxi->data,
+ sizeof(*RExC_rxi->data) + sizeof(void*) * (count + n - 1),
+ char, struct reg_data);
+ if(count)
Renew(RExC_rxi->data->what, count + n, U8);
- RExC_rxi->data->count += n;
- }
- else {
- Newxc(RExC_rxi->data, sizeof(*RExC_rxi->data) + sizeof(void*) * (n - 1),
- char, struct reg_data);
+ else
Newx(RExC_rxi->data->what, n, U8);
- RExC_rxi->data->count = n;
- }
- Copy(s, RExC_rxi->data->what + RExC_rxi->data->count - n, n, U8);
- return RExC_rxi->data->count - n;
+ RExC_rxi->data->count = count + n;
+ Copy(s, RExC_rxi->data->what + count, n, U8);
+ return count;
}
#ifndef PERL_IN_XSUB_RE
regnode *trie_op;
/* this can happen only on restudy */
if ( OP(first) == TRIE ) {
- struct regnode_1 *trieop;
- Newxz(trieop,1,struct regnode_1);
+ struct regnode_1 *trieop =
+ PerlMemShared_calloc(1, sizeof(struct regnode_1));
StructCopy(first,trieop,struct regnode_1);
trie_op=(regnode *)trieop;
} else {
- struct regnode_charclass *trieop;
- Newxz(trieop,1,struct regnode_charclass);
+ struct regnode_charclass *trieop =
+ PerlMemShared_calloc(1, sizeof(struct regnode_charclass));
StructCopy(first,trieop,struct regnode_charclass);
trie_op=(regnode *)trieop;
}
&& !(data.start_class->flags & ANYOF_EOS)
&& !cl_is_anything(data.start_class))
{
- const I32 n = add_data(pRExC_state, 1, "f");
+ const U32 n = add_data(pRExC_state, 1, "f");
Newx(RExC_rxi->data->data[n], 1,
struct regnode_charclass_class);
if (!(data.start_class->flags & ANYOF_EOS)
&& !cl_is_anything(data.start_class))
{
- const I32 n = add_data(pRExC_state, 1, "f");
+ const U32 n = add_data(pRExC_state, 1, "f");
Newx(RExC_rxi->data->data[n], 1,
struct regnode_charclass_class);
/* FALL THROUGH */
case '{': /* (?{...}) */
{
- I32 count = 1, n = 0;
+ I32 count = 1;
+ U32 n = 0;
char c;
char *s = RExC_parse;
{
char ch = RExC_parse[0] == '<' ? '>' : '\'';
char *name_start= RExC_parse++;
- I32 num = 0;
+ U32 num = 0;
SV *sv_dat=reg_scan_name(pRExC_state,
SIZE_ONLY ? REG_RSN_RETURN_NULL : REG_RSN_RETURN_DATA);
if (RExC_parse == name_start || *RExC_parse != ch)
goto defchar;
} else {
char* name_start = (RExC_parse += 2);
- I32 num = 0;
+ U32 num = 0;
SV *sv_dat = reg_scan_name(pRExC_state,
SIZE_ONLY ? REG_RSN_RETURN_NULL : REG_RSN_RETURN_DATA);
ch= (ch == '<') ? '>' : '\'';
const reg_ac_data * const ac = IS_TRIE_AC(op) ?
(reg_ac_data *)progi->data->data[n] :
NULL;
- const reg_trie_data * const trie = !IS_TRIE_AC(op) ?
- (reg_trie_data*)progi->data->data[n] :
- ac->trie;
+ const reg_trie_data * const trie
+ = (reg_trie_data*)progi->data->data[!IS_TRIE_AC(op) ? n : ac->trie];
Perl_sv_catpvf(aTHX_ sv, "-%s",reg_name[o->flags]);
DEBUG_TRIE_COMPILE_r(
switch (ri->data->what[n]) {
case 's':
case 'S':
+ case 'u':
SvREFCNT_dec((SV*)ri->data->data[n]);
break;
case 'f':
refcount = --aho->refcount;
OP_REFCNT_UNLOCK;
if ( !refcount ) {
- Safefree(aho->states);
- Safefree(aho->fail);
- aho->trie=NULL; /* not necessary to free this as it is
- handled by the 't' case */
- Safefree(ri->data->data[n]); /* do this last!!!! */
- Safefree(ri->regstclass);
+ PerlMemShared_free(aho->states);
+ PerlMemShared_free(aho->fail);
+ /* do this last!!!! */
+ PerlMemShared_free(ri->data->data[n]);
+ PerlMemShared_free(ri->regstclass);
}
}
break;
refcount = --trie->refcount;
OP_REFCNT_UNLOCK;
if ( !refcount ) {
- Safefree(trie->charmap);
- if (trie->widecharmap)
- SvREFCNT_dec((SV*)trie->widecharmap);
- Safefree(trie->states);
- Safefree(trie->trans);
+ PerlMemShared_free(trie->charmap);
+ PerlMemShared_free(trie->states);
+ PerlMemShared_free(trie->trans);
if (trie->bitmap)
- Safefree(trie->bitmap);
+ PerlMemShared_free(trie->bitmap);
if (trie->wordlen)
- Safefree(trie->wordlen);
+ PerlMemShared_free(trie->wordlen);
if (trie->jump)
- Safefree(trie->jump);
+ PerlMemShared_free(trie->jump);
if (trie->nextword)
- Safefree(trie->nextword);
+ PerlMemShared_free(trie->nextword);
#ifdef DEBUGGING
if (trie->words)
SvREFCNT_dec((SV*)trie->words);
if (trie->revcharmap)
SvREFCNT_dec((SV*)trie->revcharmap);
#endif
- Safefree(ri->data->data[n]); /* do this last!!!! */
+ /* do this last!!!! */
+ PerlMemShared_free(ri->data->data[n]);
}
}
break;
for (i = 0; i < count; i++) {
d->what[i] = ri->data->what[i];
switch (d->what[i]) {
- /* legal options are one of: sSfpontT
+ /* legal options are one of: sSfpontTu
see also regcomp.h and pregfree() */
case 's':
case 'S':
+ case 'p': /* actually an AV, but the dup function is identical. */
+ case 'u': /* actually an HV, but the dup function is identical. */
d->data[i] = sv_dup_inc((SV *)ri->data->data[i], param);
break;
- case 'p':
- d->data[i] = av_dup_inc((AV *)ri->data->data[i], param);
- break;
case 'f':
/* This is cheating. */
Newx(d->data[i], 1, struct regnode_charclass_class);
d->data[i] = (void*)OpREFCNT_inc((OP*)ri->data->data[i]);
OP_REFCNT_UNLOCK;
break;
- case 'n':
- d->data[i] = ri->data->data[i];
- break;
- case 't':
- d->data[i] = ri->data->data[i];
- OP_REFCNT_LOCK;
- ((reg_trie_data*)d->data[i])->refcount++;
- OP_REFCNT_UNLOCK;
- break;
case 'T':
- d->data[i] = ri->data->data[i];
- OP_REFCNT_LOCK;
- ((reg_ac_data*)d->data[i])->refcount++;
- OP_REFCNT_UNLOCK;
/* Trie stclasses are readonly and can thus be shared
* without duplication. We free the stclass in pregfree
* when the corresponding reg_ac_data struct is freed.
*/
reti->regstclass= ri->regstclass;
+ /* Fall through */
+ case 't':
+ OP_REFCNT_LOCK;
+ ((reg_trie_data*)ri->data->data[i])->refcount++;
+ OP_REFCNT_UNLOCK;
+ /* Fall through */
+ case 'n':
+ d->data[i] = ri->data->data[i];
break;
default:
Perl_croak(aTHX_ "panic: re_dup unknown data code '%c'", ri->data->what[i]);
const reg_ac_data * const ac = op>=AHOCORASICK ?
(reg_ac_data *)ri->data->data[n] :
NULL;
- const reg_trie_data * const trie = op<AHOCORASICK ?
- (reg_trie_data*)ri->data->data[n] :
- ac->trie;
+ const reg_trie_data * const trie =
+ (reg_trie_data*)ri->data->data[op<AHOCORASICK ? n : ac->trie];
const regnode *nextbranch= NULL;
I32 word_idx;
sv_setpvn(sv, "", 0);