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

Mark instance method bodies lazily #502

Merged

Conversation

mrvoorhe
Copy link
Contributor

Instance method bodies do not need to be marked until an instance of the type could exist. Any instance methods that were marked on types that are never instantiated will be converted to a throw.

  • A number of existing tests needed to be updated to avoid lazy body marking

  • Add a new CodeOptimization to allow disabling this mechanism. Reasoning was, (1) it's simple to support an option. (2) It may be helpful if it causes problems. (3) I could see using this option to make writing certain tests easier.

  • Marking of some small bodies will not be deferred. The idea is that the size cost of some methods is less than converting them to a throw. So we might as well leave them alone. See IsWorthConvertingToThrow

  • Factored out MarkAndCacheNotSupportedCtorString since I need to call it from multiple places now.

  • Expose the RewriteBody* methods in CodeRewriterStep for overriding. A few motivations for this. (1) We have a runtime that doesn't support exceptions. When we target that runtime we will need to override ConvertToThrow with something else. (2) I will likely override all of the RewriteBody* methods so that I can record which bodies are changed and hook it up to logging mechanisms that we have.

Note. This PR has a test that depends on #501 . That PR will need to land first and I will need to rebase after that lands. There will be 1 failing test until that happens.

@mrvoorhe mrvoorhe requested a review from marek-safar as a code owner March 22, 2019 17:25
@mrvoorhe mrvoorhe force-pushed the master-lazy-body-marking branch from f5ed424 to b5d68bd Compare March 22, 2019 19:57
@mrvoorhe
Copy link
Contributor Author

Rebased and should be ready to go pending CI results 🤞

src/linker/Linker.Steps/MarkStep.cs Outdated Show resolved Hide resolved
src/linker/Linker.Steps/MarkStep.cs Outdated Show resolved Hide resolved
src/linker/Linker.Steps/MarkStep.cs Outdated Show resolved Hide resolved
src/linker/Linker.Steps/MarkStep.cs Outdated Show resolved Hide resolved
src/linker/Linker/Driver.cs Outdated Show resolved Hide resolved
@marek-safar
Copy link
Contributor

marek-safar commented Apr 11, 2019

Did you forget to push the changes ;-)

@mrvoorhe mrvoorhe force-pushed the master-lazy-body-marking branch from b5d68bd to 084aaee Compare April 11, 2019 13:13
@mrvoorhe
Copy link
Contributor Author

mrvoorhe commented Apr 11, 2019

Did you forget to push the changes ;-)

I didn't finish making all of the changes before I had to go.

All changes are done and pushed now.

@mrvoorhe
Copy link
Contributor Author

I'm looking into the test failures with illink

@mrvoorhe mrvoorhe force-pushed the master-lazy-body-marking branch 3 times, most recently from 81ffabd to e33d11c Compare April 11, 2019 14:39
@mrvoorhe
Copy link
Contributor Author

I refactored IsWorthConvertingToThrow a bit to handle noop. A bunch of unrelated tests were failing during the illink build because roslyn likes to write empty methods as

noop
ret

I can't get the .net core tests running locally. Hopefully everything is fixed now, but I'll have to wait for CI to finish to know for certain.

@mrvoorhe mrvoorhe force-pushed the master-lazy-body-marking branch from e33d11c to d8b743a Compare April 11, 2019 15:23
@@ -71,6 +71,10 @@ public static TypeDefinition FindPredefinedType (string ns, string name, LinkCon
if (cache.TryGetValue ("System.Private.CoreLib", out corlib))
return corlib.MainModule.GetType (ns, name);

// System.NotSupportedException lives here on .netcore
Copy link
Contributor Author

Choose a reason for hiding this comment

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

fyi, I had to add this so that System.NotSupportedException could be found. This could become a tedious pattern to maintain

@mrvoorhe
Copy link
Contributor Author

@sbomer BCL.FindPredefinedType can't find System.NotSupportedException on .netcore. Any idea how I should locate that type?

I tried adding

// System.NotSupportedException lives here on .netcore
			if (cache.TryGetValue ("System.Runtime", out corlib))
				return corlib.MainModule.GetType (ns, name);

To FindPredefinedType but that didn't work.

I can't get the .netcore tests working locally so that's making iterating on this challenging.

@mrvoorhe mrvoorhe force-pushed the master-lazy-body-marking branch from d8b743a to 05b3ace Compare April 11, 2019 16:39
@sbomer
Copy link
Member

sbomer commented Apr 11, 2019

@mrvoorhe I can take a look. Could you try running the tests locally on core using ./eng/dotnet.sh test illink.sln and let me know if you have any issues?

@sbomer
Copy link
Member

sbomer commented Apr 11, 2019

Also, it looks like System.NotSupportedException in System.Runtime is just a type forwarder to System.Private.CoreLib. I'm not sure why it wouldn't have been found in SPC in the first place.

@sbomer
Copy link
Member

sbomer commented Apr 11, 2019

Switching System.Runtime -> System.Private.CoreLib in FindPredefinedType fixes at least some of the test failures when I run locally (I haven't run them all yet). I'm not sure though exactly what the intention of FindPredefinedType is or why it wouldn't work with type forwarders. If it's just to resolve a set of types that we assume are present in some particular assembly for the linker to work, then it seems like hard-coding System.PrivateCoreLib might be ok. Maybe we could use a define for the target's core library similar to https://github.com/mono/linker/blob/31555535b160c1de7ba72fd7c51ec584ef395fdb/test/Mono.Linker.Tests.Cases.Expectations/Support/PlatformAssemblies.cs?

@mrvoorhe mrvoorhe force-pushed the master-lazy-body-marking branch from 05b3ace to 35dcf49 Compare April 11, 2019 17:06
@mrvoorhe
Copy link
Contributor Author

mrvoorhe commented Apr 11, 2019

@sbomer How can I debug this? I tried what you said and I can reproduce the failure locally. However, Rider EAP and VS 2019 are not happy with illink.sln and I tried to do some Console.WriteLine debugging but it looks like dotnet.sh test illink.sln is doing something other than let stdout go to the console

@mrvoorhe
Copy link
Contributor Author

I think I know what the issue is now. The test that is failing is an IL test.

That said, I would still like some pro tips on how to debug individual tests on .netcore for future reference

Instance method bodies do not need to be marked until an instance of the type could exist.

* Add MethodConvertedToThrow callback

* Update link xml preserve test expected behavior
@mrvoorhe mrvoorhe force-pushed the master-lazy-body-marking branch from 35dcf49 to 727ccb7 Compare April 11, 2019 17:43
@sbomer
Copy link
Member

sbomer commented Apr 11, 2019

#471 may help with IDE support for the .sln, but I'm not sure. I've had lots of issues with tooling support for projects that mix configurations/targetframeworks and projectreferences. Sorry it's causing you trouble.

For debugging, I've been using VS code. Here's the best way I've found to do it so far:

  • Add this to the linker somewhere:
    while (!System.Diagnostics.Debugger.IsAttached)
        System.Threading.Thread.Sleep(500)
    
  • Set breakpoints
  • Run an individual test:
    ./eng/dotnet.sh test illink.sln --filter TestCaseName
    
    (See https://github.com/Microsoft/vstest-docs/blob/master/docs/filter.md for some docs on the filter expression)
  • Wait for it to hit the while loop above, and attach to testhost.dll.

@mrvoorhe
Copy link
Contributor Author

@marek-safar Good to go!

@alexanderkyte
Copy link

This has been shown to regress the mono harness when mono is bumped to this commit.

@mrvoorhe
Copy link
Contributor Author

@alexanderkyte Can you investigate a bit? If any types are created from native and do not get an instance .ctor marked it will cause problems. If this is the case it is not necessarily a problem with these changes. Instead the fix is to properly annotate w/e instance .ctor is needed by the type.

It's certainly possible there is a bug with these changes, but I'd prefer to rule out the above before making any changes to disable this.

@alexanderkyte
Copy link

@mrvoorhe I have a PR testing whether disabling the unreachablebodies optimization will fix the build. If so, I will triage what breaks when we enable the optimization. That way we can make use of other changes to the linker while we get unreachablebodies working separately.

tkapin pushed a commit to tkapin/runtime that referenced this pull request Jan 31, 2023
Instance method bodies do not need to be marked until an instance of the type could exist.  Any instance methods that were marked on types that are never instantiated will be converted to a throw.

* A number of existing tests needed to be updated to avoid lazy body marking

* Add a new CodeOptimization to allow disabling this mechanism.  Reasoning was, (1) it's simple to support an option.  (2) It may be helpful if it causes problems. (3) I could see using this option to make writing certain tests easier.

* Marking of some small bodies will not be deferred.  The idea is that the size cost of some methods is less than converting them to a throw.  So we might as well leave them alone.  See `IsWorthConvertingToThrow`

* Factored out `MarkAndCacheNotSupportedCtorString` since I need to call it from multiple places now.

* Expose the `RewriteBody*` methods in CodeRewriterStep for overriding.  A few motivations for this. (1) We have a runtime that doesn't support exceptions.  When we target that runtime we will need to override `ConvertToThrow` with something else.  (2) I will likely override all of the `RewriteBody*` methods so that I can record which bodies are changed and hook it up to logging mechanisms that we have.

Note.  This PR has a test that depends on dotnet/linker#501 .  That PR will need to land first and I will need to rebase after that lands.  There will be 1 failing test until that happens.


Commit migrated from dotnet/linker@e9ed848
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.

4 participants