From f7e2ce04e12f56946cea15b519bfc4204d6d630f Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Mon, 8 Oct 2018 13:15:36 -0700 Subject: [PATCH] JIT: retrieve element class for arrays of ref types (dotnet/coreclr#20292) Allows element-typed based optimizations for some array cases, say virtual calls through a `string[]`. Commit migrated from https://github.com/dotnet/coreclr/commit/bcc4cec7646f0df99c5a83e3dd72ec2d39e0ee01 --- src/coreclr/src/jit/compiler.h | 2 ++ src/coreclr/src/jit/gentree.cpp | 66 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/coreclr/src/jit/compiler.h b/src/coreclr/src/jit/compiler.h index 77ed2cc..9525745 100644 --- a/src/coreclr/src/jit/compiler.h +++ b/src/coreclr/src/jit/compiler.h @@ -2491,6 +2491,8 @@ public: CORINFO_CLASS_HANDLE gtGetStructHandle(GenTree* tree); // Get the handle for a ref type. CORINFO_CLASS_HANDLE gtGetClassHandle(GenTree* tree, bool* isExact, bool* isNonNull); + // Get the element handle for an array of ref type. + CORINFO_CLASS_HANDLE gtGetArrayElementClassHandle(GenTree* array); //------------------------------------------------------------------------- // Functions to display the trees diff --git a/src/coreclr/src/jit/gentree.cpp b/src/coreclr/src/jit/gentree.cpp index a3fcd88..92e8c27 100644 --- a/src/coreclr/src/jit/gentree.cpp +++ b/src/coreclr/src/jit/gentree.cpp @@ -16578,12 +16578,14 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* isExact, bo case GT_IND: { - // indir(addr(lcl)) --> lcl - // - // This comes up during constrained callvirt on ref types. GenTreeIndir* indir = obj->AsIndir(); + if (indir->HasBase() && !indir->HasIndex()) { + // indir(addr(lcl)) --> lcl + // + // This comes up during constrained callvirt on ref types. + GenTree* base = indir->Base(); GenTreeLclVarCommon* lcl = base->IsLocalAddrExpr(); @@ -16593,6 +16595,16 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* isExact, bo objClass = lvaTable[objLcl].lvClassHnd; *isExact = lvaTable[objLcl].lvClassIsExact; } + else if (base->OperGet() == GT_ARR_ELEM) + { + // indir(arr_elem(...)) -> array element type + + GenTree* array = base->AsArrElem()->gtArrObj; + + objClass = gtGetArrayElementClassHandle(array); + *isExact = false; + *isNonNull = false; + } } break; } @@ -16612,6 +16624,16 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* isExact, bo break; } + case GT_INDEX: + { + GenTree* array = obj->AsIndex()->Arr(); + + objClass = gtGetArrayElementClassHandle(array); + *isExact = false; + *isNonNull = false; + break; + } + default: { break; @@ -16621,6 +16643,44 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* isExact, bo return objClass; } +//------------------------------------------------------------------------ +// gtGetArrayElementClassHandle: find class handle for elements of an array +// of ref types +// +// Arguments: +// array -- array to find handle for +// +// Return Value: +// nullptr if element class handle is unknown, otherwise the class handle. + +CORINFO_CLASS_HANDLE Compiler::gtGetArrayElementClassHandle(GenTree* array) +{ + bool isArrayExact = false; + bool isArrayNonNull = false; + CORINFO_CLASS_HANDLE arrayClassHnd = gtGetClassHandle(array, &isArrayExact, &isArrayNonNull); + + if (arrayClassHnd != nullptr) + { + // We know the class of the reference + DWORD attribs = info.compCompHnd->getClassAttribs(arrayClassHnd); + + if ((attribs & CORINFO_FLG_ARRAY) != 0) + { + // We know for sure it is an array + CORINFO_CLASS_HANDLE elemClassHnd = nullptr; + CorInfoType arrayElemType = info.compCompHnd->getChildType(arrayClassHnd, &elemClassHnd); + + if (arrayElemType == CORINFO_TYPE_CLASS) + { + // We know it is an array of ref types + return elemClassHnd; + } + } + } + + return nullptr; +} + void GenTree::ParseArrayAddress( Compiler* comp, ArrayInfo* arrayInfo, GenTree** pArr, ValueNum* pInxVN, FieldSeqNode** pFldSeq) { -- 2.7.4