Skip to content

Commit 0d158f5

Browse files
committed
instead of expanding size of objects to be the same as Exception, calculate offset to the extra data from the end of the object
1 parent 3344110 commit 0d158f5

File tree

7 files changed

+80
-31
lines changed

7 files changed

+80
-31
lines changed

src/runtime/classbase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ public static int tp_is_gc(IntPtr type)
271271
public static void tp_dealloc(IntPtr ob)
272272
{
273273
ManagedType self = GetManagedObject(ob);
274-
IntPtr dict = Marshal.ReadIntPtr(ob, ObjectOffset.DictOffset(ob));
274+
IntPtr dict = Marshal.ReadIntPtr(ob, ObjectOffset.TypeDictOffset(self.tpHandle));
275275
if (dict != IntPtr.Zero)
276276
{
277277
Runtime.XDecref(dict);

src/runtime/classderived.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.Reflection;
@@ -870,7 +870,7 @@ public static void Finalize(IPythonDerivedType obj)
870870
// the C# object is being destroyed which must mean there are no more
871871
// references to the Python object as well so now we can dealloc the
872872
// python object.
873-
IntPtr dict = Marshal.ReadIntPtr(self.pyHandle, ObjectOffset.DictOffset(self.pyHandle));
873+
IntPtr dict = Marshal.ReadIntPtr(self.pyHandle, ObjectOffset.TypeDictOffset(self.tpHandle));
874874
if (dict != IntPtr.Zero)
875875
{
876876
Runtime.XDecref(dict);

src/runtime/clrobject.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ internal CLRObject(object ob, IntPtr tp)
1414
long flags = Util.ReadCLong(tp, TypeOffset.tp_flags);
1515
if ((flags & TypeFlags.Subclass) != 0)
1616
{
17-
IntPtr dict = Marshal.ReadIntPtr(py, ObjectOffset.DictOffset(tp));
17+
IntPtr dict = Marshal.ReadIntPtr(py, ObjectOffset.TypeDictOffset(tp));
1818
if (dict == IntPtr.Zero)
1919
{
2020
dict = Runtime.PyDict_New();
21-
Marshal.WriteIntPtr(py, ObjectOffset.DictOffset(tp), dict);
21+
Marshal.WriteIntPtr(py, ObjectOffset.TypeDictOffset(tp), dict);
2222
}
2323
}
2424

src/runtime/interop.cs

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using System.Diagnostics;
45
using System.Runtime.InteropServices;
56
using System.Reflection;
67
using System.Text;
@@ -67,6 +68,44 @@ public ModulePropertyAttribute()
6768
}
6869
}
6970

71+
internal static class ManagedDataOffsets
72+
{
73+
static ManagedDataOffsets()
74+
{
75+
FieldInfo[] fi = typeof(ManagedDataOffsets).GetFields(BindingFlags.Static | BindingFlags.Public);
76+
for (int i = 0; i < fi.Length; i++)
77+
{
78+
fi[i].SetValue(null, -(i * IntPtr.Size) - IntPtr.Size);
79+
}
80+
81+
size = fi.Length * IntPtr.Size;
82+
}
83+
84+
public static readonly int ob_data;
85+
public static readonly int ob_dict;
86+
87+
static int BaseOffset(IntPtr type)
88+
{
89+
Debug.Assert(type != IntPtr.Zero);
90+
int typeSize = Marshal.ReadInt32(type, TypeOffset.tp_basicsize);
91+
Debug.Assert(typeSize > 0 && typeSize <= ExceptionOffset.Size());
92+
return typeSize;
93+
}
94+
public static int DataOffset(IntPtr type)
95+
{
96+
return BaseOffset(type) + ob_data;
97+
}
98+
99+
public static int DictOffset(IntPtr type)
100+
{
101+
return BaseOffset(type) + ob_dict;
102+
}
103+
104+
public static int Size { get { return size; } }
105+
106+
static readonly int size;
107+
}
108+
70109
internal static class OriginalObjectOffsets
71110
{
72111
static OriginalObjectOffsets()
@@ -82,13 +121,14 @@ static OriginalObjectOffsets()
82121
ob_type = (n + 1) * size;
83122
}
84123

85-
public static int Size() {
124+
public static int Size { get { return size; } }
125+
126+
static readonly int size =
86127
#if PYTHON_WITH_PYDEBUG
87-
return 4 * IntPtr.Size;
128+
4 * IntPtr.Size;
88129
#else
89-
return 2 * IntPtr.Size;
130+
2 * IntPtr.Size;
90131
#endif
91-
}
92132

93133
#if PYTHON_WITH_PYDEBUG
94134
public static int _ob_next;
@@ -109,23 +149,28 @@ static ObjectOffset()
109149
#endif
110150
ob_refcnt = OriginalObjectOffsets.ob_refcnt;
111151
ob_type = OriginalObjectOffsets.ob_type;
112-
ob_dict = ExceptionOffset.ob_dict;
113-
ob_data = ExceptionOffset.ob_data;
152+
153+
size = OriginalObjectOffsets.Size + ManagedDataOffsets.Size;
114154
}
115155

116-
public static int magic(IntPtr ob)
156+
public static int magic(IntPtr type)
117157
{
118-
return ob_data;
158+
return ManagedDataOffsets.DataOffset(type);
119159
}
120160

121-
public static int DictOffset(IntPtr ob)
161+
public static int TypeDictOffset(IntPtr type)
122162
{
123-
return ob_dict;
163+
return ManagedDataOffsets.DictOffset(type);
124164
}
125165

126-
public static int Size(IntPtr ob)
166+
public static int Size(IntPtr pyType)
127167
{
128-
return ExceptionOffset.Size();
168+
if (IsException(pyType))
169+
{
170+
return ExceptionOffset.Size();
171+
}
172+
173+
return size;
129174
}
130175

131176
#if PYTHON_WITH_PYDEBUG
@@ -134,8 +179,16 @@ public static int Size(IntPtr ob)
134179
#endif
135180
public static int ob_refcnt;
136181
public static int ob_type;
137-
private static int ob_dict;
138-
private static int ob_data;
182+
183+
static readonly int size;
184+
185+
private static bool IsException(IntPtr pyObject)
186+
{
187+
var type = Runtime.PyObject_TYPE(pyObject);
188+
return Runtime.PyObjectType_TypeCheck(type, Exceptions.BaseException)
189+
|| Runtime.PyObjectType_TypeCheck(type, Runtime.PyTypeType)
190+
&& Runtime.PyType_IsSubtype(pyObject, Exceptions.BaseException);
191+
}
139192
}
140193

141194
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
@@ -147,10 +200,10 @@ static ExceptionOffset()
147200
FieldInfo[] fi = type.GetFields(BindingFlags.Static | BindingFlags.Public);
148201
for (int i = 0; i < fi.Length; i++)
149202
{
150-
fi[i].SetValue(null, (i * IntPtr.Size) + OriginalObjectOffsets.Size());
203+
fi[i].SetValue(null, (i * IntPtr.Size) + OriginalObjectOffsets.Size);
151204
}
152205

153-
size = ob_data + IntPtr.Size;
206+
size = fi.Length * IntPtr.Size + OriginalObjectOffsets.Size + ManagedDataOffsets.Size;
154207
}
155208

156209
public static int Size() { return size; }
@@ -168,10 +221,6 @@ static ExceptionOffset()
168221
public static int suppress_context = 0;
169222
#endif
170223

171-
// extra c# data
172-
public static int ob_dict;
173-
public static int ob_data;
174-
175224
static readonly int size;
176225
}
177226

src/runtime/managedtype.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ internal static ManagedType GetManagedObject(IntPtr ob)
3333
{
3434
IntPtr op = tp == ob
3535
? Marshal.ReadIntPtr(tp, TypeOffset.magic())
36-
: Marshal.ReadIntPtr(ob, ObjectOffset.magic(ob));
36+
: Marshal.ReadIntPtr(ob, ObjectOffset.magic(tp));
3737
if (op == IntPtr.Zero)
3838
{
3939
return null;

src/runtime/moduleobject.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public ModuleObject(string name)
5353
Runtime.XDecref(pyfilename);
5454
Runtime.XDecref(pydocstring);
5555

56-
Marshal.WriteIntPtr(pyHandle, ObjectOffset.DictOffset(pyHandle), dict);
56+
Marshal.WriteIntPtr(pyHandle, ObjectOffset.TypeDictOffset(tpHandle), dict);
5757

5858
InitializeModuleMembers();
5959
}

src/runtime/typemanager.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections;
33
using System.Collections.Generic;
44
using System.Reflection;
@@ -79,7 +79,7 @@ internal static IntPtr CreateType(Type impl)
7979
// Set tp_basicsize to the size of our managed instance objects.
8080
Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)ob_size);
8181

82-
var offset = (IntPtr)ObjectOffset.DictOffset(type);
82+
var offset = (IntPtr)ObjectOffset.TypeDictOffset(type);
8383
Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset);
8484

8585
InitializeSlots(type, impl);
@@ -117,17 +117,17 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType)
117117

118118
IntPtr base_ = IntPtr.Zero;
119119
int ob_size = ObjectOffset.Size(Runtime.PyTypeType);
120-
int tp_dictoffset = ObjectOffset.DictOffset(Runtime.PyTypeType);
121120

122121
// XXX Hack, use a different base class for System.Exception
123122
// Python 2.5+ allows new style class exceptions but they *must*
124123
// subclass BaseException (or better Exception).
125124
if (typeof(Exception).IsAssignableFrom(clrType))
126125
{
127126
ob_size = ObjectOffset.Size(Exceptions.Exception);
128-
tp_dictoffset = ObjectOffset.DictOffset(Exceptions.Exception);
129127
}
130128

129+
int tp_dictoffset = ob_size + ManagedDataOffsets.ob_dict;
130+
131131
if (clrType == typeof(Exception))
132132
{
133133
base_ = Exceptions.Exception;

0 commit comments

Comments
 (0)