+static const struct mro_alg dfs_alg =
+ {S_mro_get_linear_isa_dfs, "dfs", 3, 0, 0};
+
+SV *
+Perl_mro_get_private_data(pTHX_ struct mro_meta *const smeta,
+ const struct mro_alg *const which)
+{
+ SV **data;
+ PERL_ARGS_ASSERT_MRO_GET_PRIVATE_DATA;
+
+ data = (SV **)Perl_hv_common(aTHX_ smeta->mro_linear_all, NULL,
+ which->name, which->length, which->kflags,
+ HV_FETCH_JUST_SV, NULL, which->hash);
+ if (!data)
+ return NULL;
+
+ /* If we've been asked to look up the private data for the current MRO, then
+ cache it. */
+ if (smeta->mro_which == which)
+ smeta->mro_linear_current = *data;
+
+ return *data;
+}
+
+SV *
+Perl_mro_set_private_data(pTHX_ struct mro_meta *const smeta,
+ const struct mro_alg *const which, SV *const data)
+{
+ PERL_ARGS_ASSERT_MRO_SET_PRIVATE_DATA;
+
+ if (!smeta->mro_linear_all) {
+ if (smeta->mro_which == which) {
+ /* If all we need to store is the current MRO's data, then don't use
+ memory on a hash with 1 element - store it direct, and signal
+ this by leaving the would-be-hash NULL. */
+ smeta->mro_linear_current = data;
+ return data;
+ } else {
+ HV *const hv = newHV();
+ /* Start with 2 buckets. It's unlikely we'll need more. */
+ HvMAX(hv) = 1;
+ smeta->mro_linear_all = hv;
+
+ if (smeta->mro_linear_current) {
+ /* If we were storing something directly, put it in the hash
+ before we lose it. */
+ Perl_mro_set_private_data(aTHX_ smeta, smeta->mro_which,
+ smeta->mro_linear_current);
+ }
+ }
+ }
+
+ /* We get here if we're storing more than one linearisation for this stash,
+ or the linearisation we are storing is not that if its current MRO. */
+
+ if (smeta->mro_which == which) {
+ /* If we've been asked to store the private data for the current MRO,
+ then cache it. */
+ smeta->mro_linear_current = data;
+ }
+
+ if (!Perl_hv_common(aTHX_ smeta->mro_linear_all, NULL,
+ which->name, which->length, which->kflags,
+ HV_FETCH_ISSTORE, data, which->hash)) {
+ Perl_croak(aTHX_ "panic: hv_store() failed in set_mro_private_data() "
+ "for '%.*s' %d", (int) which->length, which->name,
+ which->kflags);
+ }
+
+ return data;
+}
+
+const struct mro_alg *
+Perl_mro_get_from_name(pTHX_ SV *name) {
+ SV **data;
+
+ PERL_ARGS_ASSERT_MRO_GET_FROM_NAME;
+
+ data = (SV **)Perl_hv_common(aTHX_ PL_registered_mros, name, NULL, 0, 0,
+ HV_FETCH_JUST_SV, NULL, 0);
+ if (!data)
+ return NULL;
+ assert(SvTYPE(*data) == SVt_IV);
+ assert(SvIOK(*data));
+ return INT2PTR(const struct mro_alg *, SvUVX(*data));
+}
+
+void
+Perl_mro_register(pTHX_ const struct mro_alg *mro) {
+ SV *wrapper = newSVuv(PTR2UV(mro));
+
+ PERL_ARGS_ASSERT_MRO_REGISTER;
+
+
+ if (!Perl_hv_common(aTHX_ PL_registered_mros, NULL,
+ mro->name, mro->length, mro->kflags,
+ HV_FETCH_ISSTORE, wrapper, mro->hash)) {
+ SvREFCNT_dec(wrapper);
+ Perl_croak(aTHX_ "panic: hv_store() failed in mro_register() "
+ "for '%.*s' %d", (int) mro->length, mro->name, mro->kflags);
+ }
+}
+