+STATIC SV *rep_validate_callback(SV *code) {
+ if (!SvROK(code))
+ return NULL;
+
+ code = SvRV(code);
+ if (SvTYPE(code) < SVt_PVCV)
+ return NULL;
+
+ return SvREFCNT_inc_simple_NN(code);
+}
+
+#if REP_WORKAROUND_REQUIRE_PROPAGATION
+STATIC IV rep_require_tag(pTHX) {
+#define rep_require_tag() rep_require_tag(aTHX)
+ const CV *cv, *outside;
+
+ cv = PL_compcv;
+
+ if (!cv) {
+ /* If for some reason the pragma is operational at run-time, try to discover
+ * the current cv in use. */
+ const PERL_SI *si;
+
+ for (si = PL_curstackinfo; si; si = si->si_prev) {
+ I32 cxix;
+
+ for (cxix = si->si_cxix; cxix >= 0; --cxix) {
+ const PERL_CONTEXT *cx = si->si_cxstack + cxix;
+
+ switch (CxTYPE(cx)) {
+ case CXt_SUB:
+ case CXt_FORMAT:
+ /* The propagation workaround is only needed up to 5.10.0 and at that
+ * time format and sub contexts were still identical. And even later the
+ * cv members offsets should have been kept the same. */
+ cv = cx->blk_sub.cv;
+ goto get_enclosing_cv;
+ case CXt_EVAL:
+ cv = cx->blk_eval.cv;
+ goto get_enclosing_cv;
+ default:
+ break;
+ }
+ }
+ }
+
+ cv = PL_main_cv;
+ }
+
+get_enclosing_cv:
+ for (outside = CvOUTSIDE(cv); outside; outside = CvOUTSIDE(cv))
+ cv = outside;
+
+ return PTR2IV(cv);
+}
+#endif /* REP_WORKAROUND_REQUIRE_PROPAGATION */
+
+STATIC SV *rep_tag(pTHX_ SV *comp, SV *exec) {
+#define rep_tag(C, E) rep_tag(aTHX_ (C), (E))
+ rep_hint_t *h;
+
+ h = PerlMemShared_malloc(sizeof *h);
+ h->comp = rep_validate_callback(comp);
+ h->exec = rep_validate_callback(exec);
+#if REP_WORKAROUND_REQUIRE_PROPAGATION
+ h->require_tag = rep_require_tag();
+#endif /* REP_WORKAROUND_REQUIRE_PROPAGATION */
+
+#if REP_THREADSAFE
+ {
+ dMY_CXT;
+ /* We only need for the key to be an unique tag for looking up the value later
+ * Allocated memory provides convenient unique identifiers, so that's why we
+ * use the hint as the key itself. */
+ ptable_store(MY_CXT.tbl, h, h);
+ }
+#endif /* REP_THREADSAFE */
+
+ return newSViv(PTR2IV(h));
+}
+
+STATIC const rep_hint_t *rep_detag(pTHX_ const SV *hint) {
+#define rep_detag(H) rep_detag(aTHX_ (H))
+ rep_hint_t *h;
+
+ if (!(hint && SvIOK(hint)))
+ return NULL;
+
+ h = INT2PTR(rep_hint_t *, SvIVX(hint));
+#if REP_THREADSAFE
+ {
+ dMY_CXT;
+ h = ptable_fetch(MY_CXT.tbl, h);
+ }
+#endif /* REP_THREADSAFE */