Skip to content

Commit

Permalink
fixed: #519
Browse files Browse the repository at this point in the history
  • Loading branch information
dadhi committed Aug 23, 2022
1 parent e5109e5 commit 0473ea0
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 39 deletions.
8 changes: 4 additions & 4 deletions src/DryIoc/Container.Generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ partial class Container
{
partial void GetLastGeneratedFactoryID(ref int lastFactoryID)
{
lastFactoryID = 366; // generated: equals to the last used Factory.FactoryID
lastFactoryID = 443; // generated: equals to the last used Factory.FactoryID
}

partial void ResolveGenerated(ref object service, Type serviceType)
Expand All @@ -62,7 +62,7 @@ partial void ResolveGenerated(ref object service,
requiredServiceType == null &&
Equals(preRequestParent, Request.Empty.Push(
typeof(IService),
361,
438,
typeof(MyService),
Reuse.Transient,
RequestFlags.IsResolutionCall)))
Expand Down Expand Up @@ -92,7 +92,7 @@ internal static object Get_IService_0(IResolverContext r) =>
null,
Request.Empty.Push(
typeof(IService),
361,
438,
typeof(MyService),
Reuse.Transient,
RequestFlags.IsResolutionCall|RequestFlags.StopRecursiveDependencyCheck),
Expand All @@ -104,7 +104,7 @@ internal static object Get_IService_0(IResolverContext r) =>
null,
Request.Empty.Push(
typeof(IService),
361,
438,
typeof(MyService),
Reuse.Transient,
RequestFlags.IsResolutionCall|RequestFlags.StopRecursiveDependencyCheck),
Expand Down
17 changes: 10 additions & 7 deletions src/DryIoc/Container.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3521,7 +3521,7 @@ private static bool TryInterpretMethodCall(IResolverContext r, MethodCallExpress
return true;
}

if (method == Scope.TrackDisposableMethod)
if (method.IsGenericMethod && method.GetGenericMethodDefinition() == Scope.TrackDisposableOpenGenericMethod)
{
var args = (InstanceTwoArgumentsMethodCallExpression)callExpr;
if (!TryInterpret(r, args.Argument0, paramExprs, paramValues, parentArgs, out var service))
Expand Down Expand Up @@ -13035,7 +13035,7 @@ public T TrackDisposable<T>(T item, int disposalOrder = 0) where T : IDisposable
return item;
}

internal static readonly MethodInfo TrackDisposableMethod = typeof(IScope).GetMethod(nameof(IScope.TrackDisposable));
internal static readonly MethodInfo TrackDisposableOpenGenericMethod = typeof(IScope).GetMethod(nameof(IScope.TrackDisposable));

/// <inheritdoc />
public void SetUsed(int hash, Type type, object instance)
Expand Down Expand Up @@ -13224,19 +13224,21 @@ public Expression Apply(Request request, Expression serviceFactoryExpr)
if (serviceFactoryExpr.NodeType == ExprType.Convert)
serviceFactoryExpr = ((UnaryExpression)serviceFactoryExpr).Operand;

// this is required because we cannot use ValueType for the object
if (serviceFactoryExpr.Type.IsValueType)
serviceFactoryExpr = Convert<object>(serviceFactoryExpr);

var disposalOrder = request.Factory.Setup.DisposalOrder;
var serviceExprType = serviceFactoryExpr.Type;

if (request.TracksTransientDisposable)
return Call(ResolverContext.SingletonScopeExpr, Scope.TrackDisposableMethod,
return Call(ResolverContext.SingletonScopeExpr,
Scope.TrackDisposableOpenGenericMethod.MakeGenericMethod(serviceExprType), // todo: @simplify @perf convert trackdisposable to accepting and returning object
serviceFactoryExpr, ConstantInt(disposalOrder));

var factoryId = request.FactoryType == FactoryType.Decorator
? request.CombineDecoratorWithDecoratedFactoryID() : request.FactoryID;

// this is required because we cannot use ValueType for the object
if (serviceExprType.IsValueType)
serviceFactoryExpr = Convert<object>(serviceFactoryExpr);

var lambdaExpr = new FactoryDelegateExpression(serviceFactoryExpr);

if (request.DependencyCount > 0)
Expand Down Expand Up @@ -13418,6 +13420,7 @@ public override bool TryEmit(CompilerFlags config, ref ClosureInfo closure, IPar
return false;

EmittingVisitor.TryEmitNonByRefNonValueTypeParameter(FactoryDelegateCompiler.ResolverContextParamExpr, paramExprs, il, ref closure);

return EmittingVisitor.EmitVirtualMethodCall(il, Scope.GetOrAddViaFactoryDelegateMethod);
}
}
Expand Down
62 changes: 34 additions & 28 deletions src/DryIoc/FastExpressionCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3645,6 +3645,8 @@ private static bool TryEmitListInit(ListInitExpression expr, IReadOnlyList<PE> p

var inits = expr.Initializers;
var initCount = inits.Count;
var ok = true;

// see the TryEmitMethodCall for the reason of the callFlags
var callFlags = parent & ~ParentFlags.IgnoreResult & ~ParentFlags.MemberAccess & ~ParentFlags.InstanceAccess | ParentFlags.Call;
for (var i = 0; i < initCount; ++i)
Expand All @@ -3664,29 +3666,24 @@ private static bool TryEmitListInit(ListInitExpression expr, IReadOnlyList<PE> p
var addArgs = elemInit.Arguments;
var addArgCount = addArgs.Count;
#endif
for (var a = 0; a < addArgCount; ++a)
{
var arg = addArgs.GetArgument(a);
if (!TryEmit(addArgs.GetArgument(a), paramExprs, il, ref closure, setup, callFlags, methodParams[a].ParameterType.IsByRef ? a : -1))
return false;
}
for (var a = 0; ok && a < addArgCount; ++a)
ok = TryEmit(addArgs.GetArgument(a), paramExprs, il, ref closure, setup, callFlags, methodParams[a].ParameterType.IsByRef ? a : -1);

if (!exprType.IsValueType)
EmitMethodCallOrVirtualCall(il, method);
else if (!method.IsVirtual) // #251 - no need for constrain or virtual call because it is already by-ref
EmitMethodCall(il, method);
else if (method.DeclaringType == exprType)
EmitMethodCall(il, method);
ok = EmitMethodCallOrVirtualCall(il, method);
else if (!method.IsVirtual // #251 - no need for constrain or virtual call because it is already by-ref
|| method.DeclaringType == exprType)
ok = EmitMethodCall(il, method);
else
{
il.Emit(OpCodes.Constrained, exprType); // todo: @check it is a value type so... can we de-virtualize the call?
EmitVirtualMethodCall(il, method);
ok = EmitVirtualMethodCall(il, method);
}
}

if (valueVarIndex != -1)
EmitLoadLocalVariable(il, valueVarIndex);
return true;
return ok;
}

#if LIGHT_EXPRESSION
Expand Down Expand Up @@ -4147,23 +4144,24 @@ private static bool TryEmitMethodCall(Expression expr, IReadOnlyList<PE> paramEx
#endif
}

var ok = true;
if (!objIsValueType)
EmitMethodCallOrVirtualCall(il, method);
else if (!method.IsVirtual || objExpr is ParameterExpression p && p.IsByRef)
EmitMethodCall(il, method);
else if (method.DeclaringType == objExpr.Type)
EmitMethodCall(il, method);
ok = EmitMethodCallOrVirtualCall(il, method);
else if (!method.IsVirtual ||
objExpr is ParameterExpression p && p.IsByRef ||
method.DeclaringType == objExpr.Type)
ok = EmitMethodCall(il, method);
else
{
il.Emit(OpCodes.Constrained, objExpr.Type);
EmitVirtualMethodCall(il, method);
ok = EmitVirtualMethodCall(il, method);
}

if (parent.IgnoresResult() && method.ReturnType != typeof(void))
il.Emit(OpCodes.Pop);

closure.LastEmitIsAddress = false;
return true;
return ok;
}

#if LIGHT_EXPRESSION
Expand Down Expand Up @@ -4197,8 +4195,7 @@ public static bool TryEmitMemberAccess(MemberExpression expr, IReadOnlyList<PE>
}

closure.LastEmitIsAddress = false;
EmitMethodCallOrVirtualCall(il, prop.GetMethod);
return true;
return EmitMethodCallOrVirtualCall(il, prop.GetMethod);
}

if (expr.Member is FieldInfo field)
Expand Down Expand Up @@ -5167,28 +5164,37 @@ private static Expression TryReduceCondition(Expression testExpr)
return testExpr;
}

// todo: @feature EmitCall is specifically for the varags method and not for normal conventions methods,
// for those you need to call Emit(OpCodes.Call|Callvirt, methodInfo).
// So for now the varargs methods are not supported yet.
[MethodImpl((MethodImplOptions)256)]
public static bool EmitMethodCallOrVirtualCall(ILGenerator il, MethodInfo method)
{
// todo: @feature EmitCall is specifically for the varags method and not for normal conventions methods,
// for those you need to call Emit(OpCodes.Call|Callvirt, methodInfo).
// So for now the varargs methods are not supported yet.
var ok = (method.CallingConvention & CallingConventions.VarArgs) == 0;
il.Emit(method.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, method);
return true;
return ok;
}

[MethodImpl((MethodImplOptions)256)]
public static bool EmitVirtualMethodCall(ILGenerator il, MethodInfo method)
{
// todo: @feature EmitCall is specifically for the varags method and not for normal conventions methods,
// for those you need to call Emit(OpCodes.Call|Callvirt, methodInfo).
// So for now the varargs methods are not supported yet.
var ok = (method.CallingConvention & CallingConventions.VarArgs) == 0;
il.Emit(OpCodes.Callvirt, method);
return true;
return ok;
}

[MethodImpl((MethodImplOptions)256)]
public static bool EmitMethodCall(ILGenerator il, MethodInfo method)
{
// todo: @feature EmitCall is specifically for the varags method and not for normal conventions methods,
// for those you need to call Emit(OpCodes.Call|Callvirt, methodInfo).
// So for now the varargs methods are not supported yet.
var ok = (method.CallingConvention & CallingConventions.VarArgs) == 0;
il.Emit(OpCodes.Call, method);
return true;
return ok;
}

/// Efficiently emit the int constant
Expand Down

0 comments on commit 0473ea0

Please sign in to comment.