Skip to content

Commit

Permalink
Use a MRO cache
Browse files Browse the repository at this point in the history
  • Loading branch information
sorear committed Sep 13, 2010
1 parent 9f6189f commit 72a824b
Showing 1 changed file with 93 additions and 36 deletions.
129 changes: 93 additions & 36 deletions lib/Kernel.cs
Expand Up @@ -32,10 +32,8 @@ public abstract class IP6 {
Variable[] pos, Dictionary<string, Variable> named) {
IP6 m;
//Kernel.LogNameLookup(name);
foreach (DynMetaObject k in GetMO().mro) {
if (k.local.TryGetValue(name, out m)) {
return m.Invoke(caller, pos, named);
}
if (GetMO().mro_methods.TryGetValue(name, out m)) {
return m.Invoke(caller, pos, named);
}
return Fail(caller, "Unable to resolve method " + name);
}
Expand Down Expand Up @@ -63,21 +61,19 @@ public abstract class IP6 {

public virtual Frame Invoke(Frame c, Variable[] p,
Dictionary<string, Variable> n) {
foreach (DynMetaObject k in GetMO().mro) {
DynMetaObject.InvokeHandler ih = k.OnInvoke;;
if (ih != null) {
return ih(this, c, p, n);
}
DynMetaObject.InvokeHandler ih = GetMO().mro_OnInvoke;
if (ih != null) {
return ih(this, c, p, n);
} else {
Variable[] np = new Variable[p.Length + 1];
Array.Copy(p, 0, np, 1, p.Length);
np[0] = Kernel.NewROScalar(this);
return InvokeMethod(c, "INVOKE", np, n);
}

Variable[] np = new Variable[p.Length + 1];
Array.Copy(p, 0, np, 1, p.Length);
np[0] = Kernel.NewROScalar(this);
return InvokeMethod(c, "INVOKE", np, n);
}

public virtual Frame Fetch(Frame c) {
DynMetaObject.FetchHandler fh = GetMO().OnFetch;
DynMetaObject.FetchHandler fh = GetMO().mro_OnFetch;
if (fh != null) {
return fh(this, c);
} else {
Expand All @@ -87,7 +83,7 @@ public abstract class IP6 {
}

public virtual Frame Store(Frame c, IP6 o) {
DynMetaObject.StoreHandler sh = GetMO().OnStore;
DynMetaObject.StoreHandler sh = GetMO().mro_OnStore;
if (sh != null) {
return sh(this, c, o);
} else {
Expand Down Expand Up @@ -302,6 +298,11 @@ public class DynMetaObject {
public FetchHandler OnFetch;
public StoreHandler OnStore;

public InvokeHandler mro_OnInvoke;
public FetchHandler mro_OnFetch;
public StoreHandler mro_OnStore;
public Dictionary<string, IP6> mro_methods;

public List<DynMetaObject> superclasses
= new List<DynMetaObject>();
public Dictionary<string, IP6> local
Expand All @@ -311,23 +312,79 @@ public List<DynMetaObject> superclasses
public Dictionary<string, int> slotMap = new Dictionary<string, int>();
public int nslots = 0;

private WeakReference wr_this;
// protected by static lock
private HashSet<WeakReference> subclasses = new HashSet<WeakReference>();
private static object mro_cache_lock = new object();

public int FindSlot(string name) {
//Kernel.LogNameLookup(name);
return slotMap[name];
}

public Dictionary<string, List<DynObject>> multiregex;

public List<DynMetaObject> mro;
public DynMetaObject[] mro;
public HashSet<DynMetaObject> isa;

public DynMetaObject(string name) {
this.name = name;
this.mro = new List<DynMetaObject>();
mro.Add(this);
this.wr_this = new WeakReference(this);

isa = new HashSet<DynMetaObject>();
isa.Add(this);
}

private void Revalidate() {
mro_OnStore = null;
mro_OnInvoke = null;
mro_OnFetch = null;
mro_methods = new Dictionary<string,IP6>();

if (mro == null)
return;

for (int kx = mro.Length - 1; kx >= 0; kx--) {
DynMetaObject k = mro[kx];
if (k.OnStore != null)
mro_OnStore = k.OnStore;
if (k.OnFetch != null)
mro_OnFetch = k.OnFetch;
if (k.OnInvoke != null)
mro_OnInvoke = k.OnInvoke;

foreach (KeyValuePair<string,IP6> m in k.local)
mro_methods[m.Key] = m.Value;
}
}

private void SetMRO(DynMetaObject[] arr) {
lock(mro_cache_lock) {
if (mro != null)
foreach (DynMetaObject k in mro)
k.subclasses.Remove(wr_this);
foreach (DynMetaObject k in arr)
k.subclasses.Add(wr_this);
}
mro = arr;
}

~DynMetaObject() {
lock(mro_cache_lock)
if (mro != null)
foreach (DynMetaObject k in mro)
k.subclasses.Remove(wr_this);
}

private void Invalidate() {
if (mro == null)
return;
List<DynMetaObject> notify = new List<DynMetaObject>();
lock(mro_cache_lock)
foreach (WeakReference k in subclasses)
notify.Add(k.Target as DynMetaObject);
foreach (DynMetaObject k in notify)
if (k != null)
k.Revalidate();
}

public void AddMultiRegex(string name, IP6 m) {
Expand All @@ -343,24 +400,18 @@ public List<DynMetaObject> superclasses

public IP6 Can(string name) {
IP6 m;
foreach (DynMetaObject k in mro)
if (k.local.TryGetValue(name, out m))
return m;
if (mro_methods.TryGetValue(name, out m))
return m;
return null;
}

public Dictionary<string,IP6> AllMethods() {
Dictionary<string,IP6> r = new Dictionary<string,IP6>();
foreach (DynMetaObject k in mro)
foreach (KeyValuePair<string,IP6> kv in k.local)
if (!r.ContainsKey(kv.Key))
r[kv.Key] = kv.Value;
return r;
return mro_methods;
}

public HashSet<IP6> AllMethodsSet() {
HashSet<IP6> r = new HashSet<IP6>();
foreach (KeyValuePair<string,IP6> kv in AllMethods())
foreach (KeyValuePair<string,IP6> kv in mro_methods)
r.Add(kv.Value);
return r;
}
Expand All @@ -378,18 +429,20 @@ public List<DynMetaObject> superclasses
});
}

private static void DumpC3Lists(string f, List<DynMetaObject> m,
private static void DumpC3Lists(string f, DynMetaObject[] m,
List<List<DynMetaObject>> d) {
Console.WriteLine(f + MROStr(m) + " // " +
Console.WriteLine(f + MROStr(new List<DynMetaObject>(m)) + " // " +
Kernel.JoinS(" | ", d, MROStr));
}

public void AddMethod(string name, IP6 code) {
local[name] = code;
Invalidate();
}

public void AddAttribute(string name) {
local_attr.Add(name);
Invalidate();
}

public void AddSuperclass(DynMetaObject other) {
Expand All @@ -400,7 +453,7 @@ public List<DynMetaObject> superclasses
// just be sure that the attrib list doesn't change
public void Complete() {
List<List<DynMetaObject>> toMerge = new List<List<DynMetaObject>>();
mro = new List<DynMetaObject>();
List<DynMetaObject> mro_l = new List<DynMetaObject>();
isa = new HashSet<DynMetaObject>();
toMerge.Add(new List<DynMetaObject>());
toMerge[0].Add(this);
Expand Down Expand Up @@ -436,7 +489,7 @@ public List<DynMetaObject> superclasses
}
// no reason not to immediately put this, and by loop
// order the C3 condition is kept
mro.Add(cand);
mro_l.Add(cand);
isa.Add(cand);
foreach (List<DynMetaObject> l in toMerge) {
l.Remove(cand);
Expand All @@ -456,12 +509,16 @@ public List<DynMetaObject> superclasses
break;
}

SetMRO(mro_l.ToArray());

nslots = 0;
foreach (DynMetaObject k in mro) {
foreach (string an in k.local_attr) {
slotMap[an] = nslots++;
}
}

Invalidate();
}
}

Expand Down Expand Up @@ -822,9 +879,9 @@ public class Kernel {

public static Variable DefaultNew(IP6 proto) {
DynObject n = new DynObject(((DynObject)proto).klass);
List<DynMetaObject> mro = n.klass.mro;
DynMetaObject[] mro = n.klass.mro;

for (int i = mro.Count - 1; i >= 0; i--) {
for (int i = mro.Length - 1; i >= 0; i--) {
foreach (string s in mro[i].local_attr) {
n.SetSlot(s, NewRWScalar(AnyP));
}
Expand Down

0 comments on commit 72a824b

Please sign in to comment.