diff --git a/aeneas/src/ic/IcCoverage.v3 b/aeneas/src/ic/IcCoverage.v3 index dfbf57327..6c9de26a6 100644 --- a/aeneas/src/ic/IcCoverage.v3 +++ b/aeneas/src/ic/IcCoverage.v3 @@ -2,15 +2,11 @@ // See LICENSE for details of Apache 2.0 license. // a code-coverage analyzer for IC code -class IcCoverage(compiler: Compiler, prog: Program, matcher: VstMatcher, instr: bool) { +class IcCoverage(compiler: Compiler, prog: Program, instr: bool) { var icmList: List; - new() { - compiler.icMon = onGen; - } // every time an IcMethod is generated, probe all its instructions def onGen(memberRef: IrSpec, icm: IcMethod) { - if (!matcher.matches(memberRef.source())) return; icmList = List.new(icm, icmList); for (i < icm.iccode.length) { icm.addProbeBefore(i, fire); diff --git a/aeneas/src/ic/IcProfiler.v3 b/aeneas/src/ic/IcProfiler.v3 index 27e5697ba..d56e77aac 100644 --- a/aeneas/src/ic/IcProfiler.v3 +++ b/aeneas/src/ic/IcProfiler.v3 @@ -4,14 +4,8 @@ // This class provides profiling infrastructure for Ic code, // include per-method profiling. class IcTreeProfiler extends TreeProfiler { - def matcher: VstMatcher; - - new(compiler: Compiler, matcher) { - compiler.icMon = onGen; - } // instrument the entry instruction and each return instruction def onGen(memberRef: IrSpec, icm: IcMethod) { - if (!matcher.matches(memberRef.source())) return; // do per-method CCT profiling for (i < icm.iccode.length) { var j = icm.iccode[i]; @@ -41,13 +35,10 @@ class IcInstrProfiler { var curProf: IcMethodProf; // current profiling information var curFrame: IcFrame; // current frame var printer: IcPrinter; - def matcher: VstMatcher; - new(compiler: Compiler, prog, matcher) { - compiler.icMon = onGen; + new(compiler: Compiler, prog) { } def onGen(memberRef: IrSpec, icm: IcMethod) { - if (!matcher.matches(memberRef.source())) return; // do per-instruction profiling var len = icm.iccode.length, pm = IcMethodProf.new(icm); profMap[icm] = pm; diff --git a/aeneas/src/main/Aeneas.v3 b/aeneas/src/main/Aeneas.v3 index efee24a11..7cbf038f7 100644 --- a/aeneas/src/main/Aeneas.v3 +++ b/aeneas/src/main/Aeneas.v3 @@ -87,14 +87,35 @@ component Aeneas { var compilation = Compilation.new(compiler, prog); var after: void -> void; if (CLOptions.COVERAGE.val != VstMatcher.None) { - if (CLOptions.SSA_INT.val) after = SsaCoverage.new(compiler, prog, CLOptions.COVERAGE.val, CLOptions.INSTR_COVERAGE.val).report; - else after = IcCoverage.new(compiler, prog, CLOptions.COVERAGE.val, CLOptions.INSTR_COVERAGE.val).report; + if (CLOptions.SSA_INT.val) { + var p = SsaCoverage.new(compiler, prog, CLOptions.INSTR_COVERAGE.val); + compiler.ssaMon = compiler.filter(CLOptions.COVERAGE.val, _, p.onGen); + after = p.report; + } else { + var p = IcCoverage.new(compiler, prog, CLOptions.INSTR_COVERAGE.val); + compiler.icMon = compiler.filterIc(CLOptions.COVERAGE.val, _, _, p.onGen); + after = p.report; + } } else if (CLOptions.INSTR_PROFILE.val != VstMatcher.None) { - if (CLOptions.SSA_INT.val) after = SsaBlockProfiler.new(compiler, CLOptions.INSTR_PROFILE.val).report; - else after = IcInstrProfiler.new(compiler, prog, CLOptions.INSTR_PROFILE.val).report; + if (CLOptions.SSA_INT.val) { + var p = SsaBlockProfiler.new(); + compiler.ssaMon = compiler.filter(CLOptions.INSTR_PROFILE.val, _, p.onGen); + after = p.report; + } else { + var p = IcInstrProfiler.new(compiler, prog); + compiler.icMon = compiler.filterIc(CLOptions.INSTR_PROFILE.val, _, _, p.onGen); + after = p.report; + } } else if (CLOptions.PROFILE.val != VstMatcher.None) { - if (CLOptions.SSA_INT.val) after = SsaTreeProfiler.new(compiler, CLOptions.PROFILE.val).report; - else after = IcTreeProfiler.new(compiler, CLOptions.PROFILE.val).report; + if (CLOptions.SSA_INT.val) { + var p = SsaTreeProfiler.new(); + compiler.ssaMon = compiler.filter(CLOptions.PROFILE.val, _, p.onGen); + after = p.report; + } else { + var p = IcTreeProfiler.new(); + compiler.icMon = compiler.filterIc(CLOptions.PROFILE.val, _, _, p.onGen); + after = p.report; + } } compilation.compile(); if (!prog.reportErrors()) return -1; diff --git a/aeneas/src/main/Compiler.v3 b/aeneas/src/main/Compiler.v3 index a7931503b..933ff0002 100644 --- a/aeneas/src/main/Compiler.v3 +++ b/aeneas/src/main/Compiler.v3 @@ -141,6 +141,12 @@ class Compiler(target: Target) { def boundsCheck(facts: Fact.set) -> bool { return !DisableBoundsChecks && !facts.O_NO_BOUNDS_CHECK; } + def filter(matcher: VstMatcher, spec: IrSpec, f: IrSpec -> void) { + if (matcher.matches(spec.asMethod().source)) f(spec); + } + def filterIc(matcher: VstMatcher, spec: IrSpec, icm: IcMethod, f: (IrSpec, IcMethod) -> void) { + if (matcher.matches(spec.asMethod().source)) f(spec, icm); + } } def BASH_HEADER = [ "#!/bin/bash\n", diff --git a/aeneas/src/main/Version.v3 b/aeneas/src/main/Version.v3 index 0ff837b03..9e75979ad 100644 --- a/aeneas/src/main/Version.v3 +++ b/aeneas/src/main/Version.v3 @@ -3,6 +3,6 @@ // Updated by VCS scripts. DO NOT EDIT. component Version { - def version: string = "III-7.1659"; + def version: string = "III-7.1660"; var buildData: string; } diff --git a/aeneas/src/ssa/SsaCoverage.v3 b/aeneas/src/ssa/SsaCoverage.v3 index 2200d1dca..b939e2be9 100644 --- a/aeneas/src/ssa/SsaCoverage.v3 +++ b/aeneas/src/ssa/SsaCoverage.v3 @@ -1,14 +1,10 @@ // Copyright 2023 Virgil authors. All rights reserved. // See LICENSE for details of Apache 2.0 license. -class SsaCoverage(compiler: Compiler, prog: Program, matcher: VstMatcher, instr: bool) { +class SsaCoverage(compiler: Compiler, prog: Program, instr: bool) { var methList: List; - new() { - compiler.ssaMon = onGen; - } def onGen(memberRef: IrSpec) { - if (!matcher.matches(memberRef.source())) return; var m = memberRef.asMethod(); methList = List.new(m, methList); for (b in m.ssa.bfBlocks(null)) { diff --git a/aeneas/src/ssa/SsaProfiler.v3 b/aeneas/src/ssa/SsaProfiler.v3 index 3748a0042..b2734487a 100644 --- a/aeneas/src/ssa/SsaProfiler.v3 +++ b/aeneas/src/ssa/SsaProfiler.v3 @@ -3,16 +3,9 @@ // Implements a call-tree profiler by instrumenting SSA. class SsaTreeProfiler extends TreeProfiler { - def matcher: VstMatcher; - - new(compiler: Compiler, matcher) { - compiler.ssaMon = onGen; - } // instrument the entry instruction and each return instruction def onGen(memberRef: IrSpec) { - var meth = memberRef.asMethod(); - if (!matcher.matches(meth.source)) return; - var graph = meth.ssa; + var graph = memberRef.asMethod().ssa; for (b in graph.bfBlocks(null)) { for (i = b.next; i != b; i = i.next) { match (i) { @@ -54,12 +47,8 @@ private class SsaTreeProfilerRetProbe(profiler: SsaTreeProfiler) extends SsaProb // Implements a basic-block profiler for SSA. class SsaBlockProfiler { - def matcher: VstMatcher; - var list: List; + var list: List; // only report instrumented methods - new(compiler: Compiler, matcher) { - compiler.ssaMon = onGen; - } def report() { var all = Arrays.map(Lists.toArray(list), computeMaximum); all = Arrays.sort(all, 0, all.length, byMaximum); @@ -70,10 +59,8 @@ class SsaBlockProfiler { } def onGen(memberRef: IrSpec) { var meth = memberRef.asMethod(); - if (!matcher.matches(meth.source)) return; - list = List.new(memberRef.asMethod(), list); - var graph = meth.ssa; - for (b in graph.bfBlocks(null)) { + list = List.new(meth, list); + for (b in meth.ssa.bfBlocks(null)) { var i = b.next; var p = SsaBlockProfilerProbe.new(); while (i != b && SsaPhi.?(i)) i = i.next;