@@ -4349,24 +4349,21 @@ Executor::MemoryUsage Executor::checkMemoryUsage() {
43494349
43504350 const auto &states = objectManager->getStates ();
43514351 const auto numStates = states.size ();
4352- const auto lastMaxNumStates =
4353- std::max (1UL , (unsigned long )(MaxMemory / lastWeightOfState));
4352+ const auto lastTotalUsage = (unsigned long )(lastWeightOfState * numStates);
43544353
43554354 // We need to avoid calling GetTotalMallocUsage() often because it
43564355 // is O(elts on freelist). This is really bad since we start
43574356 // to pummel the freelist once we hit the memory cap.
43584357 // every 65536 instructions
43594358 if ((stats::instructions & 0xFFFFU ) != 0 &&
4360- numStates < lastMaxNumStates * 0.4 )
4359+ lastTotalUsage <= MaxMemory * 1.01 )
43614360 return None;
43624361
43634362 // check memory limit
43644363
43654364 const auto totalUsage = getMemoryUsage () >> 20U ;
43664365 const auto weightOfState = std::max (0.001 , (double )totalUsage / numStates);
43674366 lastWeightOfState = weightOfState;
4368- const auto maxNumStates =
4369- std::max (1UL , (unsigned long )(MaxMemory / weightOfState));
43704367
43714368 if (MemoryTriggerCoverOnTheFly && totalUsage > MaxMemory * 0.75 ) {
43724369 klee_warning_once (0 ,
@@ -4376,10 +4373,9 @@ Executor::MemoryUsage Executor::checkMemoryUsage() {
43764373 }
43774374 // just guess at how many to kill
43784375 // only terminate states when threshold (+1%) exceeded
4379- if (totalUsage < MaxMemory * 0.6 && numStates < maxNumStates * 0.4 ) {
4376+ if (totalUsage < MaxMemory * 0.6 ) {
43804377 return Executor::Low;
4381- } else if (totalUsage <= MaxMemory * 1.01 &&
4382- numStates <= maxNumStates * 0.7 ) {
4378+ } else if (totalUsage <= MaxMemory * 1.01 ) {
43834379 return Executor::High;
43844380 }
43854381
@@ -4388,13 +4384,13 @@ Executor::MemoryUsage Executor::checkMemoryUsage() {
43884384 return Executor::None;
43894385 }
43904386
4391- auto toKill =
4392- std::min (numStates - 1 , numStates - (unsigned long )(maxNumStates * 0.4 ));
4387+ auto toKill = std::max (1UL , numStates - numStates * MaxMemory / totalUsage);
43934388
43944389 if (toKill != 0 ) {
43954390 klee_warning (" killing %lu states (total memory usage: %luMB)" , toKill,
43964391 totalUsage);
43974392 }
4393+
43984394 unsigned long killed = 0 ;
43994395 for (states_ty::iterator it = states.begin (), ie = states.end ();
44004396 it != ie && killed < toKill; ++it) {
@@ -4416,9 +4412,6 @@ Executor::MemoryUsage Executor::checkMemoryUsage() {
44164412 killed++;
44174413 }
44184414 }
4419- if (toKill != 0 ) {
4420- klee_warning (" stop killing" );
4421- }
44224415
44234416 return Executor::Full;
44244417}
@@ -4479,20 +4472,22 @@ const KFunction *Executor::getKFunction(const llvm::Function *f) const {
44794472}
44804473
44814474std::vector<ExecutingSeed> Executor::uploadNewSeeds () {
4482- // just guess at how many to kill
44834475 auto &states = objectManager->getStates ();
4484- const auto numStates = std::max ( 1UL , states.size () );
4485- const auto maxNumStates =
4486- std::max ( 1UL , ( unsigned long )(MaxMemory / lastWeightOfState));
4476+ const auto numStates = states.size ();
4477+ const auto lastTotalUsage = ( unsigned long )(lastWeightOfState * numStates);
4478+
44874479 std::vector<ExecutingSeed> seeds;
4488- unsigned long numStoredSeeds = storedSeeds->size ();
4489- unsigned long toUpload =
4490- numStates < maxNumStates * 0.4 ? maxNumStates * 0.4 - numStates : 0 ;
4491- toUpload = std::min (toUpload, numStoredSeeds);
4480+ if (lastTotalUsage < MaxMemory * 0.6 ) {
4481+ unsigned long numStoredSeeds = storedSeeds->size ();
4482+ auto toUpload =
4483+ std::max (numStoredSeeds,
4484+ numStoredSeeds - numStoredSeeds * lastTotalUsage / MaxMemory);
4485+ toUpload = std::min (toUpload, numStoredSeeds);
44924486
4493- while ((!toUpload || seeds.size () <= toUpload) && !storedSeeds->empty ()) {
4494- seeds.push_back (storedSeeds->front ());
4495- storedSeeds->pop_front ();
4487+ while ((!toUpload || seeds.size () <= toUpload) && !storedSeeds->empty ()) {
4488+ seeds.push_back (storedSeeds->front ());
4489+ storedSeeds->pop_front ();
4490+ }
44964491 }
44974492 return seeds;
44984493}
@@ -4693,7 +4688,7 @@ void Executor::executeAction(ref<SearcherAction> action) {
46934688 timers.invoke ();
46944689}
46954690
4696- void Executor::unseedIfReachedMacSeedInstructions (ExecutionState *state) {
4691+ void Executor::unseedIfReachedMaxSeedInstructions (ExecutionState *state) {
46974692 assert (state->isSeeded );
46984693 auto it = seedMap->find (state);
46994694 assert (it != seedMap->end ());
@@ -4749,7 +4744,7 @@ void Executor::goForward(ref<ForwardAction> action) {
47494744 targetManager->pullGlobal (state);
47504745 }
47514746 if (state.isSeeded ) {
4752- unseedIfReachedMacSeedInstructions (&state);
4747+ unseedIfReachedMaxSeedInstructions (&state);
47534748 }
47544749 if (targetCalculator && TrackCoverage != TrackCoverageBy::None &&
47554750 state.multiplexKF && functionsByModule.modules .size () > 1 &&
@@ -4920,6 +4915,13 @@ void Executor::terminateStateEarly(ExecutionState &state, const Twine &message,
49204915 if (success) {
49214916 storedSeeds->push_back (seed);
49224917 }
4918+ if (shouldWriteTest (state)) {
4919+ interpreterHandler->processTestCase (
4920+ state, (message + " \n " ).str ().c_str (),
4921+ terminationTypeFileExtension (reason).c_str (),
4922+ reason > StateTerminationType::EARLY &&
4923+ reason <= StateTerminationType::EXECERR);
4924+ }
49234925 } else if (((reason <= StateTerminationType::EARLY ||
49244926 reason == StateTerminationType::MissedAllTargets) &&
49254927 shouldWriteTest (state)) ||
0 commit comments