[dotnet-linker] Handle null fields in BackingFieldDelayHandler as unmarked fields. Fixes #16957. (#16970)
The BackingFieldDelayHandler will temporarily remove the body of Dispose methods, and then for every field accessed in the Dispose method that was preserved by the linker, we'll keep the corresponding code in the Dispose method (otherwise we'd remove the code). This is a way to remove fields that are _only_ accessed (and nulled out) in the Dispose method. However, we were running into a problem with determining if a field was marked by the linker: if the field is in a generic type, and that field was not marked by the linker, the linker might have actually removed the field from the containing type before we're processing the Dispose methods, and we'd find a null field definition where no null field definition was expected (eventually resulting in an ArgumentNullException). Fix this by treating a null field definition as an unmarked field. Also add a test. Fixes https://github.com/xamarin/xamarin-macios/issues/16957.
This commit is contained in:
Родитель
6581fcb5fb
Коммит
25fc6c84d1
|
@ -52,5 +52,19 @@ namespace LinkAnyTest {
|
|||
Assert.IsNotNull (AppContext.GetData ("PINVOKE_OVERRIDE"), "PINVOKE_OVERRIDE");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !__WATCHOS__
|
||||
[Test]
|
||||
public void BackingFieldInGenericType ()
|
||||
{
|
||||
// https://github.com/dotnet/linker/issues/3148
|
||||
#if __MACOS__
|
||||
var view = new AppKit.NSView ();
|
||||
#else
|
||||
var view = new UIKit.UIView ();
|
||||
#endif
|
||||
GC.KeepAlive (view.HeightAnchor);
|
||||
}
|
||||
#endif // !__WATCHOS__
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,8 +70,10 @@ namespace Xamarin.Linker {
|
|||
foreach (var ins in body.Instructions) {
|
||||
switch (ins.OpCode.OperandType) {
|
||||
case OperandType.InlineField:
|
||||
var field = (ins.Operand as FieldReference)?.Resolve ();
|
||||
if (!context.Annotations.IsMarked (field)) {
|
||||
var fr = ins.Operand as FieldReference;
|
||||
var field = fr?.Resolve ();
|
||||
var isMarked = field is not null && context.Annotations.IsMarked (field);
|
||||
if (!isMarked) {
|
||||
var store_field = ins;
|
||||
var load_null = ins.Previous;
|
||||
var load_this = ins.Previous.Previous;
|
||||
|
|
Загрузка…
Ссылка в новой задаче