#define VMG_OP_INFO_NAME 1
#define VMG_OP_INFO_OBJECT 2
-STATIC STRLEN *vmg_op_name_len = NULL;
+STATIC U32 vmg_op_name_refcnt = 0;
+STATIC STRLEN *vmg_op_name_len = NULL;
STATIC HV *vmg_b__op_stash = NULL;
for (t = 0; t < OP_max; ++t)
vmg_op_name_len[t] = strlen(PL_op_name[t]);
}
+ ++vmg_op_name_refcnt;
break;
case VMG_OP_INFO_OBJECT:
if (!vmg_b__op_stash) {
}
}
+STATIC void vmg_op_info_deinit(unsigned int opinfo) {
+ switch (opinfo) {
+ case VMG_OP_INFO_NAME:
+ if (vmg_op_name_refcnt > 0)
+ --vmg_op_name_refcnt;
+ if (!vmg_op_name_refcnt && vmg_op_name_len) {
+ Safefree(vmg_op_name_len);
+ vmg_op_name_len = NULL;
+ }
+ break;
+ case VMG_OP_INFO_OBJECT:
+ default:
+ break;
+ }
+}
+
STATIC SV *vmg_op_info(pTHX_ unsigned int opinfo) {
#define vmg_op_info(W) vmg_op_info(aTHX_ (W))
if (!PL_op)
}
STATIC int vmg_svt_free(pTHX_ SV *sv, MAGIC *mg) {
- SV *wiz = (SV *) mg->mg_ptr;
const MGWIZ *w;
unsigned int flags;
int ret = 0;
- /* This may happen in global destruction */
- if (SvTYPE(wiz) == SVTYPEMASK)
+ /* Don't even bother if we are in global destruction - the wizard is prisoner
+ * of circular references and we are way beyond user realm */
+ if (PL_dirty)
return 0;
w = SV2MGWIZ(mg->mg_ptr);
if (w->cb_delete != NULL) { SvREFCNT_dec(SvRV(w->cb_delete)); }
#endif /* VMG_UVAR */
+ if (w->opinfo)
+ vmg_op_info_deinit(w->opinfo);
+
Safefree(w->vtbl);
Safefree(w);
STATIC const char vmg_wrongargnum[] = "Wrong number of arguments";
STATIC const char vmg_toomanysigs[] = "Too many magic signatures used";
STATIC const char vmg_argstorefailed[] = "Error while storing arguments";
+STATIC const char vmg_globstorefail[] = "Couldn't store global wizard information";
STATIC U16 vmg_sv2sig(pTHX_ SV *sv) {
#define vmg_sv2sig(S) vmg_sv2sig(aTHX_ (S))
STRLEN len;
char *sig = HePV(key, len);
SV *sv;
+ const MGWIZ *w;
MAGIC *mg;
- sv = MGWIZ2SV(vmg_wizard_clone(SV2MGWIZ(HeVAL(key))));
+ w = SV2MGWIZ(HeVAL(key));
+ w = vmg_wizard_clone(w);
+ sv = MGWIZ2SV(w);
mg = sv_magicext(sv, NULL, PERL_MAGIC_ext, &vmg_wizard_vtbl, NULL, 0);
mg->mg_private = SIG_WIZ;
SvREADONLY_on(sv);
- hv_store(hv, sig, len, sv, HeHASH(key));
+ if (!hv_store(hv, sig, len, sv, HeHASH(key))) croak("%s during CLONE", vmg_globstorefail);
}
}
{
mg->mg_private = SIG_WIZ;
SvREADONLY_on(sv);
- hv_store(MY_CXT, buf, sprintf(buf, "%u", sig), sv, 0);
+ if (!hv_store(MY_CXT, buf, sprintf(buf, "%u", sig), sv, 0)) croak(vmg_globstorefail);
RETVAL = newRV_noinc(sv);
OUTPUT:
OUTPUT:
RETVAL
-SV *getdata(SV *sv, SV *wiz)
+void
+getdata(SV *sv, SV *wiz)
PROTOTYPE: \[$@%&*]$
PREINIT:
SV *data;
U16 sig;
-CODE:
+PPCODE:
sig = vmg_wizard_sig(wiz);
if (!sig)
XSRETURN_UNDEF;
RETVAL = newSVuv(vmg_dispell(SvRV(sv), sig));
OUTPUT:
RETVAL
-
-void
-_cleanup()
-PROTOTYPE:
-PPCODE:
- if (vmg_op_name_len) {
- Safefree(vmg_op_name_len);
- vmg_op_name_len = NULL;
- }
- XSRETURN(0);