@@ -259,6 +259,22 @@ class TraceState {
259
259
Signed >>= 16 ;
260
260
return Signed == 0 || Signed == -1L ;
261
261
}
262
+
263
+ // We don't want to create too many trace-based mutations as it is both
264
+ // expensive and useless. So after some number of mutations is collected,
265
+ // start rejecting some of them. The more there are mutations the more we
266
+ // reject.
267
+ bool WantToHandleOneMoreMutation () {
268
+ const size_t FirstN = 64 ;
269
+ // Gladly handle first N mutations.
270
+ if (NumMutations <= FirstN) return true ;
271
+ size_t Diff = NumMutations - FirstN;
272
+ size_t DiffLog = sizeof (long ) * 8 - __builtin_clzl ((long )Diff);
273
+ assert (DiffLog > 0 && DiffLog < 64 );
274
+ bool WantThisOne = USF.GetRand ()(1 << DiffLog) == 0 ; // 1 out of DiffLog.
275
+ return WantThisOne;
276
+ }
277
+
262
278
static const size_t kMaxMutations = 1 << 16 ;
263
279
size_t NumMutations;
264
280
TraceBasedMutation Mutations[kMaxMutations ];
@@ -362,7 +378,7 @@ void TraceState::DFSanSwitchCallback(uint64_t PC, size_t ValSizeInBits,
362
378
363
379
int TraceState::TryToAddDesiredData (uint64_t PresentData, uint64_t DesiredData,
364
380
size_t DataSize) {
365
- if (NumMutations >= kMaxMutations ) return 0 ;
381
+ if (NumMutations >= kMaxMutations || ! WantToHandleOneMoreMutation () ) return 0 ;
366
382
int Res = 0 ;
367
383
const uint8_t *Beg = *CurrentUnitData;
368
384
const uint8_t *End = Beg + *CurrentUnitSize;
@@ -383,7 +399,7 @@ int TraceState::TryToAddDesiredData(uint64_t PresentData, uint64_t DesiredData,
383
399
int TraceState::TryToAddDesiredData (const uint8_t *PresentData,
384
400
const uint8_t *DesiredData,
385
401
size_t DataSize) {
386
- if (NumMutations >= kMaxMutations ) return 0 ;
402
+ if (NumMutations >= kMaxMutations || ! WantToHandleOneMoreMutation () ) return 0 ;
387
403
int Res = 0 ;
388
404
const uint8_t *Beg = *CurrentUnitData;
389
405
const uint8_t *End = Beg + *CurrentUnitSize;
0 commit comments