Skip to content

Commit e80c1f5

Browse files
committed
Implement 'we should grab an array' idea
Using a sparse dictionary instead of a non-sparse plain array for track- ing mutable by-ref parameters is likely only more efficient for methods with a large number of parameters. While we're at it, prevent unnecessary allocations for parameter-less methods.
1 parent a6b90f8 commit e80c1f5

1 file changed

Lines changed: 21 additions & 14 deletions

File tree

src/Castle.Core/DynamicProxy/Generators/InvocationTypeGenerator.cs

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,9 @@ protected virtual void ImplementInvokeMethodOnTarget(ClassEmitter invocation, Pa
115115

116116
var argumentsMarshaller = new ArgumentsMarshaller(invocation, invokeMethodOnTarget, parameters);
117117

118-
argumentsMarshaller.CopyOut(out var args, out var byRefArguments);
118+
argumentsMarshaller.CopyOut(out var args, out var byRefArguments, out var hasByRefArguments);
119119

120-
if (byRefArguments.Count > 0)
120+
if (hasByRefArguments)
121121
{
122122
invokeMethodOnTarget.CodeBuilder.AddStatement(TryStatement.Instance);
123123
}
@@ -136,7 +136,7 @@ protected virtual void ImplementInvokeMethodOnTarget(ClassEmitter invocation, Pa
136136
invokeMethodOnTarget.CodeBuilder.AddStatement(methodOnTargetInvocationExpression);
137137
}
138138

139-
if (byRefArguments.Count > 0)
139+
if (hasByRefArguments)
140140
{
141141
invokeMethodOnTarget.CodeBuilder.AddStatement(FinallyStatement.Instance);
142142
argumentsMarshaller.CopyIn(byRefArguments);
@@ -264,13 +264,19 @@ public ArgumentsMarshaller(ClassEmitter invocation, MethodEmitter method, Parame
264264
this.parameters = parameters;
265265
}
266266

267-
public void CopyOut(out IExpression[] arguments, out Dictionary<int, LocalReference> byRefArguments)
267+
public void CopyOut(out IExpression[] arguments, out LocalReference[] byRefArguments, out bool hasByRefArguments)
268268
{
269-
arguments = new IExpression[parameters.Length];
269+
if (parameters.Length == 0)
270+
{
271+
arguments = [];
272+
byRefArguments = [];
273+
hasByRefArguments = false;
274+
return;
275+
}
270276

271-
// Idea: instead of grab parameters one by one
272-
// we should grab an array
273-
byRefArguments = new Dictionary<int, LocalReference>();
277+
arguments = new IExpression[parameters.Length];
278+
byRefArguments = new LocalReference[parameters.Length];
279+
hasByRefArguments = false;
274280

275281
for (int i = 0, n = parameters.Length; i < n; ++i)
276282
{
@@ -306,6 +312,7 @@ public void CopyOut(out IExpression[] arguments, out Dictionary<int, LocalRefere
306312
method.CodeBuilder.AddStatement(new AssignStatement(localCopy, dereferencedArgument));
307313
arguments[i] = new AddressOfExpression(localCopy);
308314
byRefArguments[i] = localCopy;
315+
hasByRefArguments = true;
309316
}
310317
else
311318
{
@@ -314,12 +321,12 @@ public void CopyOut(out IExpression[] arguments, out Dictionary<int, LocalRefere
314321
}
315322
}
316323

317-
public void CopyIn(Dictionary<int, LocalReference> byRefArguments)
324+
public void CopyIn(LocalReference[] byRefArguments)
318325
{
319-
foreach (var byRefArgument in byRefArguments)
326+
for (int i = 0, n = byRefArguments.Length; i < n; ++i)
320327
{
321-
var index = byRefArgument.Key;
322-
var localCopy = byRefArgument.Value;
328+
var localCopy = byRefArguments[i];
329+
if (localCopy == null) continue;
323330

324331
#if FEATURE_BYREFLIKE
325332
if (localCopy.Type.IsByRefLikeSafe())
@@ -333,7 +340,7 @@ public void CopyIn(Dictionary<int, LocalReference> byRefArguments)
333340
new MethodInvocationExpression(
334341
ThisExpression.Instance,
335342
InvocationMethods.SetArgumentValue,
336-
new LiteralIntExpression(index),
343+
new LiteralIntExpression(i),
337344
NullExpression.Instance));
338345
}
339346
else
@@ -343,7 +350,7 @@ public void CopyIn(Dictionary<int, LocalReference> byRefArguments)
343350
new MethodInvocationExpression(
344351
ThisExpression.Instance,
345352
InvocationMethods.SetArgumentValue,
346-
new LiteralIntExpression(index),
353+
new LiteralIntExpression(i),
347354
new ConvertExpression(
348355
typeof(object),
349356
localCopy.Type,

0 commit comments

Comments
 (0)