Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit14f2fd2

Browse files
committed
detect Py_TRACE_REFS at runtime and calculate object offsets accordingly
1 parentdaccc43 commit14f2fd2

File tree

5 files changed

+91
-51
lines changed

5 files changed

+91
-51
lines changed

‎src/runtime/classderived.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,7 @@ internal static IntPtr ToPython(IPythonDerivedType obj)
102102
// collected while Python still has a reference to it.
103103
if(Runtime.Refcount(self.pyHandle)==1)
104104
{
105-
106-
#ifPYTHON_WITH_PYDEBUG
107-
Runtime._Py_NewReference(self.pyHandle);
108-
#endif
105+
Runtime._Py_NewReference(self.ObjectReference);
109106
GCHandlegc=GCHandle.Alloc(self,GCHandleType.Normal);
110107
SetGCHandle(self.ObjectReference,self.TypeReference,gc);
111108
self.gcHandle.Free();

‎src/runtime/converter.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,16 @@ internal static bool ToManagedValue(IntPtr value, Type obType,
525525

526526
internaldelegateboolTryConvertFromPythonDelegate(IntPtrpyObj,outobjectresult);
527527

528+
internalstaticintToInt32(BorrowedReferencevalue)
529+
{
530+
nintnum=Runtime.PyLong_AsSignedSize_t(value);
531+
if(num==-1&&Exceptions.ErrorOccurred())
532+
{
533+
thrownewPythonException();
534+
}
535+
returnchecked((int)num);
536+
}
537+
528538
/// <summary>
529539
/// Convert a Python value to an instance of a primitive managed type.
530540
/// </summary>

‎src/runtime/native/ABI.cs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ namespace Python.Runtime.Native
77

88
staticclassABI
99
{
10+
publicstaticintRefCountOffset{get;}=GetRefCountOffset();
11+
publicstaticintObjectHeadOffset=>RefCountOffset;
12+
1013
internalstaticvoidInitialize(Versionversion,BorrowedReferencepyType)
1114
{
1215
stringoffsetsClassSuffix=string.Format(CultureInfo.InvariantCulture,
@@ -16,18 +19,34 @@ internal static void Initialize(Version version, BorrowedReference pyType)
1619

1720
conststringnativeTypeOffsetClassName="Python.Runtime.NativeTypeOffset";
1821
stringclassName="Python.Runtime.TypeOffset"+offsetsClassSuffix;
22+
TypenativeOffsetsClass=thisAssembly.GetType(nativeTypeOffsetClassName,throwOnError:false);
1923
TypetypeOffsetsClass=
2024
// Try platform native offsets first. It is only present when generated by setup.py
21-
thisAssembly.GetType(nativeTypeOffsetClassName,throwOnError:false)
22-
??thisAssembly.GetType(className,throwOnError:false);
25+
nativeOffsetsClass??thisAssembly.GetType(className,throwOnError:false);
2326
if(typeOffsetsClassisnull)
2427
{
2528
vartypes=thisAssembly.GetTypes().Select(type=>type.Name).Where(name=>name.StartsWith("TypeOffset"));
2629
stringmessage=$"Searching for{className}, found{string.Join(",",types)}.";
2730
thrownewNotSupportedException($"Python ABI v{version} is not supported:{message}");
2831
}
32+
2933
vartypeOffsets=(ITypeOffsets)Activator.CreateInstance(typeOffsetsClass);
30-
TypeOffset.Use(typeOffsets);
34+
TypeOffset.Use(typeOffsets,nativeOffsetsClass==null?ObjectHeadOffset:0);
35+
}
36+
37+
staticunsafeintGetRefCountOffset()
38+
{
39+
IntPtrtempObject=Runtime.PyList_New(0);
40+
IntPtr*tempPtr=(IntPtr*)tempObject;
41+
intoffset=0;
42+
while(tempPtr[offset]!=(IntPtr)1)
43+
{
44+
offset++;
45+
if(offset>100)
46+
thrownewInvalidProgramException("PyObject_HEAD could not be found withing reasonable distance from the start of PyObject");
47+
}
48+
Runtime.XDecref(tempObject);
49+
returnoffset*IntPtr.Size;
3150
}
3251
}
3352
}

‎src/runtime/native/TypeOffset.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ static partial class TypeOffset
7575
internalstaticinttp_str{get;privateset;}
7676
internalstaticinttp_traverse{get;privateset;}
7777

78-
internalstaticvoidUse(ITypeOffsetsoffsets)
78+
internalstaticvoidUse(ITypeOffsetsoffsets,intextraHeadOffset)
7979
{
8080
if(offsetsisnull)thrownewArgumentNullException(nameof(offsets));
8181

@@ -87,6 +87,7 @@ internal static void Use(ITypeOffsets offsets)
8787

8888
varsourceProperty=typeof(ITypeOffsets).GetProperty(offsetProperty.Name);
8989
intvalue=(int)sourceProperty.GetValue(offsets,null);
90+
value+=extraHeadOffset;
9091
offsetProperty.SetValue(obj:null,value:value,index:null);
9192
}
9293

‎src/runtime/runtime.cs

Lines changed: 56 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ internal static Version PyVersion
8585
{
8686
using(varversionTuple=newPyTuple(PySys_GetObject("version_info")))
8787
{
88-
varmajor=versionTuple[0].As<int>();
89-
varminor=versionTuple[1].As<int>();
90-
varmicro=versionTuple[2].As<int>();
88+
varmajor=Converter.ToInt32(versionTuple[0].Reference);
89+
varminor=Converter.ToInt32(versionTuple[1].Reference);
90+
varmicro=Converter.ToInt32(versionTuple[2].Reference);
9191
returnnewVersion(major,minor,micro);
9292
}
9393
}
@@ -198,15 +198,15 @@ private static void InitPyMembers()
198198
SetPyMember(refPyFalse,PyObject_GetAttrString(builtins,"False"),
199199
()=>PyFalse=IntPtr.Zero);
200200

201-
SetPyMember(refPyBoolType,PyObject_Type(PyTrue),
201+
SetPyMemberTypeOf(refPyBoolType,PyTrue,
202202
()=>PyBoolType=IntPtr.Zero);
203-
SetPyMember(refPyNoneType,PyObject_Type(PyNone),
203+
SetPyMemberTypeOf(refPyNoneType,PyNone,
204204
()=>PyNoneType=IntPtr.Zero);
205-
SetPyMember(refPyTypeType,PyObject_Type(PyNoneType),
205+
SetPyMemberTypeOf(refPyTypeType,PyNoneType,
206206
()=>PyTypeType=IntPtr.Zero);
207207

208208
op=PyObject_GetAttrString(builtins,"len");
209-
SetPyMember(refPyMethodType,PyObject_Type(op),
209+
SetPyMemberTypeOf(refPyMethodType,op,
210210
()=>PyMethodType=IntPtr.Zero);
211211
XDecref(op);
212212

@@ -215,7 +215,7 @@ private static void InitPyMembers()
215215
//
216216
// object.__init__ seems safe, though.
217217
op=PyObject_GetAttr(PyBaseObjectType,PyIdentifier.__init__);
218-
SetPyMember(refPyWrapperDescriptorType,PyObject_Type(op),
218+
SetPyMemberTypeOf(refPyWrapperDescriptorType,op,
219219
()=>PyWrapperDescriptorType=IntPtr.Zero);
220220
XDecref(op);
221221

@@ -226,47 +226,47 @@ private static void InitPyMembers()
226226
}
227227

228228
op=PyString_FromString("string");
229-
SetPyMember(refPyStringType,PyObject_Type(op),
229+
SetPyMemberTypeOf(refPyStringType,op,
230230
()=>PyStringType=IntPtr.Zero);
231231
XDecref(op);
232232

233233
op=PyUnicode_FromString("unicode");
234-
SetPyMember(refPyUnicodeType,PyObject_Type(op),
234+
SetPyMemberTypeOf(refPyUnicodeType,op,
235235
()=>PyUnicodeType=IntPtr.Zero);
236236
XDecref(op);
237237

238238
op=EmptyPyBytes();
239-
SetPyMember(refPyBytesType,PyObject_Type(op),
239+
SetPyMemberTypeOf(refPyBytesType,op,
240240
()=>PyBytesType=IntPtr.Zero);
241241
XDecref(op);
242242

243243
op=PyTuple_New(0);
244-
SetPyMember(refPyTupleType,PyObject_Type(op),
244+
SetPyMemberTypeOf(refPyTupleType,op,
245245
()=>PyTupleType=IntPtr.Zero);
246246
XDecref(op);
247247

248248
op=PyList_New(0);
249-
SetPyMember(refPyListType,PyObject_Type(op),
249+
SetPyMemberTypeOf(refPyListType,op,
250250
()=>PyListType=IntPtr.Zero);
251251
XDecref(op);
252252

253253
op=PyDict_New();
254-
SetPyMember(refPyDictType,PyObject_Type(op),
254+
SetPyMemberTypeOf(refPyDictType,op,
255255
()=>PyDictType=IntPtr.Zero);
256256
XDecref(op);
257257

258258
op=PyInt_FromInt32(0);
259-
SetPyMember(refPyIntType,PyObject_Type(op),
259+
SetPyMemberTypeOf(refPyIntType,op,
260260
()=>PyIntType=IntPtr.Zero);
261261
XDecref(op);
262262

263263
op=PyLong_FromLong(0);
264-
SetPyMember(refPyLongType,PyObject_Type(op),
264+
SetPyMemberTypeOf(refPyLongType,op,
265265
()=>PyLongType=IntPtr.Zero);
266266
XDecref(op);
267267

268268
op=PyFloat_FromDouble(0);
269-
SetPyMember(refPyFloatType,PyObject_Type(op),
269+
SetPyMemberTypeOf(refPyFloatType,op,
270270
()=>PyFloatType=IntPtr.Zero);
271271
XDecref(op);
272272

@@ -278,7 +278,8 @@ private static void InitPyMembers()
278278
_PyObject_NextNotImplemented=Get_PyObject_NextNotImplemented();
279279
{
280280
usingvarsys=PyImport_ImportModule("sys");
281-
PyModuleType=PyObject_Type(sys.DangerousMoveToPointer());
281+
SetPyMemberTypeOf(refPyModuleType,sys.DangerousGetAddress(),
282+
()=>PyModuleType=IntPtr.Zero);
282283
}
283284
}
284285

@@ -455,6 +456,12 @@ private static void SetPyMember(ref IntPtr obj, IntPtr value, Action onRelease)
455456
_pyRefs.Add(value,onRelease);
456457
}
457458

459+
privatestaticvoidSetPyMemberTypeOf(refIntPtrobj,IntPtrvalue,ActiononRelease)
460+
{
461+
vartype=PyObject_Type(newBorrowedReference(value)).DangerousMoveToPointer();
462+
SetPyMember(refobj,type,onRelease);
463+
}
464+
458465
privatestaticvoidResetPyMembers()
459466
{
460467
_pyRefs.Release();
@@ -761,16 +768,12 @@ internal static unsafe void XDecref(IntPtr op)
761768
[Pure]
762769
internalstatic unsafelong Refcount(IntPtrop)
763770
{
764-
#if PYTHON_WITH_PYDEBUG
765-
var p=(void*)(op+TypeOffset.ob_refcnt);
766-
#else
767-
var p=(void*)op;
768-
#endif
769-
if((void*)0==p)
771+
if(op==IntPtr.Zero)
770772
{
771773
return0;
772774
}
773-
return Is32Bit?(*(int*)p):(*(long*)p);
775+
var p=(nint*)(op+ABI.RefCountOffset);
776+
return*p;
774777
}
775778

776779
/// <summary>
@@ -977,14 +980,9 @@ internal static unsafe IntPtr PyObject_TYPE(IntPtr op)
977980
{
978981
returnIntPtr.Zero;
979982
}
980-
#ifPYTHON_WITH_PYDEBUG
981-
varn=3;
982-
#else
983-
varn=1;
984-
#endif
985-
returnIs32Bit
986-
?newIntPtr((void*)(*((uint*)p+n)))
987-
:new IntPtr((void*)(*((ulong*)p+n)));
983+
Debug.Assert(TypeOffset.ob_type>0);
984+
IntPtr*typePtr=(IntPtr*)(op+TypeOffset.ob_type);
985+
return*typePtr;
988986
}
989987
internalstaticunsafeBorrowedReferencePyObject_TYPE(BorrowedReferenceop)
990988
=>newBorrowedReference(PyObject_TYPE(op.DangerousGetAddress()));
@@ -1001,6 +999,9 @@ internal static IntPtr PyObject_Type(IntPtr op)
1001999
returntp;
10021000
}
10031001

1002+
internalstaticNewReferencePyObject_Type(BorrowedReferenceo)
1003+
=>Delegates.PyObject_Type(o);
1004+
10041005
internalstaticstringPyObject_GetTypeName(IntPtrop)
10051006
{
10061007
IntPtrpyType=PyObject_TYPE(op);
@@ -1145,10 +1146,11 @@ internal static IntPtr PyObject_Str(IntPtr pointer)
11451146

11461147
internalstaticIntPtrPyObject_Dir(IntPtrpointer)=>Delegates.PyObject_Dir(pointer);
11471148

1148-
#ifPYTHON_WITH_PYDEBUG
1149-
[DllImport(_PythonDll,CallingConvention=CallingConvention.Cdecl)]
1150-
internalstaticexternvoid_Py_NewReference(IntPtrob);
1151-
#endif
1149+
internalstaticvoid_Py_NewReference(BorrowedReferenceob)
1150+
{
1151+
if(Delegates._Py_NewReference!=null)
1152+
Delegates._Py_NewReference(ob);
1153+
}
11521154

11531155
//====================================================================
11541156
// Python buffer API
@@ -1912,11 +1914,6 @@ internal static string PyModule_GetName(IntPtr module)
19121914
internalstaticstringPyModule_GetFilename(IntPtrmodule)
19131915
=>Delegates.PyModule_GetFilename(module).ToString(Encoding.UTF8);
19141916

1915-
#ifPYTHON_WITH_PYDEBUG
1916-
[DllImport(_PythonDll,EntryPoint="PyModule_Create2TraceRefs",CallingConvention=CallingConvention.Cdecl)]
1917-
#else
1918-
1919-
#endif
19201917
internalstaticIntPtrPyModule_Create2(IntPtrmodule,intapiver)=>Delegates.PyModule_Create2(module,apiver);
19211918

19221919

@@ -2331,6 +2328,7 @@ static Delegates()
23312328
PyObject_Hash=(delegate* unmanaged[Cdecl]<IntPtr,IntPtr>)GetFunctionByName(nameof(PyObject_Hash),GetUnmanagedDll(_PythonDll));
23322329
PyObject_Repr=(delegate* unmanaged[Cdecl]<IntPtr,IntPtr>)GetFunctionByName(nameof(PyObject_Repr),GetUnmanagedDll(_PythonDll));
23332330
PyObject_Str=(delegate* unmanaged[Cdecl]<IntPtr,IntPtr>)GetFunctionByName(nameof(PyObject_Str),GetUnmanagedDll(_PythonDll));
2331+
PyObject_Type=(delegate* unmanaged[Cdecl]<BorrowedReference,NewReference>)GetFunctionByName(nameof(PyObject_Type),GetUnmanagedDll(_PythonDll));
23342332
PyObject_Dir=(delegate* unmanaged[Cdecl]<IntPtr,IntPtr>)GetFunctionByName(nameof(PyObject_Dir),GetUnmanagedDll(_PythonDll));
23352333
PyObject_GetBuffer=(delegate* unmanaged[Cdecl]<IntPtr,refPy_buffer,int,int>)GetFunctionByName(nameof(PyObject_GetBuffer),GetUnmanagedDll(_PythonDll));
23362334
PyBuffer_Release=(delegate* unmanaged[Cdecl]<refPy_buffer,void>)GetFunctionByName(nameof(PyBuffer_Release),GetUnmanagedDll(_PythonDll));
@@ -2466,7 +2464,14 @@ static Delegates()
24662464
PyModule_GetName=(delegate* unmanaged[Cdecl]<IntPtr,StrPtr>)GetFunctionByName(nameof(PyModule_GetName),GetUnmanagedDll(_PythonDll));
24672465
PyModule_GetDict=(delegate* unmanaged[Cdecl]<BorrowedReference,BorrowedReference>)GetFunctionByName(nameof(PyModule_GetDict),GetUnmanagedDll(_PythonDll));
24682466
PyModule_GetFilename=(delegate* unmanaged[Cdecl]<IntPtr,StrPtr>)GetFunctionByName(nameof(PyModule_GetFilename),GetUnmanagedDll(_PythonDll));
2469-
PyModule_Create2=(delegate* unmanaged[Cdecl]<IntPtr,int,IntPtr>)GetFunctionByName(nameof(PyModule_Create2),GetUnmanagedDll(_PythonDll));
2467+
try
2468+
{
2469+
PyModule_Create2=(delegate* unmanaged[Cdecl]<IntPtr,int,IntPtr>)GetFunctionByName(nameof(PyModule_Create2),GetUnmanagedDll(_PythonDll));
2470+
}
2471+
catch(MissingMethodException)
2472+
{
2473+
PyModule_Create2=(delegate* unmanaged[Cdecl]<IntPtr,int,IntPtr>)GetFunctionByName("PyModule_Create2TraceRefs",GetUnmanagedDll(_PythonDll));
2474+
}
24702475
PyImport_Import=(delegate* unmanaged[Cdecl]<IntPtr,IntPtr>)GetFunctionByName(nameof(PyImport_Import),GetUnmanagedDll(_PythonDll));
24712476
PyImport_ImportModule=(delegate* unmanaged[Cdecl]<StrPtr,NewReference>)GetFunctionByName(nameof(PyImport_ImportModule),GetUnmanagedDll(_PythonDll));
24722477
PyImport_ReloadModule=(delegate* unmanaged[Cdecl]<BorrowedReference,NewReference>)GetFunctionByName(nameof(PyImport_ReloadModule),GetUnmanagedDll(_PythonDll));
@@ -2521,6 +2526,12 @@ static Delegates()
25212526
PyThreadState_SetAsyncExcLLP64=(delegate* unmanaged[Cdecl]<uint,IntPtr,int>)GetFunctionByName("PyThreadState_SetAsyncExc",GetUnmanagedDll(_PythonDll));
25222527
PyThreadState_SetAsyncExcLP64=(delegate* unmanaged[Cdecl]<ulong,IntPtr,int>)GetFunctionByName("PyThreadState_SetAsyncExc",GetUnmanagedDll(_PythonDll));
25232528
PyType_FromSpecWithBases=(delegate* unmanaged[Cdecl]<inNativeTypeSpec,BorrowedReference,NewReference>)GetFunctionByName(nameof(PyType_FromSpecWithBases),GetUnmanagedDll(PythonDLL));
2529+
2530+
try
2531+
{
2532+
_Py_NewReference=(delegate* unmanaged[Cdecl]<BorrowedReference,void>)GetFunctionByName(nameof(_Py_NewReference),GetUnmanagedDll(_PythonDll));
2533+
}
2534+
catch(MissingMethodException){}
25242535
}
25252536

25262537
staticglobal::System.IntPtrGetUnmanagedDll(stringlibraryName)
@@ -2616,6 +2627,7 @@ static Delegates()
26162627
internalstaticdelegate* unmanaged[Cdecl]<IntPtr,IntPtr>PyObject_Hash{get;}
26172628
internalstaticdelegate* unmanaged[Cdecl]<IntPtr,IntPtr>PyObject_Repr{get;}
26182629
internalstaticdelegate* unmanaged[Cdecl]<IntPtr,IntPtr>PyObject_Str{get;}
2630+
internalstaticdelegate* unmanaged[Cdecl]<BorrowedReference,NewReference>PyObject_Type{get;}
26192631
internalstaticdelegate* unmanaged[Cdecl]<IntPtr,IntPtr>PyObject_Dir{get;}
26202632
internalstaticdelegate* unmanaged[Cdecl]<IntPtr,refPy_buffer,int,int>PyObject_GetBuffer{get;}
26212633
internalstaticdelegate* unmanaged[Cdecl]<refPy_buffer,void>PyBuffer_Release{get;}
@@ -2799,6 +2811,7 @@ static Delegates()
27992811
internalstaticdelegate* unmanaged[Cdecl]<ulong,IntPtr,int>PyThreadState_SetAsyncExcLP64{get;}
28002812
internalstaticdelegate* unmanaged[Cdecl]<BorrowedReference,IntPtr,NewReference>PyObject_GenericGetDict{get;}
28012813
internalstaticdelegate* unmanaged[Cdecl]<inNativeTypeSpec,BorrowedReference,NewReference>PyType_FromSpecWithBases{get;}
2814+
internalstaticdelegate* unmanaged[Cdecl]<BorrowedReference,void>_Py_NewReference{get;}
28022815
}
28032816
}
28042817

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp