Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs')
-rw-r--r--src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs259
1 files changed, 38 insertions, 221 deletions
diff --git a/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs b/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs
index af8cb9a05..a4e4b8896 100644
--- a/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs
+++ b/src/Common/src/TypeSystem/IL/Stubs/DelegateThunks.cs
@@ -187,11 +187,20 @@ namespace Internal.IL.Stubs
// Call a helper to get the actual method target
codeStream.EmitLdArg(0);
- codeStream.EmitLdArg(1);
- if (boxThisType != null)
+
+ if (Signature[0].IsByRef)
+ {
+ codeStream.Emit(ILOpcode.ldnull);
+ }
+ else
{
- codeStream.Emit(ILOpcode.box, emitter.NewToken(boxThisType));
+ codeStream.EmitLdArg(1);
+ if (boxThisType != null)
+ {
+ codeStream.Emit(ILOpcode.box, emitter.NewToken(boxThisType));
+ }
}
+
codeStream.Emit(ILOpcode.call, emitter.NewToken(SystemDelegateType.GetKnownMethod("GetActualTargetFunctionPointer", null)));
MethodSignature targetSignature = new MethodSignature(0, 0, Signature.ReturnType, parameters);
@@ -555,14 +564,13 @@ namespace Internal.IL.Stubs
codeStream.EmitLdc(i);
codeStream.EmitLdArg(i + 1);
- TypeDesc boxableParamType = DelegateDynamicInvokeThunk.ConvertToBoxableType(paramType);
- ILToken boxableParamToken = emitter.NewToken(boxableParamType);
+ ILToken paramToken = emitter.NewToken(paramType);
if (paramIsByRef)
{
- codeStream.Emit(ILOpcode.ldobj, boxableParamToken);
+ codeStream.Emit(ILOpcode.ldobj, paramToken);
}
- codeStream.Emit(ILOpcode.box, boxableParamToken);
+ codeStream.Emit(ILOpcode.box, paramToken);
codeStream.Emit(ILOpcode.stelem_ref);
}
}
@@ -616,16 +624,15 @@ namespace Internal.IL.Stubs
if (paramType.IsByRef)
{
paramType = ((ByRefType)paramType).ParameterType;
- TypeDesc boxableParamType = DelegateDynamicInvokeThunk.ConvertToBoxableType(paramType);
- ILToken boxableParamToken = emitter.NewToken(boxableParamType);
+ ILToken paramToken = emitter.NewToken(paramType);
// Update parameter
codeStream.EmitLdArg(i + 1);
codeStream.EmitLdLoc(argsLocal);
codeStream.EmitLdc(i);
codeStream.Emit(ILOpcode.ldelem_ref);
- codeStream.Emit(ILOpcode.unbox_any, boxableParamToken);
- codeStream.Emit(ILOpcode.stobj, boxableParamToken);
+ codeStream.Emit(ILOpcode.unbox_any, paramToken);
+ codeStream.Emit(ILOpcode.stobj, paramToken);
}
}
// ilgen.Emit(OperationCode.Endfinally);
@@ -635,9 +642,8 @@ namespace Internal.IL.Stubs
if (hasReturnValue)
{
- TypeDesc boxableReturnType = DelegateDynamicInvokeThunk.ConvertToBoxableType(Signature.ReturnType);
codeStream.EmitLdLoc(retLocal);
- codeStream.Emit(ILOpcode.unbox_any, emitter.NewToken(boxableReturnType));
+ codeStream.Emit(ILOpcode.unbox_any, emitter.NewToken(Signature.ReturnType));
}
codeStream.Emit(ILOpcode.ret);
@@ -655,213 +661,6 @@ namespace Internal.IL.Stubs
}
/// <summary>
- /// Delegate thunk that supports Delegate.DynamicInvoke. This thunk has heavy dependencies on the
- /// general dynamic invocation infrastructure in System.InvokeUtils and gets called from there
- /// at runtime. See comments in System.InvokeUtils for a more thorough explanation.
- /// </summary>
- public sealed partial class DelegateDynamicInvokeThunk : ILStubMethod
- {
- private DelegateInfo _delegateInfo;
- private MethodSignature _signature;
-
- public DelegateDynamicInvokeThunk(DelegateInfo delegateInfo)
- {
- _delegateInfo = delegateInfo;
- }
-
- public override TypeSystemContext Context
- {
- get
- {
- return _delegateInfo.Type.Context;
- }
- }
-
- public override TypeDesc OwningType
- {
- get
- {
- return _delegateInfo.Type;
- }
- }
-
- public override MethodSignature Signature
- {
- get
- {
- if (_signature == null)
- {
- _signature = new MethodSignature(0, 0,
- Context.GetWellKnownType(WellKnownType.Object),
- new TypeDesc[] {
- Context.GetWellKnownType(WellKnownType.Object),
- Context.GetWellKnownType(WellKnownType.IntPtr),
- ArgSetupStateType.MakeByRefType() });
- }
- return _signature;
- }
- }
-
- public override Instantiation Instantiation
- {
- get
- {
- return Instantiation.Empty;
- }
- }
-
- public override string Name
- {
- get
- {
- return "DynamicInvokeImpl";
- }
- }
-
- private MetadataType InvokeUtilsType
- {
- get
- {
- return Context.SystemModule.GetKnownType("System", "InvokeUtils");
- }
- }
-
- private MetadataType ArgSetupStateType
- {
- get
- {
- return InvokeUtilsType.GetNestedType("ArgSetupState");
- }
- }
-
- public override MethodIL EmitIL()
- {
- ILEmitter emitter = new ILEmitter();
- ILCodeStream argSetupStream = emitter.NewCodeStream();
- ILCodeStream callSiteSetupStream = emitter.NewCodeStream();
-
- // This function will look like
- //
- // !For each parameter to the delegate
- // !if (parameter is In Parameter)
- // localX is TypeOfParameterX&
- // ldtoken TypeOfParameterX
- // call DynamicInvokeParamHelperIn(RuntimeTypeHandle)
- // stloc localX
- // !else
- // localX is TypeOfParameter
- // ldtoken TypeOfParameterX
- // call DynamicInvokeParamHelperRef(RuntimeTypeHandle)
- // stloc localX
-
- // ldarg.3
- // call DynamicInvokeArgSetupComplete(ref ArgSetupState)
-
- // *** Second instruction stream starts here ***
-
- // ldarg.1 // Load this pointer
- // !For each parameter
- // !if (parameter is In Parameter)
- // ldloc localX
- // ldobj TypeOfParameterX
- // !else
- // ldloc localX
- // ldarg.1
- // calli ReturnType thiscall(TypeOfParameter1, ...)
- // !if ((ReturnType == void)
- // ldnull
- // !else if (ReturnType is a byref)
- // ldobj StripByRef(ReturnType)
- // box StripByRef(ReturnType)
- // !else
- // box ReturnType
- // ret
-
- callSiteSetupStream.EmitLdArg(1);
-
- MethodSignature delegateSignature = _delegateInfo.Signature;
-
- TypeDesc[] targetMethodParameters = new TypeDesc[delegateSignature.Length];
-
- for (int paramIndex = 0; paramIndex < delegateSignature.Length; paramIndex++)
- {
- TypeDesc paramType = delegateSignature[paramIndex];
- TypeDesc localType = paramType;
-
- targetMethodParameters[paramIndex] = paramType;
-
- if (localType.IsByRef)
- {
- // Strip ByRef
- localType = ((ByRefType)localType).ParameterType;
- }
- else
- {
- // Only if this is not a ByRef, convert the parameter type to something boxable.
- // Everything but pointer types are boxable.
- localType = ConvertToBoxableType(localType);
- }
-
- ILLocalVariable local = emitter.NewLocal(localType.MakeByRefType());
-
- callSiteSetupStream.EmitLdLoc(local);
-
- argSetupStream.Emit(ILOpcode.ldtoken, emitter.NewToken(localType));
-
- if (paramType.IsByRef)
- {
- argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperRef", null)));
- }
- else
- {
- argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperIn", null)));
-
- callSiteSetupStream.Emit(ILOpcode.ldobj, emitter.NewToken(paramType));
- }
- argSetupStream.EmitStLoc(local);
- }
-
- argSetupStream.EmitLdArg(3);
- argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeArgSetupComplete", null)));
-
- callSiteSetupStream.EmitLdArg(2);
-
- MethodSignature targetMethodSig = new MethodSignature(0, 0, delegateSignature.ReturnType, targetMethodParameters);
-
- callSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(targetMethodSig));
-
- if (delegateSignature.ReturnType.IsVoid)
- {
- callSiteSetupStream.Emit(ILOpcode.ldnull);
- }
- else if (delegateSignature.ReturnType.IsByRef)
- {
- TypeDesc targetType = ((ByRefType)delegateSignature.ReturnType).ParameterType;
- callSiteSetupStream.Emit(ILOpcode.ldobj, emitter.NewToken(targetType));
- callSiteSetupStream.Emit(ILOpcode.box, emitter.NewToken(targetType));
- }
- else
- {
- callSiteSetupStream.Emit(ILOpcode.box, emitter.NewToken(delegateSignature.ReturnType));
- }
-
- callSiteSetupStream.Emit(ILOpcode.ret);
-
- return emitter.Link(this);
- }
-
- internal static TypeDesc ConvertToBoxableType(TypeDesc type)
- {
- if (type.IsPointer || type.IsFunctionPointer)
- {
- return type.Context.GetWellKnownType(WellKnownType.IntPtr);
- }
-
- return type;
- }
- }
-
- /// <summary>
/// Synthetic method override of "IntPtr Delegate.GetThunk(Int32)". This method is injected
/// into all delegate types and provides means for System.Delegate to access the various thunks
/// generated by the compiler.
@@ -939,7 +738,25 @@ namespace Internal.IL.Stubs
{
codeStream.EmitLabel(labels[(int)i]);
- codeStream.Emit(ILOpcode.ldftn, emitter.NewToken(thunk.InstantiateAsOpen()));
+ if (i == DelegateThunkKind.DelegateInvokeThunk)
+ {
+ // Dynamic invoke thunk is special since we're calling into a shared helper
+ MethodDesc targetMethod;
+ if (thunk.HasInstantiation)
+ {
+ TypeDesc[] inst = DynamicInvokeMethodThunk.GetThunkInstantiationForMethod(_delegateInfo.Type.InstantiateAsOpen().GetMethod("Invoke", null));
+ targetMethod = Context.GetInstantiatedMethod(thunk, new Instantiation(inst));
+ }
+ else
+ {
+ targetMethod = thunk;
+ }
+ codeStream.Emit(ILOpcode.ldftn, emitter.NewToken(targetMethod));
+ }
+ else
+ {
+ codeStream.Emit(ILOpcode.ldftn, emitter.NewToken(thunk.InstantiateAsOpen()));
+ }
codeStream.Emit(ILOpcode.ret);
}
}