Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implement the pad cache
Frames are now kept on a number of auxilliary doubly-linked lists.  In
each list, frames can be reused after they return, because the lists
are kept monotonic by call depth.  When the call stack needs to change
shape away from a stack, for closures and gather/take, a new list is
created and the relevant frames are relinked.  +30% speedup on the call
benchmark.
  • Loading branch information
sorear committed Oct 3, 2010
1 parent 0abde70 commit ee1b582
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 13 deletions.
1 change: 1 addition & 0 deletions lib/Cursor.cs
Expand Up @@ -281,6 +281,7 @@ public sealed class RxFrame {
if (return_one) {
return Kernel.Take(th, Kernel.NewROScalar(m));
} else {
th.MarkSharedChain();
return_one = true;
VarDeque ks = new VarDeque();
ks.Push(Kernel.NewROScalar(m));
Expand Down
73 changes: 61 additions & 12 deletions lib/Kernel.cs
Expand Up @@ -215,12 +215,15 @@ public class SubInfo {
// We need hashy frames available to properly handle BEGIN; for the time
// being, all frames will be hashy for simplicity
public class Frame: IP6 {
public readonly Frame caller;
public readonly Frame outer;
public readonly SubInfo info;
public Frame caller;
public Frame outer;
public SubInfo info;
// a doubly-linked list of frames being used by a given coroutine
public Frame reusable_child;
public Frame reuser;
public object resultSlot = null;
public int ip = 0;
public readonly DynBlockDelegate code;
public DynBlockDelegate code;
public Dictionary<string, object> lex;
// statistically, most subs have between 1 and 4 anonymous lexicals
public object lex0;
Expand All @@ -234,6 +237,10 @@ public class Frame: IP6 {
public Variable[] pos;
public Dictionary<string, Variable> named;

// after MakeSub, GatherHelper
public const int SHARED = 1;
public int flags;

public Frame(Frame caller_, Frame outer_,
SubInfo info_) {
caller = caller_;
Expand All @@ -242,6 +249,29 @@ public class Frame: IP6 {
info = info_;
}

public Frame() {}

public Frame MakeChild(Frame outer, SubInfo info) {
if (reusable_child == null) {
reusable_child = new Frame();
reusable_child.reuser = this;
}
reusable_child.ip = 0;
reusable_child.resultSlot = null;
reusable_child.lexn = null;
reusable_child.lex = null;
reusable_child.lex0 = null;
reusable_child.lex1 = null;
reusable_child.lex2 = null;
reusable_child.lex3 = null;
reusable_child.caller = this;
reusable_child.outer = outer;
reusable_child.info = info;
reusable_child.code = info.code;
reusable_child.rx = null;
return reusable_child;
}

public Frame Continue() {
return code(this);
}
Expand All @@ -256,6 +286,21 @@ public class Frame: IP6 {
}
}

public void MarkShared() {
if (0 == (flags & SHARED)) {
flags |= SHARED;
if (reuser != null) reuser.reusable_child = reusable_child;
if (reusable_child != null) reusable_child.reuser = reuser;
reuser = reusable_child = null;
}
}

// when control might re-enter a function
public void MarkSharedChain() {
for (Frame x = this; x != null; x = x.caller)
x.MarkShared();
}

public override DynMetaObject GetMO() { return Kernel.CallFrameMO; }

public int ExecutingLine() {
Expand Down Expand Up @@ -617,9 +662,9 @@ public class Kernel {

public static Frame GatherHelper(Frame th, IP6 sub) {
DynObject dyo = (DynObject) sub;
Frame n = new Frame(th,
(Frame) dyo.slots[0],
(SubInfo) dyo.slots[1]);
Frame n = th.MakeChild((Frame) dyo.slots[0],
(SubInfo) dyo.slots[1]);
n.MarkSharedChain();
th.resultSlot = n;
return th;
}
Expand All @@ -630,7 +675,7 @@ public class Kernel {
Frame outer = (Frame) dyo.slots[0];
SubInfo info = (SubInfo) dyo.slots[1];

Frame n = new Frame(caller, outer, info);
Frame n = caller.MakeChild(outer, info);
n.pos = pos;
n.named = named;

Expand Down Expand Up @@ -678,6 +723,7 @@ public class Kernel {
public static IP6 MakeSub(SubInfo info, Frame outer) {
DynObject n = new DynObject(info.mo ?? SubMO);
n.slots[0] = outer;
if (outer != null) outer.MarkShared();
n.slots[1] = info;
return n;
}
Expand Down Expand Up @@ -744,7 +790,7 @@ public class Kernel {

th.resultSlot = rhs;

n = new Frame(th, null, BindSI);
n = th.MakeChild(null, BindSI);
n.pos = new Variable[1] { rhs };
return n;
}
Expand Down Expand Up @@ -783,7 +829,7 @@ public class Kernel {
return th;
}

Frame n = new Frame(th, null, AssignSI);
Frame n = th.MakeChild(null, AssignSI);
n.pos = new Variable[2] { lhs, rhs };
return n;
}
Expand Down Expand Up @@ -886,8 +932,11 @@ public class Kernel {
}

public static Frame StartP6Thread(Frame th, IP6 sub) {
th.MarkSharedChain();
Thread thr = new Thread(delegate () {
Frame current = sub.Invoke(th, new Variable[0], null);
Frame current = new Frame();
current = sub.Invoke(current, new Variable[0], null);
current.caller = current.caller.caller;
RunCore(current, th);
});
thr.Start();
Expand Down Expand Up @@ -1021,7 +1070,7 @@ public class Kernel {
Environment.Exit(1);
}
in_unhandled = true;
Frame r = new Frame(th, null, UnhandledSI);
Frame r = th.MakeChild(null, UnhandledSI);
r.lex0 = mp;
return r;
} else {
Expand Down
2 changes: 1 addition & 1 deletion perf/callmark.pl
Expand Up @@ -29,4 +29,4 @@
sub x29 () { x28; x28 } # 536870911
sub x30 () { x29; x29 } # 1073741823

x25;
x26;

0 comments on commit ee1b582

Please sign in to comment.