Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

JIT: preliminaries to improve types #10172

Merged
merged 2 commits into from
Mar 15, 2017

Conversation

AndyAyersMS
Copy link
Member

Refactor the logic in impDevirtualizeCall so that the part that determines
the type of a tree for ref types is now a new utility method that can be called
elsewhere.

Update the utility to examine calls more closely. For inline candidates that
return shared types, try and use the context to get to the unshared version of the
type. For calls that are not inline candidates, look at the type in the signature
available to the jit w/o context.

Call the utility when we've created a temp for an inlinee's argument and the
argument is not modified in the inlinee body. If we already thought we knew the
type of the temp exactly, ensure that this new information agrees.

Rework the logic in impDevirtualizeCall in anticipation of interface call
devirtualization. Update the diagnostic stream to indicate the kind of call
devirtualized nd the primary reason why devirtualization happened.
Avoid fetching class and method names unless they're going to be used. Likewise
try not to fetch attributes if we already have them on hand.

Refactor the logic in `impDevirtualizeCall` so that the part that determines
the type of a tree for ref types is now a new utility method that can be called
elsewhere.

Update the utility to examine calls more closely. For inline candidates that
return shared types, try and use the context to get to the unshared version of the
type. For calls that are not inline candidates, look at the type in the signature
available to the jit w/o context.

Call the utility when we've created a temp for an inlinee's argument and the
argument is not modified in the inlinee body. If we already thought we knew the
type of the temp exactly, ensure that this new information agrees.

Rework the logic in `impDevirtualizeCall` in anticipation of interface call
devirtualization. Update the diagnostic stream to indicate the kind of call
devirtualized nd the primary reason why devirtualization happened.
Avoid fetching class and method names unless they're going to be used. Likewise
try not to fetch attributes if we already have them on hand.
@AndyAyersMS
Copy link
Member Author

@JosephTremoulet PTAL
cc @dotnet/jit-contrib

Impacts about 80 methods in the jit-diff set. Has more impact when jitting, since many interesting shared methods are not inline candidates in R2R mode.

For instance when jitting we can now devirtualize a call whose object is the result the List.get_Item.

Copy link

@JosephTremoulet JosephTremoulet left a comment

Choose a reason for hiding this comment

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

LGTM modulo a few comments/questions.

if (lvaTable[tmpNum].lvClassIsExact)
{
assert(isExact);
assert(refClassHandle == lvaTable[tmpNum].lvClassHnd);

Choose a reason for hiding this comment

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

How do we know the new info won't be compatible but less precise than the old info?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is a bit of future proofing.

Currently the argument temps -- created over in impInlineFetchArg -- don't get any class/exact info. If/when they do, we will type them based on the method signature.

Any correct program will pass an argument value with the signature type or some subtype. So the argument type should be as good or better a bound on the type than the signature type.

In the update case, it might be worth checking for proper subtype relationship here, though if we somehow "downgrade" the type to a superclass, we still have a safeguard in the VM side of devirtualization, which also does this check.

// otherwise the class handle.
// isExact set true if tree type is known to be exactly the handle type,
// otherwise actual type may be a subtype.
// isNonNull set truee if tree value is known not to be null,

Choose a reason for hiding this comment

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

typo: truee -> true

CORINFO_CLASS_HANDLE objClass = gtGetClassHandle(thisObj, &isExact, &objIsNonNull);

// Bail if we know nothing.
if (objClass == nullptr)

Choose a reason for hiding this comment

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

How common is this case? Worth moving the check up to before fetching baseClass/baseClassAttribs?

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes sense to reorder and check for objType first, since we only get a type maybe 50% of the time. Will update.

// Bail if devirt is disabled.
if (JitConfig.JitEnableDevirtualization() == 0)
{
return;
}

const bool doPrint = JitConfig.JitPrintDevirtualizedMethods() == 1;

Choose a reason for hiding this comment

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

I'm confused what you're trying to achieve with doPrint in release builds here... looks like you only fill in the info strings under #if DEBUG, so release would just print the placeholders and the only info you really get is the total number of devirtualized calls per kind, right? If we're going to want that information from release builds, would it be better to fire an ETW event or something?

Copy link
Member Author

Choose a reason for hiding this comment

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

doPrint only exists in DEBUG. There is no release mode diagnostic stream for devirtualization.

Not sure if devirtualization warrants an VM/ETW callback/event. Inlining needs it because other runtime subsystems are sensitive to inlining -- for instance rejitting needs to know what methods have been inlined.

If we do add a notification mechanism it will traffic only in handles and string literals to avoid any need for dynamic string allocation.

Choose a reason for hiding this comment

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

Right, thanks, I was just misreading the code there, I like it how you have it.

// Bail if devirt is disabled.
if (JitConfig.JitEnableDevirtualization() == 0)
{
return;
}

const bool doPrint = JitConfig.JitPrintDevirtualizedMethods() == 1;

Choose a reason for hiding this comment

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

Right, thanks, I was just misreading the code there, I like it how you have it.

@AndyAyersMS
Copy link
Member Author

Pushed an update that fixes the typo and reorders the checks -- also fixed a dump mode AV and tweaked dump mode formatting a bit.

@AndyAyersMS
Copy link
Member Author

Windows debug timed out in one of the chaos tests -- can't repro locally, so am going to retry.

@dotnet-bot retest Windows_NT x64 Debug Build and Test

@AndyAyersMS
Copy link
Member Author

OSX failure is a known issue, so will ignore it.

@AndyAyersMS AndyAyersMS merged commit 3ea5447 into dotnet:master Mar 15, 2017
jorive pushed a commit to guhuro/coreclr that referenced this pull request May 4, 2017
Refactor the logic in `impDevirtualizeCall` so that the part that determines
the type of a tree for ref types is now a new utility method that can be called
elsewhere.

Update the utility to examine calls more closely. For inline candidates that
return shared types, try and use the context to get to the unshared version of the
type. For calls that are not inline candidates, look at the type in the signature
available to the jit w/o context.

Call the utility when we've created a temp for an inlinee's argument and the
argument is not modified in the inlinee body. If we already thought we knew the
type of the temp exactly, ensure that this new information agrees.

Rework the logic in `impDevirtualizeCall` in anticipation of interface call
devirtualization. Update the diagnostic stream to indicate the kind of call
devirtualized and the primary reason why devirtualization happened.
Avoid fetching class and method names unless they're going to be used. Likewise
try not to fetch attributes if we already have them on hand.
@karelz karelz modified the milestone: 2.0.0 Aug 28, 2017
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.

4 participants