@@ -2495,6 +2495,52 @@ ValueNum ValueNumStore::VNForMapSelectWork(
2495
2495
}
2496
2496
}
2497
2497
2498
+ // ------------------------------------------------------------------------
2499
+ // VNForFieldSelector: A specialized version (with logging) of VNForHandle
2500
+ // that is used for field handle selectors.
2501
+ //
2502
+ // Arguments:
2503
+ // fieldHnd - handle of the field in question
2504
+ // pFieldType - [out] parameter for the field's type
2505
+ // pStructHnd - optional [out] parameter for the struct handle,
2506
+ // populated if the field is of a struct type
2507
+ //
2508
+ // Return Value:
2509
+ // Value number corresponding to the given field handle.
2510
+ //
2511
+ ValueNum ValueNumStore::VNForFieldSelector (CORINFO_FIELD_HANDLE fieldHnd,
2512
+ var_types* pFieldType,
2513
+ CORINFO_CLASS_HANDLE* pStructHnd)
2514
+ {
2515
+ CORINFO_CLASS_HANDLE structHnd = NO_CLASS_HANDLE;
2516
+ ValueNum fldHndVN = VNForHandle (ssize_t (fieldHnd), GTF_ICON_FIELD_HDL);
2517
+
2518
+ CorInfoType fieldCit = m_pComp->info .compCompHnd ->getFieldType (fieldHnd, &structHnd);
2519
+ var_types fieldType = JITtype2varType (fieldCit);
2520
+
2521
+ #ifdef DEBUG
2522
+ if (m_pComp->verbose )
2523
+ {
2524
+ const char * modName;
2525
+ const char * fldName = m_pComp->eeGetFieldName (fieldHnd, &modName);
2526
+ printf (" VNForHandle(%s) is " FMT_VN " , fieldType is %s" , fldName, fldHndVN, varTypeName (fieldType));
2527
+ if (varTypeIsStruct (fieldType))
2528
+ {
2529
+ printf (" , size = %u" , m_pComp->info .compCompHnd ->getClassSize (structHnd));
2530
+ }
2531
+ printf (" \n " );
2532
+ }
2533
+ #endif
2534
+
2535
+ if (pStructHnd != nullptr )
2536
+ {
2537
+ *pStructHnd = structHnd;
2538
+ }
2539
+ *pFieldType = fieldType;
2540
+
2541
+ return fldHndVN;
2542
+ }
2543
+
2498
2544
ValueNum ValueNumStore::EvalFuncForConstantArgs (var_types typ, VNFunc func, ValueNum arg0VN)
2499
2545
{
2500
2546
assert (CanEvalForConstantArgs (func));
@@ -3812,12 +3858,11 @@ ValueNum ValueNumStore::VNApplySelectors(ValueNumKind vnk,
3812
3858
3813
3859
assert (field != FieldSeqStore::NotAField ());
3814
3860
3815
- CORINFO_FIELD_HANDLE fldHnd = field->m_fieldHnd ;
3816
- CORINFO_CLASS_HANDLE structHnd = NO_CLASS_HANDLE;
3817
- ValueNum fldHndVN = VNForHandle (ssize_t (fldHnd), GTF_ICON_FIELD_HDL);
3818
- noway_assert (fldHnd != nullptr );
3819
- CorInfoType fieldCit = m_pComp->info .compCompHnd ->getFieldType (fldHnd, &structHnd);
3820
- var_types fieldType = JITtype2varType (fieldCit);
3861
+ JITDUMP (" VNApplySelectors:\n " );
3862
+ var_types fieldType;
3863
+ CORINFO_CLASS_HANDLE structHnd;
3864
+ CORINFO_FIELD_HANDLE fldHnd = field->GetFieldHandle ();
3865
+ ValueNum fldHndVN = VNForFieldSelector (fldHnd, &fieldType, &structHnd);
3821
3866
3822
3867
size_t structSize = 0 ;
3823
3868
if (varTypeIsStruct (fieldType))
@@ -3835,21 +3880,6 @@ ValueNum ValueNumStore::VNApplySelectors(ValueNumKind vnk,
3835
3880
*wbFinalStructSize = structSize;
3836
3881
}
3837
3882
3838
- #ifdef DEBUG
3839
- if (m_pComp->verbose )
3840
- {
3841
- printf (" VNApplySelectors:\n " );
3842
- const char * modName;
3843
- const char * fldName = m_pComp->eeGetFieldName (fldHnd, &modName);
3844
- printf (" VNForHandle(%s) is " FMT_VN " , fieldType is %s" , fldName, fldHndVN, varTypeName (fieldType));
3845
- if (varTypeIsStruct (fieldType))
3846
- {
3847
- printf (" , size = %d" , structSize);
3848
- }
3849
- printf (" \n " );
3850
- }
3851
- #endif
3852
-
3853
3883
map = VNForMapSelect (vnk, fieldType, map, fldHndVN);
3854
3884
}
3855
3885
@@ -4005,48 +4035,27 @@ ValueNum ValueNumStore::VNApplySelectorsAssign(
4005
4035
return VNApplySelectorsAssign (vnk, map, fieldSeq->m_next , value, dstIndType);
4006
4036
}
4007
4037
4038
+ if (fieldSeq->m_next == nullptr )
4039
+ {
4040
+ JITDUMP (" VNApplySelectorsAssign:\n " );
4041
+ }
4042
+
4008
4043
// Otherwise, fldHnd is a real field handle.
4009
- CORINFO_FIELD_HANDLE fldHnd = fieldSeq->m_fieldHnd ;
4010
- ValueNum fldHndVN = VNForHandle (ssize_t (fldHnd), GTF_ICON_FIELD_HDL);
4011
- noway_assert (fldHnd != nullptr );
4012
- CorInfoType fieldCit = m_pComp->info .compCompHnd ->getFieldType (fldHnd);
4013
- var_types fieldType = JITtype2varType (fieldCit);
4044
+ var_types fieldType;
4045
+ ValueNum fldHndVN = VNForFieldSelector (fieldSeq->GetFieldHandle (), &fieldType);
4014
4046
4015
4047
ValueNum valueAfter;
4016
- if (fieldSeq->m_next )
4048
+ if (fieldSeq->m_next != nullptr )
4017
4049
{
4018
- #ifdef DEBUG
4019
- if (m_pComp->verbose )
4020
- {
4021
- const char * modName;
4022
- const char * fldName = m_pComp->eeGetFieldName (fldHnd, &modName);
4023
- printf (" VNForHandle(%s) is " FMT_VN " , fieldType is %s\n " , fldName, fldHndVN,
4024
- varTypeName (fieldType));
4025
- }
4026
- #endif
4027
4050
ValueNum fseqMap = VNForMapSelect (vnk, fieldType, map, fldHndVN);
4028
4051
valueAfter = VNApplySelectorsAssign (vnk, fseqMap, fieldSeq->m_next , value, dstIndType);
4029
4052
}
4030
4053
else
4031
4054
{
4032
- #ifdef DEBUG
4033
- if (m_pComp->verbose )
4034
- {
4035
- if (fieldSeq->m_next == nullptr )
4036
- {
4037
- printf (" VNApplySelectorsAssign:\n " );
4038
- }
4039
- const char * modName;
4040
- const char * fldName = m_pComp->eeGetFieldName (fldHnd, &modName);
4041
- printf (" VNForHandle(%s) is " FMT_VN " , fieldType is %s\n " , fldName, fldHndVN,
4042
- varTypeName (fieldType));
4043
- }
4044
- #endif
4045
4055
valueAfter = VNApplySelectorsAssignTypeCoerce (value, dstIndType);
4046
4056
}
4047
4057
4048
- ValueNum newMap = VNForMapStore (fieldType, map, fldHndVN, valueAfter);
4049
- return newMap;
4058
+ return VNForMapStore (fieldType, map, fldHndVN, valueAfter);
4050
4059
}
4051
4060
}
4052
4061
@@ -7768,82 +7777,80 @@ void Compiler::fgValueNumberAssignment(GenTreeOp* tree)
7768
7777
assert (fldSeq != nullptr );
7769
7778
}
7770
7779
7771
- // Get a field sequence for just the first field in the sequence
7772
- //
7773
- FieldSeqNode* firstFieldOnly = GetFieldSeqStore ()-> CreateSingleton (fldSeq-> m_fieldHnd ) ;
7780
+ // The value number from the rhs of the assignment
7781
+ ValueNum storeVal = rhsVNPair. GetLiberal ();
7782
+ ValueNum newHeapVN = ValueNumStore::NoVN ;
7774
7783
7775
- // The final field in the sequence will need to match the 'indType'
7784
+ // We will check that the final field in the sequence matches 'indType'.
7776
7785
var_types indType = lhs->TypeGet ();
7777
- ValueNum fldMapVN =
7778
- vnStore->VNApplySelectors (VNK_Liberal, fgCurMemoryVN[GcHeap], firstFieldOnly);
7779
-
7780
- // The type of the field is "struct" if there are more fields in the sequence,
7781
- // otherwise it is the type returned from VNApplySelectors above.
7782
- var_types firstFieldType = vnStore->TypeOfVN (fldMapVN);
7783
-
7784
- // The value number from the rhs of the assignment
7785
- ValueNum storeVal = rhsVNPair.GetLiberal ();
7786
- ValueNum newFldMapVN = ValueNumStore::NoVN;
7787
7786
7788
7787
// when (obj != nullptr) we have an instance field, otherwise a static field
7789
7788
// when (staticOffset != nullptr) it represents a offset into a static or the call to
7790
7789
// Shared Static Base
7791
7790
if ((obj != nullptr ) || (staticOffset != nullptr ))
7792
7791
{
7793
- ValueNum valAtAddr = fldMapVN;
7794
- ValueNum normVal = ValueNumStore::NoVN;
7792
+ var_types firstFieldType;
7793
+ ValueNum firstFieldSelectorVN =
7794
+ vnStore->VNForFieldSelector (fldSeq->GetFieldHandle (), &firstFieldType);
7795
7795
7796
+ // Construct the "field map" VN. It represents memory state of the first field
7797
+ // of all objects on the heap. This is our primary map.
7798
+ ValueNum fldMapVN = vnStore->VNForMapSelect (VNK_Liberal, firstFieldType,
7799
+ fgCurMemoryVN[GcHeap], firstFieldSelectorVN);
7800
+
7801
+ ValueNum firstFieldValueSelectorVN = ValueNumStore::NoVN;
7796
7802
if (obj != nullptr )
7797
7803
{
7798
- // Unpack, Norm,Exc for 'obj'
7799
- ValueNum vnObjExcSet;
7800
- vnStore->VNUnpackExc (obj->gtVNPair .GetLiberal (), &normVal, &vnObjExcSet);
7801
- vnExcSet = vnStore->VNExcSetUnion (vnExcSet, vnObjExcSet);
7802
-
7803
- // construct the ValueNumber for 'fldMap at obj'
7804
- valAtAddr = vnStore->VNForMapSelect (VNK_Liberal, firstFieldType, fldMapVN, normVal);
7804
+ firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue (obj->gtVNPair );
7805
7805
}
7806
7806
else // (staticOffset != nullptr)
7807
7807
{
7808
- // construct the ValueNumber for 'fldMap at staticOffset'
7809
- normVal = vnStore->VNLiberalNormalValue (staticOffset->gtVNPair );
7810
- valAtAddr = vnStore->VNForMapSelect (VNK_Liberal, firstFieldType, fldMapVN, normVal);
7808
+ firstFieldValueSelectorVN = vnStore->VNLiberalNormalValue (staticOffset->gtVNPair );
7811
7809
}
7812
- // Now get rid of any remaining struct field dereferences. (if they exist)
7813
- if (fldSeq->m_next )
7810
+
7811
+ ValueNum newFirstFieldValueVN = ValueNumStore::NoVN;
7812
+ // Optimization: avoid traversting the maps for the value of the first field if
7813
+ // we do not need it, which is the case if the rest of the field sequence is empty.
7814
+ if (fldSeq->m_next == nullptr )
7814
7815
{
7815
- storeVal = vnStore->VNApplySelectorsAssign (VNK_Liberal, valAtAddr, fldSeq->m_next ,
7816
- storeVal, indType);
7816
+ newFirstFieldValueVN = vnStore->VNApplySelectorsAssignTypeCoerce (storeVal, indType);
7817
+ }
7818
+ else
7819
+ {
7820
+ // Construct the ValueNumber for fldMap[obj/offset]. This (struct)
7821
+ // map represents the specific field we're looking to store to.
7822
+ ValueNum firstFieldValueVN =
7823
+ vnStore->VNForMapSelect (VNK_Liberal, firstFieldType, fldMapVN,
7824
+ firstFieldValueSelectorVN);
7825
+
7826
+ // Construct the maps updating the rest of the fields in the sequence.
7827
+ newFirstFieldValueVN =
7828
+ vnStore->VNApplySelectorsAssign (VNK_Liberal, firstFieldValueVN, fldSeq->m_next ,
7829
+ storeVal, indType);
7817
7830
}
7818
7831
7819
- // From which we can construct the new ValueNumber for 'fldMap at normVal'
7820
- newFldMapVN =
7821
- vnStore->VNForMapStore (vnStore->TypeOfVN (fldMapVN), fldMapVN, normVal, storeVal);
7832
+ // Finally, construct the new field map...
7833
+ ValueNum newFldMapVN =
7834
+ vnStore->VNForMapStore (vnStore->TypeOfVN (fldMapVN), fldMapVN, firstFieldValueSelectorVN,
7835
+ newFirstFieldValueVN);
7836
+
7837
+ // ...and a new value for the heap.
7838
+ newHeapVN = vnStore->VNForMapStore (TYP_REF, fgCurMemoryVN[GcHeap], firstFieldSelectorVN,
7839
+ newFldMapVN);
7822
7840
}
7823
7841
else
7824
7842
{
7825
- // plain static field
7826
-
7827
- // Now get rid of any remaining struct field dereferences. (if they exist)
7828
- if (fldSeq->m_next )
7829
- {
7830
- storeVal = vnStore->VNApplySelectorsAssign (VNK_Liberal, fldMapVN, fldSeq->m_next ,
7831
- storeVal, indType);
7832
- }
7833
-
7834
- newFldMapVN = vnStore->VNApplySelectorsAssign (VNK_Liberal, fgCurMemoryVN[GcHeap], fldSeq,
7835
- storeVal, indType);
7843
+ // Plain static field.
7844
+ newHeapVN = vnStore->VNApplySelectorsAssign (VNK_Liberal, fgCurMemoryVN[GcHeap], fldSeq,
7845
+ storeVal, indType);
7836
7846
}
7837
7847
7838
7848
// It is not strictly necessary to set the lhs value number,
7839
7849
// but the dumps read better with it set to the 'storeVal' that we just computed
7840
7850
lhs->gtVNPair .SetBoth (storeVal);
7841
7851
7842
- // Update the field map for firstField in GcHeap to this new value.
7843
- ValueNum heapVN = vnStore->VNApplySelectorsAssign (VNK_Liberal, fgCurMemoryVN[GcHeap],
7844
- firstFieldOnly, newFldMapVN, indType);
7845
-
7846
- recordGcHeapStore (tree, heapVN DEBUGARG (" StoreField" ));
7852
+ // Update the GcHeap value.
7853
+ recordGcHeapStore (tree, newHeapVN DEBUGARG (" StoreField" ));
7847
7854
}
7848
7855
}
7849
7856
else
0 commit comments