Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

jtschuster
Copy link
Member

Adds support and basic tests for ref fields. The tests ensure that a value written to an ref field is properly annotated, or an address written to a ref field has a properly annotated value, but there are some holes that can be created by assigning the address of a local or over-annotated value to an annotated ref field. Tracking issue: #2946
For example:

Type t = typeof(int);
RefStructWithMethods rs = new();
rs.T = ref t; // doesn't warn
t = GetUnannotatedValue(); // stores an unannotated value in the location pointed to by an annotated ref field

The linker also doesn't recognize ldind.ref, so when a ref variable is assigned by value to a ref field, the linker will warn for a unknown value. Tracking issue: dotnet/runtime#85465
For example:

ref Type t = ref GetReferenceToTypeWithMethods();
RefStructWithMethods rs = new();
rs.T = t; // Warns with IL2064 - unknown value assigned to field

@vitek-karas
Copy link
Member

This looks promising, but I think we should tackle some other stuff first:

  • Tests that linker can correctly round-trip ref fields (this might be "tricky", not sure how we should go about this)
  • Tests that linker will not crash on ref fields in various situations - doesn't mean it needs to do the right thing, but should not crash
  • Tests around trimming behavior of ref fields
  • RUC tests - and analyzer
  • Data flow tests - also validate that the analyzer will not crash on them

And only once we have these and fixed any round-trip or crashing issues, we may start looking into improving data over ref fields. Honestly ref fields of System.Type type are probably going to be very rare... and even rarer to have annotations, it would be perfectly OK if in .NET 7 we shipped without proper data flow around them.

@jtschuster jtschuster changed the title Final support for ref fields Dataflow support for ref fields Aug 9, 2022
@jtschuster
Copy link
Member Author

Tests that linker can correctly round-trip ref fields (this might be "tricky", not sure how we should go about this)

PR: #2960 -- Add ILVerification

Tests that linker will not crash on ref fields in various situations - doesn't mean it needs to do the right thing, but should not crash

PR: #2952

Tests around trimming behavior of ref fields

PR: #2952 -- All fields of structs should be kept
This PR also ensures that referenced types are kept.

RUC tests - and analyzer

PR: #2952

Data flow tests - also validate that the analyzer will not crash on them

This PR

Copy link
Member

@sbomer sbomer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly LGTM, only have minor comments. Thanks!

case ReferenceValue referenceValue:
throw new NotImplementedException ($"Unhandled dereference of ReferenceValue of type {referenceValue.GetType ().FullName}");
// Incomplete handling for ref values
case FieldValue fieldValue:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this case? I think it's the same as the default.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's probably not necessary, but I thought it might be nice to have the case just to point out that it's not fully / correctly implemented. I can remove it if you feel like it's just noise.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, I am fine with it as-is.

Code.Ldsflda
=> ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForAccess (Context, (FieldReference) instruction.Operand),
// For ref fields, ldfld loads an address which can be used to store values to annotated fields
Code.Ldfld when ((FieldReference) instruction.Operand).FieldType.IsByRefOrPointer ()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it would be better to look for indirect stores - the other cases above check for writes that could impose requirements, and an indirect store would be the way to get there with a ldfld of a ref field. I expect it's also less common than ldfld.

Copy link
Member Author

@jtschuster jtschuster Aug 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there's an easy way to tell where the value is being stored or what value we're storing to it since stind operates on addresses on the stack. And this will filter to only be ref fields or pointers that also have annotations, so it shouldn't cause too many more method bodies to be analyzed for dataflow. I think that's why the previous cases also look for ldflda.

@jtschuster jtschuster requested a review from sbomer August 12, 2022 17:22
Copy link
Member

@sbomer sbomer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@jtschuster jtschuster merged commit 1ef0acf into dotnet:main Aug 12, 2022
agocke pushed a commit to dotnet/runtime that referenced this pull request Nov 16, 2022
Adds support and basic tests for ref fields. The tests ensure that a value written to an ref field is properly annotated, or an address written to a ref field has a properly annotated value, but there are some holes that can be created by assigning the address of a local or over-annotated value to an annotated ref field.

Commit migrated from dotnet/linker@1ef0acf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants