+#ifdef MULTIPLICITY
+ {
+ STRLEN op_len = oi->orig_pkg_len, tp_len = oi->type_pkg_len;
+ char *buf = oi->buf;
+ orig_pkg = sv_2mortal(newSVpvn(buf, op_len));
+ SvREADONLY_on(orig_pkg);
+ buf += op_len;
+ type_pkg = sv_2mortal(newSVpvn(buf, tp_len));
+ SvREADONLY_on(type_pkg);
+ buf += tp_len;
+ type_meth = sv_2mortal(newSVpvn(buf, oi->type_meth_len));
+ SvREADONLY_on(type_meth);
+ }
+#else /* MULTIPLICITY */
+ orig_pkg = oi->orig_pkg;
+ type_pkg = oi->type_pkg;
+ type_meth = oi->type_meth;
+#endif /* !MULTIPLICITY */
+
+ PUSHMARK(SP);
+ EXTEND(SP, 3);
+ PUSHs(type_pkg);
+ var_type = SvTYPE(sv);
+ switch (var_type) {
+ case SVt_PVAV:
+ case SVt_PVHV:
+ PUSHs(sv_2mortal(newRV_inc(sv)));
+ break;
+ default:
+ PUSHs(sv);
+ break;
+ }
+ PUSHs(orig_pkg);
+ PUTBACK;
+
+ items = call_sv(type_meth, G_ARRAY | G_METHOD);
+
+ SPAGAIN;
+ switch (items) {
+ case 0:
+ break;
+ case 1: {
+ SV *rsv = POPs;
+ switch (var_type) {
+ case SVt_PVAV:
+ if (SvROK(rsv) && SvTYPE(SvRV(rsv)) == var_type) {
+ AV *av = (AV *) SvRV(rsv);
+ SV **src, **dst;
+ I32 len = av_len(av);
+ I32 i;
+ av_fill((AV *) sv, len);
+ src = AvARRAY(av);
+ dst = AvARRAY(sv);
+ for (i = 0; i <= len; ++i, ++src, ++dst) {
+ SvREFCNT_dec(*dst);
+ *dst = SvREFCNT_inc(*src);
+ }
+ } else {
+ goto type_mismatch;
+ }
+ break;
+ case SVt_PVHV:
+ if (SvROK(rsv) && SvTYPE(SvRV(rsv)) == var_type) {
+ HV *hv = (HV *) SvRV(rsv);
+ HE *he;
+ hv_iterinit(hv);
+ hv_clear((HV *) sv);
+ while ((he = hv_iternext(hv)) != NULL) {
+ SV *val = SvREFCNT_inc(HeVAL(he));
+ if (!hv_store((HV *) sv, HeKEY(he), HeKLEN(he), val, HeHASH(he)))
+ SvREFCNT_dec(val);
+ }
+ } else {
+ goto type_mismatch;
+ }
+ break;
+ default:
+ sv_setsv(sv, rsv);
+ break;
+ }
+ break;
+type_mismatch:
+ croak("Type mismatch");
+ }
+ default: {
+ const char *type_desc;
+ switch (var_type) {
+ case SVt_PVAV:
+ type_desc = lt_type_desc_array;
+ break;
+ case SVt_PVHV:
+ type_desc = lt_type_desc_hash;
+ break;
+ default:
+ type_desc = lt_type_desc_scalar;
+ break;
+ }
+ croak("Typed %s initializer method should return zero or one scalar, but got %d", type_desc, items);
+ }
+ }
+ PUTBACK;
+
+ FREETMPS;
+ LEAVE;
+
+ return;
+}
+
+STATIC void lt_padxv_map_store(pTHX_ const OP *o, SV *orig_pkg, SV *type_pkg, SV *type_meth, OP *(*old_pp)(pTHX)) {
+#define lt_padxv_map_store(O, OP, TP, TM, PP) lt_padxv_map_store(aTHX_ (O), (OP), (TP), (TM), (PP))
+ lt_op_padxv_info *oi;
+
+ LT_LOCK(<_op_map_mutex);
+
+ if (!(oi = ptable_fetch(lt_op_padxv_map, o))) {