X Tutup
Skip to content
This repository was archived by the owner on Jul 22, 2023. It is now read-only.

Commit 08fad26

Browse files
committed
* Fix refcnt error of MethodBinding
* Custom storage context
1 parent 9d57a82 commit 08fad26

File tree

9 files changed

+128
-76
lines changed

9 files changed

+128
-76
lines changed

src/runtime/classbase.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections;
33
using System.Diagnostics;
44
using System.Runtime.InteropServices;
5+
using System.Runtime.Serialization;
56

67
namespace Python.Runtime
78
{
@@ -304,9 +305,25 @@ public static int tp_clear(IntPtr ob)
304305
return 0;
305306
}
306307

307-
protected override void OnLoad()
308+
protected override void OnSave(PyObjectSerializeContext context)
308309
{
309-
base.OnLoad();
310+
base.OnSave(context);
311+
if (pyHandle != tpHandle)
312+
{
313+
IntPtr dict = GetObjectDict(pyHandle);
314+
Runtime.XIncref(dict);
315+
context.Storage.AddValue("dict", dict);
316+
}
317+
}
318+
319+
protected override void OnLoad(PyObjectSerializeContext context)
320+
{
321+
base.OnLoad(context);
322+
if (pyHandle != tpHandle)
323+
{
324+
IntPtr dict = context.Storage.GetValue<IntPtr>("dict");
325+
SetObjectDict(pyHandle, dict);
326+
}
310327
gcHandle = AllocGCHandle();
311328
Marshal.WriteIntPtr(pyHandle, TypeOffset.magic(), (IntPtr)gcHandle);
312329
}

src/runtime/classmanager.cs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,23 +84,31 @@ private static int OnVisit(IntPtr ob, IntPtr arg)
8484

8585
internal static void StashPush(RuntimeDataStorage storage)
8686
{
87-
storage.PushValue(cache);
87+
var contexts = storage.AddValue("contexts",
88+
new Dictionary<IntPtr, PyObjectSerializeContext>());
89+
storage.AddValue("cache", cache);
8890
foreach (var cls in cache.Values)
8991
{
9092
// This incref is for cache to hold the cls,
9193
// thus no need for decreasing it at StashPop.
9294
Runtime.XIncref(cls.pyHandle);
93-
cls.Save();
95+
var context = contexts[cls.pyHandle] = new PyObjectSerializeContext();
96+
cls.Save(context);
9497
}
9598
}
9699

97-
internal static void StashPop(RuntimeDataStorage storage)
100+
internal static Dictionary<ManagedType, PyObjectSerializeContext> StashPop(RuntimeDataStorage storage)
98101
{
99-
cache = storage.PopValue<Dictionary<Type, ClassBase>>();
102+
cache = storage.GetValue<Dictionary<Type, ClassBase>>("cache");
103+
var contexts = storage.GetValue <Dictionary<IntPtr, PyObjectSerializeContext>>("contexts");
104+
var loadedObjs = new Dictionary<ManagedType, PyObjectSerializeContext>();
100105
foreach (var cls in cache.Values)
101106
{
102-
cls.Load();
107+
var context = contexts[cls.pyHandle];
108+
cls.Load(context);
109+
loadedObjs.Add(cls, context);
103110
}
111+
return loadedObjs;
104112
}
105113

106114
/// <summary>

src/runtime/clrobject.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,30 +74,29 @@ internal static IntPtr GetInstHandle(object ob)
7474
return co.pyHandle;
7575
}
7676

77-
internal static CLRObject Restore(object ob, IntPtr pyHandle)
77+
internal static CLRObject Restore(object ob, IntPtr pyHandle, PyObjectSerializeContext context)
7878
{
7979
CLRObject co = new CLRObject()
8080
{
8181
inst = ob,
8282
pyHandle = pyHandle,
8383
tpHandle = Runtime.PyObject_TYPE(pyHandle)
8484
};
85-
co.Load();
85+
co.Load(context);
8686
return co;
8787
}
8888

89-
protected override void OnSave()
89+
protected override void OnSave(PyObjectSerializeContext context)
9090
{
91-
base.OnSave();
91+
base.OnSave(context);
9292
Runtime.XIncref(pyHandle);
9393
}
9494

95-
protected override void OnLoad()
95+
protected override void OnLoad(PyObjectSerializeContext context)
9696
{
97-
base.OnLoad();
97+
base.OnLoad(context);
9898
GCHandle gc = AllocGCHandle(TrackTypes.Wrapper);
9999
Marshal.WriteIntPtr(pyHandle, ObjectOffset.magic(tpHandle), (IntPtr)gc);
100-
Runtime.XDecref(pyHandle);
101100
}
102101
}
103102
}

src/runtime/extensiontype.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ public static void tp_dealloc(IntPtr ob)
9898
self.Dealloc();
9999
}
100100

101-
protected override void OnLoad()
101+
protected override void OnLoad(PyObjectSerializeContext context)
102102
{
103-
base.OnLoad();
103+
base.OnLoad(context);
104104
GCHandle gc = AllocGCHandle(TrackTypes.Extension);
105105
Marshal.WriteIntPtr(pyHandle, ObjectOffset.magic(tpHandle), (IntPtr)gc);
106106
Runtime.PyObject_GC_UnTrack(pyHandle);

src/runtime/managedtype.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,18 +200,18 @@ protected void TypeClear()
200200
ClearObjectDict(pyHandle);
201201
}
202202

203-
internal void Save()
203+
internal void Save(PyObjectSerializeContext context)
204204
{
205-
OnSave();
205+
OnSave(context);
206206
}
207207

208-
internal void Load()
208+
internal void Load(PyObjectSerializeContext context)
209209
{
210-
OnLoad();
210+
OnLoad(context);
211211
}
212212

213-
protected virtual void OnSave() { }
214-
protected virtual void OnLoad() { }
213+
protected virtual void OnSave(PyObjectSerializeContext context) { }
214+
protected virtual void OnLoad(PyObjectSerializeContext context) { }
215215

216216
protected static void ClearObjectDict(IntPtr ob)
217217
{

src/runtime/methodbinding.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,5 +254,12 @@ public static int tp_clear(IntPtr ob)
254254
self.ClearMembers();
255255
return 0;
256256
}
257+
258+
protected override void OnSave(PyObjectSerializeContext context)
259+
{
260+
base.OnSave(context);
261+
Runtime.XIncref(target);
262+
Runtime.XIncref(targetType);
263+
}
257264
}
258265
}

src/runtime/methodobject.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ internal class MethodObject : ExtensionType
1818
internal MethodBinding unbound;
1919
internal MethodBinder binder;
2020
internal bool is_static = false;
21-
[NonSerialized]
21+
2222
internal IntPtr doc;
2323
internal Type type;
2424

@@ -221,5 +221,15 @@ public static int tp_clear(IntPtr ob)
221221
ClearObjectDict(ob);
222222
return 0;
223223
}
224+
225+
protected override void OnSave(PyObjectSerializeContext context)
226+
{
227+
base.OnSave(context);
228+
if (unbound != null)
229+
{
230+
Runtime.XIncref(unbound.pyHandle);
231+
}
232+
Runtime.XIncref(doc);
233+
}
224234
}
225235
}

src/runtime/moduleobject.cs

Lines changed: 9 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,8 @@ namespace Python.Runtime
1414
[Serializable]
1515
internal class ModuleObject : ExtensionType
1616
{
17-
[NonSerialized]
1817
private Dictionary<string, ManagedType> cache;
1918

20-
[NonSerialized]
21-
// FIXME: Used by reload mode, remove it after implement a delay load handler.
22-
private bool _cacheInited;
23-
2419
internal string moduleName;
2520
internal IntPtr dict;
2621
protected string _namespace;
@@ -33,7 +28,6 @@ public ModuleObject(string name)
3328
}
3429
moduleName = name;
3530
cache = new Dictionary<string, ManagedType>();
36-
_cacheInited = true;
3731
_namespace = name;
3832

3933
// Use the filename from any of the assemblies just so there's something for
@@ -63,7 +57,7 @@ public ModuleObject(string name)
6357
Runtime.XDecref(pydocstring);
6458

6559
Runtime.XIncref(dict);
66-
Marshal.WriteIntPtr(pyHandle, ObjectOffset.DictOffset(pyHandle), dict);
60+
SetObjectDict(pyHandle, dict);
6761

6862
InitializeModuleMembers();
6963
}
@@ -77,11 +71,6 @@ public ModuleObject(string name)
7771
/// </summary>
7872
public ManagedType GetAttribute(string name, bool guess)
7973
{
80-
if (!_cacheInited)
81-
{
82-
// XXX: Used by reload mode.
83-
SetupCacheByDict();
84-
}
8574
ManagedType cached = null;
8675
cache.TryGetValue(name, out cached);
8776
if (cached != null)
@@ -360,46 +349,24 @@ public static int tp_clear(IntPtr ob)
360349
return 0;
361350
}
362351

363-
protected override void OnSave()
352+
protected override void OnSave(PyObjectSerializeContext context)
364353
{
365-
base.OnSave();
354+
base.OnSave(context);
366355
System.Diagnostics.Debug.Assert(dict == GetObjectDict(pyHandle));
356+
foreach (var attr in cache.Values)
357+
{
358+
Runtime.XIncref(attr.pyHandle);
359+
}
367360
// Decref twice in tp_clear, equilibrate them.
368361
Runtime.XIncref(dict);
369362
Runtime.XIncref(dict);
370363
}
371364

372-
protected override void OnLoad()
365+
protected override void OnLoad(PyObjectSerializeContext context)
373366
{
374-
base.OnLoad();
375-
// XXX: Set the cache after all objects loaded.
376-
cache = new Dictionary<string, ManagedType>();
377-
_cacheInited = false;
367+
base.OnLoad(context);
378368
SetObjectDict(pyHandle, dict);
379369
}
380-
381-
private void SetupCacheByDict()
382-
{
383-
System.Diagnostics.Debug.Assert(!_cacheInited);
384-
_cacheInited = true;
385-
IntPtr key, value;
386-
IntPtr pos;
387-
while (Runtime.PyDict_Next(dict, out pos, out key, out value) != 0)
388-
{
389-
ManagedType obj = GetManagedObject(value);
390-
if (obj == null)
391-
{
392-
continue;
393-
}
394-
string name = Runtime.GetManagedString(key);
395-
if (cache.ContainsKey(name))
396-
{
397-
continue;
398-
}
399-
Runtime.XIncref(value);
400-
cache.Add(name, obj);
401-
}
402-
}
403370
}
404371

405372
/// <summary>

0 commit comments

Comments
 (0)
X Tutup