Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 5.6k
Preserve IL for CoreCLR interpreter fallback on Apple mobile#130622
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
Changes from all commits
eacd9d2f5f5cce7462331bbff0da7276e8a6f8d7a012d0b933b82391a4ce2cf7729441ab2af53027c501c0998878b8c81033097397d4fd8b5c33a994537bbc9c231eac86b9e1fae3aeb7e1cc8dFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -11,6 +11,7 @@ | ||
| using Internal.TypeSystem; | ||
| using InstructionSet = Internal.JitInterface.InstructionSet; | ||
| using InstructionSetFlags = Internal.JitInterface.InstructionSetFlags; | ||
| namespace System.CommandLine | ||
| { | ||
| @@ -353,5 +354,35 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru | ||
| InstructionSetSupportBuilder.GetNonSpecifiableInstructionSetsForArch(targetArchitecture), | ||
| targetArchitecture); | ||
| } | ||
| // Produces an InstructionSetSupport where the instruction sets are fixed at compile time: every | ||
| // specifiable instruction set that is not already supported is marked explicitly unsupported, and the | ||
| // supported sets are also treated as optimistic. This is used for targets without runtime code generation | ||
| // (for example Apple mobile and WASM), where the pre-compiled code must hard code its ISA usage because | ||
| // there is no JIT to recover from an instruction set mismatch. | ||
| public static InstructionSetSupport GetFixedInstructionSetSupport(InstructionSetSupport instructionSetSupport) | ||
| { | ||
| InstructionSetFlags unsupportedInstructionSets = instructionSetSupport.ExplicitlyUnsupportedFlags; | ||
| foreach (var instructionSetInfo in InstructionSetFlags.ArchitectureToValidInstructionSets(instructionSetSupport.Architecture)) | ||
| { | ||
| if (instructionSetInfo.Specifiable && | ||
| !instructionSetSupport.IsInstructionSetSupported(instructionSetInfo.InstructionSet)) | ||
| { | ||
| unsupportedInstructionSets.AddInstructionSet(instructionSetInfo.InstructionSet); | ||
| } | ||
| } | ||
| unsupportedInstructionSets.ExpandInstructionSetByReverseImplication(instructionSetSupport.Architecture); | ||
kotlarmilos marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| unsupportedInstructionSets.Set64BitInstructionSetVariants(instructionSetSupport.Architecture); | ||
| if (instructionSetSupport.Architecture is TargetArchitecture.X86 or TargetArchitecture.ARM) | ||
| unsupportedInstructionSets.Set64BitInstructionSetVariantsUnconditionally(instructionSetSupport.Architecture); | ||
| return new InstructionSetSupport( | ||
| instructionSetSupport.SupportedFlags, | ||
| unsupportedInstructionSets, | ||
| instructionSetSupport.SupportedFlags, | ||
| instructionSetSupport.NonSpecifiableFlags, | ||
| instructionSetSupport.Architecture); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -570,6 +570,7 @@ public void RuntimeAsyncStripILBodiesPreservesTaskReturningIL() | ||
| new(nameof(RuntimeAsyncStripILBodiesPreservesTaskReturningIL), [new CrossgenAssembly(stripILBodies)]) | ||
| { | ||
| Options = [Crossgen2Option.Composite, Crossgen2Option.Optimize, Crossgen2Option.StripILBodies], | ||
| AdditionalArgs = ["--targetarch:x64"], | ||
| Validate = Validate, | ||
| }, | ||
| ])); | ||
| @@ -593,6 +594,7 @@ static void Validate(ReadyToRunReader reader) | ||
| Assert.True(R2RAssert.MethodILIsStripped(componentFile, "StripILBodies", "PlainStrippableMethod", out diag), diag); | ||
| Assert.True(R2RAssert.MethodILIsStripped(componentFile, "StripILBodies", "ComputeTag", out diag), diag); | ||
| Assert.True(R2RAssert.MethodILIsStripped(componentFile, "StripILBodies", "Root", out diag), diag); | ||
| Assert.True(R2RAssert.MethodILIsStripped(componentFile, "StripILBodies", "UsesRuntimeCheckedInstructionSet", out diag), diag); | ||
kotlarmilos marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
kotlarmilos marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| Assert.True(R2RAssert.MethodILIsStripped(componentFile, "StripILBodies", "AsyncTaskMethod", out diag), diag); | ||
| Assert.True(R2RAssert.MethodILIsStripped(componentFile, "StripILBodies", "AsyncValueTaskMethod", out diag), diag); | ||
| @@ -604,6 +606,50 @@ static void Validate(ReadyToRunReader reader) | ||
| } | ||
| } | ||
| [Fact] | ||
| public void AppleMobileStripILBodiesUsesFixedInstructionSet() | ||
| { | ||
| var stripILBodies = new CompiledAssembly | ||
| { | ||
| AssemblyName = nameof(AppleMobileStripILBodiesUsesFixedInstructionSet), | ||
| SourceResourceNames = | ||
| [ | ||
| "RuntimeAsync/StripILBodies.cs", | ||
| "RuntimeAsync/RuntimeAsyncMethodGenerationAttribute.cs", | ||
| ], | ||
| Features = { RuntimeAsyncFeature }, | ||
| }; | ||
| new R2RTestRunner(_output).Run(new R2RTestCase( | ||
| nameof(AppleMobileStripILBodiesUsesFixedInstructionSet), | ||
| [ | ||
| new(nameof(AppleMobileStripILBodiesUsesFixedInstructionSet), [new CrossgenAssembly(stripILBodies)]) | ||
| { | ||
| Options = [Crossgen2Option.Composite, Crossgen2Option.Optimize, Crossgen2Option.StripILBodies], | ||
| AdditionalArgs = ["--targetos:ios", "--targetarch:arm64"], | ||
| Validate = Validate, | ||
| }, | ||
| ])); | ||
| static void Validate(ReadyToRunReader reader) | ||
| { | ||
| string componentFile = Path.Combine( | ||
| Path.GetDirectoryName(reader.Filename)!, | ||
| nameof(AppleMobileStripILBodiesUsesFixedInstructionSet) + ".dll"); | ||
| Assert.True(R2RAssert.MethodILIsStripped(componentFile, "StripILBodies", "PlainStrippableMethod", out string diag), diag); | ||
| Assert.True(R2RAssert.MethodILIsStripped(componentFile, "StripILBodies", "UsesRuntimeCheckedInstructionSet", out diag), diag); | ||
kotlarmilos marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| Assert.False( | ||
| R2RAssert.HasFixupKindOnMethod( | ||
| reader, | ||
| ReadyToRunFixupKind.Check_InstructionSetSupport, | ||
| ".UsesRuntimeCheckedInstructionSet(", | ||
| out diag), | ||
| diag); | ||
| Assert.True(R2RAssert.EagerInstructionSetSupportHasNoUnsupportedEntries(reader, out diag), diag); | ||
| } | ||
| } | ||
| /// <summary> | ||
| /// PR #123643: Async methods capturing GC refs across await points | ||
| /// produce ContinuationLayout fixups encoding the GC ref map. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -954,6 +954,47 @@ public static bool HasFixupKindCountOnMethod(ReadyToRunReader reader, ReadyToRun | ||
| return true; | ||
| } | ||
| /// <summary> | ||
| /// Returns true if the global eager baseline <see cref="ReadyToRunFixupKind.Check_InstructionSetSupport"/> | ||
| /// fixup does not assert that any instruction set must be absent at runtime ("must be absent" entries render | ||
| /// with a <c>-</c> suffix; supported entries use <c>+</c>). Targets that cannot generate code at runtime must | ||
| /// not encode these assertions, as a failing eager fixup fatally disables all ReadyToRun code with no JIT fallback. | ||
| /// </summary> | ||
kotlarmilos marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| public static bool EagerInstructionSetSupportHasNoUnsupportedEntries(ReadyToRunReader reader, out string diagnostic) | ||
| { | ||
| var options = new SignatureFormattingOptions(); | ||
| var signatures = new List<string>(); | ||
| foreach (ReadyToRunImportSection section in reader.ImportSections) | ||
| { | ||
| if (section.Entries is null) | ||
| continue; | ||
kotlarmilos marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| foreach (ReadyToRunImportSection.ImportSectionEntry entry in section.Entries) | ||
| { | ||
| if (entry.Signature is not null && entry.Signature.FixupKind == ReadyToRunFixupKind.Check_InstructionSetSupport) | ||
| signatures.Add(entry.Signature.ToString(options)); | ||
| } | ||
| } | ||
| if (signatures.Count == 0) | ||
| { | ||
| diagnostic = "Expected a global Check_InstructionSetSupport eager fixup, but none was found."; | ||
| return false; | ||
| } | ||
| var withUnsupported = signatures.Where(s => s.Contains('-')).ToList(); | ||
| if (withUnsupported.Count > 0) | ||
| { | ||
| diagnostic = | ||
| "Global Check_InstructionSetSupport fixup must not assert any instruction set is absent " + | ||
| $"on no-JIT targets, but found: [{string.Join(", ", withUnsupported)}]"; | ||
| return false; | ||
| } | ||
| diagnostic = $"Global Check_InstructionSetSupport fixup asserts only supported instruction sets: [{string.Join(", ", signatures)}]"; | ||
| return true; | ||
| } | ||
| /// <summary> | ||
| /// Returns true if the R2R image contains at least one fixup of the given kind. | ||
| /// </summary> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -382,8 +382,11 @@ internal ReadyToRunCodegenCompilation( | ||
| CompilationModuleGroup = (ReadyToRunCompilationModuleGroupBase)nodeFactory.CompilationModuleGroup; | ||
| // Generate baseline support specification for InstructionSetSupport. This will prevent usage of the generated | ||
| // code if the runtime environment doesn't support the specified instruction set | ||
| string instructionSetSupportString = ReadyToRunInstructionSetSupportSignature.ToInstructionSetSupportString(instructionSetSupport); | ||
| // code if the runtime environment doesn't support the specified instruction set. Targets that cannot generate | ||
| // code at runtime must not encode "must be absent" assertions, since a failing eager fixup is a fatal startup | ||
| // error with no JIT fallback (see ToInstructionSetSupportString). | ||
kotlarmilos marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| bool targetAllowsRuntimeCodeGeneration = ((ReadyToRunCompilerContext)nodeFactory.TypeSystemContext).TargetAllowsRuntimeCodeGeneration; | ||
| string instructionSetSupportString = ReadyToRunInstructionSetSupportSignature.ToInstructionSetSupportString(instructionSetSupport, emitExplicitlyUnsupported: targetAllowsRuntimeCodeGeneration); | ||
| ReadyToRunInstructionSetSupportSignature instructionSetSupportSig = new ReadyToRunInstructionSetSupportSignature(instructionSetSupportString); | ||
| _dependencyGraph.AddRoot(new Import(NodeFactory.EagerImports, instructionSetSupportSig), "Baseline instruction set support"); | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.