[net8.0] Merge main into net8.0.

This commit is contained in:
Rolf Bjarne Kvinge 2023-08-07 20:21:34 +02:00
Родитель 64077229cb b17626ff1c
Коммит 58b5d14d8c
7 изменённых файлов: 151 добавлений и 28 удалений

4
configure поставляемый
Просмотреть файл

@ -70,12 +70,12 @@ while test "x$1" != x; do
echo "Disabled all platforms"
shift
;;
--disable-mac)
--disable-mac | --disable-macos)
echo "INCLUDE_MAC=" >> $CONFIGURED_FILE
echo "Mac Build disabled"
shift
;;
--enable-mac)
--enable-mac | --enable-macos)
echo "INCLUDE_MAC=1" >> $CONFIGURED_FILE
echo "Mac Build enabled"
shift

Просмотреть файл

@ -231,16 +231,14 @@ namespace Foundation {
GC.SuppressFinalize (this);
}
static T AllocateNSObject<T> (IntPtr handle) where T : NSObject
{
var obj = (T) RuntimeHelpers.GetUninitializedObject (typeof (T));
obj.handle = handle;
obj.flags = Flags.NativeRef;
return obj;
}
internal static IntPtr CreateNSObject (IntPtr type_gchandle, IntPtr handle, Flags flags)
{
#if NET
if (Runtime.IsManagedStaticRegistrar) {
throw new System.Diagnostics.UnreachableException ();
}
#endif
// This function is called from native code before any constructors have executed.
var type = (Type) Runtime.GetGCHandleTarget (type_gchandle);
try {

Просмотреть файл

@ -1820,7 +1820,7 @@ namespace HealthKit {
bool HasUndeterminedDuration { get; }
}
delegate void HKSampleQueryResultsHandler (HKSampleQuery query, HKSample [] results, NSError error);
delegate void HKSampleQueryResultsHandler (HKSampleQuery query, [NullAllowed] HKSample [] results, [NullAllowed] NSError error);
[Mac (13, 0)]
[MacCatalyst (13, 1)]

Просмотреть файл

@ -919,6 +919,9 @@ namespace Xamarin.Tests {
public static IEnumerable<ApplePlatform> GetIncludedPlatforms (bool dotnet)
{
if (dotnet && !include_dotnet)
yield break;
if (include_ios)
yield return ApplePlatform.iOS;
if (include_tvos)

Просмотреть файл

@ -51,6 +51,7 @@ namespace Xamarin.Linker {
Dictionary<AssemblyDefinition, Dictionary<string, (TypeDefinition, TypeReference)>> type_map = new ();
Dictionary<string, (MethodDefinition, MethodReference)> method_map = new ();
Dictionary<string, (FieldDefinition, FieldReference)> field_map = new ();
public AppBundleRewriter (LinkerConfiguration configuration)
{
@ -176,6 +177,23 @@ namespace Xamarin.Linker {
return $"{method?.ReturnType?.FullName ?? "(null)"} {method?.DeclaringType?.FullName ?? "(null)"}::{method?.Name ?? "(null)"} ({string.Join (", ", method?.Parameters?.Select (v => v?.ParameterType?.FullName + " " + v?.Name) ?? Array.Empty<string> ())})";
}
public FieldReference GetFieldReference (AssemblyDefinition assembly, TypeReference tr, string name, string key, out FieldDefinition field)
{
if (!field_map.TryGetValue (key, out var tuple)) {
var td = tr.Resolve ();
var fd = td.Fields.SingleOrDefault (v => v.Name == name);
if (fd is null)
throw new InvalidOperationException ($"Unable to find the field '{tr.FullName}::{name}' (for key '{key}') in {assembly.Name.Name}. Fields in type:\n\t{string.Join ("\n\t", td.Fields.Select (f => f.Name).OrderBy (v => v))}");
tuple.Item1 = fd;
tuple.Item2 = CurrentAssembly.MainModule.ImportReference (fd);
field_map.Add (key, tuple);
}
field = tuple.Item1;
return tuple.Item2;
}
/* Types */
public TypeReference System_Boolean {
@ -267,6 +285,12 @@ namespace Xamarin.Linker {
}
}
public TypeReference System_ValueType {
get {
return GetTypeReference (CorlibAssembly, "System.ValueType", out var _);
}
}
public TypeReference System_Collections_Generic_Dictionary2 {
get {
return GetTypeReference (CorlibAssembly, "System.Collections.Generic.Dictionary`2", out var _);
@ -321,6 +345,26 @@ namespace Xamarin.Linker {
}
}
public FieldReference Foundation_NSObject_HandleField {
get {
return GetFieldReference (PlatformAssembly, Foundation_NSObject, "handle", "Foundation.NSObject::handle", out var _);
}
}
#if NET
public MethodReference Foundation_NSObject_FlagsSetterMethod {
get {
return GetMethodReference (PlatformAssembly, Foundation_NSObject, "set_flags", "Foundation.NSObject::set_flags", predicate: null, out var _);
}
}
#else
public FieldReference Foundation_NSObject_FlagsField {
get {
return GetFieldReference (PlatformAssembly, Foundation_NSObject, "flags", "Foundation.NSObject::flags", out var _);
}
}
#endif
public TypeReference ObjCRuntime_BindAs {
get {
return GetTypeReference (PlatformAssembly, "ObjCRuntime.BindAs", out var _);
@ -449,17 +493,6 @@ namespace Xamarin.Linker {
}
}
public MethodReference NSObject_AllocateNSObject {
get {
return GetMethodReference (PlatformAssembly,
Foundation_NSObject, "AllocateNSObject",
nameof (NSObject_AllocateNSObject),
isStatic: true,
genericParameterCount: 1,
System_IntPtr);
}
}
public MethodReference BindAs_ConvertNSArrayToManagedArray {
get {
return GetMethodReference (PlatformAssembly, ObjCRuntime_BindAs, "ConvertNSArrayToManagedArray", (v) =>

Просмотреть файл

@ -30,6 +30,14 @@ namespace Xamarin.Linker {
return rv;
}
public static FieldDefinition AddField (this TypeDefinition self, string name, FieldAttributes attributes, TypeReference type)
{
var rv = new FieldDefinition (name, attributes, type);
rv.DeclaringType = self;
self.Fields.Add (rv);
return rv;
}
public static MethodBody CreateBody (this MethodDefinition self, out ILProcessor il)
{
var body = new MethodBody (self);

Просмотреть файл

@ -401,6 +401,7 @@ namespace Xamarin.Linker {
var placeholderType = abr.System_IntPtr;
ParameterDefinition? callSuperParameter = null;
VariableDefinition? returnVariable = null;
MethodReference? ctor = null;
var leaveTryInstructions = new List<Instruction> ();
var isVoid = method.ReturnType.Is ("System", "Void");
@ -425,6 +426,7 @@ namespace Xamarin.Linker {
// and later on remove everything after this instruction. Maybe at a later point I'll figure out a way to make the code emission conditional without
// littering the logic with conditional statements.
Instruction? skipEverythingAfter = null;
if (isInstanceCategory) {
il.Emit (OpCodes.Ldarg_0);
EmitConversion (method, il, method.Parameters [0].ParameterType, true, 0, out var nativeType, postProcessing);
@ -459,12 +461,32 @@ namespace Xamarin.Linker {
// We're throwing an exception, so there's no need for any more code.
skipEverythingAfter = il.Body.Instructions.Last ();
} else {
il.Emit (OpCodes.Ldarg_0);
// Whenever there's an NSObject constructor that we call from a registrar callback, we need to create
// a separate constructor that will first set the `handle` and `flags` values of the NSObject before
// calling the original constructor. Here's an example of the code we generate:
//
// // The original constructor:
// public .ctor (T0 p0, T1 p1, ...) { /* ... */ }
//
// // The generated constructor with pre-initialization:
// public .ctor (T0 p0, T1 p1, ..., IntPtr nativeHandle, IManagedRegistrar dummy) {
// this.handle = (NativeHandle)nativeHandle;
// this.flags = 2; // Flags.NativeRef == 2
// this..ctor (p0, p1, ...);
// }
//
// - This code can't be expressed in C# and it can only be expressed directly in IL.
// - The reason we need to do this is because the base NSObject parameterless constructor
// would allocate a new Objective-C object if `handle` is a zero pointer.
// - The `IManagedRegistrar` dummy parameter is used only to make sure that the signature
// is unique and there aren't any conflicts. The IManagedRegistrar type is internal and
// we only make it public through a custom linker step.
ctor = CloneConstructorWithNativeHandle (method);
method.DeclaringType.Methods.Add (ctor.Resolve ());
il.Emit (OpCodes.Nop);
postLeaveBranch.Operand = il.Body.Instructions.Last ();
var git = new GenericInstanceMethod (abr.NSObject_AllocateNSObject);
git.GenericArguments.Add (method.DeclaringType);
il.Emit (OpCodes.Call, git);
il.Emit (OpCodes.Dup); // this is for the call to ObjCRuntime.NativeObjectExtensions::GetHandle after the call to the constructor
}
} else if (isGeneric) {
// this is a proxy method and we can simply use `this` without any conversion
@ -509,7 +531,13 @@ namespace Xamarin.Linker {
callback.AddParameter ("exception_gchandle", new PointerType (abr.System_IntPtr));
if (isGeneric && !method.IsConstructor) {
if (ctor is not null) {
// in addition to the params of the original ctor we pass also the native handle and a null
// value for the dummy (de-duplication) parameter
il.Emit (OpCodes.Ldarg_0);
il.Emit (OpCodes.Ldnull);
il.Emit (OpCodes.Newobj, ctor);
} else if (isGeneric && !method.IsConstructor) {
var targetMethod = method.DeclaringType.CreateMethodReferenceOnGenericType (method, method.DeclaringType.GenericParameters.ToArray ());
il.Emit (OpCodes.Call, targetMethod);
} else if (method.IsStatic) {
@ -1270,5 +1298,58 @@ namespace Xamarin.Linker {
il.Append (endTarget);
}
}
MethodDefinition CloneConstructorWithNativeHandle (MethodDefinition ctor)
{
var clonedCtor = new MethodDefinition (ctor.Name, ctor.Attributes, ctor.ReturnType);
clonedCtor.IsPublic = false;
// clone the original parameters firsts
foreach (var parameter in ctor.Parameters) {
clonedCtor.AddParameter (parameter.Name, parameter.ParameterType);
}
// add a native handle param + a dummy parameter that we know for a fact won't be used anywhere
// to make the signature of the new constructor unique
var handleParameter = clonedCtor.AddParameter ("nativeHandle", abr.System_IntPtr);
var dummyParameter = clonedCtor.AddParameter ("dummy", abr.ObjCRuntime_IManagedRegistrar);
var body = clonedCtor.CreateBody (out var il);
// ensure visible
abr.Foundation_NSObject_HandleField.Resolve ().IsFamily = true;
#if NET
abr.Foundation_NSObject_FlagsSetterMethod.Resolve ().IsFamily = true;
#else
abr.Foundation_NSObject_FlagsField.Resolve ().IsFamily = true;
#endif
// store the handle and flags first
il.Emit (OpCodes.Ldarg_0);
il.Emit (OpCodes.Ldarg, handleParameter);
#if NET
il.Emit (OpCodes.Call, abr.NativeObject_op_Implicit_NativeHandle);
#endif
il.Emit (OpCodes.Stfld, abr.CurrentAssembly.MainModule.ImportReference (abr.Foundation_NSObject_HandleField));
il.Emit (OpCodes.Ldarg_0);
il.Emit (OpCodes.Ldc_I4_2); // Flags.NativeRef == 2
#if NET
il.Emit (OpCodes.Call, abr.Foundation_NSObject_FlagsSetterMethod);
#else
il.Emit (OpCodes.Stfld, abr.Foundation_NSObject_FlagsField);
#endif
// call the original constructor with all of the original parameters
il.Emit (OpCodes.Ldarg_0);
foreach (var parameter in clonedCtor.Parameters.SkipLast (2)) {
il.Emit (OpCodes.Ldarg, parameter);
}
il.Emit (OpCodes.Call, ctor);
il.Emit (OpCodes.Ret);
return clonedCtor;
}
}
}