From 86f8e7887eb73b94525f2a51462ef97d9c435fbf Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Wed, 30 Aug 2017 17:36:07 -0700 Subject: [PATCH] JIT: don't reuse box temps when optimizing (#13703) The importer reuses temps for different box operations that do not overlap. This keeps the number of temps to a minimum and reduces prolog zeroing if the temps end up untracked. But reuse prevents the importer from accurately typing the temp. So now, when optimizing, allocate a new temp for each box operation, and type the temp with the type of the box. This, along with a small update in `gtGetClassHandle` to obtain the box type, enables some devirtualization of interface calls on boxes and will facilitate future changes to optimize away boxes entirely (eg #5626). --- src/jit/gentree.cpp | 15 +++++++++++++++ src/jit/importer.cpp | 18 ++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index df700a8884..753bb56455 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -15978,6 +15978,21 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTreePtr tree, bool* isExact, break; } + case GT_BOX: + { + // Box should just wrap a local var reference which has + // the type we're looking for. Also box only represents a + // non-nullable value type so result cannot be null. + GenTreeBox* box = obj->AsBox(); + GenTree* boxTemp = box->BoxOp(); + assert(boxTemp->IsLocal()); + const unsigned boxTempLcl = boxTemp->AsLclVar()->GetLclNum(); + objClass = lvaTable[boxTempLcl].lvClassHnd; + *isExact = lvaTable[boxTempLcl].lvClassIsExact; + *isNonNull = true; + break; + } + default: { break; diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index e325d05c5e..0e456a8eae 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -5255,9 +5255,23 @@ void Compiler::impImportAndPushBox(CORINFO_RESOLVED_TOKEN* pResolvedToken) // and the other you get // *(temp+4) = expr - if (impBoxTempInUse || impBoxTemp == BAD_VAR_NUM) + if (opts.MinOpts() || opts.compDbgCode) { - impBoxTemp = lvaGrabTemp(true DEBUGARG("Box Helper")); + // For minopts/debug code, try and minimize the total number + // of box temps by reusing an existing temp when possible. + if (impBoxTempInUse || impBoxTemp == BAD_VAR_NUM) + { + impBoxTemp = lvaGrabTemp(true DEBUGARG("Reusable Box Helper")); + } + } + else + { + // When optimizing, use a new temp for each box operation + // since we then know the exact class of the box temp. + impBoxTemp = lvaGrabTemp(true DEBUGARG("Single-def Box Helper")); + lvaTable[impBoxTemp].lvType = TYP_REF; + const bool isExact = true; + lvaSetClass(impBoxTemp, pResolvedToken->hClass, isExact); } // needs to stay in use until this box expression is appended -- 2.34.1