Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 3fc07ad

Browse files
committed
Fix issue where the unsigned value used for the the map select budget could underflow
resulting in an unlimited budget Changed m_mapSelectBudget and budget to be a signed integer Added an assert that ensures that the remaining budget is between [0..m_mapSelectBudget] Change the test for running out of budge to be a <= zero test instead of an equal zero test. Fixed the bug in the handling of phiArgs in VNForMapSelectWork by adding a check if we exceeded our budget when processing the first phiArg. Added a define for DEFAULT_MAP_SELECT_BUDGET
1 parent 41d23b0 commit 3fc07ad

File tree

3 files changed

+37
-11
lines changed

3 files changed

+37
-11
lines changed

src/jit/jitconfigvalues.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -282,11 +282,13 @@ CONFIG_METHODSET(JitOptRepeat, W("JitOptRepeat")) // Runs optimizer m
282282
CONFIG_INTEGER(JitOptRepeatCount, W("JitOptRepeatCount"), 2) // Number of times to repeat opts when repeating
283283
#endif // defined(OPT_CONFIG)
284284

285-
CONFIG_INTEGER(JitRegisterFP, W("JitRegisterFP"), 3) // Control FP enregistration
286-
CONFIG_INTEGER(JitTelemetry, W("JitTelemetry"), 1) // If non-zero, gather JIT telemetry data
287-
CONFIG_INTEGER(JitVNMapSelBudget, W("JitVNMapSelBudget"), 100) // Max # of MapSelect's considered for a particular
288-
// top-level invocation.
289-
CONFIG_INTEGER(TailCallLoopOpt, W("TailCallLoopOpt"), 1) // Convert recursive tail calls to loops
285+
CONFIG_INTEGER(JitRegisterFP, W("JitRegisterFP"), 3) // Control FP enregistration
286+
CONFIG_INTEGER(JitTelemetry, W("JitTelemetry"), 1) // If non-zero, gather JIT telemetry data
287+
288+
// Max # of MapSelect's considered for a particular top-level invocation.
289+
CONFIG_INTEGER(JitVNMapSelBudget, W("JitVNMapSelBudget"), DEFAULT_MAP_SELECT_BUDGET)
290+
291+
CONFIG_INTEGER(TailCallLoopOpt, W("TailCallLoopOpt"), 1) // Convert recursive tail calls to loops
290292
CONFIG_METHODSET(AltJit, W("AltJit")) // Enables AltJit and selectively limits it to the specified methods.
291293
CONFIG_METHODSET(AltJitNgen,
292294
W("AltJitNgen")) // Enables AltJit for NGEN and selectively limits it to the specified methods.

src/jit/valuenum.cpp

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,13 @@ ValueNumStore::ValueNumStore(Compiler* comp, CompAllocator* alloc)
9595
ChunkNum cn = m_chunks.Push(specialConstChunk);
9696
assert(cn == 0);
9797

98-
m_mapSelectBudget = JitConfig.JitVNMapSelBudget();
98+
m_mapSelectBudget = (int)JitConfig.JitVNMapSelBudget(); // We cast the unsigned DWORD to a signed int.
99+
100+
// This value must be non-negative and non-zero, reset the value to DEFAULT_MAP_SELECT_BUDGET if it isn't.
101+
if (m_mapSelectBudget <= 0)
102+
{
103+
m_mapSelectBudget = DEFAULT_MAP_SELECT_BUDGET;
104+
}
99105
}
100106

101107
// static.
@@ -1326,9 +1332,13 @@ ValueNum ValueNumStore::VNForMapStore(var_types typ, ValueNum arg0VN, ValueNum a
13261332

13271333
ValueNum ValueNumStore::VNForMapSelect(ValueNumKind vnk, var_types typ, ValueNum arg0VN, ValueNum arg1VN)
13281334
{
1329-
unsigned budget = m_mapSelectBudget;
1335+
int budget = m_mapSelectBudget;
13301336
bool usedRecursiveVN = false;
13311337
ValueNum result = VNForMapSelectWork(vnk, typ, arg0VN, arg1VN, &budget, &usedRecursiveVN);
1338+
1339+
// The remaining budget should always be between [0..m_mapSelectBudget]
1340+
assert((budget >= 0) && (budget <= m_mapSelectBudget));
1341+
13321342
#ifdef DEBUG
13331343
if (m_pComp->verbose)
13341344
{
@@ -1362,7 +1372,7 @@ ValueNum ValueNumStore::VNForMapSelect(ValueNumKind vnk, var_types typ, ValueNum
13621372
// (liberal/conservative) to read from the SSA def referenced in the phi argument.
13631373

13641374
ValueNum ValueNumStore::VNForMapSelectWork(
1365-
ValueNumKind vnk, var_types typ, ValueNum arg0VN, ValueNum arg1VN, unsigned* pBudget, bool* pUsedRecursiveVN)
1375+
ValueNumKind vnk, var_types typ, ValueNum arg0VN, ValueNum arg1VN, int* pBudget, bool* pUsedRecursiveVN)
13661376
{
13671377
TailCall:
13681378
// This label allows us to directly implement a tail call by setting up the arguments, and doing a goto to here.
@@ -1393,7 +1403,7 @@ ValueNum ValueNumStore::VNForMapSelectWork(
13931403
{
13941404

13951405
// Give up if we've run out of budget.
1396-
if (--(*pBudget) == 0)
1406+
if (--(*pBudget) <= 0)
13971407
{
13981408
// We have to use 'nullptr' for the basic block here, because subsequent expressions
13991409
// in different blocks may find this result in the VNFunc2Map -- other expressions in
@@ -1491,6 +1501,16 @@ ValueNum ValueNumStore::VNForMapSelectWork(
14911501
ValueNum argRest = phiFuncApp.m_args[1];
14921502
ValueNum sameSelResult =
14931503
VNForMapSelectWork(vnk, typ, phiArgVN, arg1VN, pBudget, pUsedRecursiveVN);
1504+
1505+
// It is possible that we just now exceeded our budget, if so we need to force an early exit
1506+
// and stop calling VNForMapSelectWork
1507+
if (*pBudget <= 0)
1508+
{
1509+
// We don't have any budget remaining to verify that all phiArgs are the same
1510+
// so setup the default failure case now.
1511+
allSame = false;
1512+
}
1513+
14941514
while (allSame && argRest != ValueNumStore::NoVN)
14951515
{
14961516
ValueNum cur = argRest;
@@ -6914,6 +6934,7 @@ void Compiler::fgValueNumberTree(GenTreePtr tree, bool evalAsgLhsInd)
69146934
ValueNumPair op1VNP;
69156935
ValueNumPair op1VNPx = ValueNumStore::VNPForEmptyExcSet();
69166936
vnStore->VNPUnpackExc(tree->gtOp.gtOp1->gtVNPair, &op1VNP, &op1VNPx);
6937+
69176938
tree->gtVNPair =
69186939
vnStore->VNPWithExc(vnStore->VNPairForFunc(tree->TypeGet(),
69196940
GetVNFuncForOper(oper, (tree->gtFlags &

src/jit/valuenum.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,12 @@ class ValueNumStore
225225
unsigned m_numMapSels;
226226
#endif
227227

228+
// This is the constant value used for the default value of m_mapSelectBudget
229+
#define DEFAULT_MAP_SELECT_BUDGET 100 // used by JitVNMapSelBudget
230+
228231
// This is the maximum number of MapSelect terms that can be "considered" as part of evaluation of a top-level
229232
// MapSelect application.
230-
unsigned m_mapSelectBudget;
233+
int m_mapSelectBudget;
231234

232235
public:
233236
// Initializes any static variables of ValueNumStore.
@@ -406,7 +409,7 @@ class ValueNumStore
406409

407410
// A method that does the work for VNForMapSelect and may call itself recursively.
408411
ValueNum VNForMapSelectWork(
409-
ValueNumKind vnk, var_types typ, ValueNum op1VN, ValueNum op2VN, unsigned* pBudget, bool* pUsedRecursiveVN);
412+
ValueNumKind vnk, var_types typ, ValueNum op1VN, ValueNum op2VN, int* pBudget, bool* pUsedRecursiveVN);
410413

411414
// A specialized version of VNForFunc that is used for VNF_MapStore and provides some logging when verbose is set
412415
ValueNum VNForMapStore(var_types typ, ValueNum arg0VN, ValueNum arg1VN, ValueNum arg2VN);

0 commit comments

Comments
 (0)