Skip to content

Commit 43c5724

Browse files
committed
Merge branch 'main' of github.com:dotnet/runtime into boxed-statics-foh
2 parents c92a6c3 + cc712fd commit 43c5724

File tree

15 files changed

+106
-227
lines changed

15 files changed

+106
-227
lines changed

docs/deep-dive-blog-posts.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
- [Performance improvements in .NET Core 3.0](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/)
99
- [Performance improvements in .NET 5](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-5/)
1010
- [Performance improvements in .NET 6](https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-6/)
11-
11+
- [Performance improvements in .NET 7](https://devblogs.microsoft.com/dotnet/performance_improvements_in_net_7/)
1212

1313
### Posts that take a high-level look at the entire source:
1414

src/coreclr/System.Private.CoreLib/src/System/Reflection/MdFieldInfo.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ o is MdFieldInfo m &&
4646

4747
public override bool Equals(object? obj) =>
4848
ReferenceEquals(this, obj) ||
49-
(MetadataUpdater.IsSupported && CacheEquals(obj));
49+
(MetadataUpdater.IsSupported &&
50+
obj is MdFieldInfo fi &&
51+
fi.m_tkField == m_tkField &&
52+
ReferenceEquals(fi.m_declaringType, m_declaringType) &&
53+
ReferenceEquals(fi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType()));
5054

5155
public override int GetHashCode() =>
5256
HashCode.Combine(m_tkField.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());

src/coreclr/System.Private.CoreLib/src/System/Reflection/RtFieldInfo.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,10 @@ internal override RuntimeModule GetRuntimeModule()
118118

119119
public override bool Equals(object? obj) =>
120120
ReferenceEquals(this, obj) ||
121-
(MetadataUpdater.IsSupported && CacheEquals(obj));
121+
(MetadataUpdater.IsSupported &&
122+
obj is RtFieldInfo fi &&
123+
fi.m_fieldHandle == m_fieldHandle &&
124+
ReferenceEquals(fi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType()));
122125

123126
public override int GetHashCode() =>
124127
HashCode.Combine(m_fieldHandle.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());

src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeEventInfo.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,11 @@ public override string ToString()
7171

7272
public override bool Equals(object? obj) =>
7373
ReferenceEquals(this, obj) ||
74-
(MetadataUpdater.IsSupported && CacheEquals(obj));
74+
(MetadataUpdater.IsSupported &&
75+
obj is RuntimeEventInfo ei &&
76+
ei.m_token == m_token &&
77+
ReferenceEquals(ei.m_declaringType, m_declaringType) &&
78+
ReferenceEquals(ei.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType()));
7579

7680
public override int GetHashCode() =>
7781
HashCode.Combine(m_token.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());

src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,10 @@ public override IList<CustomAttributeData> GetCustomAttributesData()
182182

183183
public override bool Equals(object? obj) =>
184184
ReferenceEquals(this, obj) ||
185-
(MetadataUpdater.IsSupported && CacheEquals(obj));
185+
(MetadataUpdater.IsSupported && obj is RuntimePropertyInfo rpi &&
186+
rpi.m_token == m_token &&
187+
ReferenceEquals(rpi.m_declaringType, m_declaringType) &&
188+
ReferenceEquals(rpi.m_reflectedTypeCache.GetRuntimeType(), m_reflectedTypeCache.GetRuntimeType()));
186189

187190
public override int GetHashCode() =>
188191
HashCode.Combine(m_token.GetHashCode(), m_declaringType.GetUnderlyingNativeHandle().GetHashCode());

src/coreclr/jit/compiler.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5783,7 +5783,6 @@ class Compiler
57835783
GenTree* fgMorphLeaf(GenTree* tree);
57845784
GenTree* fgMorphOneAsgBlockOp(GenTree* tree);
57855785
GenTree* fgMorphInitBlock(GenTree* tree);
5786-
GenTree* fgMorphBlockOperand(GenTree* tree, var_types asgType, ClassLayout* blockLayout, bool isBlkReqd);
57875786
GenTree* fgMorphCopyBlock(GenTree* tree);
57885787
GenTree* fgMorphStoreDynBlock(GenTreeStoreDynBlk* tree);
57895788
GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optAssertionPropDone = nullptr);

src/coreclr/jit/morph.cpp

Lines changed: 6 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -8700,150 +8700,6 @@ GenTree* Compiler::fgMorphOneAsgBlockOp(GenTree* tree)
87008700
return tree;
87018701
}
87028702

8703-
//------------------------------------------------------------------------
8704-
// fgMorphBlockOperand: Canonicalize an operand of a block assignment
8705-
//
8706-
// Arguments:
8707-
// tree - The block operand
8708-
// asgType - The type of the assignment
8709-
// blockLayout - The struct layout of the block (for STRUCT "asgType"s)
8710-
// isBlkReqd - true iff this operand must remain a block node
8711-
//
8712-
// Return Value:
8713-
// Returns the morphed block operand
8714-
//
8715-
// Notes:
8716-
// This does the following:
8717-
// - Ensures that a struct operand is a block node or lclVar.
8718-
// - Ensures that any COMMAs are above ADDR nodes.
8719-
// Although 'tree' WAS an operand of a block assignment, the assignment
8720-
// may have been retyped to be a scalar assignment.
8721-
//
8722-
GenTree* Compiler::fgMorphBlockOperand(GenTree* tree, var_types asgType, ClassLayout* blockLayout, bool isBlkReqd)
8723-
{
8724-
GenTree* effectiveVal = tree->gtEffectiveVal();
8725-
8726-
if (asgType != TYP_STRUCT)
8727-
{
8728-
unsigned blockWidth = genTypeSize(asgType);
8729-
8730-
if (effectiveVal->OperIsIndir())
8731-
{
8732-
if (!isBlkReqd)
8733-
{
8734-
GenTree* addr = effectiveVal->AsIndir()->Addr();
8735-
if ((addr->OperGet() == GT_ADDR) && (addr->gtGetOp1()->TypeGet() == asgType))
8736-
{
8737-
effectiveVal = addr->gtGetOp1();
8738-
}
8739-
else if (effectiveVal->OperIsBlk())
8740-
{
8741-
effectiveVal->SetOper(GT_IND);
8742-
}
8743-
}
8744-
effectiveVal->gtType = asgType;
8745-
}
8746-
else if (effectiveVal->TypeGet() != asgType)
8747-
{
8748-
if (effectiveVal->IsCall())
8749-
{
8750-
#ifdef DEBUG
8751-
GenTreeCall* call = effectiveVal->AsCall();
8752-
assert(call->TypeGet() == TYP_STRUCT);
8753-
assert(blockWidth == info.compCompHnd->getClassSize(call->gtRetClsHnd));
8754-
#endif
8755-
}
8756-
else
8757-
{
8758-
GenTree* addr = gtNewOperNode(GT_ADDR, TYP_BYREF, effectiveVal);
8759-
effectiveVal = gtNewIndir(asgType, addr);
8760-
}
8761-
}
8762-
}
8763-
else
8764-
{
8765-
assert(blockLayout != nullptr);
8766-
8767-
GenTreeIndir* indirTree = nullptr;
8768-
GenTreeLclVarCommon* lclNode = nullptr;
8769-
bool needsIndirection = true;
8770-
8771-
if (effectiveVal->OperIsIndir())
8772-
{
8773-
indirTree = effectiveVal->AsIndir();
8774-
GenTree* addr = effectiveVal->AsIndir()->Addr();
8775-
if ((addr->OperGet() == GT_ADDR) && (addr->gtGetOp1()->OperGet() == GT_LCL_VAR))
8776-
{
8777-
lclNode = addr->gtGetOp1()->AsLclVarCommon();
8778-
}
8779-
}
8780-
else if (effectiveVal->OperGet() == GT_LCL_VAR)
8781-
{
8782-
lclNode = effectiveVal->AsLclVarCommon();
8783-
}
8784-
else if (effectiveVal->OperIs(GT_LCL_FLD))
8785-
{
8786-
needsIndirection = false;
8787-
assert(ClassLayout::AreCompatible(effectiveVal->AsLclFld()->GetLayout(), blockLayout));
8788-
}
8789-
else if (effectiveVal->IsCall())
8790-
{
8791-
needsIndirection = false;
8792-
#ifdef DEBUG
8793-
GenTreeCall* call = effectiveVal->AsCall();
8794-
assert(call->TypeGet() == TYP_STRUCT);
8795-
assert(blockLayout->GetSize() == info.compCompHnd->getClassSize(call->gtRetClsHnd));
8796-
#endif
8797-
}
8798-
#ifdef TARGET_ARM64
8799-
else if (effectiveVal->OperIsHWIntrinsic())
8800-
{
8801-
needsIndirection = false;
8802-
#ifdef DEBUG
8803-
GenTreeHWIntrinsic* intrinsic = effectiveVal->AsHWIntrinsic();
8804-
assert(intrinsic->TypeGet() == TYP_STRUCT);
8805-
assert(HWIntrinsicInfo::IsMultiReg(intrinsic->GetHWIntrinsicId()));
8806-
#endif
8807-
}
8808-
#endif // TARGET_ARM64
8809-
8810-
if (lclNode != nullptr)
8811-
{
8812-
const LclVarDsc* varDsc = lvaGetDesc(lclNode);
8813-
if (varTypeIsStruct(varDsc) && ClassLayout::AreCompatible(varDsc->GetLayout(), blockLayout))
8814-
{
8815-
if (effectiveVal != lclNode)
8816-
{
8817-
JITDUMP("Replacing block node [%06d] with lclVar V%02u\n", dspTreeID(tree), lclNode->GetLclNum());
8818-
effectiveVal = lclNode;
8819-
}
8820-
needsIndirection = false;
8821-
}
8822-
else
8823-
{
8824-
// This may be a lclVar that was determined to be address-exposed.
8825-
effectiveVal->gtFlags |= (lclNode->gtFlags & GTF_ALL_EFFECT);
8826-
}
8827-
}
8828-
8829-
if (needsIndirection)
8830-
{
8831-
if ((indirTree != nullptr) && (indirTree->OperIsBlk() || !isBlkReqd))
8832-
{
8833-
effectiveVal->gtType = asgType;
8834-
}
8835-
else
8836-
{
8837-
effectiveVal = gtNewStructVal(blockLayout, gtNewOperNode(GT_ADDR, TYP_BYREF, effectiveVal));
8838-
gtUpdateNodeSideEffects(effectiveVal);
8839-
}
8840-
}
8841-
}
8842-
8843-
assert(effectiveVal->TypeIs(asgType) || (varTypeIsSIMD(asgType) && varTypeIsStruct(effectiveVal)));
8844-
return effectiveVal;
8845-
}
8846-
88478703
#ifdef FEATURE_SIMD
88488704

88498705
//--------------------------------------------------------------------------------------------------------------
@@ -9269,19 +9125,12 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA
92699125
}
92709126
#endif
92719127

9272-
// We can't CSE the LHS of an assignment. Only r-values can be CSEed.
9273-
// Previously, the "lhs" (addr) of a block op was CSE'd. So, to duplicate the former
9274-
// behavior, allow CSE'ing if is a struct type (or a TYP_REF transformed from a struct type)
9275-
// TODO-1stClassStructs: improve this.
9276-
if (op1->IsLocal() || (op1->TypeGet() != TYP_STRUCT))
9277-
{
9278-
op1->gtFlags |= GTF_DONT_CSE;
9279-
}
9128+
// Location nodes cannot be CSEd.
9129+
op1->gtFlags |= GTF_DONT_CSE;
92809130
break;
92819131

92829132
case GT_ADDR:
9283-
9284-
/* op1 of a GT_ADDR is an l-value. Only r-values can be CSEed */
9133+
// Location nodes cannot be CSEd.
92859134
op1->gtFlags |= GTF_DONT_CSE;
92869135
break;
92879136

@@ -10229,17 +10078,11 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA
1022910078
*/
1023010079

1023110080
GenTree* temp;
10232-
GenTree* lclVarTree;
1023310081

1023410082
switch (oper)
1023510083
{
1023610084
case GT_ASG:
10237-
10238-
lclVarTree = fgIsIndirOfAddrOfLocal(op1);
10239-
if (lclVarTree != nullptr)
10240-
{
10241-
lclVarTree->gtFlags |= GTF_VAR_DEF;
10242-
}
10085+
fgAssignSetVarDef(tree);
1024310086

1024410087
if (op2->OperIs(GT_CAST))
1024510088
{
@@ -10251,14 +10094,8 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA
1025110094
op2 = tree->gtGetOp2();
1025210095
}
1025310096

10254-
fgAssignSetVarDef(tree);
10255-
10256-
/* We can't CSE the LHS of an assignment */
10257-
/* We also must set in the pre-morphing phase, otherwise assertionProp doesn't see it */
10258-
if (op1->IsLocal() || (op1->TypeGet() != TYP_STRUCT))
10259-
{
10260-
op1->gtFlags |= GTF_DONT_CSE;
10261-
}
10097+
// Location nodes cannot be CSEd.
10098+
op1->gtFlags |= GTF_DONT_CSE;
1026210099
break;
1026310100

1026410101
case GT_CAST:

src/coreclr/jit/morphblock.cpp

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -357,13 +357,8 @@ void MorphInitBlockHelper::MorphStructCases()
357357

358358
if (m_transformationDecision == BlockTransformation::Undefined)
359359
{
360-
// For an InitBlock we always require a block operand.
361-
m_dst = m_comp->fgMorphBlockOperand(m_dst, m_dst->TypeGet(), m_blockLayout, true /*isBlkReqd*/);
360+
m_result = m_asg;
362361
m_transformationDecision = BlockTransformation::StructBlock;
363-
m_dst->gtFlags |= GTF_DONT_CSE;
364-
m_result = m_asg;
365-
m_result->AsOp()->gtOp1 = m_dst;
366-
m_result->gtFlags |= (m_dst->gtFlags & GTF_ALL_EFFECT);
367362

368363
if (m_dstVarDsc != nullptr)
369364
{
@@ -401,29 +396,20 @@ GenTree* MorphInitBlockHelper::MorphBlock(Compiler* comp, GenTree* tree, bool is
401396
JITDUMP("MorphBlock for %s tree, before:\n", (isDest ? "dst" : "src"));
402397
DISPTREE(tree);
403398

404-
// Src can be a primitive type.
405-
assert(!isDest || varTypeIsStruct(tree));
406-
407-
GenTree* handleTree = nullptr;
408-
GenTree* addr = nullptr;
399+
assert(varTypeIsStruct(tree));
409400

410401
if (tree->OperIs(GT_COMMA))
411402
{
412403
// TODO-Cleanup: this block is not needed for not struct nodes, but
413404
// fgMorphOneAsgBlockOp works wrong without this transformation.
414405
tree = MorphCommaBlock(comp, tree->AsOp());
406+
if (isDest)
407+
{
408+
tree->SetDoNotCSE();
409+
}
415410
}
416411

417-
if (!tree->OperIsBlk())
418-
{
419-
JITDUMP("MorphBlock after:\n");
420-
DISPTREE(tree);
421-
return tree;
422-
}
423-
424-
GenTree* blkAddr = tree->AsBlk()->Addr();
425-
assert(blkAddr != nullptr);
426-
assert(blkAddr->TypeIs(TYP_I_IMPL, TYP_BYREF, TYP_REF));
412+
assert(!tree->OperIsIndir() || varTypeIsI(genActualType(tree->AsIndir()->Addr())));
427413

428414
JITDUMP("MorphBlock after:\n");
429415
DISPTREE(tree);
@@ -833,13 +819,28 @@ void MorphCopyBlockHelper::PrepareSrc()
833819
m_srcVarDsc = m_comp->lvaGetDesc(m_srcLclNum);
834820
}
835821

836-
// Verify that the types on the LHS and RHS match.
822+
// Verify that the types on the LHS and RHS match and morph away "IND<struct>" nodes.
837823
assert(m_dst->TypeGet() == m_src->TypeGet());
838-
// TODO-1stClassStructs: delete the "!IND" condition once "IND<struct>" nodes are no more.
839-
if (m_dst->TypeIs(TYP_STRUCT) && !m_src->OperIs(GT_IND))
824+
if (m_dst->TypeIs(TYP_STRUCT))
840825
{
826+
// TODO-1stClassStructs: delete this once "IND<struct>" nodes are no more.
827+
if (m_src->OperIs(GT_IND))
828+
{
829+
m_src->SetOper(m_blockLayout->IsBlockLayout() ? GT_BLK : GT_OBJ);
830+
m_src->AsBlk()->SetLayout(m_blockLayout);
831+
m_src->AsBlk()->gtBlkOpKind = GenTreeBlk::BlkOpKindInvalid;
832+
#ifndef JIT32_GCENCODER
833+
m_src->AsBlk()->gtBlkOpGcUnsafe = false;
834+
#endif // !JIT32_GCENCODER
835+
}
836+
841837
assert(ClassLayout::AreCompatible(m_blockLayout, m_src->GetLayout(m_comp)));
842838
}
839+
// TODO-1stClassStructs: produce simple "IND<simd>" nodes in importer.
840+
else if (m_src->OperIsBlk())
841+
{
842+
m_src->SetOper(GT_IND);
843+
}
843844
}
844845

845846
// TrySpecialCases: check special cases that require special transformations.
@@ -976,7 +977,7 @@ void MorphCopyBlockHelper::MorphStructCases()
976977
// promotion.
977978
if ((m_srcVarDsc == nullptr) && !m_src->OperIsIndir())
978979
{
979-
JITDUMP(" src is a not an L-value");
980+
JITDUMP(" src is not an L-value");
980981
requiresCopyBlock = true;
981982
}
982983

@@ -1117,18 +1118,6 @@ void MorphCopyBlockHelper::MorphStructCases()
11171118

11181119
if (requiresCopyBlock)
11191120
{
1120-
const var_types asgType = m_dst->TypeGet();
1121-
bool isBlkReqd = (asgType == TYP_STRUCT);
1122-
m_dst = m_comp->fgMorphBlockOperand(m_dst, asgType, m_blockLayout, isBlkReqd);
1123-
m_dst->gtFlags |= GTF_DONT_CSE;
1124-
m_asg->gtOp1 = m_dst;
1125-
1126-
m_src = m_comp->fgMorphBlockOperand(m_src, asgType, m_blockLayout, isBlkReqd);
1127-
m_asg->gtOp2 = m_src;
1128-
1129-
m_asg->SetAllEffectsFlags(m_dst, m_src);
1130-
m_asg->gtFlags |= GTF_ASG;
1131-
11321121
m_result = m_asg;
11331122
m_transformationDecision = BlockTransformation::StructBlock;
11341123
}

0 commit comments

Comments
 (0)