Skip to content

[mono][wasm] marshal-ilgen is dropped when not required#86035

Merged
jandupej merged 33 commits intodotnet:mainfrom
jandupej:marshal-analyzer-metadata
Jun 14, 2023
Merged

[mono][wasm] marshal-ilgen is dropped when not required#86035
jandupej merged 33 commits intodotnet:mainfrom
jandupej:marshal-analyzer-metadata

Conversation

@jandupej
Copy link
Contributor

@jandupej jandupej commented May 10, 2023

A new analyzer MarshlingPInvokeScanner is added, that scans all assemblies for constructs incompatible with the lightweight marshaller. This is essentially every P/Invoke that uses a nonblittable type as argument or returns it. The analyzer uses System.Reflection.Metadata to remain compatible with .NET Framework.

Additionally, the wasm toolchain uses this analyzer to decide whether marshal-ilgen is needed. If it is not, the full marshaller is dropped in favor of the lightweight one.

EDIT: The reduction in dotnet.native.wasm is approx. 74 KB when marshal-ilgen is dropped in favor of its stub.

@jandupej jandupej added the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label May 10, 2023
@jandupej jandupej requested a review from lambdageek May 10, 2023 12:58
@jandupej jandupej self-assigned this May 10, 2023
@ghost ghost added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label May 10, 2023
@teo-tsirpanis teo-tsirpanis added area-Build-mono and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels May 13, 2023
Copy link
Member

@lambdageek lambdageek left a comment

Choose a reason for hiding this comment

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

I wonder if the stub emit method can assert in a few places.

@jandupej jandupej marked this pull request as ready for review June 2, 2023 09:22
@jandupej jandupej removed the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Jun 2, 2023
Copy link
Member

@lambdageek lambdageek left a comment

Choose a reason for hiding this comment

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

native code changes lgtm. I have a couple of suggestions for the build task - the biggest one being whether we can use the type system from NativeAOT instead of building our own signature provider. if we use our own, then I think we need some comments to explain what is going on. It is not obvious.

Also check the weird ECMA edge-case of "generic" enum types that arise from nested types.

lambdageek

This comment was marked as duplicate.


<UsingTask TaskName="Microsoft.WebAssembly.Build.Tasks.ManagedToNativeGenerator" AssemblyFile="$(WasmAppBuilderTasksAssemblyPath)" />
<UsingTask TaskName="Microsoft.WebAssembly.Build.Tasks.EmccCompile" AssemblyFile="$(WasmAppBuilderTasksAssemblyPath)" />
<UsingTask TaskName="MarshalingPInvokeScanner" AssemblyFile="$(MonoTargetsTasksAssemblyPath)" />
Copy link
Member

Choose a reason for hiding this comment

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

Add namespace for the task

Comment on lines +238 to +239


Copy link
Member

Choose a reason for hiding this comment

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

Suggested change



}

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change



#pragma warning disable CS0649
internal sealed class PInvokeCallback
Copy link
Member

Choose a reason for hiding this comment

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

This could be a record like:

internal sealed record PInvokeCallback(MethodInfo method, string? EntryName = null);

Comment on lines +55 to +57



Copy link
Member

Choose a reason for hiding this comment

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

Suggested change


internal sealed class PInvokeCollector {
private readonly Dictionary<Assembly, bool> _assemblyDisableRuntimeMarshallingAttributeCache = new();
private TaskLoggingHelper Log { get; set; }
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
private TaskLoggingHelper Log { get; set; }
private readonly TaskLoggingHelper Log { get; init; }

if(mdtReader.GetString(td.Name) == "DisableRuntimeMarshallingAttribute")
return false;
}
catch(InvalidCastException)
Copy link
Member

Choose a reason for hiding this comment

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

Which part can throw this exception?

TypeDefinitionHandle tdh = md.GetDeclaringType();
TypeDefinition td = mdtReader.GetTypeDefinition(tdh);

if(mdtReader.GetString(td.Name) == "DisableRuntimeMarshallingAttribute")
Copy link
Member

Choose a reason for hiding this comment

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

.. and check namespace

Comment on lines +284 to +285
SignatureDecoder<Compatibility, object> decoder = new SignatureDecoder<Compatibility, object>(
mmtcp, mdtReader, null!);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
SignatureDecoder<Compatibility, object> decoder = new SignatureDecoder<Compatibility, object>(
mmtcp, mdtReader, null!);
SignatureDecoder<Compatibility, object> decoder = new(mmtcp, mdtReader, null!);

MethodSignature<Compatibility> sgn = decoder.DecodeMethodSignature(ref sgnBlobReader);
if(sgn.ReturnType == Compatibility.Incompatible || sgn.ParameterTypes.Any(p => p == Compatibility.Incompatible))
{
Log.LogMessage(MessageImportance.Low, string.Format("Assebly {0} requires marhsal-ilgen for method {1}.{2}:{3} (first pass).",
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Log.LogMessage(MessageImportance.Low, string.Format("Assebly {0} requires marhsal-ilgen for method {1}.{2}:{3} (first pass).",
Log.LogMessage(MessageImportance.Low, string.Format("Assembly {0} requires marhsal-ilgen for method {1}.{2}:{3} (first pass).",

var pinvokes = new List<PInvoke>();
var callbacks = new List<PInvokeCallback>();

PInvokeCollector pinvokeCollector = new PInvokeCollector(Log);
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
PInvokeCollector pinvokeCollector = new PInvokeCollector(Log);
PInvokeCollector pinvokeCollector = new(Log);

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants