Skip to content

Commit c05c6ec

Browse files
committed
switched methodbinder.cs to the new style references
1 parent 1b58cf4 commit c05c6ec

File tree

3 files changed

+62
-72
lines changed

3 files changed

+62
-72
lines changed

src/runtime/Util.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ internal static class Util
2121
internal const string UseOverloadWithReferenceTypes =
2222
"This API is unsafe, and will be removed in the future. Use overloads working with *Reference types";
2323

24+
internal const string BadStr = "bad __str__";
25+
2426

2527
[MethodImpl(MethodImplOptions.AggressiveInlining)]
2628
internal static int ReadInt32(BorrowedReference ob, int offset)

src/runtime/methodbinder.cs

Lines changed: 59 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ internal static int ArgPrecedence(Type t)
300300
/// <param name="args">The Python arguments.</param>
301301
/// <param name="kw">The Python keyword arguments.</param>
302302
/// <returns>A Binding if successful. Otherwise null.</returns>
303-
internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw)
303+
internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedReference kw)
304304
{
305305
return Bind(inst, args, kw, null, null);
306306
}
@@ -316,7 +316,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw)
316316
/// <param name="kw">The Python keyword arguments.</param>
317317
/// <param name="info">If not null, only bind to that method.</param>
318318
/// <returns>A Binding if successful. Otherwise null.</returns>
319-
internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info)
319+
internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedReference kw, MethodBase info)
320320
{
321321
return Bind(inst, args, kw, info, null);
322322
}
@@ -363,24 +363,23 @@ public MismatchedMethod(Exception exception, MethodBase mb)
363363
/// <param name="info">If not null, only bind to that method.</param>
364364
/// <param name="methodinfo">If not null, additionally attempt to bind to the generic methods in this array by inferring generic type parameters.</param>
365365
/// <returns>A Binding if successful. Otherwise null.</returns>
366-
internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, MethodInfo[] methodinfo)
366+
internal Binding Bind(BorrowedReference inst, BorrowedReference args, BorrowedReference kw, MethodBase info, MethodInfo[] methodinfo)
367367
{
368368
// loop to find match, return invoker w/ or w/o error
369369
MethodBase[] _methods = null;
370370

371-
var kwargDict = new Dictionary<string, IntPtr>();
372-
if (kw != IntPtr.Zero)
371+
var kwargDict = new Dictionary<string, PyObject>();
372+
if (kw != null)
373373
{
374-
var pynkwargs = (int)Runtime.PyDict_Size(kw);
375-
IntPtr keylist = Runtime.PyDict_Keys(kw);
376-
IntPtr valueList = Runtime.PyDict_Values(kw);
374+
nint pynkwargs = Runtime.PyDict_Size(kw);
375+
using var keylist = Runtime.PyDict_Keys(kw);
376+
using var valueList = Runtime.PyDict_Values(kw);
377377
for (int i = 0; i < pynkwargs; ++i)
378378
{
379-
var keyStr = Runtime.GetManagedString(Runtime.PyList_GetItem(new BorrowedReference(keylist), i));
380-
kwargDict[keyStr] = Runtime.PyList_GetItem(new BorrowedReference(valueList), i).DangerousGetAddress();
379+
var keyStr = Runtime.GetManagedString(Runtime.PyList_GetItem(keylist.Borrow(), i));
380+
BorrowedReference value = Runtime.PyList_GetItem(valueList.Borrow(), i);
381+
kwargDict[keyStr] = new PyObject(value);
381382
}
382-
Runtime.XDecref(keylist);
383-
Runtime.XDecref(valueList);
384383
}
385384

386385
var pynargs = (int)Runtime.PyTuple_Size(args);
@@ -442,7 +441,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
442441
}
443442
if (isOperator)
444443
{
445-
if (inst != IntPtr.Zero)
444+
if (inst != null)
446445
{
447446
if (ManagedType.GetManagedObject(inst) is CLRObject co)
448447
{
@@ -514,7 +513,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth
514513
var mi = bestMatch.Method;
515514

516515
object target = null;
517-
if (!mi.IsStatic && inst != IntPtr.Zero)
516+
if (!mi.IsStatic && inst != null)
518517
{
519518
//CLRObject co = (CLRObject)ManagedType.GetManagedObject(inst);
520519
// InvalidCastException: Unable to cast object of type
@@ -561,33 +560,33 @@ static AggregateException GetAggregateException(IEnumerable<MismatchedMethod> mi
561560
return new AggregateException(mismatchedMethods.Select(m => new ArgumentException($"{m.Exception.Message} in method {m.Method}", m.Exception)));
562561
}
563562

564-
static IntPtr HandleParamsArray(IntPtr args, int arrayStart, int pyArgCount, out bool isNewReference)
563+
static BorrowedReference HandleParamsArray(BorrowedReference args, int arrayStart, int pyArgCount, out NewReference tempObject)
565564
{
566-
isNewReference = false;
567-
IntPtr op;
565+
BorrowedReference op;
566+
tempObject = default;
568567
// for a params method, we may have a sequence or single/multiple items
569568
// here we look to see if the item at the paramIndex is there or not
570569
// and then if it is a sequence itself.
571570
if ((pyArgCount - arrayStart) == 1)
572571
{
573572
// we only have one argument left, so we need to check it
574573
// to see if it is a sequence or a single item
575-
IntPtr item = Runtime.PyTuple_GetItem(args, arrayStart);
574+
BorrowedReference item = Runtime.PyTuple_GetItem(args, arrayStart);
576575
if (!Runtime.PyString_Check(item) && Runtime.PySequence_Check(item))
577576
{
578577
// it's a sequence (and not a string), so we use it as the op
579578
op = item;
580579
}
581580
else
582581
{
583-
isNewReference = true;
584-
op = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount);
582+
tempObject = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount);
583+
op = tempObject.Borrow();
585584
}
586585
}
587586
else
588587
{
589-
isNewReference = true;
590-
op = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount);
588+
tempObject = Runtime.PyTuple_GetSlice(args, arrayStart, pyArgCount);
589+
op = tempObject.Borrow();
591590
}
592591
return op;
593592
}
@@ -607,8 +606,8 @@ static IntPtr HandleParamsArray(IntPtr args, int arrayStart, int pyArgCount, out
607606
/// <param name="outs">Returns number of output parameters</param>
608607
/// <returns>If successful, an array of .NET arguments that can be passed to the method. Otherwise null.</returns>
609608
static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
610-
IntPtr args, int pyArgCount,
611-
Dictionary<string, IntPtr> kwargDict,
609+
BorrowedReference args, int pyArgCount,
610+
Dictionary<string, PyObject> kwargDict,
612611
ArrayList defaultArgList,
613612
out int outs)
614613
{
@@ -620,7 +619,6 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
620619
{
621620
var parameter = pi[paramIndex];
622621
bool hasNamedParam = parameter.Name != null ? kwargDict.ContainsKey(parameter.Name) : false;
623-
bool isNewReference = false;
624622

625623
if (paramIndex >= pyArgCount && !(hasNamedParam || (paramsArray && paramIndex == arrayStart)))
626624
{
@@ -632,7 +630,8 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
632630
continue;
633631
}
634632

635-
IntPtr op;
633+
BorrowedReference op;
634+
NewReference tempObject = default;
636635
if (hasNamedParam)
637636
{
638637
op = kwargDict[parameter.Name];
@@ -641,7 +640,7 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
641640
{
642641
if(arrayStart == paramIndex)
643642
{
644-
op = HandleParamsArray(args, arrayStart, pyArgCount, out isNewReference);
643+
op = HandleParamsArray(args, arrayStart, pyArgCount, out tempObject);
645644
}
646645
else
647646
{
@@ -652,16 +651,11 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
652651
bool isOut;
653652
if (!TryConvertArgument(op, parameter.ParameterType, out margs[paramIndex], out isOut))
654653
{
654+
tempObject.Dispose();
655655
return null;
656656
}
657657

658-
if (isNewReference)
659-
{
660-
// TODO: is this a bug? Should this happen even if the conversion fails?
661-
// GetSlice() creates a new reference but GetItem()
662-
// returns only a borrow reference.
663-
Runtime.XDecref(op);
664-
}
658+
tempObject.Dispose();
665659

666660
if (isOut)
667661
{
@@ -681,7 +675,7 @@ static object[] TryConvertArguments(ParameterInfo[] pi, bool paramsArray,
681675
/// <param name="arg">Converted argument.</param>
682676
/// <param name="isOut">Whether the CLR type is passed by reference.</param>
683677
/// <returns>true on success</returns>
684-
static bool TryConvertArgument(IntPtr op, Type parameterType,
678+
static bool TryConvertArgument(BorrowedReference op, Type parameterType,
685679
out object arg, out bool isOut)
686680
{
687681
arg = null;
@@ -707,22 +701,21 @@ static bool TryConvertArgument(IntPtr op, Type parameterType,
707701
/// <param name="parameterType">The parameter's managed type.</param>
708702
/// <param name="argument">Pointer to the Python argument object.</param>
709703
/// <returns>null if conversion is not possible</returns>
710-
static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument)
704+
static Type TryComputeClrArgumentType(Type parameterType, BorrowedReference argument)
711705
{
712706
// this logic below handles cases when multiple overloading methods
713707
// are ambiguous, hence comparison between Python and CLR types
714708
// is necessary
715709
Type clrtype = null;
716-
IntPtr pyoptype;
717710

718711
if (clrtype != null)
719712
{
720713
if ((parameterType != typeof(object)) && (parameterType != clrtype))
721714
{
722-
IntPtr pytype = Converter.GetPythonTypeByAlias(parameterType);
723-
pyoptype = Runtime.PyObject_Type(argument);
715+
BorrowedReference pytype = Converter.GetPythonTypeByAlias(parameterType);
716+
BorrowedReference pyoptype = Runtime.PyObject_TYPE(argument);
724717
var typematch = false;
725-
if (pyoptype != IntPtr.Zero)
718+
if (pyoptype != null)
726719
{
727720
if (pytype != pyoptype)
728721
{
@@ -749,7 +742,6 @@ static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument)
749742
Exceptions.RaiseTypeError($"Expected {parameterTypeCode}, got {clrTypeCode}");
750743
}
751744
}
752-
Runtime.XDecref(pyoptype);
753745
if (!typematch)
754746
{
755747
return null;
@@ -779,7 +771,7 @@ static Type TryComputeClrArgumentType(Type parameterType, IntPtr argument)
779771
/// <param name="defaultsNeeded">Number of non-null defaultsArgs.</param>
780772
/// <returns></returns>
781773
static bool MatchesArgumentCount(int positionalArgumentCount, ParameterInfo[] parameters,
782-
Dictionary<string, IntPtr> kwargDict,
774+
Dictionary<string, PyObject> kwargDict,
783775
out bool paramsArray,
784776
out ArrayList defaultArgList,
785777
out int kwargsMatched,
@@ -847,30 +839,29 @@ internal virtual NewReference Invoke(BorrowedReference inst, BorrowedReference a
847839
return Invoke(inst, args, kw, info, null);
848840
}
849841

850-
protected static void AppendArgumentTypes(StringBuilder to, IntPtr args)
842+
protected static void AppendArgumentTypes(StringBuilder to, BorrowedReference args)
851843
{
852-
long argCount = Runtime.PyTuple_Size(args);
844+
Runtime.AssertNoErorSet();
845+
846+
nint argCount = Runtime.PyTuple_Size(args);
853847
to.Append("(");
854-
for (long argIndex = 0; argIndex < argCount; argIndex++)
848+
for (nint argIndex = 0; argIndex < argCount; argIndex++)
855849
{
856-
var arg = Runtime.PyTuple_GetItem(args, argIndex);
857-
if (arg != IntPtr.Zero)
850+
BorrowedReference arg = Runtime.PyTuple_GetItem(args, argIndex);
851+
if (arg != null)
858852
{
859-
var type = Runtime.PyObject_Type(arg);
860-
if (type != IntPtr.Zero)
853+
BorrowedReference type = Runtime.PyObject_TYPE(arg);
854+
if (type != null)
861855
{
862-
try
856+
using var description = Runtime.PyObject_Str(type);
857+
if (description.IsNull())
863858
{
864-
var description = Runtime.PyObject_Str(type);
865-
if (description != IntPtr.Zero)
866-
{
867-
to.Append(Runtime.GetManagedString(description));
868-
Runtime.XDecref(description);
869-
}
859+
Exceptions.Clear();
860+
to.Append(Util.BadStr);
870861
}
871-
finally
862+
else
872863
{
873-
Runtime.XDecref(type);
864+
to.Append(Runtime.GetManagedString(description.Borrow()));
874865
}
875866
}
876867
}
@@ -914,8 +905,7 @@ internal virtual NewReference Invoke(BorrowedReference inst, BorrowedReference a
914905
Runtime.PyErr_Fetch(out var errType, out var errVal, out var errTrace);
915906
AppendArgumentTypes(to: value, args);
916907
Runtime.PyErr_Restore(errType.StealNullable(), errVal.StealNullable(), errTrace.StealNullable());
917-
Exceptions.RaiseTypeError(value.ToString());
918-
return IntPtr.Zero;
908+
return Exceptions.RaiseTypeError(value.ToString());
919909
}
920910

921911
if (allow_threads)
@@ -938,7 +928,7 @@ internal virtual NewReference Invoke(BorrowedReference inst, BorrowedReference a
938928
PythonEngine.EndAllowThreads(ts);
939929
}
940930
Exceptions.SetError(e);
941-
return IntPtr.Zero;
931+
return default;
942932
}
943933

944934
if (allow_threads)
@@ -962,11 +952,11 @@ internal virtual NewReference Invoke(BorrowedReference inst, BorrowedReference a
962952

963953
bool isVoid = mi.ReturnType == typeof(void);
964954
int tupleSize = binding.outs + (isVoid ? 0 : 1);
965-
IntPtr t = Runtime.PyTuple_New(tupleSize);
955+
using var t = Runtime.PyTuple_New(tupleSize);
966956
if (!isVoid)
967957
{
968-
IntPtr v = Converter.ToPython(result, mi.ReturnType);
969-
Runtime.PyTuple_SetItem(t, n, v);
958+
using var v = Converter.ToPython(result, mi.ReturnType);
959+
Runtime.PyTuple_SetItem(t.Borrow(), n, v.Steal());
970960
n++;
971961
}
972962

@@ -975,21 +965,19 @@ internal virtual NewReference Invoke(BorrowedReference inst, BorrowedReference a
975965
Type pt = pi[i].ParameterType;
976966
if (pt.IsByRef)
977967
{
978-
IntPtr v = Converter.ToPython(binding.args[i], pt.GetElementType());
979-
Runtime.PyTuple_SetItem(t, n, v);
968+
using var v = Converter.ToPython(binding.args[i], pt.GetElementType());
969+
Runtime.PyTuple_SetItem(t.Borrow(), n, v.Steal());
980970
n++;
981971
}
982972
}
983973

984974
if (binding.outs == 1 && mi.ReturnType == typeof(void))
985975
{
986-
IntPtr v = Runtime.PyTuple_GetItem(t, 0);
987-
Runtime.XIncref(v);
988-
Runtime.XDecref(t);
989-
return v;
976+
BorrowedReference item = Runtime.PyTuple_GetItem(t.Borrow(), 0);
977+
return new NewReference(item);
990978
}
991979

992-
return t;
980+
return new NewReference(t.Borrow());
993981
}
994982

995983
return Converter.ToPython(result, mi.ReturnType);

src/runtime/runtime.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1586,7 +1586,7 @@ internal static int PyTuple_SetItem(BorrowedReference pointer, nint index, Borro
15861586

15871587
internal static int PyTuple_SetItem(BorrowedReference pointer, nint index, StolenReference value) => Delegates.PyTuple_SetItem(pointer, index, value);
15881588

1589-
private static NewReference PyTuple_GetSlice(BorrowedReference pointer, nint start, nint end) => Delegates.PyTuple_GetSlice(pointer, start, end);
1589+
internal static NewReference PyTuple_GetSlice(BorrowedReference pointer, nint start, nint end) => Delegates.PyTuple_GetSlice(pointer, start, end);
15901590

15911591
internal static nint PyTuple_Size(BorrowedReference pointer) => Delegates.PyTuple_Size(pointer);
15921592

0 commit comments

Comments
 (0)