Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[dotnet] A little refactor to s-table to avoid having to do so many c…
…alls through lambdas; instead we only do that if dispatch/invocation is specialized in some way and mov ethe common path into a plain old method, which the runtime can better optimize.
  • Loading branch information
jnthn committed Nov 13, 2010
1 parent 8f4d667 commit ca07d19
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 37 deletions.
2 changes: 1 addition & 1 deletion dotnet/runtime/Metamodel/KnowHOW/KnowHOWBootstrapper.cs
Expand Up @@ -130,7 +130,7 @@ public static RakudoObject Bootstrap()

// And put a fake FindMethod in there that just looks in the
// dictionary.
KnowHOWHOW.STable.FindMethod = (TC, Obj, Name, Hint) =>
KnowHOWHOW.STable.SpecialFindMethod = (TC, Obj, Name, Hint) =>
{
var MTable = ((KnowHOWREPR.KnowHOWInstance)Obj).Methods;
if (MTable.ContainsKey(Name))
Expand Down
2 changes: 1 addition & 1 deletion dotnet/runtime/Metamodel/Representations/RakudoCodeRef.cs
Expand Up @@ -93,7 +93,7 @@ public override RakudoObject type_object_for(ThreadContext TC, RakudoObject Meta

// Also twiddle the S-Table's Invoke to invoke the contained
// function.
STable.Invoke = (TCi, Obj, Cap) =>
STable.SpecialInvoke = (TCi, Obj, Cap) =>
((RakudoCodeRef.Instance)Obj).Body(TCi, Obj, Cap);

return STable.WHAT;
Expand Down
88 changes: 54 additions & 34 deletions dotnet/runtime/Metamodel/SharedTable.cs
Expand Up @@ -33,54 +33,74 @@ public sealed class SharedTable
public RakudoObject WHAT;

/// <summary>
/// This finds a method with the given name or using a hint.
/// We keep a cache of the find_method method.
/// </summary>
public Func<ThreadContext, RakudoObject, string, int, RakudoObject> FindMethod =
(TC, Obj, Name, Hint) =>
{
// See if we can find it by hint.
if (Hint != Hints.NO_HINT && Obj.STable.VTable != null && Hint < Obj.STable.VTable.Length)
{
// Yes, just grab it from the v-table.
return Obj.STable.VTable[Hint];
}
else
{
// Find the find_method method.
var HOW = Obj.STable.HOW;
RakudoObject Meth = Obj.STable.CachedFindMethod;
if (Meth == null)
Obj.STable.CachedFindMethod = Meth = HOW.STable.FindMethod(
TC, HOW, "find_method", Hints.NO_HINT);
// Call it.
var Cap = CaptureHelper.FormWith(new RakudoObject[] { HOW, Obj, Ops.box_str(TC, Name, TC.DefaultStrBoxType) });
return Meth.STable.Invoke(TC, Meth, Cap);
}
};
internal RakudoObject CachedFindMethod;

/// <summary>
/// We keep a cache of the find_method method.
/// Sometimes, we may want to install a hook for overriding method
/// finding. This does that. (We used to just give this a default
/// closure, but it makes dispatch a bit more expensive, and this is
/// path is red hot...)
/// </summary>
internal RakudoObject CachedFindMethod;
public Func<ThreadContext, RakudoObject, string, int, RakudoObject> SpecialFindMethod;

/// <summary>
/// The default invoke looks up a postcircumfix:<( )> and runs that.
/// XXX Cache the hint where we can.
/// This finds a method with the given name or using a hint.
/// </summary>
public Func<ThreadContext, RakudoObject, RakudoObject, RakudoObject> Invoke =
(TC, Obj, Cap) =>
public RakudoObject FindMethod(ThreadContext TC, RakudoObject Obj, string Name, int Hint)
{
// Does this s-table have a special overridden finder?
if (SpecialFindMethod != null)
return SpecialFindMethod(TC, Obj, Name, Hint);

// See if we can find it by hint.
if (Hint != Hints.NO_HINT && Obj.STable.VTable != null && Hint < Obj.STable.VTable.Length)
{
var STable = Obj.STable;
var Invokable = STable.CachedInvoke ?? (STable.CachedInvoke = Obj.STable.FindMethod(TC, Obj, "postcircumfix:<( )>", Hints.NO_HINT));
return Invokable.STable.Invoke(TC, Obj, Cap);
};
// Yes, just grab it from the v-table.
return Obj.STable.VTable[Hint];
}
else
{
// Find the find_method method.
var HOW = Obj.STable.HOW;
RakudoObject Meth = Obj.STable.CachedFindMethod;
if (Meth == null)
Obj.STable.CachedFindMethod = Meth = HOW.STable.FindMethod(
TC, HOW, "find_method", Hints.NO_HINT);

// Call it.
var Cap = CaptureHelper.FormWith(new RakudoObject[] { HOW, Obj, Ops.box_str(TC, Name, TC.DefaultStrBoxType) });
return Meth.STable.Invoke(TC, Meth, Cap);
}
}

/// <summary>
/// We keep a cache of the postcircumfix:<( )> method.
/// </summary>
internal RakudoObject CachedInvoke;

/// <summary>
/// Hook for overriding invocation.
/// </summary>
public Func<ThreadContext, RakudoObject, RakudoObject, RakudoObject> SpecialInvoke;

/// <summary>
/// Invokes. By default, looks up a postcircumfix:<( )> and runs that.
/// </summary>
/// <param name="TC"></param>
/// <param name="Obj"></param>
/// <param name="Cap"></param>
/// <returns></returns>
public RakudoObject Invoke(ThreadContext TC, RakudoObject Obj, RakudoObject Cap)
{
if (SpecialInvoke != null)
return SpecialInvoke(TC, Obj, Cap);
var STable = Obj.STable;
var Invokable = STable.CachedInvoke ?? (STable.CachedInvoke = Obj.STable.FindMethod(TC, Obj, "postcircumfix:<( )>", Hints.NO_HINT));
return Invokable.STable.Invoke(TC, Obj, Cap);
}

/// <summary>
/// The serialization context of this STable, if any.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion dotnet/runtime/Runtime/CodeObjectUtility.cs
Expand Up @@ -29,7 +29,7 @@ public static RakudoObject WrapNativeMethod(Func<ThreadContext, RakudoObject, Ra
{
var REPR = REPRRegistry.get_REPR_by_name("KnowHOWREPR");
var Wrapper = REPR.type_object_for(null, null);
Wrapper.STable.Invoke = Code;
Wrapper.STable.SpecialInvoke = Code;
return Wrapper;
}

Expand Down

0 comments on commit ca07d19

Please sign in to comment.