diff options
author | Fabian Meumertzheim <meumertzheim@code-intelligence.com> | 2021-02-12 14:18:37 +0100 |
---|---|---|
committer | Fabian Meumertzheim <fabian@meumertzhe.im> | 2021-02-22 14:14:52 +0100 |
commit | 0677032a0a698c920f02b44fcf7528fc3a6ce448 (patch) | |
tree | 370a96ae73a0fb0f0ca0e494f9c578f538d8be06 /agent/src/test/java/com/code_intelligence | |
parent | 97942a9f4924ca4c9cad2a2756e44ad29fb44fca (diff) | |
download | jazzer-api-0677032a0a698c920f02b44fcf7528fc3a6ce448.tar.gz |
Skip instrumentation for known no-throw methods
A method invocation only needs to be instrumented for coverage if the
method can throw an exception (including RuntimeException, which is not
declared via `throws`). For methods in the Java standard library
(in `java.*`), this property is thoroughly documented via Javadoc.
This commit adds a doclet, i.e., a Java program that parses Javadoc, for
automatically compiling a list of known no-throw methods in `java.*`.
The list is loaded lazily at runtime and used to skip calls to these
methods in the coverage instrumentation.
With OpenJDK 15, the list consists of almost 9000 methods, many of which
are used very frequently and in performance-critical parts, e.g.,
StringBuilder#append(String) and List#size().
Diffstat (limited to 'agent/src/test/java/com/code_intelligence')
2 files changed, 13 insertions, 8 deletions
diff --git a/agent/src/test/java/com/code_intelligence/jazzer/instrumentor/CoverageInstrumentationTarget.java b/agent/src/test/java/com/code_intelligence/jazzer/instrumentor/CoverageInstrumentationTarget.java index 5725ba23..7502481d 100644 --- a/agent/src/test/java/com/code_intelligence/jazzer/instrumentor/CoverageInstrumentationTarget.java +++ b/agent/src/test/java/com/code_intelligence/jazzer/instrumentor/CoverageInstrumentationTarget.java @@ -23,7 +23,7 @@ public class CoverageInstrumentationTarget implements DynamicTestContract { @Override public Map<String, Boolean> selfCheck() { - Map<String, Boolean> results = new HashMap<>(); + HashMap<String, Boolean> results = new HashMap<>(); results.put("for0", false); results.put("for1", false); @@ -50,16 +50,18 @@ public class CoverageInstrumentationTarget implements DynamicTestContract { return results; } - private void foo(Map<String, Boolean> results) { + private void foo(HashMap<String, Boolean> results) { bar(results); } + // The use of Map instead of HashMap is deliberate here: Since Map#put can throw exceptions, the + // invocation should be instrumented for coverage. private void bar(Map<String, Boolean> results) { results.put("foobar", true); } @SuppressWarnings("unused") - private void baz(Map<String, Boolean> results) { + private void baz(HashMap<String, Boolean> results) { results.put("baz", false); } } diff --git a/agent/src/test/java/com/code_intelligence/jazzer/instrumentor/CoverageInstrumentationTest.kt b/agent/src/test/java/com/code_intelligence/jazzer/instrumentor/CoverageInstrumentationTest.kt index c689e1ac..31f40575 100644 --- a/agent/src/test/java/com/code_intelligence/jazzer/instrumentor/CoverageInstrumentationTest.kt +++ b/agent/src/test/java/com/code_intelligence/jazzer/instrumentor/CoverageInstrumentationTest.kt @@ -55,11 +55,14 @@ class CoverageInstrumentationTest { private val innerForBodyIfSecondRun = 5 private val innerForIncrementCounter = 7 private val outerForIncrementCounter = 8 - private val selfCheckReturn = 9 - private val fooReturn = 10 - private val barReturn = 11 + private val fooInvocation = 9 + private val selfCheckReturn = 10 + private val barInvocation = 11 + private val fooReturn = 12 + private val barMapPutInvocation = 13 + private val barReturn = 14 @Suppress("unused") - private val bazReturn = 12 + private val bazReturn = 15 @Test fun testOriginal() { @@ -91,7 +94,7 @@ class CoverageInstrumentationTest { assertControlFlow( listOf(constructorReturn, ifFirstBranch, ifEnd) + outerForControlFlow + - listOf(barReturn, fooReturn, selfCheckReturn) + listOf(fooInvocation, barInvocation, barMapPutInvocation, barReturn, fooReturn, selfCheckReturn) ) } |