Skip to content

Commit 3344110

Browse files
committed
increase C# custom Python object size to match that of exception to avoid type checks
1 parent de514d8 commit 3344110

File tree

1 file changed

+41
-38
lines changed

1 file changed

+41
-38
lines changed

src/runtime/interop.cs

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,9 @@ public ModulePropertyAttribute()
6767
}
6868
}
6969

70-
71-
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
72-
internal class ObjectOffset
70+
internal static class OriginalObjectOffsets
7371
{
74-
static ObjectOffset()
72+
static OriginalObjectOffsets()
7573
{
7674
int size = IntPtr.Size;
7775
var n = 0; // Py_TRACE_REFS add two pointers to PyObject_HEAD
@@ -82,39 +80,52 @@ static ObjectOffset()
8280
#endif
8381
ob_refcnt = (n + 0) * size;
8482
ob_type = (n + 1) * size;
85-
ob_dict = (n + 2) * size;
86-
ob_data = (n + 3) * size;
83+
}
84+
85+
public static int Size() {
86+
#if PYTHON_WITH_PYDEBUG
87+
return 4 * IntPtr.Size;
88+
#else
89+
return 2 * IntPtr.Size;
90+
#endif
91+
}
92+
93+
#if PYTHON_WITH_PYDEBUG
94+
public static int _ob_next;
95+
public static int _ob_prev;
96+
#endif
97+
public static int ob_refcnt;
98+
public static int ob_type;
99+
}
100+
101+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
102+
internal class ObjectOffset
103+
{
104+
static ObjectOffset()
105+
{
106+
#if PYTHON_WITH_PYDEBUG
107+
_ob_next = OriginalObjectOffsets._ob_next;
108+
_ob_prev = OriginalObjectOffsets._ob_prev;
109+
#endif
110+
ob_refcnt = OriginalObjectOffsets.ob_refcnt;
111+
ob_type = OriginalObjectOffsets.ob_type;
112+
ob_dict = ExceptionOffset.ob_dict;
113+
ob_data = ExceptionOffset.ob_data;
87114
}
88115

89116
public static int magic(IntPtr ob)
90117
{
91-
if (IsException(ob))
92-
{
93-
return ExceptionOffset.ob_data;
94-
}
95118
return ob_data;
96119
}
97120

98121
public static int DictOffset(IntPtr ob)
99122
{
100-
if (IsException(ob))
101-
{
102-
return ExceptionOffset.ob_dict;
103-
}
104123
return ob_dict;
105124
}
106125

107126
public static int Size(IntPtr ob)
108127
{
109-
if (IsException(ob))
110-
{
111-
return ExceptionOffset.Size();
112-
}
113-
#if PYTHON_WITH_PYDEBUG
114-
return 6 * IntPtr.Size;
115-
#else
116-
return 4 * IntPtr.Size;
117-
#endif
128+
return ExceptionOffset.Size();
118129
}
119130

120131
#if PYTHON_WITH_PYDEBUG
@@ -125,14 +136,6 @@ public static int Size(IntPtr ob)
125136
public static int ob_type;
126137
private static int ob_dict;
127138
private static int ob_data;
128-
129-
private static bool IsException(IntPtr pyObject)
130-
{
131-
var type = Runtime.PyObject_TYPE(pyObject);
132-
return Runtime.PyObjectType_TypeCheck(type, Exceptions.BaseException)
133-
|| Runtime.PyObjectType_TypeCheck(type, Runtime.PyTypeType)
134-
&& Runtime.PyType_IsSubtype(pyObject, Exceptions.BaseException);
135-
}
136139
}
137140

138141
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
@@ -141,19 +144,17 @@ internal class ExceptionOffset
141144
static ExceptionOffset()
142145
{
143146
Type type = typeof(ExceptionOffset);
144-
FieldInfo[] fi = type.GetFields();
145-
int size = IntPtr.Size;
147+
FieldInfo[] fi = type.GetFields(BindingFlags.Static | BindingFlags.Public);
146148
for (int i = 0; i < fi.Length; i++)
147149
{
148-
fi[i].SetValue(null, (i * size) + ObjectOffset.ob_type + size);
150+
fi[i].SetValue(null, (i * IntPtr.Size) + OriginalObjectOffsets.Size());
149151
}
150-
}
151152

152-
public static int Size()
153-
{
154-
return ob_data + IntPtr.Size;
153+
size = ob_data + IntPtr.Size;
155154
}
156155

156+
public static int Size() { return size; }
157+
157158
// PyException_HEAD
158159
// (start after PyObject_HEAD)
159160
public static int dict = 0;
@@ -170,6 +171,8 @@ public static int Size()
170171
// extra c# data
171172
public static int ob_dict;
172173
public static int ob_data;
174+
175+
static readonly int size;
173176
}
174177

175178

0 commit comments

Comments
 (0)