stack_grow(SV **sp, SV **p, int n)
{
dTHR;
+#if defined(DEBUGGING) && !defined(USE_THREADS)
+ static int growing = 0;
+ if (growing++)
+ abort();
+#endif
stack_sp = sp;
+#ifndef STRESS_REALLOC
av_extend(curstack, (p - stack_base) + (n) + 128);
+#else
+ av_extend(curstack, (p - stack_base) + (n) + 1);
+#endif
+#if defined(DEBUGGING) && !defined(USE_THREADS)
+ growing--;
+#endif
return stack_sp;
}
+#ifndef STRESS_REALLOC
+#define GROW(old) ((old) * 3 / 2)
+#else
+#define GROW(old) ((old) + 1)
+#endif
+
+PERL_SI *
+new_stackinfo(I32 stitems, I32 cxitems)
+{
+ PERL_SI *si;
+ PERL_CONTEXT *cxt;
+ New(56, si, 1, PERL_SI);
+ si->si_stack = newAV();
+ AvREAL_off(si->si_stack);
+ av_extend(si->si_stack, stitems > 0 ? stitems-1 : 0);
+ AvALLOC(si->si_stack)[0] = &sv_undef;
+ AvFILLp(si->si_stack) = 0;
+ si->si_prev = 0;
+ si->si_next = 0;
+ si->si_cxmax = cxitems - 1;
+ si->si_cxix = -1;
+ si->si_type = SI_UNDEF;
+ New(56, si->si_cxstack, cxitems, PERL_CONTEXT);
+ return si;
+}
+
I32
cxinc(void)
{
dTHR;
- cxstack_max = cxstack_max * 3 / 2;
+ cxstack_max = GROW(cxstack_max);
Renew(cxstack, cxstack_max + 1, PERL_CONTEXT); /* XXX should fix CXINC macro */
return cxstack_ix + 1;
}
{
dTHR;
if (retstack_ix == retstack_max) {
- retstack_max = retstack_max * 3 / 2;
+ retstack_max = GROW(retstack_max);
Renew(retstack, retstack_max, OP*);
}
retstack[retstack_ix++] = retop;
{
dTHR;
if (scopestack_ix == scopestack_max) {
- scopestack_max = scopestack_max * 3 / 2;
+ scopestack_max = GROW(scopestack_max);
Renew(scopestack, scopestack_max, I32);
}
scopestack[scopestack_ix++] = savestack_ix;
{
dTHR;
I32 oldmax = markstack_max - markstack;
- I32 newmax = oldmax * 3 / 2;
+ I32 newmax = GROW(oldmax);
Renew(markstack, newmax, I32);
markstack_ptr = markstack + oldmax;
savestack_grow(void)
{
dTHR;
- savestack_max = savestack_max * 3 / 2;
+ savestack_max = GROW(savestack_max) + 4;
Renew(savestack, savestack_max, ANY);
}
+#undef GROW
+
void
free_tmps(void)
{
save_scalar(GV *gv)
{
dTHR;
+ SV **sptr = &GvSV(gv);
SSCHECK(3);
- SSPUSHPTR(gv);
- SSPUSHPTR(GvSV(gv));
+ SSPUSHPTR(SvREFCNT_inc(gv));
+ SSPUSHPTR(SvREFCNT_inc(*sptr));
SSPUSHINT(SAVEt_SV);
- return save_scalar_at(&GvSV(gv));
+ return save_scalar_at(sptr);
}
SV*
dTHR;
SSCHECK(3);
SSPUSHPTR(sptr);
- SSPUSHPTR(*sptr);
+ SSPUSHPTR(SvREFCNT_inc(*sptr));
SSPUSHINT(SAVEt_SVREF);
return save_scalar_at(sptr);
}
save_ary(GV *gv)
{
dTHR;
- AV *oav, *av;
+ AV *oav = GvAVn(gv);
+ AV *av;
+ if (!AvREAL(oav) && AvREIFY(oav))
+ av_reify(oav);
SSCHECK(3);
SSPUSHPTR(gv);
- SSPUSHPTR(oav = GvAVn(gv));
+ SSPUSHPTR(oav);
SSPUSHINT(SAVEt_AV);
GvAV(gv) = Null(AV*);
save_item(register SV *item)
{
dTHR;
- register SV *sv;
+ register SV *sv = NEWSV(0,0);
+ sv_setsv(sv,item);
SSCHECK(3);
SSPUSHPTR(item); /* remember the pointer */
- sv = NEWSV(0,0);
- sv_setsv(sv,item);
SSPUSHPTR(sv); /* remember the value */
SSPUSHINT(SAVEt_ITEM);
}
{
#ifdef USE_THREADS
dTHR;
- SV **svp = av_fetch(thr->threadsv, i, FALSE);
+ SV **svp = &THREADSV(i); /* XXX Change to save by offset */
DEBUG_L(PerlIO_printf(PerlIO_stderr(), "save_threadsv %u: %p %p:%s\n",
i, svp, *svp, SvPEEK(*svp)));
save_svref(svp);
SSCHECK(4);
SSPUSHINT(klen);
SSPUSHPTR(key);
- SSPUSHPTR(hv);
+ SSPUSHPTR(SvREFCNT_inc(hv));
SSPUSHINT(SAVEt_DELETE);
}
register SV *sv;
register I32 i;
- SSCHECK(3 * maxsarg);
for (i = 1; i <= maxsarg; i++) {
- SSPUSHPTR(sarg[i]); /* remember the pointer */
sv = NEWSV(0,0);
sv_setsv(sv,sarg[i]);
+ SSCHECK(3);
+ SSPUSHPTR(sarg[i]); /* remember the pointer */
SSPUSHPTR(sv); /* remember the value */
SSPUSHINT(SAVEt_ITEM);
}
}
void
+save_aelem(AV *av, I32 idx, SV **sptr)
+{
+ dTHR;
+ SSCHECK(4);
+ SSPUSHPTR(SvREFCNT_inc(av));
+ SSPUSHINT(idx);
+ SSPUSHPTR(SvREFCNT_inc(*sptr));
+ SSPUSHINT(SAVEt_AELEM);
+ save_scalar_at(sptr);
+}
+
+void
+save_helem(HV *hv, SV *key, SV **sptr)
+{
+ dTHR;
+ SSCHECK(4);
+ SSPUSHPTR(SvREFCNT_inc(hv));
+ SSPUSHPTR(SvREFCNT_inc(key));
+ SSPUSHPTR(SvREFCNT_inc(*sptr));
+ SSPUSHINT(SAVEt_HELEM);
+ save_scalar_at(sptr);
+}
+
+void
save_op(void)
{
dTHR;
register AV *av;
register HV *hv;
register void* ptr;
+ I32 i;
if (base < -1)
croak("panic: corrupt saved stack index");
value = (SV*)SSPOPPTR;
gv = (GV*)SSPOPPTR;
ptr = &GvSV(gv);
+ SvREFCNT_dec(gv);
goto restore_sv;
case SAVEt_SVREF: /* scalar reference */
value = (SV*)SSPOPPTR;
localizing = 2;
SvSETMAGIC(value);
localizing = 0;
+ SvREFCNT_dec(value);
break;
case SAVEt_AV: /* array reference */
av = (AV*)SSPOPPTR;
case SAVEt_GP: /* scalar reference */
ptr = SSPOPPTR;
gv = (GV*)SSPOPPTR;
- gp_free(gv);
- GvGP(gv) = (GP*)ptr;
if (SvPOK(gv) && SvLEN(gv) > 0) {
Safefree(SvPVX(gv));
}
SvPVX(gv) = (char *)SSPOPPTR;
SvCUR(gv) = (STRLEN)SSPOPIV;
SvLEN(gv) = (STRLEN)SSPOPIV;
+ gp_free(gv);
+ GvGP(gv) = (GP*)ptr;
SvREFCNT_dec(gv);
break;
case SAVEt_FREESV:
}
else { /* Someone has a claim on this, so abandon it. */
U32 padflags = SvFLAGS(sv) & (SVs_PADBUSY|SVs_PADMY|SVs_PADTMP);
- SvREFCNT_dec(sv); /* Cast current value to the winds. */
switch (SvTYPE(sv)) { /* Console ourselves with a new value */
case SVt_PVAV: *(SV**)ptr = (SV*)newAV(); break;
case SVt_PVHV: *(SV**)ptr = (SV*)newHV(); break;
default: *(SV**)ptr = NEWSV(0,0); break;
}
+ SvREFCNT_dec(sv); /* Cast current value to the winds. */
SvFLAGS(*(SV**)ptr) |= padflags; /* preserve pad nature */
}
break;
hv = (HV*)ptr;
ptr = SSPOPPTR;
(void)hv_delete(hv, (char*)ptr, (U32)SSPOPINT, G_DISCARD);
+ SvREFCNT_dec(hv);
Safefree(ptr);
break;
case SAVEt_DESTRUCTOR:
(*SSPOPDPTR)(ptr);
break;
case SAVEt_REGCONTEXT:
- {
- I32 delta = SSPOPINT;
- savestack_ix -= delta; /* regexp must have croaked */
- }
+ i = SSPOPINT;
+ savestack_ix -= i; /* regexp must have croaked */
break;
case SAVEt_STACK_POS: /* Position on Perl stack */
- {
- I32 delta = SSPOPINT;
- stack_sp = stack_base + delta;
+ i = SSPOPINT;
+ stack_sp = stack_base + i;
+ break;
+ case SAVEt_AELEM: /* array element */
+ value = (SV*)SSPOPPTR;
+ i = SSPOPINT;
+ av = (AV*)SSPOPPTR;
+ ptr = av_fetch(av,i,1);
+ if (ptr) {
+ sv = *(SV**)ptr;
+ if (sv && sv != &sv_undef) {
+ if (SvRMAGICAL(av) && mg_find((SV*)av, 'P'))
+ (void)SvREFCNT_inc(sv);
+ SvREFCNT_dec(av);
+ goto restore_sv;
+ }
+ }
+ SvREFCNT_dec(av);
+ SvREFCNT_dec(value);
+ break;
+ case SAVEt_HELEM: /* hash element */
+ value = (SV*)SSPOPPTR;
+ sv = (SV*)SSPOPPTR;
+ hv = (HV*)SSPOPPTR;
+ ptr = hv_fetch_ent(hv, sv, 1, 0);
+ if (ptr) {
+ SV *oval = HeVAL((HE*)ptr);
+ if (oval && oval != &sv_undef) {
+ ptr = &HeVAL((HE*)ptr);
+ if (SvRMAGICAL(hv) && mg_find((SV*)hv, 'P'))
+ (void)SvREFCNT_inc(*(SV**)ptr);
+ SvREFCNT_dec(hv);
+ SvREFCNT_dec(sv);
+ goto restore_sv;
+ }
}
+ SvREFCNT_dec(hv);
+ SvREFCNT_dec(sv);
+ SvREFCNT_dec(value);
break;
case SAVEt_OP:
op = (OP*)SSPOPPTR;