Skip to content

Kill a non-gc-type lclVar if it has a gc-type value#679

Merged
CarolEidt merged 5 commits intodotnet:masterfrom
CarolEidt:FixKillGCRef
Dec 11, 2019
Merged

Kill a non-gc-type lclVar if it has a gc-type value#679
CarolEidt merged 5 commits intodotnet:masterfrom
CarolEidt:FixKillGCRef

Conversation

@CarolEidt
Copy link
Contributor

No description provided.

@CarolEidt
Copy link
Contributor Author

This was exposed by the EH Write-thru work. It is a rare case where we have a re-typed lclVar that is live at a pinvoke. In the current JIT, the case where this occurred involved an EH-exposed lclVar, so it was not a register candidate.

@CarolEidt
Copy link
Contributor Author

@dotnet/jit-contrib PTAL

@CarolEidt CarolEidt closed this Dec 9, 2019
@CarolEidt CarolEidt reopened this Dec 9, 2019
// The importer will assign a GC type to the rhs of an assignment if the lhs type is a GC type,
// even if the rhs is not. See the CEE_STLOC* case in impImportBlockCode(). As a result,
// we can have an integer type lclVar that behaves as a GC type. In that case we need to
// kill the local.
Copy link
Contributor

Choose a reason for hiding this comment

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

In that case we need to kill the local

Why? Ideally comments should explain why something is done, not that it's supposed to be done.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is because 1) we can't have any gc refs in registers (even callee-saves) during a pinvoke, 2) the emitter will mark the register as having a GC type if the node has a GC type, and 3) then the code generator asserts that there are no GC types in registers (even callee-save) at the pinvoke prolog.

I'll expand the comment - also it probably should say "spill" the local, even though the code describes it as "killing" gc refs.

@sandreenko sandreenko added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Dec 9, 2019
// The importer will assign a GC type to the rhs of an assignment if the lhs type is a GC type,
// even if the rhs is not. See the CEE_STLOC* case in impImportBlockCode(). As a result,
// we can have an integer type lclVar that behaves as a GC type. In that case we need to
// kill the local.
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to kill that local because GC will try to add that address as alive or because its value won't be correct after whatever we are spilling for?
Can we improve that and do not spill such locals?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need to spill (not really "kill") the local because we don't support GC refs in registers for unmanaged calls. I think that we could possibly improve the handling of stack references, because even though the address of stack locals is generally marked as a byref, we don't really have to report it to the GC if we know it's on the stack. That said, this case is rare enough (I don't think it can be done in C#) that I'm not sure it's worth optimizing for.

@AndyAyersMS
Copy link
Member

Is this the importer code you're referring to?

// The code generator generates GC tracking information
// based on the RHS of the assignment. Later the LHS (which is
// is a BYREF) gets used and the emitter checks that that variable
// is being tracked. It is not (since the RHS was an int and did
// not need tracking). To keep this assert happy, we change the RHS
if (lclTyp == TYP_BYREF && !varTypeIsGC(op1->gtType))
{
op1->gtType = TYP_BYREF;
}

Do you have a motivating test case you can add?

@CarolEidt
Copy link
Contributor Author

@AndyAyersMS - Yes, that's the importer code I was referring to. And I didn't spend a lot of time, but was unable to come up with a test case for this. It caused a failure in a test case on arm32 with my EH write-thru changes.

continue;
}
unassignPhysReg(regRecord, assignedInterval->recentRefPosition);
bool needsKill = varTypeIsGC(assignedInterval->registerType);
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like I am missing something, the prev line has:

if (!varTypeIsGC(assignedInterval->registerType)))
  continue;

varTypeIsGC(assignedInterval->registerType)) is always true after that, means:

bool needsKill = varTypeIsGC(assignedInterval->registerType); always true.
if (!needsKill) always false, so the code and the comment under that block is never executed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That was a mistake in extracting the fix from my EHWriteThru branch to this one. Thanks for catching that!

Copy link
Contributor

@sandreenko sandreenko left a comment

Choose a reason for hiding this comment

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

LGTM

// even if the rhs is not. See the CEE_STLOC* case in impImportBlockCode(). As a result,
// we can have a 'GT_LCL_VAR' node with a GC type, when the lclVar itself is an integer type.
// The emitter will mark this register as holding a GC type. Therfore we must spill this value.
// This was exposed by the Interop\StructMarshalling\ReversePInvoke\MarshalSeqStruct\
Copy link
Contributor

Choose a reason for hiding this comment

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

// This was exposed by

Nit: I believe that including an exposing test reference in source code is not a common practice. I would leave that in the PR, so people can find that PR (by running git blame/annotate) and find the test reference here if they ever need it.

@CarolEidt CarolEidt merged commit f08b853 into dotnet:master Dec 11, 2019
@CarolEidt CarolEidt deleted the FixKillGCRef branch December 27, 2019 17:25
@ghost ghost locked as resolved and limited conversation to collaborators Dec 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants