@@ -512,12 +512,8 @@ public static NativeCode Active
512
512
return I386 ;
513
513
case MachineType . x86_64 :
514
514
return X86_64 ;
515
- case MachineType . armv7l :
516
- return Armv7l ;
517
- case MachineType . armv8 :
518
- return Armv8 ;
519
515
default :
520
- throw new NotImplementedException ( $ "No support for { Runtime . MachineName } " ) ;
516
+ return null ;
521
517
}
522
518
}
523
519
}
@@ -552,34 +548,6 @@ public static NativeCode Active
552
548
/// <see cref="NativeCode.X86_64"/>
553
549
/// </summary>
554
550
public static readonly NativeCode I386 = X86_64 ;
555
-
556
- public static readonly NativeCode Armv7l = new NativeCode ( )
557
- {
558
- Return0 = 0 ,
559
- Return1 = 0x08 ,
560
- Code = new byte [ ]
561
- {
562
- 0xe3 , 0xa0 , 0x00 , 0x00 , // mov r0, #0
563
- 0xe1 , 0x2f , 0xff , 0x1e , // bx lr
564
-
565
- 0xe3 , 0xa0 , 0x00 , 0x01 , // mov r0, #1
566
- 0xe1 , 0x2f , 0xff , 0x1e , // bx lr
567
- }
568
- } ;
569
-
570
- public static readonly NativeCode Armv8 = new NativeCode ( )
571
- {
572
- Return0 = 0 ,
573
- Return1 = 0x08 ,
574
- Code = new byte [ ]
575
- {
576
- 0x52 , 0x80 , 0x00 , 0x00 , // mov w0, #0x0
577
- 0xd6 , 0x5f , 0x03 , 0xc0 , // ret
578
-
579
- 0x52 , 0x80 , 0x00 , 0x20 , // mov w0, #0x1
580
- 0xd6 , 0x5f , 0x03 , 0xc0 , // ret
581
- }
582
- } ;
583
551
}
584
552
585
553
/// <summary>
@@ -702,7 +670,7 @@ internal static void InitializeNativeCodePage()
702
670
Marshal . Copy ( NativeCode . Active . Code , 0 , NativeCodePage , codeLength ) ;
703
671
mapper . SetReadExec ( NativeCodePage , codeLength ) ;
704
672
}
705
- #endregion
673
+ #endregion
706
674
707
675
/// <summary>
708
676
/// Given a newly allocated Python type object and a managed Type that
@@ -745,21 +713,40 @@ internal static void InitializeSlots(IntPtr type, Type impl)
745
713
impl = impl . BaseType ;
746
714
}
747
715
748
- // See the TestDomainReload test: there was a crash related to
749
- // the gc-related slots. They always return 0 or 1 because we don't
750
- // really support gc:
716
+ var native = NativeCode . Active ;
717
+
718
+ // The garbage collection related slots always have to return 1 or 0
719
+ // since .NET objects don't take part in Python's gc:
751
720
// tp_traverse (returns 0)
752
721
// tp_clear (returns 0)
753
722
// tp_is_gc (returns 1)
754
- // We can't do without: python really wants those slots to exist.
755
- // We can't implement those in C# because the application domain
756
- // can be shut down and the memory released.
757
- InitializeNativeCodePage ( ) ;
758
- InitializeSlot ( type , NativeCodePage + NativeCode . Active . Return0 , "tp_traverse" ) ;
759
- InitializeSlot ( type , NativeCodePage + NativeCode . Active . Return0 , "tp_clear" ) ;
760
- InitializeSlot ( type , NativeCodePage + NativeCode . Active . Return1 , "tp_is_gc" ) ;
723
+ // These have to be defined, though, so by default we fill these with
724
+ // static C# functions from this class.
725
+
726
+ var ret0 = Interop . GetThunk ( ( ( Func < IntPtr , int > ) Return0 ) . Method ) ;
727
+ var ret1 = Interop . GetThunk ( ( ( Func < IntPtr , int > ) Return1 ) . Method ) ;
728
+
729
+ if ( native != null )
730
+ {
731
+ // If we want to support domain reload, the C# implementation
732
+ // cannot be used as the assembly may get released before
733
+ // CPython calls these functions. Instead, for amd64 and x86 we
734
+ // load them into a separate code page that is leaked
735
+ // intentionally.
736
+ InitializeNativeCodePage ( ) ;
737
+ ret1 = NativeCodePage + native . Return1 ;
738
+ ret0 = NativeCodePage + native . Return0 ;
739
+ }
740
+
741
+ InitializeSlot ( type , ret0 , "tp_traverse" ) ;
742
+ InitializeSlot ( type , ret0 , "tp_clear" ) ;
743
+ InitializeSlot ( type , ret1 , "tp_is_gc" ) ;
761
744
}
762
745
746
+ static int Return1 ( IntPtr _ ) => 1 ;
747
+
748
+ static int Return0 ( IntPtr _ ) => 0 ;
749
+
763
750
/// <summary>
764
751
/// Helper for InitializeSlots.
765
752
///
0 commit comments