1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-08 03:27:04 +09:00

Use function pointers in crossgen2 (#42655)

Co-authored-by: Adeel Mujahid <adeelbm@outlook.com>
This commit is contained in:
Jan Kotas 2020-09-24 02:38:23 -07:00 committed by GitHub
parent 11350c5902
commit 7c3d2384f3
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 706 additions and 1313 deletions

File diff suppressed because it is too large Load diff

View file

@ -55,7 +55,6 @@ namespace Internal.JitInterface
private IntPtr _jit; private IntPtr _jit;
private IntPtr _unmanagedCallbacks; // array of pointers to JIT-EE interface callbacks private IntPtr _unmanagedCallbacks; // array of pointers to JIT-EE interface callbacks
private Object _keepAlive; // Keeps delegates for the callbacks alive
private ExceptionDispatchInfo _lastException; private ExceptionDispatchInfo _lastException;
@ -122,7 +121,7 @@ namespace Internal.JitInterface
throw new IOException("Failed to initialize JIT"); throw new IOException("Failed to initialize JIT");
} }
_unmanagedCallbacks = GetUnmanagedCallbacks(out _keepAlive); _unmanagedCallbacks = GetUnmanagedCallbacks();
} }
public TextWriter Log public TextWriter Log
@ -1043,7 +1042,7 @@ namespace Internal.JitInterface
private bool satisfiesMethodConstraints(CORINFO_CLASS_STRUCT_* parent, CORINFO_METHOD_STRUCT_* method) private bool satisfiesMethodConstraints(CORINFO_CLASS_STRUCT_* parent, CORINFO_METHOD_STRUCT_* method)
{ throw new NotImplementedException("satisfiesMethodConstraints"); } { throw new NotImplementedException("satisfiesMethodConstraints"); }
private bool isCompatibleDelegate(CORINFO_CLASS_STRUCT_* objCls, CORINFO_CLASS_STRUCT_* methodParentCls, CORINFO_METHOD_STRUCT_* method, CORINFO_CLASS_STRUCT_* delegateCls, ref bool pfIsOpenDelegate) private bool isCompatibleDelegate(CORINFO_CLASS_STRUCT_* objCls, CORINFO_CLASS_STRUCT_* methodParentCls, CORINFO_METHOD_STRUCT_* method, CORINFO_CLASS_STRUCT_* delegateCls, BOOL* pfIsOpenDelegate)
{ throw new NotImplementedException("isCompatibleDelegate"); } { throw new NotImplementedException("isCompatibleDelegate"); }
private void setPatchpointInfo(PatchpointInfo* patchpointInfo) private void setPatchpointInfo(PatchpointInfo* patchpointInfo)
{ throw new NotImplementedException("setPatchpointInfo"); } { throw new NotImplementedException("setPatchpointInfo"); }
@ -1529,7 +1528,7 @@ namespace Internal.JitInterface
Marshal.FreeCoTaskMem((IntPtr)obj); Marshal.FreeCoTaskMem((IntPtr)obj);
} }
private byte* getClassModuleIdForStatics(CORINFO_CLASS_STRUCT_* cls, CORINFO_MODULE_STRUCT_** pModule, void** ppIndirection) private UIntPtr getClassModuleIdForStatics(CORINFO_CLASS_STRUCT_* cls, CORINFO_MODULE_STRUCT_** pModule, void** ppIndirection)
{ throw new NotImplementedException("getClassModuleIdForStatics"); } { throw new NotImplementedException("getClassModuleIdForStatics"); }
private uint getClassSize(CORINFO_CLASS_STRUCT_* cls) private uint getClassSize(CORINFO_CLASS_STRUCT_* cls)
@ -2525,7 +2524,7 @@ namespace Internal.JitInterface
return (uint)HandleToObject(ftn).GetHashCode(); return (uint)HandleToObject(ftn).GetHashCode();
} }
private byte* findNameOfToken(CORINFO_MODULE_STRUCT_* moduleHandle, mdToken token, byte* szFQName, UIntPtr FQNameCapacity) private UIntPtr findNameOfToken(CORINFO_MODULE_STRUCT_* moduleHandle, mdToken token, byte* szFQName, UIntPtr FQNameCapacity)
{ throw new NotImplementedException("findNameOfToken"); } { throw new NotImplementedException("findNameOfToken"); }
private bool getSystemVAmd64PassStructInRegisterDescriptor(CORINFO_CLASS_STRUCT_* structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) private bool getSystemVAmd64PassStructInRegisterDescriptor(CORINFO_CLASS_STRUCT_* structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr)
@ -2615,7 +2614,7 @@ namespace Internal.JitInterface
ppIndirection = null; ppIndirection = null;
return null; return null;
} }
private void GetProfilingHandle(ref bool pbHookFunction, ref void* pProfilerHandle, ref bool pbIndirectedHandles) private void GetProfilingHandle(BOOL* pbHookFunction, ref void* pProfilerHandle, BOOL* pbIndirectedHandles)
{ throw new NotImplementedException("GetProfilingHandle"); } { throw new NotImplementedException("GetProfilingHandle"); }
/// <summary> /// <summary>

View file

@ -8,6 +8,12 @@ using Internal.TypeSystem;
namespace Internal.JitInterface namespace Internal.JitInterface
{ {
public enum BOOL : int
{
FALSE = 0,
TRUE = 1,
}
public static class CORINFO public static class CORINFO
{ {
// CORINFO_MAXINDIRECTIONS is the maximum number of // CORINFO_MAXINDIRECTIONS is the maximum number of
@ -20,40 +26,14 @@ namespace Internal.JitInterface
public struct CORINFO_METHOD_STRUCT_ public struct CORINFO_METHOD_STRUCT_
{ {
internal static unsafe CORINFO_METHOD_STRUCT_* Construct(int i)
{
return (CORINFO_METHOD_STRUCT_*)((i + 1) << 4);
}
internal static unsafe int GetValue(CORINFO_METHOD_STRUCT_* val)
{
return ((int)val - 1) >> 4;
}
} }
public struct CORINFO_FIELD_STRUCT_ public struct CORINFO_FIELD_STRUCT_
{ {
internal static unsafe CORINFO_FIELD_STRUCT_* Construct(int i)
{
return (CORINFO_FIELD_STRUCT_*)((i + 1) << 4);
}
internal static unsafe int GetValue(CORINFO_FIELD_STRUCT_* val)
{
return ((int)val - 1) >> 4;
}
} }
public struct CORINFO_CLASS_STRUCT_ public struct CORINFO_CLASS_STRUCT_
{ {
internal static unsafe CORINFO_CLASS_STRUCT_* Construct(int i)
{
return (CORINFO_CLASS_STRUCT_*)((i + 1) << 4);
}
internal static unsafe int GetValue(CORINFO_CLASS_STRUCT_* val)
{
return ((int)val - 1) >> 4;
}
} }
public struct CORINFO_ARG_LIST_STRUCT_ public struct CORINFO_ARG_LIST_STRUCT_
@ -62,14 +42,6 @@ namespace Internal.JitInterface
public struct CORINFO_MODULE_STRUCT_ public struct CORINFO_MODULE_STRUCT_
{ {
internal static unsafe CORINFO_MODULE_STRUCT_* Construct(int i)
{
return (CORINFO_MODULE_STRUCT_*)((i + 1) << 4);
}
internal static unsafe int GetValue(CORINFO_MODULE_STRUCT_* val)
{
return ((int)val - 1) >> 4;
}
} }
public struct CORINFO_ASSEMBLY_STRUCT_ public struct CORINFO_ASSEMBLY_STRUCT_

View file

@ -27,7 +27,6 @@ namespace Internal.JitInterface
private CorJitFlag[] _jitFlags; private CorJitFlag[] _jitFlags;
private Dictionary<string, string> _config = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); private Dictionary<string, string> _config = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
private object _keepAlive; // Keeps callback delegates alive
public static void Initialize( public static void Initialize(
TargetDetails target, TargetDetails target,
@ -151,43 +150,34 @@ namespace Internal.JitInterface
#region Unmanaged instance #region Unmanaged instance
private unsafe IntPtr CreateUnmanagedInstance() private static unsafe IntPtr CreateUnmanagedInstance()
{ {
// TODO: this potentially leaks memory, but since we only expect to have one per compilation, // This potentially leaks memory, but since we only expect to have one per compilation,
// it shouldn't matter... // it shouldn't matter...
const int numCallbacks = 2; const int numCallbacks = 2;
IntPtr* callbacks = (IntPtr*)Marshal.AllocCoTaskMem(sizeof(IntPtr) * numCallbacks); void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * numCallbacks);
object[] delegates = new object[numCallbacks];
var d0 = new __getIntConfigValue(getIntConfigValue); callbacks[0] = (delegate* <IntPtr, char*, int, int>)&getIntConfigValue;
callbacks[0] = Marshal.GetFunctionPointerForDelegate(d0); callbacks[1] = (delegate* <IntPtr, char*, char*, int, int>)&getStringConfigValue;
delegates[0] = d0;
var d1 = new __getStringConfigValue(getStringConfigValue);
callbacks[1] = Marshal.GetFunctionPointerForDelegate(d1);
delegates[1] = d1;
_keepAlive = delegates;
IntPtr instance = Marshal.AllocCoTaskMem(sizeof(IntPtr)); IntPtr instance = Marshal.AllocCoTaskMem(sizeof(IntPtr));
*(IntPtr**)instance = callbacks; *(IntPtr*)instance = (IntPtr)callbacks;
return instance; return instance;
} }
[UnmanagedFunctionPointer(default(CallingConvention))] [UnmanagedCallersOnly]
private unsafe delegate int __getIntConfigValue(IntPtr thisHandle, [MarshalAs(UnmanagedType.LPWStr)] string name, int defaultValue); private static unsafe int getIntConfigValue(IntPtr thisHandle, char* name, int defaultValue)
private unsafe int getIntConfigValue(IntPtr thisHandle, string name, int defaultValue)
{ {
return GetIntConfigValue(name, defaultValue); return s_instance.GetIntConfigValue(new string(name), defaultValue);
} }
[UnmanagedFunctionPointer(default(CallingConvention))] [UnmanagedCallersOnly]
private unsafe delegate int __getStringConfigValue(IntPtr thisHandle, [MarshalAs(UnmanagedType.LPWStr)] string name, char* retBuffer, int retBufferLength); private static unsafe int getStringConfigValue(IntPtr thisHandle, char* name, char* retBuffer, int retBufferLength)
private unsafe int getStringConfigValue(IntPtr thisHandle, string name, char* retBuffer, int retBufferLength)
{ {
string result = GetStringConfigValue(name); string result = s_instance.GetStringConfigValue(new string(name));
for (int i = 0; i < Math.Min(retBufferLength, result.Length); i++) for (int i = 0; i < Math.Min(retBufferLength, result.Length); i++)
retBuffer[i] = result[i]; retBuffer[i] = result[i];

View file

@ -66,6 +66,28 @@ namespace Thunkerator
public readonly string ThunkTypeName; public readonly string ThunkTypeName;
public readonly string NativeTypeName; public readonly string NativeTypeName;
public readonly string ManagedTypeName; public readonly string ManagedTypeName;
public bool IsByRef => ManagedTypeName.Contains("ref ");
public bool IsBoolean => ManagedTypeName == "[MarshalAs(UnmanagedType.I1)]bool";
public bool IsBOOL => ManagedTypeName == "[MarshalAs(UnmanagedType.Bool)]bool";
public string UnmanagedTypeName
{
get
{
if (IsBoolean)
return "byte";
if (IsBOOL)
return "int";
if (IsByRef)
return ManagedTypeName.Replace("ref ", "") + "*";
// No special marshaling rules
return ManagedTypeName;
}
}
} }
class Parameter class Parameter
@ -92,12 +114,6 @@ namespace Thunkerator
line = line.Replace("[ManualNativeWrapper]", string.Empty); line = line.Replace("[ManualNativeWrapper]", string.Empty);
} }
if (line.Contains("[ReturnAsParm]"))
{
ReturnAsParm = true;
line = line.Replace("[ReturnAsParm]", string.Empty);
}
int indexOfOpenParen = line.IndexOf('('); int indexOfOpenParen = line.IndexOf('(');
int indexOfCloseParen = line.IndexOf(')'); int indexOfCloseParen = line.IndexOf(')');
string returnTypeAndFunctionName = line.Substring(0, indexOfOpenParen).Canonicalize(); string returnTypeAndFunctionName = line.Substring(0, indexOfOpenParen).Canonicalize();
@ -136,7 +152,6 @@ namespace Thunkerator
public readonly TypeReplacement ReturnType; public readonly TypeReplacement ReturnType;
public readonly Parameter[] Parameters; public readonly Parameter[] Parameters;
public readonly bool ManualNativeWrapper = false; public readonly bool ManualNativeWrapper = false;
public readonly bool ReturnAsParm = false;
} }
class Program class Program
@ -249,65 +264,13 @@ namespace Internal.JitInterface
{ {
"); ");
#if false
foreach (FunctionDecl decl in functionData) foreach (FunctionDecl decl in functionData)
{ {
string returnType = decl.ReturnType.ManagedTypeName; tr.WriteLine(" [UnmanagedCallersOnly]");
tr.Write($" static {decl.ReturnType.UnmanagedTypeName} _{decl.FunctionName}(IntPtr thisHandle, IntPtr* ppException");
tr.Write(" " + returnType + " " + decl.FunctionName + "(");
tr.Write("IntPtr thisHandle");
foreach (Parameter param in decl.Parameters) foreach (Parameter param in decl.Parameters)
{ {
tr.Write(", "); tr.Write($", {param.Type.UnmanagedTypeName} {param.Name}");
tr.Write(param.Type.ManagedTypeName + " " + param.Name);
}
tr.WriteLine(")");
tr.WriteLine(" { throw new NotImplementedException(); }");
}
tr.WriteLine();
#endif
foreach (FunctionDecl decl in functionData)
{
tr.WriteLine(" [UnmanagedFunctionPointerAttribute(default(CallingConvention))]");
string returnType = decl.ReturnAsParm ? "void" : decl.ReturnType.ManagedTypeName;
int marshalAs = returnType.LastIndexOf(']');
string returnTypeWithDelegate = returnType.Insert((marshalAs != -1) ? (marshalAs + 1) : 0, "delegate ");
tr.Write(" " + returnTypeWithDelegate + " " + "__" + decl.FunctionName + "(");
tr.Write("IntPtr _this");
tr.Write(", IntPtr* ppException");
if (decl.ReturnAsParm)
{
tr.Write(", out " + decl.ReturnType.ManagedTypeName + " _return");
}
foreach (Parameter param in decl.Parameters)
{
tr.Write(", ");
tr.Write(param.Type.ManagedTypeName + " " + param.Name);
}
tr.WriteLine(");");
}
tr.WriteLine();
foreach (FunctionDecl decl in functionData)
{
string returnType = decl.ReturnAsParm ? "void" : decl.ReturnType.ManagedTypeName;
int marshalAs = returnType.LastIndexOf(']');
string returnTypeWithStatic = returnType.Insert((marshalAs != -1) ? (marshalAs + 1) : 0, "static ");
tr.Write(" " + returnTypeWithStatic + " " + "_" + decl.FunctionName + "(");
tr.Write("IntPtr thisHandle");
tr.Write(", IntPtr* ppException");
if (decl.ReturnAsParm)
{
tr.Write(", out " + decl.ReturnType.ManagedTypeName + " _return");
}
foreach (Parameter param in decl.Parameters)
{
tr.Write(", ");
tr.Write(param.Type.ManagedTypeName + " " + param.Name);
} }
tr.Write(@") tr.Write(@")
{ {
@ -315,14 +278,9 @@ namespace Internal.JitInterface
try try
{ {
"); ");
bool isVoid = decl.ReturnAsParm || decl.ReturnType.ManagedTypeName == "void"; bool isVoid = decl.ReturnType.ManagedTypeName == "void";
tr.Write(" " + (isVoid ? "" : "return ") + "_this." + decl.FunctionName + "("); tr.Write($" {(isVoid ? "" : "return ")}_this.{decl.FunctionName}(");
bool isFirst = true; bool isFirst = true;
if (decl.ReturnAsParm)
{
tr.Write("out _return");
isFirst = false;
}
foreach (Parameter param in decl.Parameters) foreach (Parameter param in decl.Parameters)
{ {
if (isFirst) if (isFirst)
@ -334,13 +292,22 @@ namespace Internal.JitInterface
tr.Write(", "); tr.Write(", ");
} }
if (param.Type.ManagedTypeName.Contains("ref ")) if (param.Type.IsByRef)
{ {
tr.Write("ref "); tr.Write("ref *");
} }
tr.Write(param.Name); tr.Write(param.Name);
if (param.Type.IsBoolean || param.Type.IsBOOL)
{
tr.Write(" != 0");
}
} }
tr.Write(");"); tr.Write(")");
if (decl.ReturnType.IsBOOL || decl.ReturnType.IsBoolean)
{
tr.Write(" ? 1 : 0");
}
tr.Write(";");
tr.Write(@" tr.Write(@"
} }
catch (Exception ex) catch (Exception ex)
@ -349,12 +316,7 @@ namespace Internal.JitInterface
"); ");
if (!isVoid) if (!isVoid)
{ {
string retunTypeWithoutMarshalAs = marshalAs == -1 ? returnType : returnType.Substring(marshalAs + 1); tr.WriteLine(" return default;");
tr.WriteLine(" return default(" + retunTypeWithoutMarshalAs + ");");
}
else if (decl.ReturnAsParm)
{
tr.WriteLine(" _return = default(" + decl.ReturnType.ManagedTypeName + ");");
} }
tr.WriteLine(@" }"); tr.WriteLine(@" }");
tr.WriteLine(" }"); tr.WriteLine(" }");
@ -363,23 +325,24 @@ namespace Internal.JitInterface
int total = functionData.Count(); int total = functionData.Count();
tr.WriteLine(@" tr.WriteLine(@"
static IntPtr GetUnmanagedCallbacks(out Object keepAlive) static IntPtr GetUnmanagedCallbacks()
{ {
IntPtr * callbacks = (IntPtr *)Marshal.AllocCoTaskMem(sizeof(IntPtr) * " + total + @"); void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * " + total + @");
Object[] delegates = new Object[" + total + @"];
"); ");
int index = 0; int index = 0;
foreach (FunctionDecl decl in functionData) foreach (FunctionDecl decl in functionData)
{ {
tr.WriteLine(" var d" + index + " = new " + "__" + decl.FunctionName + "(" + "_" + decl.FunctionName + ");"); tr.Write($" callbacks[{index}] = (delegate* <IntPtr, IntPtr*");
tr.WriteLine(" callbacks[" + index + "] = Marshal.GetFunctionPointerForDelegate(d" + index + ");"); foreach (Parameter param in decl.Parameters)
tr.WriteLine(" delegates[" + index + "] = d" + index + ";"); {
tr.Write($", {param.Type.UnmanagedTypeName}");
}
tr.WriteLine($", {decl.ReturnType.UnmanagedTypeName}>)&_{decl.FunctionName};");
index++; index++;
} }
tr.WriteLine(@" tr.WriteLine(@"
keepAlive = delegates;
return (IntPtr)callbacks; return (IntPtr)callbacks;
} }
} }
@ -395,26 +358,16 @@ namespace Internal.JitInterface
// DO NOT EDIT THIS FILE! It IS AUTOGENERATED // DO NOT EDIT THIS FILE! It IS AUTOGENERATED
#include ""corinfoexception.h"" #include ""corinfoexception.h""
struct CORINFO_LOOKUP_KIND;
struct JitInterfaceCallbacks struct JitInterfaceCallbacks
{ {
"); ");
foreach (FunctionDecl decl in functionData) foreach (FunctionDecl decl in functionData)
{ {
string returnType = decl.ReturnAsParm ? "void" : decl.ReturnType.NativeTypeName; tw.Write($" {decl.ReturnType.NativeTypeName} (* {decl.FunctionName})(void * thisHandle, CorInfoException** ppException");
tw.Write(" " + returnType + " (* " + decl.FunctionName + ")(");
tw.Write("void * thisHandle");
tw.Write(", CorInfoException** ppException");
if (decl.ReturnAsParm)
{
tw.Write(", " + decl.ReturnType.NativeTypeName + "* _return");
}
foreach (Parameter param in decl.Parameters) foreach (Parameter param in decl.Parameters)
{ {
tw.Write(", "); tw.Write($", {param.Type.NativeTypeName} {param.Name}");
tw.Write(param.Type.NativeTypeName + " " + param.Name);
} }
tw.WriteLine(");"); tw.WriteLine(");");
} }
@ -464,12 +417,12 @@ public:
"); ");
if (decl.ReturnType.NativeTypeName != "void") if (decl.ReturnType.NativeTypeName != "void")
{ {
tw.Write(decl.ReturnType.NativeTypeName + " _ret = "); tw.Write($"{decl.ReturnType.NativeTypeName} _ret = ");
} }
tw.Write("_callbacks->" + decl.FunctionName + "(_thisHandle, &pException"); tw.Write($"_callbacks->{decl.FunctionName}(_thisHandle, &pException");
foreach (Parameter param in decl.Parameters) foreach (Parameter param in decl.Parameters)
{ {
tw.Write(", " + param.Name); tw.Write($", {param.Name}");
} }
tw.Write(@"); tw.Write(@");
if (pException != nullptr) if (pException != nullptr)

View file

@ -59,8 +59,8 @@ BYTE*,byte*,unsigned char*
GSCookie*,IntPtr*,void* GSCookie*,IntPtr*,void*
GSCookie**,IntPtr**,void** GSCookie**,IntPtr**,void**
BOOL*,[MarshalAs(UnmanagedType.Bool)] ref bool,int* BOOL*,BOOL*,int*
bool*,[MarshalAs(UnmanagedType.U1)] ref bool bool*,ref bool,bool*
BoolStar,byte*,bool* BoolStar,byte*,bool*
UINT32*,ref uint,unsigned int* UINT32*,ref uint,unsigned int*
ULONG*,ref uint,unsigned long* ULONG*,ref uint,unsigned long*
@ -155,12 +155,6 @@ ICorDebugInfo::BoundaryTypes*,BoundaryTypes*,void*
struct _EXCEPTION_POINTERS*,_EXCEPTION_POINTERS*,void* struct _EXCEPTION_POINTERS*,_EXCEPTION_POINTERS*,void*
RETURNTYPES
BOOL,[return: MarshalAs(UnmanagedType.Bool)]bool,int
bool,[return: MarshalAs(UnmanagedType.I1)]bool
; NOTE in managed SIZE_T is an enum that is 64bits in size, and returning one of those causing mcg to do the wrong thing.
size_t,byte*,size_t
FUNCTIONS FUNCTIONS
DWORD getMethodAttribs( CORINFO_METHOD_HANDLE ftn ); DWORD getMethodAttribs( CORINFO_METHOD_HANDLE ftn );
void setMethodAttribs( CORINFO_METHOD_HANDLE ftn, CorInfoMethodRuntimeFlags attribs ); void setMethodAttribs( CORINFO_METHOD_HANDLE ftn, CorInfoMethodRuntimeFlags attribs );

View file

@ -4,8 +4,6 @@
// DO NOT EDIT THIS FILE! It IS AUTOGENERATED // DO NOT EDIT THIS FILE! It IS AUTOGENERATED
#include "corinfoexception.h" #include "corinfoexception.h"
struct CORINFO_LOOKUP_KIND;
struct JitInterfaceCallbacks struct JitInterfaceCallbacks
{ {
unsigned int (* getMethodAttribs)(void * thisHandle, CorInfoException** ppException, void* ftn); unsigned int (* getMethodAttribs)(void * thisHandle, CorInfoException** ppException, void* ftn);