Skip to content

Commit 93a1313

Browse files
committed
use PyType instances instead of raw pointers in TypeManager type cache and ConstructorBinding instances
1 parent db746aa commit 93a1313

13 files changed

+142
-157
lines changed

src/runtime/classbase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ public static int tp_clear(IntPtr ob)
373373
protected override void OnSave(InterDomainContext context)
374374
{
375375
base.OnSave(context);
376-
if (pyHandle != tpHandle)
376+
if (!this.IsClrMetaTypeInstance())
377377
{
378378
IntPtr dict = GetObjectDict(pyHandle);
379379
Runtime.XIncref(dict);
@@ -384,7 +384,7 @@ protected override void OnSave(InterDomainContext context)
384384
protected override void OnLoad(InterDomainContext context)
385385
{
386386
base.OnLoad(context);
387-
if (pyHandle != tpHandle)
387+
if (!this.IsClrMetaTypeInstance())
388388
{
389389
IntPtr dict = context.Storage.GetValue<IntPtr>("dict");
390390
SetObjectDict(pyHandle, dict);

src/runtime/classderived.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,13 @@ internal static IntPtr ToPython(IPythonDerivedType obj)
122122
/// </summary>
123123
internal static Type CreateDerivedType(string name,
124124
Type baseType,
125-
IntPtr py_dict,
125+
BorrowedReference dictRef,
126126
string namespaceStr,
127127
string assemblyName,
128128
string moduleName = "Python.Runtime.Dynamic.dll")
129129
{
130+
// TODO: clean up
131+
IntPtr py_dict = dictRef.DangerousGetAddress();
130132
if (null != namespaceStr)
131133
{
132134
name = namespaceStr + "." + name;
@@ -824,7 +826,7 @@ public static void InvokeCtor(IPythonDerivedType obj, string origCtorName, objec
824826
try
825827
{
826828
// create the python object
827-
IntPtr type = TypeManager.GetTypeHandle(obj.GetType());
829+
BorrowedReference type = TypeManager.GetTypeReference(obj.GetType());
828830
self = new CLRObject(obj, type);
829831

830832
// set __pyobj__ to self and deref the python object which will allow this

src/runtime/classmanager.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ internal static void SaveRuntimeData(RuntimeDataStorage storage)
117117
// Python object's dictionary tool; thus raising an AttributeError
118118
// instead of a TypeError.
119119
// Classes are re-initialized on in RestoreRuntimeData.
120-
var dict = new BorrowedReference(Marshal.ReadIntPtr(cls.Value.tpHandle, TypeOffset.tp_dict));
120+
using var dict = Runtime.PyObject_GenericGetDict(cls.Value.TypeReference);
121121
foreach (var member in cls.Value.dotNetMembers)
122122
{
123123
// No need to decref the member, the ClassBase instance does
@@ -135,7 +135,7 @@ internal static void SaveRuntimeData(RuntimeDataStorage storage)
135135
}
136136
}
137137
// We modified the Type object, notify it we did.
138-
Runtime.PyType_Modified(cls.Value.tpHandle);
138+
Runtime.PyType_Modified(cls.Value.TypeReference);
139139
}
140140
}
141141

@@ -155,7 +155,7 @@ internal static Dictionary<ManagedType, InterDomainContext> RestoreRuntimeData(R
155155
// re-init the class
156156
InitClassBase(pair.Key.Value, pair.Value);
157157
// We modified the Type object, notify it we did.
158-
Runtime.PyType_Modified(pair.Value.tpHandle);
158+
Runtime.PyType_Modified(pair.Value.TypeReference);
159159
var context = contexts[pair.Value.pyHandle];
160160
pair.Value.Load(context);
161161
loadedObjs.Add(pair.Value, context);
@@ -266,10 +266,10 @@ private static void InitClassBase(Type type, ClassBase impl)
266266
// point to the managed methods providing the implementation.
267267

268268

269-
IntPtr tp = TypeManager.GetTypeHandle(impl, type);
269+
var pyType = TypeManager.GetType(impl, type);
270270

271271
// Finally, initialize the class __dict__ and return the object.
272-
var dict = new BorrowedReference(Marshal.ReadIntPtr(tp, TypeOffset.tp_dict));
272+
using var dict = Runtime.PyObject_GenericGetDict(pyType.Reference);
273273

274274

275275
if (impl.dotNetMembers == null)
@@ -312,7 +312,7 @@ private static void InitClassBase(Type type, ClassBase impl)
312312
// Implement Overloads on the class object
313313
if (!CLRModule._SuppressOverloads)
314314
{
315-
var ctors = new ConstructorBinding(type, tp, co.binder);
315+
var ctors = new ConstructorBinding(type, pyType, co.binder);
316316
// ExtensionType types are untracked, so don't Incref() them.
317317
// TODO: deprecate __overloads__ soon...
318318
Runtime.PyDict_SetItem(dict, PyIdentifier.__overloads__, ctors.ObjectReference);
@@ -332,7 +332,7 @@ private static void InitClassBase(Type type, ClassBase impl)
332332

333333
// The type has been modified after PyType_Ready has been called
334334
// Refresh the type
335-
Runtime.PyType_Modified(tp);
335+
Runtime.PyType_Modified(pyType.Reference);
336336
}
337337

338338
internal static bool ShouldBindMethod(MethodBase mb)

src/runtime/clrobject.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ internal CLRObject(object ob, IntPtr tp)
2626
if (ob is Exception e) Exceptions.SetArgsAndCause(e, py);
2727
}
2828

29+
internal CLRObject(object ob, BorrowedReference tp) : this(ob, tp.DangerousGetAddress()) { }
30+
2931
protected CLRObject()
3032
{
3133
}

src/runtime/constructorbinding.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@ namespace Python.Runtime
2323
internal class ConstructorBinding : ExtensionType
2424
{
2525
private MaybeType type; // The managed Type being wrapped in a ClassObject
26-
private IntPtr pyTypeHndl; // The python type tells GetInstHandle which Type to create.
26+
private PyType typeToCreate; // The python type tells GetInstHandle which Type to create.
2727
private ConstructorBinder ctorBinder;
2828

2929
[NonSerialized]
3030
private IntPtr repr;
3131

32-
public ConstructorBinding(Type type, IntPtr pyTypeHndl, ConstructorBinder ctorBinder)
32+
public ConstructorBinding(Type type, PyType typeToCreate, ConstructorBinder ctorBinder)
3333
{
3434
this.type = type;
35-
this.pyTypeHndl = pyTypeHndl; // steal a type reference
35+
this.typeToCreate = typeToCreate;
3636
this.ctorBinder = ctorBinder;
3737
repr = IntPtr.Zero;
3838
}
@@ -110,7 +110,7 @@ public static IntPtr mp_subscript(IntPtr op, IntPtr key)
110110
{
111111
return Exceptions.RaiseTypeError("No match found for constructor signature");
112112
}
113-
var boundCtor = new BoundContructor(tp, self.pyTypeHndl, self.ctorBinder, ci);
113+
var boundCtor = new BoundContructor(tp, self.typeToCreate, self.ctorBinder, ci);
114114

115115
return boundCtor.pyHandle;
116116
}
@@ -169,7 +169,7 @@ public static int tp_clear(IntPtr ob)
169169
public static int tp_traverse(IntPtr ob, IntPtr visit, IntPtr arg)
170170
{
171171
var self = (ConstructorBinding)GetManagedObject(ob);
172-
int res = PyVisit(self.pyTypeHndl, visit, arg);
172+
int res = PyVisit(self.typeToCreate.Handle, visit, arg);
173173
if (res != 0) return res;
174174

175175
res = PyVisit(self.repr, visit, arg);
@@ -190,15 +190,15 @@ public static int tp_traverse(IntPtr ob, IntPtr visit, IntPtr arg)
190190
internal class BoundContructor : ExtensionType
191191
{
192192
private Type type; // The managed Type being wrapped in a ClassObject
193-
private IntPtr pyTypeHndl; // The python type tells GetInstHandle which Type to create.
193+
private PyType typeToCreate; // The python type tells GetInstHandle which Type to create.
194194
private ConstructorBinder ctorBinder;
195195
private ConstructorInfo ctorInfo;
196196
private IntPtr repr;
197197

198-
public BoundContructor(Type type, IntPtr pyTypeHndl, ConstructorBinder ctorBinder, ConstructorInfo ci)
198+
public BoundContructor(Type type, PyType typeToCreate, ConstructorBinder ctorBinder, ConstructorInfo ci)
199199
{
200200
this.type = type;
201-
this.pyTypeHndl = pyTypeHndl; // steal a type reference
201+
this.typeToCreate = typeToCreate;
202202
this.ctorBinder = ctorBinder;
203203
ctorInfo = ci;
204204
repr = IntPtr.Zero;
@@ -229,7 +229,7 @@ public static IntPtr tp_call(IntPtr op, IntPtr args, IntPtr kw)
229229
}
230230
// Instantiate the python object that wraps the result of the method call
231231
// and return the PyObject* to it.
232-
return CLRObject.GetInstHandle(obj, self.pyTypeHndl);
232+
return CLRObject.GetInstHandle(obj, self.typeToCreate.Reference).DangerousMoveToPointer();
233233
}
234234

235235
/// <summary>
@@ -272,7 +272,7 @@ public static int tp_clear(IntPtr ob)
272272
public static int tp_traverse(IntPtr ob, IntPtr visit, IntPtr arg)
273273
{
274274
var self = (BoundContructor)GetManagedObject(ob);
275-
int res = PyVisit(self.pyTypeHndl, visit, arg);
275+
int res = PyVisit(self.typeToCreate.Handle, visit, arg);
276276
if (res != 0) return res;
277277

278278
res = PyVisit(self.repr, visit, arg);

src/runtime/exceptions.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,15 @@ internal static void ErrorOccurredCheck(IntPtr pointer)
206206
}
207207
}
208208

209+
internal static IntPtr ErrorCheckIfNull(IntPtr pointer)
210+
{
211+
if (pointer == IntPtr.Zero && ErrorOccurred())
212+
{
213+
throw new PythonException();
214+
}
215+
return pointer;
216+
}
217+
209218
/// <summary>
210219
/// ExceptionMatches Method
211220
/// </summary>

src/runtime/extensiontype.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public ExtensionType()
1818
// The Python instance object is related to an instance of a
1919
// particular concrete subclass with a hidden CLR gchandle.
2020

21-
IntPtr tp = TypeManager.GetTypeHandle(GetType());
21+
BorrowedReference tp = TypeManager.GetTypeReference(GetType());
2222

2323
//int rc = (int)Marshal.ReadIntPtr(tp, TypeOffset.ob_refcnt);
2424
//if (rc > 1050)
@@ -27,11 +27,11 @@ public ExtensionType()
2727
// DebugUtil.DumpType(tp);
2828
//}
2929

30-
IntPtr py = Runtime.PyType_GenericAlloc(tp, 0);
30+
NewReference py = Runtime.PyType_GenericAlloc(tp, 0);
3131

32-
// Steals a ref to tpHandle.
33-
tpHandle = tp;
34-
pyHandle = py;
32+
// Borrowed reference. Valid as long as pyHandle is valid.
33+
tpHandle = tp.DangerousGetAddress();
34+
pyHandle = py.DangerousMoveToPointer();
3535

3636
#if DEBUG
3737
GetGCHandle(ObjectReference, TypeReference, out var existing);

src/runtime/managedtype.cs

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#nullable enable
12
using System;
23
using System.Collections.Generic;
34
using System.Diagnostics;
@@ -27,8 +28,8 @@ internal enum TrackTypes
2728
internal IntPtr pyHandle; // PyObject *
2829
internal IntPtr tpHandle; // PyType *
2930

30-
internal BorrowedReference ObjectReference => new BorrowedReference(pyHandle);
31-
internal BorrowedReference TypeReference => new BorrowedReference(tpHandle);
31+
internal BorrowedReference ObjectReference => new(pyHandle);
32+
internal BorrowedReference TypeReference => new(tpHandle);
3233

3334
private static readonly Dictionary<ManagedType, TrackTypes> _managedObjs = new Dictionary<ManagedType, TrackTypes>();
3435

@@ -78,12 +79,12 @@ internal void FreeGCHandle()
7879
}
7980
}
8081

81-
internal static ManagedType GetManagedObject(BorrowedReference ob)
82+
internal static ManagedType? GetManagedObject(BorrowedReference ob)
8283
=> GetManagedObject(ob.DangerousGetAddress());
8384
/// <summary>
8485
/// Given a Python object, return the associated managed object or null.
8586
/// </summary>
86-
internal static ManagedType GetManagedObject(IntPtr ob)
87+
internal static ManagedType? GetManagedObject(IntPtr ob)
8788
{
8889
if (ob != IntPtr.Zero)
8990
{
@@ -106,7 +107,7 @@ internal static ManagedType GetManagedObject(IntPtr ob)
106107
/// <summary>
107108
/// Given a Python object, return the associated managed object type or null.
108109
/// </summary>
109-
internal static ManagedType GetManagedObjectType(IntPtr ob)
110+
internal static ManagedType? GetManagedObjectType(IntPtr ob)
110111
{
111112
if (ob != IntPtr.Zero)
112113
{
@@ -121,18 +122,6 @@ internal static ManagedType GetManagedObjectType(IntPtr ob)
121122
return null;
122123
}
123124

124-
125-
internal static ManagedType GetManagedObjectErr(IntPtr ob)
126-
{
127-
ManagedType result = GetManagedObject(ob);
128-
if (result == null)
129-
{
130-
Exceptions.SetError(Exceptions.TypeError, "invalid argument, expected CLR type");
131-
}
132-
return result;
133-
}
134-
135-
136125
internal static bool IsInstanceOfManagedType(BorrowedReference ob)
137126
=> IsInstanceOfManagedType(ob.DangerousGetAddressOrNull());
138127
internal static bool IsInstanceOfManagedType(IntPtr ob)
@@ -156,6 +145,13 @@ internal static bool IsManagedType(BorrowedReference type)
156145
return (flags & TypeFlags.HasClrInstance) != 0;
157146
}
158147

148+
public bool IsClrMetaTypeInstance()
149+
{
150+
Debug.Assert(Runtime.PyCLRMetaType != IntPtr.Zero);
151+
Debug.Assert(pyHandle != IntPtr.Zero);
152+
return Runtime.PyObject_TYPE(pyHandle) == Runtime.PyCLRMetaType;
153+
}
154+
159155
internal static IDictionary<ManagedType, TrackTypes> GetManagedObjects()
160156
{
161157
return _managedObjs;
@@ -185,7 +181,8 @@ internal void CallTypeClear()
185181
{
186182
return;
187183
}
188-
var clearPtr = Marshal.ReadIntPtr(tpHandle, TypeOffset.tp_clear);
184+
185+
var clearPtr = Runtime.PyType_GetSlot(TypeReference, TypeSlotID.tp_clear);
189186
if (clearPtr == IntPtr.Zero)
190187
{
191188
return;
@@ -203,7 +200,7 @@ internal void CallTypeTraverse(Interop.ObjObjFunc visitproc, IntPtr arg)
203200
{
204201
return;
205202
}
206-
var traversePtr = Marshal.ReadIntPtr(tpHandle, TypeOffset.tp_traverse);
203+
var traversePtr = Runtime.PyType_GetSlot(TypeReference, TypeSlotID.tp_traverse);
207204
if (traversePtr == IntPtr.Zero)
208205
{
209206
return;

src/runtime/metatype.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw)
132132
{
133133
if (clsDict.HasKey("__assembly__") || clsDict.HasKey("__namespace__"))
134134
{
135-
return TypeManager.CreateSubType(name, base_type, dict);
135+
return TypeManager.CreateSubType(name, base_type, clsDict.Reference);
136136
}
137137
}
138138
}
@@ -266,7 +266,7 @@ public static int tp_setattro(IntPtr tp, IntPtr name, IntPtr value)
266266
}
267267

268268
int res = Runtime.PyObject_GenericSetAttr(tp, name, value);
269-
Runtime.PyType_Modified(tp);
269+
Runtime.PyType_Modified(new BorrowedReference(tp));
270270

271271
return res;
272272
}

src/runtime/pytype.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,20 @@
66

77
namespace Python.Runtime
88
{
9+
[Serializable]
910
public class PyType : PyObject
1011
{
1112
/// <summary>Creates heap type object from the <paramref name="spec"/>.</summary>
1213
public PyType(TypeSpec spec, PyTuple? bases = null) : base(FromSpec(spec, bases)) { }
1314
/// <summary>Wraps an existing type object.</summary>
1415
public PyType(PyObject o) : base(FromObject(o)) { }
1516

17+
internal PyType(BorrowedReference reference) : base(reference)
18+
{
19+
if (!Runtime.PyType_Check(this.Handle))
20+
throw new ArgumentException("object is not a type");
21+
}
22+
1623
/// <summary>Checks if specified object is a Python type.</summary>
1724
public static bool IsType(PyObject value)
1825
{
@@ -21,6 +28,12 @@ public static bool IsType(PyObject value)
2128
return Runtime.PyType_Check(value.obj);
2229
}
2330

31+
internal IntPtr GetSlot(TypeSlotID slot)
32+
{
33+
IntPtr result = Runtime.PyType_GetSlot(this.Reference, slot);
34+
return Exceptions.ErrorCheckIfNull(result);
35+
}
36+
2437
private static BorrowedReference FromObject(PyObject o)
2538
{
2639
if (o is null) throw new ArgumentNullException(nameof(o));

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy