@@ -33,6 +33,8 @@ public sealed partial class PythonFunction : PythonTypeSlot, IWeakReferenceable,
3333 public readonly MutableTuple Closure ;
3434
3535 private object [ ] /*!*/ _defaults ; // the default parameters of the method
36+ private PythonDictionary _kwdefaults ; // the keyword-only arguments defaults for the method
37+
3638 internal PythonDictionary _dict ; // a dictionary to story arbitrary members on the function object
3739 private object _module ; // the module name
3840
@@ -89,7 +91,7 @@ internal PythonFunction(CodeContext/*!*/ context, FunctionCode funcInfo, object
8991
9092 _context = context ;
9193 _defaults = defaults ?? ArrayUtils . EmptyObjects ;
92- __kwdefaults__ = kwdefaults ;
94+ _kwdefaults = kwdefaults ;
9395 _code = funcInfo ;
9496 _doc = funcInfo . _initialDoc ;
9597 _name = funcInfo . co_name ;
@@ -145,8 +147,13 @@ public PythonTuple __defaults__ {
145147 }
146148 }
147149
148- // TODO: update CalculatedCachedCompat?
149- public PythonDictionary __kwdefaults__ { get ; set ; }
150+ public PythonDictionary __kwdefaults__ {
151+ get => _kwdefaults ;
152+ set {
153+ _kwdefaults = value ;
154+ FunctionCompatibility = CalculatedCachedCompat ( ) ;
155+ }
156+ }
150157
151158 [ System . Diagnostics . CodeAnalysis . SuppressMessage ( "Microsoft.Usage" , "CA2227:CollectionPropertiesShouldBeReadOnly" ) ]
152159 public object __closure__ {
@@ -277,6 +284,14 @@ internal string GetSignatureString() {
277284 /// </summary>
278285 internal int FunctionCompatibility { get ; private set ; }
279286
287+ internal bool NeedsCodeTest {
288+ get {
289+ return NormalArgumentCount > 0x3ff
290+ || Defaults . Length > 0x3ff
291+ || KeywordOnlyArgumentCount > 0x1ff ;
292+ }
293+ }
294+
280295 /// <summary>
281296 /// Calculates the _compat value which is used for call-compatibility checks
282297 /// for simple calls. Whenver any of the dependent values are updated this
@@ -289,20 +304,20 @@ internal string GetSignatureString() {
289304 /// expand dict/list - based on nparams and flags, both read-only
290305 ///
291306 /// Bits are allocated as:
292- /// 000000ff - Normal argument count
293- /// 0000ff00 - Default count
294- /// 007f0000 - Keyword-only argument count
295- /// 3f800000 - Keyword -only defaults count
307+ /// 000003ff - Normal argument count
308+ /// 000ffc00 - Default count
309+ /// 1ff00000 - Keyword-only argument count
310+ /// 20000000 - has keyword -only defaults
296311 /// 40000000 - expand list
297312 /// 80000000 - expand dict
298313 ///
299314 /// Enforce recursion is added at runtime.
300315 /// </summary>
301316 private int CalculatedCachedCompat ( ) {
302- return ( NormalArgumentCount ) |
303- ( Defaults . Length << 8 ) |
304- ( KeywordOnlyArgumentCount << 16 ) |
305- ( ( __kwdefaults__ ? . Count ?? 0 ) << 23 ) |
317+ return NormalArgumentCount |
318+ ( Defaults . Length << 10 ) |
319+ ( KeywordOnlyArgumentCount << 20 ) |
320+ ( __kwdefaults__ is not null ? 0x20000000 : 0 ) |
306321 ( ( ExpandListPosition != - 1 ) ? 0x40000000 : 0 ) |
307322 ( ( ExpandDictPosition != - 1 ) ? unchecked ( ( int ) 0x80000000 ) : 0 ) ;
308323 }
0 commit comments