+/* --- Module setup/teardown ----------------------------------------------- */
+
+static void indirect_teardown(pTHX_ void *interp) {
+ dMY_CXT;
+
+#if I_MULTIPLICITY
+ if (aTHX != interp)
+ return;
+#endif
+
+ I_LOADED_LOCK;
+
+ if (indirect_clear_loaded_locked(&MY_CXT)) {
+ indirect_ck_restore(OP_CONST, &indirect_old_ck_const);
+ indirect_ck_restore(OP_RV2SV, &indirect_old_ck_rv2sv);
+ indirect_ck_restore(OP_PADANY, &indirect_old_ck_padany);
+ indirect_ck_restore(OP_SCOPE, &indirect_old_ck_scope);
+ indirect_ck_restore(OP_LINESEQ, &indirect_old_ck_lineseq);
+
+ indirect_ck_restore(OP_METHOD, &indirect_old_ck_method);
+ indirect_ck_restore(OP_METHOD_NAMED, &indirect_old_ck_method_named);
+ indirect_ck_restore(OP_ENTERSUB, &indirect_old_ck_entersub);
+ }
+
+ I_LOADED_UNLOCK;
+
+ SvREFCNT_dec(MY_CXT.global_code);
+ MY_CXT.global_code = NULL;
+
+ ptable_free(MY_CXT.map);
+ MY_CXT.map = NULL;
+
+#if I_THREADSAFE
+ ptable_hints_free(MY_CXT.tbl);
+ MY_CXT.tbl = NULL;
+#endif
+
+ return;
+}
+
+static void indirect_setup(pTHX) {
+#define indirect_setup() indirect_setup(aTHX)
+ MY_CXT_INIT; /* Takes/release PL_my_ctx_mutex */
+
+ I_LOADED_LOCK;
+
+ if (indirect_set_loaded_locked(&MY_CXT)) {
+ PERL_HASH(indirect_hash, __PACKAGE__, __PACKAGE_LEN__);
+
+ indirect_ck_replace(OP_CONST, indirect_ck_const, &indirect_old_ck_const);
+ indirect_ck_replace(OP_RV2SV, indirect_ck_rv2sv, &indirect_old_ck_rv2sv);
+ indirect_ck_replace(OP_PADANY, indirect_ck_padany, &indirect_old_ck_padany);
+ indirect_ck_replace(OP_SCOPE, indirect_ck_scope, &indirect_old_ck_scope);
+ indirect_ck_replace(OP_LINESEQ, indirect_ck_scope, &indirect_old_ck_lineseq);
+
+ indirect_ck_replace(OP_METHOD, indirect_ck_method,
+ &indirect_old_ck_method);
+ indirect_ck_replace(OP_METHOD_NAMED, indirect_ck_method_named,
+ &indirect_old_ck_method_named);
+ indirect_ck_replace(OP_ENTERSUB, indirect_ck_entersub,
+ &indirect_old_ck_entersub);
+ }
+
+ I_LOADED_UNLOCK;
+
+ {
+ HV *stash;
+
+ stash = gv_stashpvn(__PACKAGE__, __PACKAGE_LEN__, 1);
+ newCONSTSUB(stash, "I_THREADSAFE", newSVuv(I_THREADSAFE));
+ newCONSTSUB(stash, "I_FORKSAFE", newSVuv(I_FORKSAFE));
+
+#if I_THREADSAFE
+ MY_CXT.tbl = ptable_new();
+ MY_CXT.owner = aTHX;
+#endif
+
+ MY_CXT.map = ptable_new();
+ MY_CXT.global_code = NULL;
+ }
+
+#if I_MULTIPLICITY
+ call_atexit(indirect_teardown, aTHX);
+#else
+ call_atexit(indirect_teardown, NULL);
+#endif
+
+ return;
+}