Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 430ea6e

Browse files
authored
Merge branch 'master' into features/PerfTests-CI
2 parents fb6015e + 3b938a5 commit 430ea6e

File tree

2 files changed

+139
-87
lines changed

2 files changed

+139
-87
lines changed

src/runtime/importhook.cs

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,6 @@ internal static void ReleaseModuleDef()
3535
}
3636
#endif
3737

38-
/// <summary>
39-
/// Get a <i>New reference</i> to the builtins module.
40-
/// </summary>
41-
static IntPtr GetNewRefToBuiltins()
42-
{
43-
if (Runtime.IsPython3)
44-
{
45-
return Runtime.PyImport_ImportModule("builtins");
46-
}
47-
else
48-
{
49-
// dict is a borrowed ref, no need to decref
50-
IntPtr dict = Runtime.PyImport_GetModuleDict();
51-
52-
// GetItemString is a borrowed ref; incref to get a new ref
53-
IntPtr builtins = Runtime.PyDict_GetItemString(dict, "__builtin__");
54-
Runtime.XIncref(builtins);
55-
return builtins;
56-
}
57-
}
58-
5938
/// <summary>
6039
/// Initialize just the __import__ hook itself.
6140
/// </summary>
@@ -64,7 +43,7 @@ static void InitImport()
6443
// We replace the built-in Python __import__ with our own: first
6544
// look in CLR modules, then if we don't find any call the default
6645
// Python __import__.
67-
IntPtr builtins = GetNewRefToBuiltins();
46+
IntPtr builtins = Runtime.GetBuiltins();
6847
py_import = Runtime.PyObject_GetAttrString(builtins, "__import__");
6948
PythonException.ThrowIfIsNull(py_import);
7049

@@ -80,7 +59,7 @@ static void InitImport()
8059
/// </summary>
8160
static void RestoreImport()
8261
{
83-
IntPtr builtins = GetNewRefToBuiltins();
62+
IntPtr builtins = Runtime.GetBuiltins();
8463

8564
int res = Runtime.PyObject_SetAttrString(builtins, "__import__", py_import);
8665
PythonException.ThrowIfIsNotZero(res);

src/runtime/runtime.cs

Lines changed: 137 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ public class Runtime
169169
/// </summary>
170170
internal static readonly Encoding PyEncoding = _UCS == 2 ? Encoding.Unicode : Encoding.UTF32;
171171

172+
private static PyReferenceCollection _pyRefs = new PyReferenceCollection();
173+
172174
/// <summary>
173175
/// Initialize the runtime...
174176
/// </summary>
@@ -194,99 +196,116 @@ internal static void Initialize(bool initSigs = false)
194196
TypeManager.Reset();
195197

196198
IntPtr op;
197-
IntPtr dict;
198-
if (IsPython3)
199-
{
200-
op = PyImport_ImportModule("builtins");
201-
dict = PyObject_GetAttrString(op, "__dict__");
202-
}
203-
else // Python2
204199
{
205-
dict = PyImport_GetModuleDict();
206-
op = PyDict_GetItemString(dict, "__builtin__");
200+
var builtins = GetBuiltins();
201+
SetPyMember(ref PyNotImplemented, PyObject_GetAttrString(builtins, "NotImplemented"),
202+
() => PyNotImplemented = IntPtr.Zero);
203+
204+
SetPyMember(ref PyBaseObjectType, PyObject_GetAttrString(builtins, "object"),
205+
() => PyBaseObjectType = IntPtr.Zero);
206+
207+
SetPyMember(ref PyNone, PyObject_GetAttrString(builtins, "None"),
208+
() => PyNone = IntPtr.Zero);
209+
SetPyMember(ref PyTrue, PyObject_GetAttrString(builtins, "True"),
210+
() => PyTrue = IntPtr.Zero);
211+
SetPyMember(ref PyFalse, PyObject_GetAttrString(builtins, "False"),
212+
() => PyFalse = IntPtr.Zero);
213+
214+
SetPyMember(ref PyBoolType, PyObject_Type(PyTrue),
215+
() => PyBoolType = IntPtr.Zero);
216+
SetPyMember(ref PyNoneType, PyObject_Type(PyNone),
217+
() => PyNoneType = IntPtr.Zero);
218+
SetPyMember(ref PyTypeType, PyObject_Type(PyNoneType),
219+
() => PyTypeType = IntPtr.Zero);
220+
221+
op = PyObject_GetAttrString(builtins, "len");
222+
SetPyMember(ref PyMethodType, PyObject_Type(op),
223+
() => PyMethodType = IntPtr.Zero);
224+
XDecref(op);
225+
226+
// For some arcane reason, builtins.__dict__.__setitem__ is *not*
227+
// a wrapper_descriptor, even though dict.__setitem__ is.
228+
//
229+
// object.__init__ seems safe, though.
230+
op = PyObject_GetAttrString(PyBaseObjectType, "__init__");
231+
SetPyMember(ref PyWrapperDescriptorType, PyObject_Type(op),
232+
() => PyWrapperDescriptorType = IntPtr.Zero);
233+
XDecref(op);
234+
235+
SetPyMember(ref PySuper_Type, PyObject_GetAttrString(builtins, "super"),
236+
() => PySuper_Type = IntPtr.Zero);
237+
238+
XDecref(builtins);
207239
}
208-
PyNotImplemented = PyObject_GetAttrString(op, "NotImplemented");
209-
PyBaseObjectType = PyObject_GetAttrString(op, "object");
210-
211-
PyNone = PyObject_GetAttrString(op, "None");
212-
PyTrue = PyObject_GetAttrString(op, "True");
213-
PyFalse = PyObject_GetAttrString(op, "False");
214-
215-
PyBoolType = PyObject_Type(PyTrue);
216-
PyNoneType = PyObject_Type(PyNone);
217-
PyTypeType = PyObject_Type(PyNoneType);
218-
219-
op = PyObject_GetAttrString(dict, "keys");
220-
PyMethodType = PyObject_Type(op);
221-
XDecref(op);
222-
223-
// For some arcane reason, builtins.__dict__.__setitem__ is *not*
224-
// a wrapper_descriptor, even though dict.__setitem__ is.
225-
//
226-
// object.__init__ seems safe, though.
227-
op = PyObject_GetAttrString(PyBaseObjectType, "__init__");
228-
PyWrapperDescriptorType = PyObject_Type(op);
229-
XDecref(op);
230-
231-
#if PYTHON3
232-
XDecref(dict);
233-
#endif
234240

235241
op = PyString_FromString("string");
236-
PyStringType = PyObject_Type(op);
242+
SetPyMember(ref PyStringType, PyObject_Type(op),
243+
() => PyStringType = IntPtr.Zero);
237244
XDecref(op);
238245

239246
op = PyUnicode_FromString("unicode");
240-
PyUnicodeType = PyObject_Type(op);
247+
SetPyMember(ref PyUnicodeType, PyObject_Type(op),
248+
() => PyUnicodeType = IntPtr.Zero);
241249
XDecref(op);
242250

243251
#if PYTHON3
244252
op = PyBytes_FromString("bytes");
245-
PyBytesType = PyObject_Type(op);
253+
SetPyMember(ref PyBytesType, PyObject_Type(op),
254+
() => PyBytesType = IntPtr.Zero);
246255
XDecref(op);
247256
#endif
248257

249258
op = PyTuple_New(0);
250-
PyTupleType = PyObject_Type(op);
259+
SetPyMember(ref PyTupleType, PyObject_Type(op),
260+
() => PyTupleType = IntPtr.Zero);
251261
XDecref(op);
252262

253263
op = PyList_New(0);
254-
PyListType = PyObject_Type(op);
264+
SetPyMember(ref PyListType, PyObject_Type(op),
265+
() => PyListType = IntPtr.Zero);
255266
XDecref(op);
256267

257268
op = PyDict_New();
258-
PyDictType = PyObject_Type(op);
269+
SetPyMember(ref PyDictType, PyObject_Type(op),
270+
() => PyDictType = IntPtr.Zero);
259271
XDecref(op);
260272

261273
op = PyInt_FromInt32(0);
262-
PyIntType = PyObject_Type(op);
274+
SetPyMember(ref PyIntType, PyObject_Type(op),
275+
() => PyIntType = IntPtr.Zero);
263276
XDecref(op);
264277

265278
op = PyLong_FromLong(0);
266-
PyLongType = PyObject_Type(op);
279+
SetPyMember(ref PyLongType, PyObject_Type(op),
280+
() => PyLongType = IntPtr.Zero);
267281
XDecref(op);
268282

269283
op = PyFloat_FromDouble(0);
270-
PyFloatType = PyObject_Type(op);
284+
SetPyMember(ref PyFloatType, PyObject_Type(op),
285+
() => PyFloatType = IntPtr.Zero);
271286
XDecref(op);
272287

273-
#if PYTHON3
288+
#if !PYTHON2
274289
PyClassType = IntPtr.Zero;
275290
PyInstanceType = IntPtr.Zero;
276-
#elif PYTHON2
277-
IntPtr s = PyString_FromString("_temp");
278-
IntPtr d = PyDict_New();
291+
#else
292+
{
293+
IntPtr s = PyString_FromString("_temp");
294+
IntPtr d = PyDict_New();
279295

280-
IntPtr c = PyClass_New(IntPtr.Zero, d, s);
281-
PyClassType = PyObject_Type(c);
296+
IntPtr c = PyClass_New(IntPtr.Zero, d, s);
297+
SetPyMember(ref PyClassType, PyObject_Type(c),
298+
() => PyClassType = IntPtr.Zero);
282299

283-
IntPtr i = PyInstance_New(c, IntPtr.Zero, IntPtr.Zero);
284-
PyInstanceType = PyObject_Type(i);
300+
IntPtr i = PyInstance_New(c, IntPtr.Zero, IntPtr.Zero);
301+
SetPyMember(ref PyInstanceType, PyObject_Type(i),
302+
() => PyInstanceType = IntPtr.Zero);
285303

286-
XDecref(s);
287-
XDecref(i);
288-
XDecref(c);
289-
XDecref(d);
304+
XDecref(s);
305+
XDecref(i);
306+
XDecref(c);
307+
XDecref(d);
308+
}
290309
#endif
291310

292311
Error = new IntPtr(-1);
@@ -380,6 +399,9 @@ internal static void Shutdown()
380399
Exceptions.Shutdown();
381400
ImportHook.Shutdown();
382401
Finalizer.Shutdown();
402+
// TOOD: PyCLRMetaType's release operation still in #958
403+
PyCLRMetaType = IntPtr.Zero;
404+
ResetPyMembers();
383405
Py_Finalize();
384406
}
385407

@@ -393,6 +415,19 @@ internal static int AtExit()
393415
return 0;
394416
}
395417

418+
private static void SetPyMember(ref IntPtr obj, IntPtr value, Action onRelease)
419+
{
420+
// XXX: For current usages, value should not be null.
421+
PythonException.ThrowIfIsNull(value);
422+
obj = value;
423+
_pyRefs.Add(value, onRelease);
424+
}
425+
426+
private static void ResetPyMembers()
427+
{
428+
_pyRefs.Release();
429+
}
430+
396431
internal static IntPtr Py_single_input = (IntPtr)256;
397432
internal static IntPtr Py_file_input = (IntPtr)257;
398433
internal static IntPtr Py_eval_input = (IntPtr)258;
@@ -401,6 +436,7 @@ internal static int AtExit()
401436
internal static IntPtr PyModuleType;
402437
internal static IntPtr PyClassType;
403438
internal static IntPtr PyInstanceType;
439+
internal static IntPtr PySuper_Type;
404440
internal static IntPtr PyCLRMetaType;
405441
internal static IntPtr PyMethodType;
406442
internal static IntPtr PyWrapperDescriptorType;
@@ -963,7 +999,7 @@ internal static int PyObject_Compare(IntPtr value1, IntPtr value2)
963999

9641000
internal static long PyObject_Size(IntPtr pointer)
9651001
{
966-
return (long) _PyObject_Size(pointer);
1002+
return (long)_PyObject_Size(pointer);
9671003
}
9681004

9691005
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyObject_Size")]
@@ -1079,7 +1115,7 @@ internal static bool PyLong_Check(IntPtr ob)
10791115

10801116
internal static IntPtr PyLong_FromUnsignedLong(object value)
10811117
{
1082-
if(Is32Bit || IsWindows)
1118+
if (Is32Bit || IsWindows)
10831119
return PyLong_FromUnsignedLong32(Convert.ToUInt32(value));
10841120
else
10851121
return PyLong_FromUnsignedLong64(Convert.ToUInt64(value));
@@ -1269,7 +1305,7 @@ internal static int PySequence_DelSlice(IntPtr pointer, long i1, long i2)
12691305

12701306
internal static long PySequence_Size(IntPtr pointer)
12711307
{
1272-
return (long) _PySequence_Size(pointer);
1308+
return (long)_PySequence_Size(pointer);
12731309
}
12741310

12751311
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PySequence_Size")]
@@ -1294,7 +1330,7 @@ internal static IntPtr PySequence_Repeat(IntPtr pointer, long count)
12941330

12951331
internal static long PySequence_Count(IntPtr pointer, IntPtr value)
12961332
{
1297-
return (long) _PySequence_Count(pointer, value);
1333+
return (long)_PySequence_Count(pointer, value);
12981334
}
12991335

13001336
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PySequence_Count")]
@@ -1337,7 +1373,7 @@ internal static IntPtr PyString_FromString(string value)
13371373

13381374
internal static long PyBytes_Size(IntPtr op)
13391375
{
1340-
return (long) _PyBytes_Size(op);
1376+
return (long)_PyBytes_Size(op);
13411377
}
13421378

13431379
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyBytes_Size")]
@@ -1568,7 +1604,7 @@ internal static bool PyDict_Check(IntPtr ob)
15681604

15691605
internal static long PyDict_Size(IntPtr pointer)
15701606
{
1571-
return (long) _PyDict_Size(pointer);
1607+
return (long)_PyDict_Size(pointer);
15721608
}
15731609

15741610
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyDict_Size")]
@@ -1646,7 +1682,7 @@ internal static int PyList_SetSlice(IntPtr pointer, long start, long end, IntPtr
16461682

16471683
internal static long PyList_Size(IntPtr pointer)
16481684
{
1649-
return (long) _PyList_Size(pointer);
1685+
return (long)_PyList_Size(pointer);
16501686
}
16511687

16521688
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyList_Size")]
@@ -1695,7 +1731,7 @@ internal static IntPtr PyTuple_GetSlice(IntPtr pointer, long start, long end)
16951731

16961732
internal static long PyTuple_Size(IntPtr pointer)
16971733
{
1698-
return (long) _PyTuple_Size(pointer);
1734+
return (long)_PyTuple_Size(pointer);
16991735
}
17001736

17011737
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyTuple_Size")]
@@ -1746,6 +1782,9 @@ internal static bool PyIter_Check(IntPtr pointer)
17461782
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
17471783
internal static extern IntPtr PyImport_Import(IntPtr name);
17481784

1785+
/// <summary>
1786+
/// Return value: New reference.
1787+
/// </summary>
17491788
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
17501789
internal static extern IntPtr PyImport_ImportModule(string name);
17511790

@@ -1945,5 +1984,39 @@ internal static void SetNoSiteFlag()
19451984
}
19461985
}
19471986
}
1987+
1988+
/// <summary>
1989+
/// Return value: New reference.
1990+
/// </summary>
1991+
internal static IntPtr GetBuiltins()
1992+
{
1993+
return IsPython3 ? PyImport_ImportModule("builtins")
1994+
: PyImport_ImportModule("__builtin__");
1995+
}
1996+
}
1997+
1998+
1999+
class PyReferenceCollection
2000+
{
2001+
private List<KeyValuePair<IntPtr, Action>> _actions = new List<KeyValuePair<IntPtr, Action>>();
2002+
2003+
/// <summary>
2004+
/// Record obj's address to release the obj in the future,
2005+
/// obj must alive before calling Release.
2006+
/// </summary>
2007+
public void Add(IntPtr ob, Action onRelease)
2008+
{
2009+
_actions.Add(new KeyValuePair<IntPtr, Action>(ob, onRelease));
2010+
}
2011+
2012+
public void Release()
2013+
{
2014+
foreach (var item in _actions)
2015+
{
2016+
Runtime.XDecref(item.Key);
2017+
item.Value?.Invoke();
2018+
}
2019+
_actions.Clear();
2020+
}
19482021
}
19492022
}

0 commit comments

Comments
 (0)