Skip to content

Commit

Permalink
Store object fields in an array
Browse files Browse the repository at this point in the history
We still use a dictionary and name lookup for getting indexes; that will need
to be fixed.  50% speedup on the parser benchmark
  • Loading branch information
sorear committed Sep 7, 2010
1 parent 09519c3 commit c54087f
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 60 deletions.
44 changes: 22 additions & 22 deletions lib/Cursor.cs
Expand Up @@ -58,13 +58,13 @@ public struct State {
return Kernel.Take(th, Kernel.NewROScalar(EMPTYP));
} else {
DynObject obs = new DynObject(LLArrayMO);
obs.slots["value"] = new List<Variable>();
obs.SetSlot("value", new List<Variable>());
DynObject its = new DynObject(LLArrayMO);
its.slots["value"] = new List<Variable>();
its.SetSlot("value", new List<Variable>());
DynObject lst = new DynObject(ListMO);
lst.slots["items"] = Kernel.NewROScalar(obs);
lst.slots["rest"] = Kernel.NewROScalar(its);
lst.slots["flat"] = Kernel.NewROScalar(Kernel.AnyP);
lst.SetSlot("items", Kernel.NewROScalar(obs));
lst.SetSlot("rest", Kernel.NewROScalar(its));
lst.SetSlot("flat", Kernel.NewROScalar(Kernel.AnyP));
th.caller.resultSlot = Kernel.NewRWListVar(lst);
}

Expand Down Expand Up @@ -208,20 +208,20 @@ public struct State {
DynObject obs = new DynObject(LLArrayMO);
List<Variable> ks = new List<Variable>();
ks.Add(Kernel.NewROScalar(MakeCursor()));
obs.slots["value"] = ks;
obs.SetSlot("value", ks);
DynObject it = new DynObject(GatherIteratorMO);
it.slots["value"] = Kernel.NewRWScalar(Kernel.AnyP);
it.slots["next"] = Kernel.NewRWScalar(Kernel.AnyP);
it.slots["valid"] = Kernel.NewRWScalar(Kernel.AnyP);
it.slots["frame"] = Kernel.NewRWScalar(th);
it.SetSlot("value", Kernel.NewRWScalar(Kernel.AnyP));
it.SetSlot("next", Kernel.NewRWScalar(Kernel.AnyP));
it.SetSlot("valid", Kernel.NewRWScalar(Kernel.AnyP));
it.SetSlot("frame", Kernel.NewRWScalar(th));
DynObject its = new DynObject(LLArrayMO);
List<Variable> iss = new List<Variable>();
iss.Add(Kernel.NewROScalar(it));
its.slots["value"] = iss;
its.SetSlot("value", iss);
DynObject lst = new DynObject(ListMO);
lst.slots["items"] = Kernel.NewROScalar(obs);
lst.slots["rest"] = Kernel.NewROScalar(its);
lst.slots["flat"] = Kernel.NewROScalar(Kernel.AnyP);
lst.SetSlot("items", Kernel.NewROScalar(obs));
lst.SetSlot("rest", Kernel.NewROScalar(its));
lst.SetSlot("flat", Kernel.NewROScalar(Kernel.AnyP));
th.caller.resultSlot = Kernel.NewRWListVar(lst);
}
return th.caller;
Expand Down Expand Up @@ -288,15 +288,15 @@ public Cursor(IP6 proto, string text)

DynObject obs = new DynObject(RxFrame.LLArrayMO);
List<Variable> ks = new List<Variable>();
obs.slots["value"] = ks;
obs.SetSlot("value", ks);

DynObject its = new DynObject(RxFrame.LLArrayMO);
its.slots["value"] = new List<Variable>();
its.SetSlot("value", new List<Variable>());

DynObject lst = new DynObject(RxFrame.ListMO);
lst.slots["items"] = Kernel.NewROScalar(obs);
lst.slots["rest"] = Kernel.NewROScalar(its);
lst.slots["flat"] = Kernel.NewROScalar(Kernel.AnyP);
lst.SetSlot("items", Kernel.NewROScalar(obs));
lst.SetSlot("rest", Kernel.NewROScalar(its));
lst.SetSlot("flat", Kernel.NewROScalar(Kernel.AnyP));

if (p != 0 && p != l && CC.Word.Accepts(backing[p]) &&
CC.Word.Accepts(backing[p-1])) {
Expand Down Expand Up @@ -435,7 +435,7 @@ public sealed class Edge {
if (Lexer.LtmTrace && method != null)
Console.WriteLine("+ Found method");

sub = ((SubInfo)(((DynObject)method).slots["info"])).ltm;
sub = ((SubInfo)(((DynObject)method).GetSlot("info"))).ltm;

if (Lexer.LtmTrace)
Console.WriteLine("+ {0} to sub-automaton",
Expand Down Expand Up @@ -712,7 +712,7 @@ public class LADProtoRegex : LAD {

public override void ToNFA(NFA pad, int from, int to) {
foreach (DynObject cand in Lexer.ResolveProtoregex(pad.cursor_class, name)) {
((SubInfo)cand.slots["info"]).ltm.ToNFA(pad, from, to);
((SubInfo)cand.GetSlot("info")).ltm.ToNFA(pad, from, to);
}
}

Expand Down Expand Up @@ -911,7 +911,7 @@ public class Lexer {
kl.name, name);
LAD[] branches = new LAD[candidates.Length];
for (int i = 0; i < candidates.Length; i++)
branches[i] = ((SubInfo) candidates[i].slots["info"]).ltm;
branches[i] = ((SubInfo) candidates[i].GetSlot("info")).ltm;
lc.protorx_nfa[name] = l = new Lexer(cursor.GetMO(), name, branches);
} else {
if (LtmTrace)
Expand Down
72 changes: 49 additions & 23 deletions lib/Kernel.cs
Expand Up @@ -302,6 +302,17 @@ public List<DynMetaObject> superclasses
public Dictionary<string, IP6> local_attr
= new Dictionary<string, IP6>();

public Dictionary<string, int> slotMap = new Dictionary<string, int>();
public int nslots = 0;

public int FindSlot(string name) {
int v;
if (slotMap.TryGetValue(name, out v))
return v;
else
return slotMap[name] = nslots++;
}

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

public List<DynMetaObject> mro;
Expand Down Expand Up @@ -435,27 +446,39 @@ public List<DynMetaObject> superclasses
public class DynObject: IP6 {
// the slots have to support non-containerized values, because
// containers are objects now
public Dictionary<string, object> slots
= new Dictionary<string, object>();
public object[] slots;
public DynMetaObject klass;

public DynObject(DynMetaObject klass) {
this.klass = klass;
this.slots = new object[klass.nslots];
}

public override DynMetaObject GetMO() { return klass; }

public override Frame GetAttribute(Frame caller, string name) {
if (slots == null) {
return Fail(caller, "Attempted to access slot " + name +
" via a protoobject");
" via an object with no slots");
}
caller.resultSlot = slots[name];
caller.resultSlot = GetSlot(name);
return caller;
}

public void SetSlot(string name, object obj) {
int ix = klass.FindSlot(name);
if (ix >= slots.Length)
Array.Resize(ref slots, ix+1);
slots[klass.FindSlot(name)] = obj;
}

public object GetSlot(string name) {
int ix = klass.FindSlot(name);
return (ix >= slots.Length) ? null : slots[ix];
}

public override bool IsDefined() {
return slots != null;
return this != klass.typeObject;
}
}

Expand All @@ -480,7 +503,7 @@ public class Kernel {
public static DynBlockDelegate MainlineContinuation;

public static object UnboxDO(DynObject o) {
return o.slots["value"];
return o.GetSlot("value");
}

public static object UnboxAny(IP6 o) {
Expand All @@ -489,12 +512,14 @@ public class Kernel {
}

private static Frame SCFetch(IP6 th, Frame caller) {
caller.resultSlot = UnboxAny(th);
DynObject dyo = (DynObject) th;
caller.resultSlot = dyo.GetSlot("value");
return caller;
}

private static Frame SCStore(IP6 th, Frame caller, IP6 nv) {
((DynObject)th).slots["value"] = nv;
DynObject dyo = (DynObject) th;
dyo.SetSlot("value", nv);
return caller;
}

Expand All @@ -516,17 +541,17 @@ public class Kernel {
public static Frame GatherHelper(Frame th, IP6 sub) {
DynObject dyo = (DynObject) sub;
Frame n = new Frame(th,
(Frame) dyo.slots["outer"],
(SubInfo) dyo.slots["info"]);
(Frame) dyo.GetSlot("outer"),
(SubInfo) dyo.GetSlot("info"));
th.resultSlot = n;
return th;
}

private static Frame SubInvoke(IP6 th, Frame caller,
Variable[] pos, Dictionary<string,Variable> named) {
Dictionary<string,object> sl = ((DynObject) th).slots;
Frame outer = (Frame) sl["outer"];
SubInfo info = (SubInfo) sl["info"];
DynObject dyo = ((DynObject) th);
Frame outer = (Frame) dyo.GetSlot("outer");
SubInfo info = (SubInfo) dyo.GetSlot("info");

Frame n = new Frame(caller, outer, info);
n.pos = pos;
Expand All @@ -551,7 +576,7 @@ public class Kernel {

public static Frame Die(Frame caller, string msg) {
DynObject n = new DynObject(((DynObject)StrP).klass);
n.slots["value"] = msg;
n.SetSlot("value", msg);
return new FatalException(n).SearchForHandler(caller);
}

Expand All @@ -562,28 +587,28 @@ public class Kernel {

public static IP6 MakeSub(SubInfo info, Frame outer) {
DynObject n = new DynObject(info.mo ?? SubMO);
n.slots["outer"] = outer;
n.slots["info"] = info;
n.SetSlot("outer", outer);
n.SetSlot("info", info);
return n;
}

public static DynObject MockBox(object v) {
DynObject n = new DynObject(ScalarMO);
n.slots["value"] = v;
n.SetSlot("value", v);
return n;
}

public static Variable BoxAny(object v, IP6 proto) {
if (v == null)
return NewROScalar(proto);
DynObject n = new DynObject(((DynObject)proto).klass);
n.slots["value"] = v;
n.SetSlot("value", v);
return NewROScalar(n);
}

public static IP6 MakeSC(IP6 inside) {
DynObject n = new DynObject(ScalarMO);
n.slots["value"] = inside;
n.slots[0] = inside;
return n;
}

Expand Down Expand Up @@ -768,7 +793,7 @@ public class Kernel {

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

Expand All @@ -778,7 +803,7 @@ public class Kernel {
public static IP6 AnyP;
public static IP6 ArrayP;
public static IP6 HashP;
public static IP6 StrP = new DynObject(null);
public static IP6 StrP = new DynObject(new DynMetaObject("proto-Str"));
public static DynMetaObject CallFrameMO;

public static Variable PackageLookup(IP6 parent, string name) {
Expand Down Expand Up @@ -853,6 +878,7 @@ public class Kernel {
SubMO.local["INVOKE"] = MakeSub(SubInvokeSubSI, null);

ScalarMO = new DynMetaObject("Scalar");
ScalarMO.FindSlot("value");
ScalarMO.OnFetch = new DynMetaObject.FetchHandler(SCFetch);
ScalarMO.OnStore = new DynMetaObject.StoreHandler(SCStore);

Expand Down Expand Up @@ -947,8 +973,8 @@ public abstract class ExceptionPacket {
CLRImportObject cp = p as CLRImportObject;
DynObject dp = p as DynObject;
Exception e = (cp != null) ? (cp.val as Exception) : null;
string s = (dp != null && dp.slots.ContainsKey("value")) ?
(dp.slots["value"] as string) : null;
string s = (dp != null && dp.klass.slotMap.ContainsKey("value")) ?
(dp.GetSlot("value") as string) : null;

if (e != null) {
// Wrapped CLR exception; has a message, and inner frames
Expand Down
21 changes: 9 additions & 12 deletions lib/SAFE.setting
Expand Up @@ -36,7 +36,7 @@ PRE-INIT {
(cast DynObject (@ (pos 0)))))]
[setfield how (l $mo) (l $self)]
[setindex meta-object (getfield slots (l $self))
[rawcall (l $self) SetSlot (clr_string meta-object)
(nsw (rawnew CLRImportObject (l $mo)))]
[ns (l $self)])
Expand Down Expand Up @@ -81,7 +81,7 @@ PRE-INIT {
[rawcall (l $mo) BuildC3MRO]
[setfield slots (l $p) (null Dictionary<string,object>)]
[setfield slots (l $p) (null 'object[]')]
[setfield typeObject (l $mo) (l $p)]
[newscalar (l $p)])
Expand All @@ -95,8 +95,8 @@ PRE-INIT {
[l $chch (ns (rawnew DynObject (l $chmo)))]
[setfield how (l $chmo) (@ (l $chch))]
[setindex meta-object (getfield slots (cast DynObject (@ (l $chch))))
(w (l $chmo))]
[rawcall (cast DynObject (@ (l $chch))) SetSlot
(clr_string meta-object) (w (l $chmo))]
[sink (subcall (@ (l &add-method)) (l $chch)
(string_var "new") (l &new))]
Expand Down Expand Up @@ -370,9 +370,8 @@ PRE-INIT {
[l obj (rawnew DynObject (getfield klass (cast DynObject
(@ (pos 0)))))]
[whileloop 0 0 (< (l i) (l max)) (prog
[setindex
[rawcall (l obj) SetSlot
(unbox String (@ (pos (l i))))
(getfield slots (l obj))
(nsw (@ (pos (+ (l i) (int 1)))))]
[l i (+ (l i) (int 2))])]
[ns (l obj)])
Expand Down Expand Up @@ -484,9 +483,8 @@ sub unfold-iter($fn) {
Any, "fun", $f);
Q:CgOp {
(prog
[setindex value (getfield slots
(cast DynObject (@ (l self))))
(subcall (@ (l $f)))]
[rawcall (cast DynObject (@ (l self))) SetSlot
(clr_string value) (subcall (@ (l $f)))]
[null Variable])
};
}
Expand Down Expand Up @@ -528,9 +526,8 @@ my class Parcel is Cool {
$it = $nit;
Q:CgOp {
(prog
[setindex value (getfield slots
(cast DynObject (@ (l $it))))
(methodcall (l $ll) at-pos (l $ix))]
[rawcall (cast DynObject (@ (l $it))) SetSlot
(clr_string value) (methodcall (l $ll) at-pos (l $ix))]
[null Variable])
};
$ix--;
Expand Down
2 changes: 2 additions & 0 deletions src/CodeGen.pm
Expand Up @@ -20,6 +20,8 @@ use 5.010;
HOW => [c => 'IP6'] },
DynObject =>
{ klass => [f => 'DynMetaObject'],
GetSlot => [m => 'object'],
SetSlot => [m => 'Void'],
slots => [f => 'Dictionary<string,Object>'] },

DynMetaObject =>
Expand Down
6 changes: 3 additions & 3 deletions src/Sig.pm
Expand Up @@ -35,11 +35,11 @@ use 5.010;
CgOp::cast('DynObject', CgOp::fetch(CgOp::scopedlex('List'))))), sub {
my $do = shift;
CgOp::prog(
CgOp::setindex('flat', CgOp::getfield('slots', $do),
CgOp::rawcall($do, 'SetSlot', CgOp::clr_string('flat'),
CgOp::box('Bool', CgOp::bool(1))),
CgOp::setindex('items', CgOp::getfield('slots', $do),
CgOp::rawcall($do, 'SetSlot', CgOp::clr_string('items'),
CgOp::box('LLArray', CgOp::rawnew('List<Variable>'))),
CgOp::setindex('rest', CgOp::getfield('slots', $do),
CgOp::rawcall($do, 'SetSlot', CgOp::clr_string('rest'),
CgOp::box('LLArray',
CgOp::rawscall('Kernel.SlurpyHelper',
CgOp::callframe, CgOp::letvar('!ix')))),
Expand Down

0 comments on commit c54087f

Please sign in to comment.