caching for calcMRO
[gitmo/Class-C3-XS.git] / lib / Class / C3 / XS.xs
index 990b51d..951a382 100644 (file)
@@ -32,10 +32,13 @@ __mro_linear_isa_c3(pTHX_ HV* stash, HV* cache, I32 level)
               stashname);
 
     if(!cache) {
-        cache = newHV();
+        cache = (HV*)sv_2mortal((SV*)newHV());
     }
     else {
-        /* XXX return cached entry for stashname if available */
+        sv_dump(cache);
+        SV** cache_entry = hv_fetch(cache, stashname, stashname_len, 0);
+        if(cache_entry)
+            return (AV*)SvREFCNT_inc(*cache_entry);
     }
 
     /* not in cache, make a new one */
@@ -139,8 +142,8 @@ __mro_linear_isa_c3(pTHX_ HV* stash, HV* cache, I32 level)
 
     SvREADONLY_on(retval);
     SvREFCNT_inc(retval); /* for cache storage */
-    SvREFCNT_inc(retval); /* for return to caller */
-    /* XXX store in cache storage */
+    SvREFCNT_inc(retval); /* for return */
+    hv_store(cache, stashname, stashname_len, (SV*)retval, 0);
     return retval;
 }
 
@@ -277,8 +280,7 @@ __nextcan(pTHX_ SV* self, I32 throw_nomethod)
     stashname_len = subname - fq_subname - 2;
     stashname = sv_2mortal(newSVpvn(fq_subname, stashname_len));
 
-    linear_av = __mro_linear_isa_c3(selfstash, NULL, 0); /* has ourselves at the top of the list */
-    sv_2mortal((SV*)linear_av);
+    linear_av = (AV*)sv_2mortal((SV*)__mro_linear_isa_c3(selfstash, NULL, 0));
 
     linear_svp = AvARRAY(linear_av);
     items = AvFILLp(linear_av) + 1;
@@ -293,7 +295,6 @@ __nextcan(pTHX_ SV* self, I32 throw_nomethod)
     if(items > 0) {
         SV* sub_sv = sv_2mortal(newSVpv(subname, subname_len));
         HV* cc3_mro = get_hv("Class::C3::MRO", 0);
-        SV* methods = sv_2mortal(newSVpv("methods", 7));
 
         while (items--) {
             linear_sv = *linear_svp++;
@@ -302,10 +303,10 @@ __nextcan(pTHX_ SV* self, I32 throw_nomethod)
             if(cc3_mro) {
                 HE* he_cc3_mro_class = hv_fetch_ent(cc3_mro, linear_sv, 0, 0);
                 if(he_cc3_mro_class) {
-                    HV* cc3_mro_class = (HV*)HeVAL(he_cc3_mro_class);
-                    HE* he_cc3_mro_class_methods = hv_fetch_ent(cc3_mro_class, methods, 0, 0);
-                    if(he_cc3_mro_class_methods) {
-                        HV* cc3_mro_class_methods = (HV*)HeVAL(he_cc3_mro_class_methods);
+                    HV* cc3_mro_class = (HV*)SvRV(HeVAL(he_cc3_mro_class));
+                    SV** svp_cc3_mro_class_methods = hv_fetch(cc3_mro_class, "methods", 7, 0);
+                    if(svp_cc3_mro_class_methods) {
+                        HV* cc3_mro_class_methods = (HV*)SvRV(*svp_cc3_mro_class_methods);
                         if(hv_exists_ent(cc3_mro_class_methods, sub_sv, 0))
                             continue;
                     }
@@ -368,14 +369,13 @@ XS(XS_Class_C3_XS_calculateMRO)
         croak("Usage: calculateMRO(classname[, cache])");
 
     classname = ST(0);
-    if(items == 2) cache = (HV*)ST(1);
+    if(items == 2) cache = (HV*)SvRV(ST(1));
 
     class_stash = gv_stashsv(classname, 0);
     if(!class_stash) croak("No such class: '%s'!", SvPV_nolen(classname));
 
     res = (AV*)sv_2mortal((SV*)__mro_linear_isa_c3(class_stash, cache, 0));
 
-
     res_items = ret_items = AvFILLp(res) + 1;
     res_ptr = AvARRAY(res);