ret->endp = ret->startp + npar;
ret->refcnt = 1;
if (r->substrs) {
- struct reg_substr_datum *s;
- I32 i;
Newx(ret->substrs, 1, struct reg_substr_data);
- for (s = ret->substrs->data, i = 0; i < 3; i++, s++) {
- s->min_offset = r->substrs->data[i].min_offset;
- s->max_offset = r->substrs->data[i].max_offset;
- s->end_shift = r->substrs->data[i].end_shift;
- if (i < 2) {
- s->substr = SvREFCNT_inc(r->substrs->data[i].substr);
- s->utf8_substr = SvREFCNT_inc(r->substrs->data[i].utf8_substr);
- }
- }
- if (r->check_substr == r->anchored_substr)
- ret->check_substr = ret->anchored_substr;
- else if (r->check_substr == r->float_substr)
- ret->check_substr = ret->float_substr;
- else {
- assert(!r->check_substr);
- ret->check_substr = NULL;
- }
- if (r->check_utf8 == r->anchored_utf8)
- ret->check_utf8 = ret->anchored_utf8;
- else if (r->check_utf8 == r->float_utf8)
- ret->check_utf8 = ret->float_utf8;
- else {
- assert(!r->check_utf8);
- ret->check_utf8 = NULL;
- }
+ StructCopy(r->substrs, ret->substrs, struct reg_substr_data);
+
+ SvREFCNT_inc_void(ret->anchored_substr);
+ SvREFCNT_inc_void(ret->anchored_utf8);
+ SvREFCNT_inc_void(ret->float_substr);
+ SvREFCNT_inc_void(ret->float_utf8);
+
+ /* check_substr and check_utf8, if non-NULL, point to either their
+ anchored or float namesakes, and don't hold a second reference. */
}
RX_MATCH_COPIED_off(ret);
#ifdef PERL_OLD_COPY_ON_WRITE
#define SAVEPVN(p,n) ((p) ? savepvn(p,n) : NULL)
/*
- regdupe - duplicate a regexp.
-
- This routine is called by sv.c's re_dup and is expected to clone a
- given regexp structure. It is a no-op when not under USE_ITHREADS.
- (Originally this *was* re_dup() for change history see sv.c)
+ re_dup - duplicate a regexp.
+ This routine is expected to clone a given regexp structure. It is not
+ compiler under USE_ITHREADS.
+
After all of the core data stored in struct regexp is duplicated
the regexp_engine.dupe method is used to copy any private data
stored in the *pprivate pointer. This allows extensions to handle
npar = r->nparens+1;
- Newxz(ret, 1, regexp);
+ Newx(ret, 1, regexp);
+ StructCopy(r, ret, regexp);
Newx(ret->startp, npar * 2, I32);
Copy(r->startp, ret->startp, npar * 2, I32);
ret->endp = ret->startp + npar;
- if(r->swap) {
+ if(ret->swap) {
Newx(ret->swap, 1, regexp_paren_ofs);
/* no need to copy these */
Newx(ret->swap->startp, npar * 2, I32);
ret->swap->endp = ret->swap->startp + npar;
- } else {
- ret->swap = NULL;
}
- if (r->substrs) {
- struct reg_substr_datum *s;
- const struct reg_substr_datum *s_end;
-
+ if (ret->substrs) {
+ /* Do it this way to avoid reading from *r after the StructCopy().
+ That way, if any of the sv_dup_inc()s dislodge *r from the L1
+ cache, it doesn't matter. */
+ const bool anchored = r->check_substr == r->anchored_substr;
Newx(ret->substrs, 1, struct reg_substr_data);
StructCopy(r->substrs, ret->substrs, struct reg_substr_data);
- s = ret->substrs->data;
- s_end
- = s + sizeof(ret->substrs->data) / sizeof(struct reg_substr_datum);
+ ret->anchored_substr = sv_dup_inc(ret->anchored_substr, param);
+ ret->anchored_utf8 = sv_dup_inc(ret->anchored_utf8, param);
+ ret->float_substr = sv_dup_inc(ret->float_substr, param);
+ ret->float_utf8 = sv_dup_inc(ret->float_utf8, param);
- do {
- s->substr = sv_dup_inc(s->substr, param);
- s->utf8_substr = sv_dup_inc(s->utf8_substr, param);
- } while (++s < s_end);
- } else
- ret->substrs = NULL;
+ /* check_substr and check_utf8, if non-NULL, point to either their
+ anchored or float namesakes, and don't hold a second reference. */
- ret->wrapped = SAVEPVN(r->wrapped, r->wraplen+1);
- ret->precomp = ret->wrapped + (r->precomp - r->wrapped);
- ret->prelen = r->prelen;
- ret->wraplen = r->wraplen;
+ if (ret->check_substr) {
+ if (anchored) {
+ assert(r->check_utf8 == r->anchored_utf8);
+ ret->check_substr = ret->anchored_substr;
+ ret->check_utf8 = ret->anchored_utf8;
+ } else {
+ assert(r->check_substr == r->float_substr);
+ assert(r->check_utf8 == r->float_utf8);
+ ret->check_substr = ret->float_substr;
+ ret->check_utf8 = ret->float_utf8;
+ }
+ }
+ }
- ret->mother_re = NULL;
- ret->refcnt = r->refcnt;
- ret->minlen = r->minlen;
- ret->minlenret = r->minlenret;
- ret->nparens = r->nparens;
- ret->lastparen = r->lastparen;
- ret->lastcloseparen = r->lastcloseparen;
- ret->intflags = r->intflags;
- ret->extflags = r->extflags;
-
- ret->sublen = r->sublen;
-
- ret->engine = r->engine;
-
- ret->paren_names = hv_dup_inc(r->paren_names, param);
+ ret->wrapped = SAVEPVN(ret->wrapped, ret->wraplen+1);
+ ret->precomp = ret->wrapped + (ret->precomp - ret->wrapped);
+ ret->paren_names = hv_dup_inc(ret->paren_names, param);
+
+ if (ret->pprivate)
+ RXi_SET(ret,CALLREGDUPE_PVT(ret,param));
if (RX_MATCH_COPIED(ret))
- ret->subbeg = SAVEPVN(r->subbeg, r->sublen);
+ ret->subbeg = SAVEPVN(ret->subbeg, ret->sublen);
else
ret->subbeg = NULL;
#ifdef PERL_OLD_COPY_ON_WRITE
ret->saved_copy = NULL;
#endif
-
- ret->pprivate = r->pprivate;
- if (ret->pprivate)
- RXi_SET(ret,CALLREGDUPE_PVT(ret,param));
+
+ ret->mother_re = NULL;
+ ret->gofs = 0;
+ ret->seen_evals = 0;
ptr_table_store(PL_ptr_table, r, ret);
return ret;