From 776ae3244a91a3a3b047362089e8920c438a5732 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Sat, 12 Sep 2020 21:45:24 -0500 Subject: [PATCH 1/6] apply amos changes from soft shutdown --- src/runtime/interop.cs | 106 +++++++++++++++++++++++++++------------ src/runtime/interop36.cs | 18 +------ src/runtime/interop37.cs | 18 +------ src/runtime/interop38.cs | 20 +------- 4 files changed, 77 insertions(+), 85 deletions(-) diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 95f3e5b9f..e58983435 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -5,7 +5,6 @@ using System.Runtime.InteropServices; using System.Reflection; using System.Text; -using System.Collections.Generic; namespace Python.Runtime { @@ -69,27 +68,66 @@ public ModulePropertyAttribute() } } + internal static partial class TypeOffset + { + static TypeOffset() + { + Type type = typeof(TypeOffset); + FieldInfo[] fields = type.GetFields(); + int size = IntPtr.Size; + for (int i = 0; i < fields.Length; i++) + { + int offset = i * size; + FieldInfo fi = fields[i]; + fi.SetValue(null, offset); + } + } + + public static int magic() => ManagedDataOffsets.Magic; + } + internal static class ManagedDataOffsets { - static ManagedDataOffsets() + public static int Magic { get; private set; } + public static readonly Dictionary NameMapping = new Dictionary(); + + static class DataOffsets { - FieldInfo[] fi = typeof(ManagedDataOffsets).GetFields(BindingFlags.Static | BindingFlags.Public); - for (int i = 0; i < fi.Length; i++) + public static readonly int ob_data; + public static readonly int ob_dict; + + static DataOffsets() { - fi[i].SetValue(null, -(i * IntPtr.Size) - IntPtr.Size); + FieldInfo[] fields = typeof(DataOffsets).GetFields(BindingFlags.Static | BindingFlags.Public); + for (int i = 0; i < fields.Length; i++) + { + fields[i].SetValue(null, -(i * IntPtr.Size) - IntPtr.Size); + } } + } - size = fi.Length * IntPtr.Size; + static ManagedDataOffsets() + { + Type type = typeof(TypeOffset); + foreach (FieldInfo fi in type.GetFields()) + { + NameMapping[fi.Name] = (int)fi.GetValue(null); + } + Magic = TypeOffset.members; + FieldInfo[] fields = typeof(DataOffsets).GetFields(BindingFlags.Static | BindingFlags.Public); + size = fields.Length * IntPtr.Size; } - public static readonly int ob_data; - public static readonly int ob_dict; + public static int GetSlotOffset(string name) + { + return NameMapping[name]; + } private static int BaseOffset(IntPtr type) { Debug.Assert(type != IntPtr.Zero); int typeSize = Marshal.ReadInt32(type, TypeOffset.tp_basicsize); - Debug.Assert(typeSize > 0 && typeSize <= ExceptionOffset.Size()); + Debug.Assert(typeSize > 0); return typeSize; } public static int DataOffset(IntPtr type) @@ -102,6 +140,8 @@ public static int DictOffset(IntPtr type) return BaseOffset(type) + ob_dict; } + public static int ob_data => DataOffsets.ob_data; + public static int ob_dict => DataOffsets.ob_dict; public static int Size { get { return size; } } private static readonly int size; @@ -320,34 +360,34 @@ public static void FreeModuleDef(IntPtr ptr) /// internal class TypeFlags { - public static int HeapType = (1 << 9); - public static int BaseType = (1 << 10); - public static int Ready = (1 << 12); - public static int Readying = (1 << 13); - public static int HaveGC = (1 << 14); + public const int HeapType = (1 << 9); + public const int BaseType = (1 << 10); + public const int Ready = (1 << 12); + public const int Readying = (1 << 13); + public const int HaveGC = (1 << 14); // 15 and 16 are reserved for stackless - public static int HaveStacklessExtension = 0; + public const int HaveStacklessExtension = 0; /* XXX Reusing reserved constants */ - public static int Managed = (1 << 15); // PythonNet specific - public static int Subclass = (1 << 16); // PythonNet specific - public static int HaveIndex = (1 << 17); + public const int Managed = (1 << 15); // PythonNet specific + public const int Subclass = (1 << 16); // PythonNet specific + public const int HaveIndex = (1 << 17); /* Objects support nb_index in PyNumberMethods */ - public static int HaveVersionTag = (1 << 18); - public static int ValidVersionTag = (1 << 19); - public static int IsAbstract = (1 << 20); - public static int HaveNewBuffer = (1 << 21); + public const int HaveVersionTag = (1 << 18); + public const int ValidVersionTag = (1 << 19); + public const int IsAbstract = (1 << 20); + public const int HaveNewBuffer = (1 << 21); // TODO: Implement FastSubclass functions - public static int IntSubclass = (1 << 23); - public static int LongSubclass = (1 << 24); - public static int ListSubclass = (1 << 25); - public static int TupleSubclass = (1 << 26); - public static int StringSubclass = (1 << 27); - public static int UnicodeSubclass = (1 << 28); - public static int DictSubclass = (1 << 29); - public static int BaseExceptionSubclass = (1 << 30); - public static int TypeSubclass = (1 << 31); - - public static int Default = ( + public const int IntSubclass = (1 << 23); + public const int LongSubclass = (1 << 24); + public const int ListSubclass = (1 << 25); + public const int TupleSubclass = (1 << 26); + public const int StringSubclass = (1 << 27); + public const int UnicodeSubclass = (1 << 28); + public const int DictSubclass = (1 << 29); + public const int BaseExceptionSubclass = (1 << 30); + public const int TypeSubclass = (1 << 31); + + public const int Default = ( HaveStacklessExtension | HaveVersionTag); } diff --git a/src/runtime/interop36.cs b/src/runtime/interop36.cs index c46bcc2f5..cc305bc2a 100644 --- a/src/runtime/interop36.cs +++ b/src/runtime/interop36.cs @@ -12,25 +12,9 @@ namespace Python.Runtime { - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + [StructLayout(LayoutKind.Sequential)] internal class TypeOffset { - static TypeOffset() - { - Type type = typeof(TypeOffset); - FieldInfo[] fi = type.GetFields(); - int size = IntPtr.Size; - for (int i = 0; i < fi.Length; i++) - { - fi[i].SetValue(null, i * size); - } - } - - public static int magic() - { - return ob_size; - } - // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; public static int ob_type = 0; diff --git a/src/runtime/interop37.cs b/src/runtime/interop37.cs index d5fc76ad3..964b8b480 100644 --- a/src/runtime/interop37.cs +++ b/src/runtime/interop37.cs @@ -12,25 +12,9 @@ namespace Python.Runtime { - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + [StructLayout(LayoutKind.Sequential)] internal class TypeOffset { - static TypeOffset() - { - Type type = typeof(TypeOffset); - FieldInfo[] fi = type.GetFields(); - int size = IntPtr.Size; - for (int i = 0; i < fi.Length; i++) - { - fi[i].SetValue(null, i * size); - } - } - - public static int magic() - { - return ob_size; - } - // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; public static int ob_type = 0; diff --git a/src/runtime/interop38.cs b/src/runtime/interop38.cs index 9126bca6a..1180962ff 100644 --- a/src/runtime/interop38.cs +++ b/src/runtime/interop38.cs @@ -13,25 +13,9 @@ namespace Python.Runtime { - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class TypeOffset + [StructLayout(LayoutKind.Sequential)] + internal static partial class TypeOffset { - static TypeOffset() - { - Type type = typeof(TypeOffset); - FieldInfo[] fi = type.GetFields(); - int size = IntPtr.Size; - for (int i = 0; i < fi.Length; i++) - { - fi[i].SetValue(null, i * size); - } - } - - public static int magic() - { - return ob_size; - } - // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; public static int ob_type = 0; From e8a53d0fab01ea1b240f61cf9b12f42f912d417f Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Sat, 12 Sep 2020 21:58:30 -0500 Subject: [PATCH 2/6] fix other versions --- src/runtime/interop36.cs | 2 +- src/runtime/interop37.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/runtime/interop36.cs b/src/runtime/interop36.cs index cc305bc2a..536168275 100644 --- a/src/runtime/interop36.cs +++ b/src/runtime/interop36.cs @@ -13,7 +13,7 @@ namespace Python.Runtime { [StructLayout(LayoutKind.Sequential)] - internal class TypeOffset + internal static partial class TypeOffset { // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; diff --git a/src/runtime/interop37.cs b/src/runtime/interop37.cs index 964b8b480..beb2bb5c9 100644 --- a/src/runtime/interop37.cs +++ b/src/runtime/interop37.cs @@ -13,7 +13,7 @@ namespace Python.Runtime { [StructLayout(LayoutKind.Sequential)] - internal class TypeOffset + internal static partial class TypeOffset { // Auto-generated from PyHeapTypeObject in Python.h public static int ob_refcnt = 0; From c26c6f83ac60f36423cd82fd8e634c1721517ee5 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Sun, 13 Sep 2020 20:39:03 -0500 Subject: [PATCH 3/6] interop template --- tools/geninterop/geninterop.py | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/tools/geninterop/geninterop.py b/tools/geninterop/geninterop.py index 902296229..86305dd57 100644 --- a/tools/geninterop/geninterop.py +++ b/tools/geninterop/geninterop.py @@ -243,25 +243,9 @@ def gen_interop_code(members): namespace Python.Runtime { - [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] - internal class TypeOffset + [StructLayout(LayoutKind.Sequential)] + internal static partial class TypeOffset { - static TypeOffset() - { - Type type = typeof(TypeOffset); - FieldInfo[] fi = type.GetFields(); - int size = IntPtr.Size; - for (int i = 0; i < fi.Length; i++) - { - fi[i].SetValue(null, i * size); - } - } - - public static int magic() - { - return ob_size; - } - // Auto-generated from PyHeapTypeObject in Python.h """ % (filename, defines_str) From bb1ebe3f67a3d72f056d3f9ab4a6231d7920a642 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Tue, 15 Sep 2020 19:44:26 -0500 Subject: [PATCH 4/6] fixes --- src/runtime/clrobject.cs | 2 +- src/runtime/interop.cs | 60 ++++++++++++++++++-------------------- src/runtime/managedtype.cs | 4 +-- src/runtime/metatype.cs | 6 ++-- src/runtime/typemanager.cs | 16 +++++----- 5 files changed, 42 insertions(+), 46 deletions(-) diff --git a/src/runtime/clrobject.cs b/src/runtime/clrobject.cs index 5c7ad7891..d6ef09f79 100644 --- a/src/runtime/clrobject.cs +++ b/src/runtime/clrobject.cs @@ -12,7 +12,7 @@ internal CLRObject(object ob, IntPtr tp) IntPtr py = Runtime.PyType_GenericAlloc(tp, 0); long flags = Util.ReadCLong(tp, TypeOffset.tp_flags); - if ((flags & TypeFlags.Subclass) != 0) + if ((flags & (int)TypeFlags.Subclass) != 0) { IntPtr dict = Marshal.ReadIntPtr(py, ObjectOffset.TypeDictOffset(tp)); if (dict == IntPtr.Zero) diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index e58983435..49db99e70 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -118,16 +118,11 @@ static ManagedDataOffsets() size = fields.Length * IntPtr.Size; } - public static int GetSlotOffset(string name) - { - return NameMapping[name]; - } - private static int BaseOffset(IntPtr type) { Debug.Assert(type != IntPtr.Zero); int typeSize = Marshal.ReadInt32(type, TypeOffset.tp_basicsize); - Debug.Assert(typeSize > 0); + Debug.Assert(typeSize > 0 && typeSize <= ExceptionOffset.Size()); return typeSize; } public static int DataOffset(IntPtr type) @@ -358,38 +353,39 @@ public static void FreeModuleDef(IntPtr ptr) /// Note that the two values reserved for stackless have been put /// to good use as PythonNet specific flags (Managed and Subclass) /// - internal class TypeFlags + [Flags] + internal enum TypeFlags { - public const int HeapType = (1 << 9); - public const int BaseType = (1 << 10); - public const int Ready = (1 << 12); - public const int Readying = (1 << 13); - public const int HaveGC = (1 << 14); + HeapType = (1 << 9), + BaseType = (1 << 10), + Ready = (1 << 12), + Readying = (1 << 13), + HaveGC = (1 << 14), // 15 and 16 are reserved for stackless - public const int HaveStacklessExtension = 0; + HaveStacklessExtension = 0, /* XXX Reusing reserved constants */ - public const int Managed = (1 << 15); // PythonNet specific - public const int Subclass = (1 << 16); // PythonNet specific - public const int HaveIndex = (1 << 17); + Managed = (1 << 15), // PythonNet specific + Subclass = (1 << 16), // PythonNet specific + HaveIndex = (1 << 17), /* Objects support nb_index in PyNumberMethods */ - public const int HaveVersionTag = (1 << 18); - public const int ValidVersionTag = (1 << 19); - public const int IsAbstract = (1 << 20); - public const int HaveNewBuffer = (1 << 21); + HaveVersionTag = (1 << 18), + ValidVersionTag = (1 << 19), + IsAbstract = (1 << 20), + HaveNewBuffer = (1 << 21), // TODO: Implement FastSubclass functions - public const int IntSubclass = (1 << 23); - public const int LongSubclass = (1 << 24); - public const int ListSubclass = (1 << 25); - public const int TupleSubclass = (1 << 26); - public const int StringSubclass = (1 << 27); - public const int UnicodeSubclass = (1 << 28); - public const int DictSubclass = (1 << 29); - public const int BaseExceptionSubclass = (1 << 30); - public const int TypeSubclass = (1 << 31); - - public const int Default = ( + IntSubclass = (1 << 23), + LongSubclass = (1 << 24), + ListSubclass = (1 << 25), + TupleSubclass = (1 << 26), + StringSubclass = (1 << 27), + UnicodeSubclass = (1 << 28), + DictSubclass = (1 << 29), + BaseExceptionSubclass = (1 << 30), + TypeSubclass = (1 << 31), + + Default = ( HaveStacklessExtension | - HaveVersionTag); + HaveVersionTag) } diff --git a/src/runtime/managedtype.cs b/src/runtime/managedtype.cs index 23f5898d1..58ccece67 100644 --- a/src/runtime/managedtype.cs +++ b/src/runtime/managedtype.cs @@ -29,7 +29,7 @@ internal static ManagedType GetManagedObject(IntPtr ob) } var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); - if ((flags & TypeFlags.Managed) != 0) + if ((flags & (int)TypeFlags.Managed) != 0) { IntPtr op = tp == ob ? Marshal.ReadIntPtr(tp, TypeOffset.magic()) @@ -68,7 +68,7 @@ internal static bool IsManagedType(IntPtr ob) } var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); - if ((flags & TypeFlags.Managed) != 0) + if ((flags & (int)TypeFlags.Managed) != 0) { return true; } diff --git a/src/runtime/metatype.cs b/src/runtime/metatype.cs index 5af2e1a7e..5175964e0 100644 --- a/src/runtime/metatype.cs +++ b/src/runtime/metatype.cs @@ -99,13 +99,13 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) return IntPtr.Zero; } - int flags = TypeFlags.Default; + TypeFlags flags = TypeFlags.Default; flags |= TypeFlags.Managed; flags |= TypeFlags.HeapType; flags |= TypeFlags.BaseType; flags |= TypeFlags.Subclass; flags |= TypeFlags.HaveGC; - Util.WriteCLong(type, TypeOffset.tp_flags, flags); + Util.WriteCLong(type, TypeOffset.tp_flags, (int)flags); TypeManager.CopySlot(base_type, type, TypeOffset.tp_dealloc); @@ -238,7 +238,7 @@ public static void tp_dealloc(IntPtr tp) // Fix this when we dont cheat on the handle for subclasses! var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); - if ((flags & TypeFlags.Subclass) == 0) + if ((flags & (int)TypeFlags.Subclass) == 0) { IntPtr gc = Marshal.ReadIntPtr(tp, TypeOffset.magic()); ((GCHandle)gc).Free(); diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 04d40a2ba..641139985 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -92,9 +92,9 @@ internal static IntPtr CreateType(Type impl) InitializeSlots(type, impl); - int flags = TypeFlags.Default | TypeFlags.Managed | + TypeFlags flags = TypeFlags.Default | TypeFlags.Managed | TypeFlags.HeapType | TypeFlags.HaveGC; - Util.WriteCLong(type, TypeOffset.tp_flags, flags); + Util.WriteCLong(type, TypeOffset.tp_flags, (int)flags); Runtime.PyType_Ready(type); @@ -170,12 +170,12 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) Runtime.XIncref(base_); } - int flags = TypeFlags.Default; + TypeFlags flags = TypeFlags.Default; flags |= TypeFlags.Managed; flags |= TypeFlags.HeapType; flags |= TypeFlags.BaseType; flags |= TypeFlags.HaveGC; - Util.WriteCLong(type, TypeOffset.tp_flags, flags); + Util.WriteCLong(type, TypeOffset.tp_flags, (int)flags); // Leverage followup initialization from the Python runtime. Note // that the type of the new type must PyType_Type at the time we @@ -342,11 +342,11 @@ internal static IntPtr CreateMetaType(Type impl) InitializeSlots(type, impl); - int flags = TypeFlags.Default; + TypeFlags flags = TypeFlags.Default; flags |= TypeFlags.Managed; flags |= TypeFlags.HeapType; flags |= TypeFlags.HaveGC; - Util.WriteCLong(type, TypeOffset.tp_flags, flags); + Util.WriteCLong(type, TypeOffset.tp_flags, (int)flags); // We need space for 3 PyMethodDef structs, each of them // 4 int-ptrs in size. @@ -401,11 +401,11 @@ internal static IntPtr BasicSubType(string name, IntPtr base_, Type impl) Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_); Runtime.XIncref(base_); - int flags = TypeFlags.Default; + TypeFlags flags = TypeFlags.Default; flags |= TypeFlags.Managed; flags |= TypeFlags.HeapType; flags |= TypeFlags.HaveGC; - Util.WriteCLong(type, TypeOffset.tp_flags, flags); + Util.WriteCLong(type, TypeOffset.tp_flags, (int)flags); CopySlot(base_, type, TypeOffset.tp_traverse); CopySlot(base_, type, TypeOffset.tp_clear); From 7f576cfc8dc505cce30c0adb4d3d4d62d76207df Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Tue, 15 Sep 2020 19:49:42 -0500 Subject: [PATCH 5/6] use HasFlag --- src/runtime/clrobject.cs | 4 ++-- src/runtime/managedtype.cs | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/runtime/clrobject.cs b/src/runtime/clrobject.cs index d6ef09f79..26a52cece 100644 --- a/src/runtime/clrobject.cs +++ b/src/runtime/clrobject.cs @@ -11,8 +11,8 @@ internal CLRObject(object ob, IntPtr tp) { IntPtr py = Runtime.PyType_GenericAlloc(tp, 0); - long flags = Util.ReadCLong(tp, TypeOffset.tp_flags); - if ((flags & (int)TypeFlags.Subclass) != 0) + var flags = (TypeFlags)Util.ReadCLong(tp, TypeOffset.tp_flags); + if (flags.HasFlag(TypeFlags.Subclass)) { IntPtr dict = Marshal.ReadIntPtr(py, ObjectOffset.TypeDictOffset(tp)); if (dict == IntPtr.Zero) diff --git a/src/runtime/managedtype.cs b/src/runtime/managedtype.cs index 58ccece67..aa300332e 100644 --- a/src/runtime/managedtype.cs +++ b/src/runtime/managedtype.cs @@ -67,11 +67,8 @@ internal static bool IsManagedType(IntPtr ob) tp = ob; } - var flags = Util.ReadCLong(tp, TypeOffset.tp_flags); - if ((flags & (int)TypeFlags.Managed) != 0) - { - return true; - } + var flags = (TypeFlags)Util.ReadCLong(tp, TypeOffset.tp_flags); + return flags.HasFlag(TypeFlags.Managed); } return false; } From 8e1fa206af347a4710e8733fe32147012d985e58 Mon Sep 17 00:00:00 2001 From: Mohamed Koubaa Date: Thu, 17 Sep 2020 20:52:12 -0500 Subject: [PATCH 6/6] remove unused dictionary --- src/runtime/interop.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 49db99e70..7d8c2ac2e 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -89,7 +89,6 @@ static TypeOffset() internal static class ManagedDataOffsets { public static int Magic { get; private set; } - public static readonly Dictionary NameMapping = new Dictionary(); static class DataOffsets { @@ -108,11 +107,6 @@ static DataOffsets() static ManagedDataOffsets() { - Type type = typeof(TypeOffset); - foreach (FieldInfo fi in type.GetFields()) - { - NameMapping[fi.Name] = (int)fi.GetValue(null); - } Magic = TypeOffset.members; FieldInfo[] fields = typeof(DataOffsets).GetFields(BindingFlags.Static | BindingFlags.Public); size = fields.Length * IntPtr.Size;