Skip to content

Commit 3a08990

Browse files
greateggsgregfilmor
authored andcommitted
Cache HasClrMember and align DLR setter exception path
- Cache HasClrMember reflection per (Type, name) so tp_getattro_dlr_proxy / tp_setattro_dlr_proxy avoid repeated GetMember() calls on every attribute access of DLR-aware objects. - Mirror tp_setattro_dlr_proxy's catch arm to the getter's safer SetError(RuntimeError, e.Message) shape instead of SetError(Exception), keeping both slots re-entry-safe on live dynamic objects. Related to #2706.
1 parent 8b12b56 commit 3a08990

1 file changed

Lines changed: 11 additions & 2 deletions

File tree

src/runtime/TypeManager.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Concurrent;
23
using System.Collections.Generic;
34
using System.Dynamic;
45
using System.Linq;
@@ -41,8 +42,14 @@ internal class TypeManager
4142

4243
static readonly DynamicObjectMemberAccessor dynamicMemberAccessor = new();
4344

45+
// tp_getattro_dlr_proxy / tp_setattro_dlr_proxy hit HasClrMember on every
46+
// attribute access; cache the reflection result per (Type, name).
47+
static readonly ConcurrentDictionary<(Type, string), bool> _hasClrMemberCache = new();
48+
4449
static bool HasClrMember(object instance, string memberName) =>
45-
instance.GetType().GetMember(memberName, BindingFlags.Public | BindingFlags.Instance).Length > 0;
50+
_hasClrMemberCache.GetOrAdd(
51+
(instance.GetType(), memberName),
52+
k => k.Item1.GetMember(k.Item2, BindingFlags.Public | BindingFlags.Instance).Length > 0);
4653

4754
static bool IsPythonSpecialAttributeName(string memberName) =>
4855
memberName.Length > 4 && memberName.StartsWith("__") && memberName.EndsWith("__");
@@ -198,7 +205,9 @@ public static int tp_setattro_dlr_proxy(BorrowedReference ob, BorrowedReference
198205
}
199206
catch (Exception e)
200207
{
201-
Exceptions.SetError(e);
208+
// Same reasoning as the getter: avoid Converter.ToPython(e) to keep this
209+
// slot re-entry-safe on live dynamic objects.
210+
Exceptions.SetError(Exceptions.RuntimeError, e.Message);
202211
return -1;
203212
}
204213

0 commit comments

Comments
 (0)