Skip to content

Commit 3f6aaa9

Browse files
pieter-bosPieter Bos
andauthored
Improve SymbExLogger (#622)
* Improve SymbExLogger: - Thread safe as long as silicon parallelizes up to the entity level: SymbLog itself is not thread safe. --ideModeAdvanced accordingly does not require --numberOfParallelVerifiers 1 anymore. - Change SymbLog to accept a listener for appropriate events. * move smt delta calculation to ProverStdIO for thread safety * move smt statistics calculations out of ProverStdIO * Bump silver submodule to master branch version * move symbexlogger state into classes, shim the old usage * make Verifier own a current MemberSymbExLogger * Give Verifier the capability to open symbexlogs for members The root symbexlog comes from Silicon and is computed explicitly on configuration, so it can be overridden From there, the MainVerifier owns the root log, and WorkerVerifiers ask the MainVerifier for a member-scoped symbexlog * swap out shims * some bugs: - do not use newEntityLogger directly, because it's not inserted in the members of the root log - synchronize on the log instead of the map, because I'm using a var instead of mutable.Map - delay opening the member scope to avoid using early initializers * address comment * make NoopLog do nothing * also do nothing on whenEnabled for NoopLog * symbexlogs can be closed: they do not accept further records (now unrelated to closeMemberScope) * close log on timeout * SymbExLogger.ofConfig makes the silicon slightly less lazy, so invalid options are not silently ignored when doing nothing * use NoopMemberSymbExLog if there is no log yet (a bug, but better than crashing) disallow use of ideModeAdvanced in the presence of parallelizeBranches * move config to concrete logger; state is always null, so drop it. * update silver * change by-name trickery to lambdas * remove debug println * namespace Member * clarify val names for Config vs LogConfig * Revert "change by-name trickery to lambdas" This reverts commit 505c61b. * validateFileOpt already checks whether the file exists * log a warning when the symbexlog config cannot be parsed * no delta for values not yet encountered * use the symbExLog of the current verifier * resolve warnings: clean up imports; mark unused vals as @unused * missed merge conflict: just use ours * adjust documentation * update silver Co-authored-by: Pieter Bos <p.h.bos@student.utwente.nl>
1 parent 2f72f07 commit 3f6aaa9

36 files changed

Lines changed: 471 additions & 457 deletions

src/main/scala/Config.scala

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -754,19 +754,15 @@ class Config(args: Seq[String]) extends SilFrontendConfig(args, "Silicon") {
754754
case _ => Right(())
755755
}
756756

757-
validateOpt(ideModeAdvanced, numberOfParallelVerifiers) {
758-
case (Some(false), _) =>
759-
Right(())
760-
case (Some(true), Some(n)) =>
761-
if (n == 1)
762-
Right(())
763-
else
764-
Left( s"Option ${ideModeAdvanced.name} requires setting "
765-
+ s"${numberOfParallelVerifiers.name} to 1")
757+
validateOpt(ideModeAdvanced, parallelizeBranches) {
758+
case (Some(false), _) => Right(())
759+
case (_, Some(false)) => Right(())
760+
case (Some(true), Some(true)) =>
761+
Left(s"Option ${ideModeAdvanced.name} is not supported in combination with ${parallelizeBranches.name}")
766762
case other =>
767763
sys.error(s"Unexpected combination: $other")
768764
}
769-
765+
770766
validateOpt(counterexample, enableMoreCompleteExhale) {
771767
case (Some(_), Some(false)) => Left( s"Option ${counterexample.name} requires setting "
772768
+ s"flag ${enableMoreCompleteExhale.name}")

src/main/scala/Silicon.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ package viper.silicon
88

99
import java.text.SimpleDateFormat
1010
import java.util.concurrent.{Callable, Executors, TimeUnit, TimeoutException}
11-
1211
import scala.collection.immutable.ArraySeq
1312
import scala.util.{Left, Right}
1413
import ch.qos.logback.classic.{Level, Logger}
@@ -19,7 +18,7 @@ import viper.silver.frontend.{DefaultStates, SilFrontend}
1918
import viper.silver.reporter._
2019
import viper.silver.verifier.{AbstractVerificationError => SilAbstractVerificationError, Failure => SilFailure, Success => SilSuccess, TimeoutOccurred => SilTimeoutOccurred, VerificationResult => SilVerificationResult, Verifier => SilVerifier}
2120
import viper.silicon.interfaces.Failure
22-
import viper.silicon.logger.SymbExLogger
21+
import viper.silicon.logger.{MemberSymbExLogger, SymbExLogger}
2322
import viper.silicon.reporting.{MultiRunRecorders, condenseToViperResult}
2423
import viper.silicon.verifier.DefaultMainVerifier
2524
import viper.silicon.decider.{Cvc5ProverStdIO, Z3ProverStdIO}
@@ -93,6 +92,10 @@ class Silicon(val reporter: Reporter, private var debugInfo: Seq[(String, Any)]
9392
private var _config: Config = _
9493
final def config = _config
9594

95+
private var _symbExLog: SymbExLogger[_ <: MemberSymbExLogger] = _
96+
final def symbExLog = _symbExLog
97+
final def symbExLog_=(log: SymbExLogger[_ <: MemberSymbExLogger]) = { _symbExLog = log }
98+
9699
private sealed trait LifetimeState
97100

98101
private object LifetimeState {
@@ -113,6 +116,7 @@ class Silicon(val reporter: Reporter, private var debugInfo: Seq[(String, Any)]
113116
lifetimeState = LifetimeState.Configured
114117

115118
_config = new Config(args)
119+
_symbExLog = SymbExLogger.ofConfig(_config)
116120
}
117121

118122
def debugInfo(debugInfo: Seq[(String, Any)]): Unit = { this.debugInfo = debugInfo }
@@ -129,7 +133,7 @@ class Silicon(val reporter: Reporter, private var debugInfo: Seq[(String, Any)]
129133

130134
setLogLevelsFromConfig()
131135

132-
verifier = new DefaultMainVerifier(config, reporter)
136+
verifier = new DefaultMainVerifier(config, reporter, symbExLog)
133137
verifier.start()
134138
}
135139

@@ -202,10 +206,9 @@ class Silicon(val reporter: Reporter, private var debugInfo: Seq[(String, Any)]
202206
result = Some(condenseToViperResult(failures))
203207
} catch { /* Catch exceptions thrown during verification (errors are not caught) */
204208
case _: TimeoutException =>
205-
// verification was interrupted, therefore close the current member's scope:
206-
SymbExLogger.currentLog().closeMemberScope()
207209
if (config.ideModeAdvanced()) {
208-
reporter report ExecutionTraceReport(SymbExLogger.memberList, List(), List())
210+
symbExLog.close()
211+
reporter report ExecutionTraceReport(symbExLog.logs.toSeq, List(), List())
209212
}
210213
result = Some(SilFailure(SilTimeoutOccurred(config.timeout(), "second(s)") :: Nil))
211214
case exception: Exception if !config.disableCatchingExceptions() =>

src/main/scala/decider/Decider.scala

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import viper.silicon._
1515
import viper.silicon.common.collections.immutable.InsertionOrderedSet
1616
import viper.silicon.interfaces._
1717
import viper.silicon.interfaces.decider._
18-
import viper.silicon.logger.SymbExLogger
1918
import viper.silicon.logger.records.data.{DeciderAssertRecord, DeciderAssumeRecord, ProverAssertRecord}
2019
import viper.silicon.state._
2120
import viper.silicon.state.terms._
@@ -183,18 +182,18 @@ trait DefaultDeciderProvider extends VerifierComponent { this: Verifier =>
183182

184183
def pushScope(): Unit = {
185184
//val commentRecord = new CommentRecord("push", null, null)
186-
//val sepIdentifier = SymbExLogger.currentLog().openScope(commentRecord)
185+
//val sepIdentifier = symbExLog.openScope(commentRecord)
187186
pathConditions.pushScope()
188187
_prover.push(timeout = Verifier.config.pushTimeout.toOption)
189-
//SymbExLogger.currentLog().closeScope(sepIdentifier)
188+
//symbExLog.closeScope(sepIdentifier)
190189
}
191190

192191
def popScope(): Unit = {
193192
//val commentRecord = new CommentRecord("pop", null, null)
194-
//val sepIdentifier = SymbExLogger.currentLog().openScope(commentRecord)
193+
//val sepIdentifier = symbExLog.openScope(commentRecord)
195194
_prover.pop()
196195
pathConditions.popScope()
197-
//SymbExLogger.currentLog().closeScope(sepIdentifier)
196+
//symbExLog.closeScope(sepIdentifier)
198197
}
199198

200199
def setCurrentBranchCondition(t: Term, te: Option[ast.Exp] = None): Unit = {
@@ -223,15 +222,15 @@ trait DefaultDeciderProvider extends VerifierComponent { this: Verifier =>
223222

224223
private def assumeWithoutSmokeChecks(terms: InsertionOrderedSet[Term]) = {
225224
val assumeRecord = new DeciderAssumeRecord(terms)
226-
val sepIdentifier = SymbExLogger.currentLog().openScope(assumeRecord)
225+
val sepIdentifier = symbExLog.openScope(assumeRecord)
227226

228227
/* Add terms to Silicon-managed path conditions */
229228
terms foreach pathConditions.add
230229

231230
/* Add terms to the prover's assumptions */
232231
terms foreach prover.assume
233232

234-
SymbExLogger.currentLog().closeScope(sepIdentifier)
233+
symbExLog.closeScope(sepIdentifier)
235234
None
236235
}
237236

@@ -252,21 +251,21 @@ trait DefaultDeciderProvider extends VerifierComponent { this: Verifier =>
252251
// previously (it did not cause a verification failure) and ignore the
253252
// current one, because it cannot cause a verification error.
254253
if (success)
255-
SymbExLogger.currentLog().discardSMTQuery()
254+
symbExLog.discardSMTQuery()
256255
else
257-
SymbExLogger.currentLog().setSMTQuery(t)
256+
symbExLog.setSMTQuery(t)
258257

259258
Q(success)
260259
}
261260

262261
private def deciderAssert(t: Term, timeout: Option[Int]) = {
263262
val assertRecord = new DeciderAssertRecord(t, timeout)
264-
val sepIdentifier = SymbExLogger.currentLog().openScope(assertRecord)
263+
val sepIdentifier = symbExLog.openScope(assertRecord)
265264

266265
val asserted = isKnownToBeTrue(t)
267266
val result = asserted || proverAssert(t, timeout)
268267

269-
SymbExLogger.currentLog().closeScope(sepIdentifier)
268+
symbExLog.closeScope(sepIdentifier)
270269
result
271270
}
272271

@@ -280,17 +279,15 @@ trait DefaultDeciderProvider extends VerifierComponent { this: Verifier =>
280279

281280
private def proverAssert(t: Term, timeout: Option[Int]) = {
282281
val assertRecord = new ProverAssertRecord(t, timeout)
283-
val sepIdentifier = SymbExLogger.currentLog().openScope(assertRecord)
282+
val sepIdentifier = symbExLog.openScope(assertRecord)
284283

285284
val result = prover.assert(t, timeout)
286285

287-
if (SymbExLogger.enabled) {
288-
val statistics = prover.statistics()
289-
val deltaStatistics = SymbExLogger.getDeltaSmtStatistics(statistics)
290-
assertRecord.statistics = Some(statistics ++ deltaStatistics)
286+
symbExLog.whenEnabled {
287+
assertRecord.statistics = Some(symbExLog.deltaStatistics(prover.statistics()))
291288
}
292289

293-
SymbExLogger.currentLog().closeScope(sepIdentifier)
290+
symbExLog.closeScope(sepIdentifier)
294291

295292
result
296293
}

src/main/scala/logger/LogConfig.scala

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,23 @@
77
package viper.silicon.logger
88

99
import spray.json._
10+
import viper.silicon.logger.records.data.DataRecord
1011

1112
case class LogConfig(isBlackList: Boolean,
1213
includeStore: Boolean, includeHeap: Boolean, includeOldHeap: Boolean, includePcs: Boolean,
13-
recordConfigs: List[RecordConfig])
14+
recordConfigs: List[RecordConfig]) {
15+
def getRecordConfig(d: DataRecord): Option[RecordConfig] = {
16+
for (rc <- recordConfigs) {
17+
if (rc.kind.equals(d.toTypeString)) {
18+
rc.value match {
19+
case Some(value) => if (value.equals(d.toSimpleString)) return Some(rc)
20+
case None => return Some(rc)
21+
}
22+
}
23+
}
24+
None
25+
}
26+
}
1427

1528
object LogConfig {
1629
def default(): LogConfig = LogConfig(

0 commit comments

Comments
 (0)