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

[mono] Add conditional substitution for IsDynamicCodeSupported when targeting ios-like platforms #86971

Merged
merged 3 commits into from
Jun 19, 2023

Conversation

ivanpovazan
Copy link
Member

This PR introduces conditional linker substitution for get_IsDynamicCodeSupported method when targeting ios-like platforms with mono.
The substitution is enabled when feature switch DynamicCodeSupport is set to false, which should only happen in fullAOT mode - with no interpreter fallback.

Contributes to: xamarin/xamarin-macios#18340

@ivanpovazan ivanpovazan self-assigned this May 31, 2023
@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label May 31, 2023
@ivanpovazan ivanpovazan added the os-ios Apple iOS label May 31, 2023
@ghost
Copy link

ghost commented May 31, 2023

Tagging subscribers to 'os-ios': @steveisok, @akoeplinger
See info in area-owners.md if you want to be subscribed.

Issue Details

This PR introduces conditional linker substitution for get_IsDynamicCodeSupported method when targeting ios-like platforms with mono.
The substitution is enabled when feature switch DynamicCodeSupport is set to false, which should only happen in fullAOT mode - with no interpreter fallback.

Contributes to: xamarin/xamarin-macios#18340

Author: ivanpovazan
Assignees: ivanpovazan
Labels:

os-ios, needs-area-label

Milestone: -

@ivanpovazan ivanpovazan added area-Codegen-AOT-mono and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels May 31, 2023
@ivanpovazan
Copy link
Member Author

/azp run runtime-ioslike

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@ivanpovazan
Copy link
Member Author

NativeAOT sets the feature switch in the sdk: https://github.com/dotnet/sdk/blob/9ca8336afab6247a22e745c2de4960e9b660d164/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets#L27
not sure if there is another place (except in Xamarin sdk) to set it for Mono (apart from dotnet/runtime functional testing)

@steveisok
Copy link
Member

steveisok commented May 31, 2023

NativeAOT sets the feature switch in the sdk: https://github.com/dotnet/sdk/blob/9ca8336afab6247a22e745c2de4960e9b660d164/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets#L27 not sure if there is another place (except in Xamarin sdk) to set it for Mono (apart from dotnet/runtime functional testing)

I think once Alex can land a fix for dotnet/sdk#25392, we would have the option of having it set in the SDK. There will likely need to be properties for nativeaot and monoaot.

@lewing
Copy link
Member

lewing commented Jun 1, 2023

NativeAOT sets the feature switch in the sdk: https://github.com/dotnet/sdk/blob/9ca8336afab6247a22e745c2de4960e9b660d164/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets#L27 not sure if there is another place (except in Xamarin sdk) to set it for Mono (apart from dotnet/runtime functional testing)

I think once Alex can land a fix for dotnet/sdk#25392, we would have the option of having it set in the SDK. There will likely need to be properties for nativeaot and monoaot.

You can set it in WorkloadManifest.targets now

Copy link
Member

@lewing lewing left a comment

Choose a reason for hiding this comment

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

The linker substitution doesn't look conditional to me?

@ivanpovazan
Copy link
Member Author

@lewing thanks for your input, I have a couple of questions:

You can set it in WorkloadManifest.targets now

The linker substitution doesn't look conditional to me?

  • feature="System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported" featurevalue="false" makes it conditional in the sense that the method get_IsDynamicCodeSupported() will be replaced with false by the trimmer if the DynamicCodeSupport feature switch is set to false. Otherwise, there will be no substitution.

@marek-safar
Copy link
Contributor

This needs to be wired up into some internal msbuild property otherwise it has no effect because we don't want anyone to change this manually.

@ivanpovazan
Copy link
Member Author

ivanpovazan commented Jun 2, 2023

This needs to be wired up into some internal msbuild property otherwise it has no effect because we don't want anyone to change this manually.

Agreed.
I propose as a mid-term solution to set DynamicCodeSupport around here: https://github.com/xamarin/xamarin-macios/blob/cc35efe4bc46f2aa32a0190356cedaad2723e266/dotnet/targets/Xamarin.Shared.Sdk.targets#L118-L122 once this PR lands.
As a long-term solution, it will be set in the SDK once the work dotnet/sdk#25392 is completed.

Do you agree @marek-safar ?

@ivanpovazan
Copy link
Member Author

/cc: @lambdageek

@ivanpovazan
Copy link
Member Author

/azp run runtime-ioslike

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@ivanpovazan
Copy link
Member Author

/azp run runtime-extra-platforms

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@ivanpovazan
Copy link
Member Author

Failures seem unrelated

This reverts commit 682a3c0.
@ivanpovazan
Copy link
Member Author

ivanpovazan commented Jun 16, 2023

I have removed the previously added test as this set up is not unit testable for which I have considered:

  1. Using reflection to test whether a code path guarded by RuntimeFeature.IsDynamicCodeSupported is preserved; but in that case ILLink will preserve dependencies that are referenced dynamically (through reflection) defeating the purpose of the test
  2. Manually setting AppContext.SetSwitch("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", true); and making sure it does not have any effect. However, in that case MonoAOT actually does not look into managed side (and the AppContext) when determining the value for RuntimeFeature.IsDynamicCodeSupported, instead it performs an instrinsic optimisation:
    // On FullAOT, return false for RuntimeFeature:
    // - IsDynamicCodeCompiled
    // - IsDynamicCodeSupported and no interpreter
    // otherwise use the C# code in System.Private.CoreLib
    if (in_corlib &&
    cfg->full_aot &&
    !strcmp ("System.Runtime.CompilerServices", cmethod_klass_name_space) &&
    !strcmp ("RuntimeFeature", cmethod_klass_name)) {
    if (!strcmp (cmethod->name, "get_IsDynamicCodeCompiled")) {
    EMIT_NEW_ICONST (cfg, ins, 0);
    ins->type = STACK_I4;
    return ins;
    } else if (!strcmp (cmethod->name, "get_IsDynamicCodeSupported") && !cfg->interp) {
    EMIT_NEW_ICONST (cfg, ins, 0);
    ins->type = STACK_I4;
    return ins;
    }
    }

None of the approaches seems feasible.


Finally, as this change only affects app size, the verification and impact should be observable in size/perf measurements.
This will also open opportunities for further size optimisations like:

Copy link
Member

@eerhardt eerhardt left a comment

Choose a reason for hiding this comment

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

LGTM. I agree testing this change here is not really feasible at this time. Maybe if we had "dotnet-linker-tests" for iOS working, it could be possible.

@ivanpovazan ivanpovazan merged commit 2975717 into dotnet:main Jun 19, 2023
144 of 147 checks passed
@ghost ghost locked as resolved and limited conversation to collaborators Jul 19, 2023
@ivanpovazan ivanpovazan deleted the ios-trim-dyn-code-supported branch August 15, 2023 09:44
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.

8 participants