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

Fix for bugs related to clasifying System.TypedReference - issue #2854. #2860

Merged
merged 1 commit into from
Feb 2, 2016

Conversation

LLITCHEV
Copy link

It was a long standing assumption in the Jit that a field of a struct can
never be of ByRef type. It turns out this assumption is not entirely
holding.
The System.TypedReference is a very special type that is a struct, defined
to have two IntPtr fields. When the VM instantiates this type it changes
the type of the first field to ByRef.
This change closes a GC hole in the passing this struct by value on the
stack. It adds support to the classification algorithm for ByRef
references. It also uses the tree types for generating the code that
places struct field on the stack by value for passin to a callee.

@LLITCHEV
Copy link
Author

test OSX x64 Release Build and Test please

@LLITCHEV
Copy link
Author

@jkotas @janvorli @sivarv PTAL
/cc @dotnet/jit-contrib

@@ -276,12 +276,14 @@ enum SystemVClassificationType : unsigned __int8
SystemVClassificationTypeMemory = 3,
SystemVClassificationTypeInteger = 4,
SystemVClassificationTypeIntegerReference = 5,
SystemVClassificationTypeSSE = 6,
SystemVClassificationTypeIntegerByReference = 6,

Choose a reason for hiding this comment

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

Minor point - but I think these names confusing. It sounds like it's describing a integer being passed by reference. Also, "byref" is a specific term used in the CLI and so it would be more accurate to use that term. I think it should really be ByRefAsInteger (and the previous one "ReferenceAsInteger"), but at least change "ByReference" to "ByRef".

@LLITCHEV
Copy link
Author

Comments addressed. PTAL.

(structDesc.eightByteClassifications[slotCounter] == SystemVClassificationTypeIntegerReference))) ||
(doingFloat && structDesc.eightByteClassifications[slotCounter] == SystemVClassificationTypeSSE))
if ((!doingFloat && (structDesc.IsIntegralSlot(slotCounter))) ||
(doingFloat && (structDesc.IsSseSlot(slotCounter))))
{

Choose a reason for hiding this comment

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

Such an improvement in readability - thanks!

@CarolEidt
Copy link

Aside from the genGet vs. getGet question above, LGTM

// Internal flags - never returned outside of the classification implementation.

// This value represents a very special type with two eightbytes.
// First ByRef, secont Integer (platform int).
Copy link
Member

Choose a reason for hiding this comment

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

Typo - "second"

Suggestion: "First field is of type ByRef and second field an IntPtr"

Copy link
Author

Choose a reason for hiding this comment

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

Fixed.

@LLITCHEV
Copy link
Author

@CarolEidt @sivarv PTAL

@@ -1412,6 +1412,221 @@ void CodeGen::genCodeForBinary(GenTree* treeNode)
genProduceReg(treeNode);
}

// Deals with codegen for muti-register struct returns.

Choose a reason for hiding this comment

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

These methods lack function headers.

Choose a reason for hiding this comment

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

Also, could you add a line not to indicate what has changed? It is difficult to tell now that you have extracted this functionality into a separate method (a good thing to do, but also one of the reasons it is usually prudent to separate refactoring changes from functional changes).

@LLITCHEV
Copy link
Author

LLITCHEV commented Feb 1, 2016

@CarolEidt Good catch. Added function headers and added a comment in the PR description describing the genReturn related refactoring.

void getStructReturnRegisters(var_types type0,
var_types type1,
regNumber* retRegPtr0,
regNumber* retRegPtr1);
Copy link
Member

Choose a reason for hiding this comment

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

Nit: formatting of the above 3 params not aligned with the first one.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed.

@LLITCHEV
Copy link
Author

LLITCHEV commented Feb 1, 2016

@CarolEidt @sivarv PTAL the latest changes.

@sivarv
Copy link
Member

sivarv commented Feb 1, 2016

Looks good.

getEmitter()->emitIns_R_S(ins_Load(type1), emitTypeSize(type1), retReg1, lclVarPtr->gtLclNum, offset1);
}

// Nothing to do if the op1 of the return statement is a GT_CALL. The call already has the return

Choose a reason for hiding this comment

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

Please add a comment here indicating that we are assuming that the registers will not be spilled or moved, and reference the newly created issue that will ensure correct codegen even in the presence of stress modes or other unforeseen changes.

@CarolEidt
Copy link

LGTM if you add the comment I suggest to refer to issue #2966

It was a long standing assumption in the Jit that a field of a struct can
never be of ByRef type. It turns out this assumption is not entirely
holding.
The System.TypedReference is a very special type that is a struct, defined
to have two IntPtr fields. When the VM instantiates this type it changes
the type of the first field to ByRef.
This change closes a GC hole in the passing this struct by value on the
stack. It adds support to the classification algorithm for ByRef
references. It also uses the tree types for generating the code that
places struct field on the stack by value for passin to a callee.

The handling of GT_RETURN in the codegenxarch.cpp has been extracted as a
separate routine - genReturn. In case of struct return (multi-register
struct return or an implicit retBuf return, it delegates to the
genStructReturn method. This is a refactoring as well as making
sure that GT_RETFILT is handled properly - the return type of it is always
bool or void for the last statement of a finally block.

More feedback addressed.
@LLITCHEV
Copy link
Author

LLITCHEV commented Feb 2, 2016

@dotnet-bot OSX x64 Checked Build and Test

@LLITCHEV
Copy link
Author

LLITCHEV commented Feb 2, 2016

@dotnet-bot test OSX x64 Checked Build and Test

@LLITCHEV
Copy link
Author

LLITCHEV commented Feb 2, 2016

@dotnet-bot test Ubuntu x64 Checked Build and Test

3 similar comments
@LLITCHEV
Copy link
Author

LLITCHEV commented Feb 2, 2016

@dotnet-bot test Ubuntu x64 Checked Build and Test

@LLITCHEV
Copy link
Author

LLITCHEV commented Feb 2, 2016

@dotnet-bot test Ubuntu x64 Checked Build and Test

@LLITCHEV
Copy link
Author

LLITCHEV commented Feb 2, 2016

@dotnet-bot test Ubuntu x64 Checked Build and Test

@LLITCHEV
Copy link
Author

LLITCHEV commented Feb 2, 2016

@dotnet-bot test Ubuntu x64 Checked Build and Test

LLITCHEV added a commit that referenced this pull request Feb 2, 2016
Fix for bugs related to clasifying System.TypedReference - issue #2854.
@LLITCHEV LLITCHEV merged commit 5472176 into dotnet:master Feb 2, 2016
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.

5 participants