Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace linker descriptor for AssemblyBuilder with DynamicDependency #38710

Merged
merged 2 commits into from
Jul 3, 2020

Conversation

marek-safar
Copy link
Contributor

for better linking when AssemblyBuilder is not instantiated.

Contributes to #38692

@eerhardt

for better linking when AssemblyBuilder is not instantiated.

Contributes to dotnet#38692
@Dotnet-GitSync-Bot
Copy link
Collaborator

I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label.

[DynamicDependency("machine")]
[DynamicDependency("corlib_internal")]
[DynamicDependency("type_forwarders")]
[DynamicDependency("pktoken")]
Copy link
Member

Choose a reason for hiding this comment

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

Nit: are you able to use nameof in any of these?

Copy link
Contributor

@vargaz vargaz Jul 2, 2020

Choose a reason for hiding this comment

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

Could use a comment as to why the dependencies are on this method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah, will switch to nameof

@@ -202,13 +197,12 @@ public sealed class AssemblyBuilder : Assembly
private object? permissions_minimum;
private object? permissions_optional;
private object? permissions_refused;
private PortableExecutableKinds peKind;
private ImageFileMachine machine;
private int peKind;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this needed ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the field is not used and it drops additional dependencies

@eerhardt
Copy link
Member

eerhardt commented Jul 2, 2020

I tried using this change locally (with local fixes for #38693 and #38678). However, the ILLinker still isn't able to trim the fields from AssemblyBuilder. @marek-safar pointed out offline that it is because AssemblyBuilder has a StructLayout attribute.

[StructLayout(LayoutKind.Sequential)]
public sealed class AssemblyBuilder : Assembly

Even after changing that, there are other edges into Ref.Emit that are preserving most of the types (because of the other preserve=fields on other types):

TypeDef:System.Reflection.Emit.DynamicMethod size: 770
| Method:System.Delegate System.Delegate::CreateDelegate(System.Type,System.Object,System.Reflection.MethodInfo,System.Boolean,System.Boolean) [2 deps]
| Method:System.Delegate System.Delegate::CreateDelegate(System.Type,System.Reflection.MethodInfo,System.Boolean) [1 deps]
| Method:System.Delegate System.Delegate::CreateDelegate(System.Type,System.Reflection.MethodInfo) [3 deps]
| Method:System.Void Microsoft.AspNetCore.Components.Reflection.MemberAssignment/PropertySetter`2::.ctor(System.Reflection.MethodInfo,System.Boolean) [2 deps]

and

 TypeDef:System.Reflection.Emit.ModuleBuilder size: 423
| Field:System.Reflection.Emit.ModuleBuilder System.Reflection.Emit.TypeBuilder::pmodule [1 deps]
| TypeDef:System.Reflection.Emit.TypeBuilder [72 deps]
| Method:System.Object System.Activator::CreateInstance(System.Type,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo,System.Object[]) [3 deps]
| Method:System.Object System.Activator::CreateInstance(System.Type,System.Object[]) [5 deps]
| Method:Microsoft.AspNetCore.Components.Reflection.IPropertySetter Microsoft.AspNetCore.Components.Reflection.MemberAssignment::CreatePropertySetter(System.Type,System.Reflection.PropertyInfo,System.Boolean) [3 deps]

@MichalStrehovsky
Copy link
Member

I think this should be doable without any annotations.

StructLayout.Sequential keeps all fields on the type, for good reasons.

But linker is too eager to respect the layout. For reference types (and only reference types), the layout only becomes relevant once you allocate an instance. Linker should defer marking the fields until it sees the type as instantiated (i.e. constructor called).

Once linker does that, the annotation will be unnecessary and this will Just Work™.

@MichalStrehovsky
Copy link
Member

I think this should be doable without any annotations.

Linker change: dotnet/linker#1309

@@ -224,7 +218,8 @@ public sealed class AssemblyBuilder : Assembly
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern void UpdateNativeCustomAttributes(AssemblyBuilder ab);

internal AssemblyBuilder(AssemblyName n, string? directory, AssemblyBuilderAccess access, bool corlib_internal)
[DynamicDependency(nameof(pktoken))] // Automatically keeps all previous fields too due to StructLayout
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need DynamicDependency at all? The class is marked StructLayout.Sequential and this annotation is on a constructor - linker is going to keep all the fields anyway if it sees the constructor is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Technically we don't right now but I wanted to make this dependency more explicit. We could also fix linker to keep only used fields for struct layout classes.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure I understand how an explicit DynamicDependency on what appears to be an arbitrary field achieves that - I think we'll find that part quite confusing when we look at this code again 5 years from now.

Copy link
Member

Choose a reason for hiding this comment

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

If we want to be explicit, can we instead use the attribute that says to keep all fields?

@marek-safar marek-safar merged commit 054fb2e into dotnet:master Jul 3, 2020
@marek-safar marek-safar deleted the subst branch July 3, 2020 15:11
@ghost ghost locked as resolved and limited conversation to collaborators Dec 8, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants