diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 4e9ec67b31a467..3f239a3d29c919 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -5591,6 +5591,8 @@ class Compiler void fgValueNumberFieldStore( GenTree* storeNode, GenTree* baseAddr, FieldSeq* fieldSeq, ssize_t offset, unsigned storeSize, ValueNum value); + static bool fgGetStaticFieldSeqAndAddress(ValueNumStore* vnStore, GenTree* tree, ssize_t* byteOffset, FieldSeq** pFseq); + bool fgValueNumberConstLoad(GenTreeIndir* tree); // Compute the value number for a byref-exposed load of the given type via the given pointerVN. diff --git a/src/coreclr/jit/fginline.cpp b/src/coreclr/jit/fginline.cpp index 6ebe709888a4b1..8ea17f2bff05a0 100644 --- a/src/coreclr/jit/fginline.cpp +++ b/src/coreclr/jit/fginline.cpp @@ -590,9 +590,9 @@ class SubstitutePlaceholdersAndDevirtualizeWalker : public GenTreeVisitorlvSingleDef) { - bool isExact = false; - bool isNonNull = false; - CORINFO_CLASS_HANDLE newClass = m_compiler->gtGetClassHandle(value, &isExact, &isNonNull); + bool isExact; + bool isNonNull; + CORINFO_CLASS_HANDLE newClass = m_compiler->gtGetClassHandle(value, &isExact, &isNonNull); if (newClass != NO_CLASS_HANDLE) { diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 0ada2ec1425c09..60c99db2db3752 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -14124,13 +14124,13 @@ GenTree* Compiler::gtFoldTypeCompare(GenTree* tree) objOp = opOther->AsCall()->gtArgs.GetThisArg()->GetNode(); } - bool pIsExact = false; - bool pIsNonNull = false; - CORINFO_CLASS_HANDLE objCls = gtGetClassHandle(objOp, &pIsExact, &pIsNonNull); + bool isExact = false; + bool isNonNull = false; + CORINFO_CLASS_HANDLE objCls = gtGetClassHandle(objOp, &isExact, &isNonNull); // if both classes are "final" (e.g. System.String[]) we can replace the comparison // with `true/false` + null check. - if ((objCls != NO_CLASS_HANDLE) && (pIsExact || info.compCompHnd->isExactType(objCls))) + if ((objCls != NO_CLASS_HANDLE) && (isExact || info.compCompHnd->isExactType(objCls))) { TypeCompareState tcs = info.compCompHnd->compareTypesForEquality(objCls, clsHnd); if (tcs != TypeCompareState::May) @@ -14139,7 +14139,7 @@ GenTree* Compiler::gtFoldTypeCompare(GenTree* tree) const bool typesAreEqual = tcs == TypeCompareState::Must; GenTree* compareResult = gtNewIconNode((operatorIsEQ ^ typesAreEqual) ? 0 : 1); - if (!pIsNonNull) + if (!isNonNull) { // we still have to emit a null-check // obj.GetType == typeof() -> (nullcheck) true/false @@ -18398,24 +18398,23 @@ bool Compiler::gtStoreDefinesField( // otherwise actual type may be a subtype. // *pIsNonNull set true if tree value is known not to be null, // otherwise a null value is possible. - +// CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, bool* pIsNonNull) { // Set default values for our out params. - *pIsNonNull = false; - *pIsExact = false; - CORINFO_CLASS_HANDLE objClass = nullptr; + *pIsNonNull = false; + *pIsExact = false; // Bail out if the tree is not a ref type. - var_types treeType = tree->TypeGet(); - if (treeType != TYP_REF) + if (!tree->TypeIs(TYP_REF)) { - return objClass; + return NO_CLASS_HANDLE; } // Tunnel through commas. - GenTree* obj = tree->gtEffectiveVal(); - const genTreeOps objOp = obj->OperGet(); + GenTree* obj = tree->gtEffectiveVal(); + const genTreeOps objOp = obj->OperGet(); + CORINFO_CLASS_HANDLE objClass = NO_CLASS_HANDLE; switch (objOp) { @@ -18564,7 +18563,6 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b assert(runtimeType != NO_CLASS_HANDLE); objClass = runtimeType; - *pIsExact = false; *pIsNonNull = true; } @@ -18608,9 +18606,6 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b { objClass = gtGetArrayElementClassHandle(base->AsArrElem()->gtArrObj); } - - *pIsExact = false; - *pIsNonNull = false; } else if (base->OperGet() == GT_ADD) { @@ -18647,7 +18642,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b FieldSeq* fldSeq = base->AsIntCon()->gtFieldSeq; if ((fldSeq != nullptr) && (fldSeq->GetOffset() == base->AsIntCon()->IconValue())) { - CORINFO_FIELD_HANDLE fldHandle = base->AsIntCon()->gtFieldSeq->GetFieldHandle(); + CORINFO_FIELD_HANDLE fldHandle = fldSeq->GetFieldHandle(); objClass = gtGetFieldClassHandle(fldHandle, pIsExact, pIsNonNull); } } @@ -18714,7 +18709,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b // Return Value: // nullptr if helper call result is not a ref class, or the class handle // is unknown, otherwise the class handle. - +// CORINFO_CLASS_HANDLE Compiler::gtGetHelperCallClassHandle(GenTreeCall* call, bool* pIsExact, bool* pIsNonNull) { assert(call->gtCallType == CT_HELPER); @@ -18856,7 +18851,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetHelperCallClassHandle(GenTreeCall* call, boo // // Return Value: // nullptr if element class handle is unknown, otherwise the class handle. - +// CORINFO_CLASS_HANDLE Compiler::gtGetArrayElementClassHandle(GenTree* array) { bool isArrayExact = false; @@ -18898,9 +18893,12 @@ CORINFO_CLASS_HANDLE Compiler::gtGetArrayElementClassHandle(GenTree* array) // is unknown, otherwise the class handle. // // May examine runtime state of static field instances. - +// CORINFO_CLASS_HANDLE Compiler::gtGetFieldClassHandle(CORINFO_FIELD_HANDLE fieldHnd, bool* pIsExact, bool* pIsNonNull) { + *pIsExact = false; + *pIsNonNull = false; + CORINFO_CLASS_HANDLE fieldClass = NO_CLASS_HANDLE; CorInfoType fieldCorType = info.compCompHnd->getFieldType(fieldHnd, &fieldClass); @@ -18913,11 +18911,14 @@ CORINFO_CLASS_HANDLE Compiler::gtGetFieldClassHandle(CORINFO_FIELD_HANDLE fieldH if (queryForCurrentClass) { #if DEBUG - char fieldNameBuffer[128]; - char classNameBuffer[128]; - JITDUMP("\nQuerying runtime about current class of field %s (declared as %s)\n", - eeGetFieldName(fieldHnd, true, fieldNameBuffer, sizeof(fieldNameBuffer)), - eeGetClassName(fieldClass, classNameBuffer, sizeof(classNameBuffer))); + if (verbose || JitConfig.EnableExtraSuperPmiQueries()) + { + char fieldNameBuffer[128]; + char classNameBuffer[128]; + const char* fieldName = eeGetFieldName(fieldHnd, true, fieldNameBuffer, sizeof(fieldNameBuffer)); + const char* className = eeGetClassName(fieldClass, classNameBuffer, sizeof(classNameBuffer)); + JITDUMP("\nQuerying runtime about current class of field %s (declared as %s)\n", fieldName, className); + } #endif // DEBUG // Is this a fully initialized init-only static field? @@ -18932,10 +18933,13 @@ CORINFO_CLASS_HANDLE Compiler::gtGetFieldClassHandle(CORINFO_FIELD_HANDLE fieldH *pIsExact = true; *pIsNonNull = true; #ifdef DEBUG - char buffer[128]; - JITDUMP("Runtime reports field is init-only and initialized and has class %s\n", - eeGetClassName(fieldClass, buffer, sizeof(buffer))); -#endif + if (verbose || JitConfig.EnableExtraSuperPmiQueries()) + { + char classNameBuffer2[128]; + const char* className2 = eeGetClassName(fieldClass, classNameBuffer2, sizeof(classNameBuffer2)); + JITDUMP("Runtime reports field is init-only and initialized and has class %s\n", className2); + } +#endif // DEBUG } else { diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 28abf35f37e828..adab2ead88a12f 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -10939,7 +10939,11 @@ void Compiler::fgValueNumberSsaVarDef(GenTreeLclVarCommon* lcl) // Return Value: // true if the given tree is a static field address // -static bool GetStaticFieldSeqAndAddress(ValueNumStore* vnStore, GenTree* tree, ssize_t* byteOffset, FieldSeq** pFseq) +/* static */ +bool Compiler::fgGetStaticFieldSeqAndAddress(ValueNumStore* vnStore, + GenTree* tree, + ssize_t* byteOffset, + FieldSeq** pFseq) { VNFuncApp funcApp; if (vnStore->GetVNFunc(tree->gtVNPair.GetLiberal(), &funcApp) && (funcApp.m_func == VNF_PtrToStatic)) @@ -10954,7 +10958,6 @@ static bool GetStaticFieldSeqAndAddress(ValueNumStore* vnStore, GenTree* tree, s return true; } } - ssize_t val = 0; // Special cases for NativeAOT: // ADD(ICON_STATIC, CNS_INT) // nonGC-static base @@ -10972,6 +10975,7 @@ static bool GetStaticFieldSeqAndAddress(ValueNumStore* vnStore, GenTree* tree, s } // Accumulate final offset + ssize_t val = 0; while (tree->OperIs(GT_ADD)) { GenTree* op1 = tree->gtGetOp1(); @@ -11011,6 +11015,7 @@ static bool GetStaticFieldSeqAndAddress(ValueNumStore* vnStore, GenTree* tree, s return true; } } + return false; } @@ -11094,7 +11099,7 @@ bool Compiler::fgValueNumberConstLoad(GenTreeIndir* tree) const int maxElementSize = sizeof(simd_t); if (!tree->TypeIs(TYP_BYREF, TYP_STRUCT) && - GetStaticFieldSeqAndAddress(vnStore, tree->gtGetOp1(), &byteOffset, &fieldSeq)) + fgGetStaticFieldSeqAndAddress(vnStore, tree->gtGetOp1(), &byteOffset, &fieldSeq)) { CORINFO_FIELD_HANDLE fieldHandle = fieldSeq->GetFieldHandle(); if ((fieldHandle != nullptr) && (size > 0) && (size <= maxElementSize) && ((size_t)byteOffset < INT_MAX)) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index f98d7b0fc06505..0c283d9f53a67a 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2336,12 +2336,16 @@ private bool getStaticFieldContent(CORINFO_FIELD_STRUCT_* fieldHandle, byte* buf if (value == null) { - Debug.Assert(valueOffset == 0); - Debug.Assert(bufferSize == targetPtrSize); - - // Write "null" to buffer - new Span(buffer, targetPtrSize).Clear(); - return true; + if ((valueOffset == 0) && (bufferSize == targetPtrSize)) + { + // Write "null" to buffer + new Span(buffer, targetPtrSize).Clear(); + return true; + } + else + { + return false; + } } if (value.GetRawData(_compilation.NodeFactory, out object data)) @@ -2357,13 +2361,14 @@ private bool getStaticFieldContent(CORINFO_FIELD_STRUCT_* fieldHandle, byte* buf return false; case FrozenObjectNode: - Debug.Assert(valueOffset == 0); - Debug.Assert(bufferSize == targetPtrSize); - - // save handle's value to buffer - nint handle = ObjectToHandle(data); - new Span(&handle, targetPtrSize).CopyTo(new Span(buffer, targetPtrSize)); - return true; + if ((valueOffset == 0) && (bufferSize == targetPtrSize)) + { + // save handle's value to buffer + nint handle = ObjectToHandle(data); + new Span(&handle, targetPtrSize).CopyTo(new Span(buffer, targetPtrSize)); + return true; + } + return false; } } } diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index b5b8ec66d2d61a..4f92c805a7347d 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11777,13 +11777,13 @@ bool CEEInfo::getStaticFieldContent(CORINFO_FIELD_HANDLE fieldHnd, uint8_t* buff { if (field->IsObjRef()) { - GCX_COOP(); - - _ASSERT(!field->IsRVA()); - _ASSERT(valueOffset == 0); // there is no point in returning a chunk of a gc handle - _ASSERT((UINT)bufferSize == field->GetSize()); + // there is no point in returning a chunk of a gc handle + if ((valueOffset == 0) && (sizeof(CORINFO_OBJECT_HANDLE) <= (UINT)bufferSize) && !field->IsRVA()) + { + GCX_COOP(); - result = getStaticObjRefContent(field->GetStaticOBJECTREF(), buffer, ignoreMovableObjects); + result = getStaticObjRefContent(field->GetStaticOBJECTREF(), buffer, ignoreMovableObjects); + } } else {