seafoam 0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/probots.yml +2 -0
- data/.github/workflows/rubocop.yml +10 -0
- data/.github/workflows/specs.yml +19 -0
- data/.gitignore +7 -0
- data/.rubocop.yml +34 -0
- data/.ruby-version +1 -0
- data/.seafoam/config +1 -0
- data/CODE_OF_CONDUCT.md +128 -0
- data/CONTRIBUTING.md +5 -0
- data/Gemfile +2 -0
- data/LICENSE.md +7 -0
- data/README.md +298 -0
- data/bin/bgv2isabelle +53 -0
- data/bin/bgv2json +42 -0
- data/bin/seafoam +24 -0
- data/docs/annotators.md +43 -0
- data/docs/bgv.md +284 -0
- data/docs/getting-graphs.md +47 -0
- data/examples/Fib.java +24 -0
- data/examples/MatMult.java +39 -0
- data/examples/fib-java.bgv +0 -0
- data/examples/fib-js.bgv +0 -0
- data/examples/fib-ruby.bgv +0 -0
- data/examples/fib.js +15 -0
- data/examples/fib.rb +15 -0
- data/examples/identity.bgv +0 -0
- data/examples/identity.rb +13 -0
- data/examples/java/Irreducible.j +35 -0
- data/examples/java/IrreducibleDecompiled.java +21 -0
- data/examples/java/JavaExamples.java +418 -0
- data/examples/java/exampleArithOperator.bgv +0 -0
- data/examples/java/exampleArithOperator.cfg +925 -0
- data/examples/java/exampleArrayAllocation.bgv +0 -0
- data/examples/java/exampleArrayAllocation.cfg +5268 -0
- data/examples/java/exampleArrayRead.bgv +0 -0
- data/examples/java/exampleArrayRead.cfg +2263 -0
- data/examples/java/exampleArrayWrite.bgv +0 -0
- data/examples/java/exampleArrayWrite.cfg +2315 -0
- data/examples/java/exampleCatch.bgv +0 -0
- data/examples/java/exampleCatch.cfg +4150 -0
- data/examples/java/exampleCompareOperator.bgv +0 -0
- data/examples/java/exampleCompareOperator.cfg +1109 -0
- data/examples/java/exampleDoubleSynchronized.bgv +0 -0
- data/examples/java/exampleDoubleSynchronized.cfg +26497 -0
- data/examples/java/exampleExactArith.bgv +0 -0
- data/examples/java/exampleExactArith.cfg +1888 -0
- data/examples/java/exampleFieldRead.bgv +0 -0
- data/examples/java/exampleFieldRead.cfg +1228 -0
- data/examples/java/exampleFieldWrite.bgv +0 -0
- data/examples/java/exampleFieldWrite.cfg +1102 -0
- data/examples/java/exampleFor.bgv +0 -0
- data/examples/java/exampleFor.cfg +3936 -0
- data/examples/java/exampleFullEscape.bgv +0 -0
- data/examples/java/exampleFullEscape.cfg +5893 -0
- data/examples/java/exampleIf.bgv +0 -0
- data/examples/java/exampleIf.cfg +2462 -0
- data/examples/java/exampleIfNeverTaken.bgv +0 -0
- data/examples/java/exampleIfNeverTaken.cfg +2476 -0
- data/examples/java/exampleInstanceOfManyImpls.bgv +0 -0
- data/examples/java/exampleInstanceOfManyImpls.cfg +6391 -0
- data/examples/java/exampleInstanceOfOneImpl.bgv +0 -0
- data/examples/java/exampleInstanceOfOneImpl.cfg +2604 -0
- data/examples/java/exampleIntSwitch.bgv +0 -0
- data/examples/java/exampleIntSwitch.cfg +3121 -0
- data/examples/java/exampleInterfaceCallManyImpls.bgv +0 -0
- data/examples/java/exampleInterfaceCallManyImpls.cfg +1358 -0
- data/examples/java/exampleInterfaceCallOneImpl.bgv +0 -0
- data/examples/java/exampleInterfaceCallOneImpl.cfg +3859 -0
- data/examples/java/exampleLocalInstanceOf.bgv +0 -0
- data/examples/java/exampleLocalInstanceOf.cfg +5276 -0
- data/examples/java/exampleLocalSynchronized.bgv +0 -0
- data/examples/java/exampleLocalSynchronized.cfg +1364 -0
- data/examples/java/exampleLocalVariables.bgv +0 -0
- data/examples/java/exampleLocalVariables.cfg +1195 -0
- data/examples/java/exampleLocalVariablesState.bgv +0 -0
- data/examples/java/exampleLocalVariablesState.cfg +1673 -0
- data/examples/java/exampleNestedWhile.bgv +0 -0
- data/examples/java/exampleNestedWhile.cfg +15499 -0
- data/examples/java/exampleNestedWhileBreak.bgv +0 -0
- data/examples/java/exampleNestedWhileBreak.cfg +11162 -0
- data/examples/java/exampleNoEscape.bgv +0 -0
- data/examples/java/exampleNoEscape.cfg +974 -0
- data/examples/java/exampleObjectAllocation.bgv +0 -0
- data/examples/java/exampleObjectAllocation.cfg +5287 -0
- data/examples/java/examplePartialEscape.bgv +0 -0
- data/examples/java/examplePartialEscape.cfg +7042 -0
- data/examples/java/examplePhi.bgv +0 -0
- data/examples/java/examplePhi.cfg +3227 -0
- data/examples/java/exampleReducible.bgv +0 -0
- data/examples/java/exampleReducible.cfg +5578 -0
- data/examples/java/exampleSimpleCall.bgv +0 -0
- data/examples/java/exampleSimpleCall.cfg +1435 -0
- data/examples/java/exampleStamp.bgv +0 -0
- data/examples/java/exampleStamp.cfg +913 -0
- data/examples/java/exampleStaticCall.bgv +0 -0
- data/examples/java/exampleStaticCall.cfg +1154 -0
- data/examples/java/exampleStringSwitch.bgv +0 -0
- data/examples/java/exampleStringSwitch.cfg +15377 -0
- data/examples/java/exampleSynchronized.bgv +0 -0
- data/examples/java/exampleSynchronized.cfg +26027 -0
- data/examples/java/exampleThrow.bgv +0 -0
- data/examples/java/exampleThrow.cfg +780 -0
- data/examples/java/exampleThrowCatch.bgv +0 -0
- data/examples/java/exampleThrowCatch.cfg +744 -0
- data/examples/java/exampleUnsafeRead.bgv +0 -0
- data/examples/java/exampleUnsafeRead.cfg +912 -0
- data/examples/java/exampleUnsafeWrite.bgv +0 -0
- data/examples/java/exampleUnsafeWrite.cfg +962 -0
- data/examples/java/exampleWhile.bgv +0 -0
- data/examples/java/exampleWhile.cfg +3936 -0
- data/examples/java/exampleWhileBreak.bgv +0 -0
- data/examples/java/exampleWhileBreak.cfg +5963 -0
- data/examples/matmult-java.bgv +0 -0
- data/examples/matmult-ruby.bgv +0 -0
- data/examples/matmult.rb +29 -0
- data/examples/overflow.bgv +0 -0
- data/examples/overflow.rb +13 -0
- data/lib/seafoam.rb +13 -0
- data/lib/seafoam/annotators.rb +54 -0
- data/lib/seafoam/annotators/fallback.rb +27 -0
- data/lib/seafoam/annotators/graal.rb +376 -0
- data/lib/seafoam/bgv/bgv_parser.rb +602 -0
- data/lib/seafoam/binary/binary_reader.rb +21 -0
- data/lib/seafoam/binary/io_binary_reader.rb +88 -0
- data/lib/seafoam/colors.rb +18 -0
- data/lib/seafoam/commands.rb +447 -0
- data/lib/seafoam/config.rb +34 -0
- data/lib/seafoam/graph.rb +91 -0
- data/lib/seafoam/graphviz_writer.rb +213 -0
- data/lib/seafoam/spotlight.rb +28 -0
- data/lib/seafoam/version.rb +5 -0
- data/seafoam.gemspec +20 -0
- data/spec/seafoam/annotators/fallback_spec.rb +69 -0
- data/spec/seafoam/annotators/graal_spec.rb +96 -0
- data/spec/seafoam/annotators_spec.rb +61 -0
- data/spec/seafoam/bgv/bgv_parser_spec.rb +144 -0
- data/spec/seafoam/bgv/fixtures/not.bgv +1 -0
- data/spec/seafoam/bgv/fixtures/unsupported.bgv +1 -0
- data/spec/seafoam/binary/io_binary_reader_spec.rb +176 -0
- data/spec/seafoam/command_spec.rb +252 -0
- data/spec/seafoam/graph_spec.rb +172 -0
- data/spec/seafoam/graphviz_writer_spec.rb +63 -0
- data/spec/seafoam/spec_helpers.rb +30 -0
- data/spec/seafoam/spotlight_spec.rb +38 -0
- data/tools/render-all +36 -0
- metadata +238 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
# Getting Graphs
|
2
|
+
|
3
|
+
## GraalVM Compiler as a Java compiler
|
4
|
+
|
5
|
+
`-Dgraal.Dump=:2` is a simple option to enable Graal graph dumping.
|
6
|
+
|
7
|
+
The value of `Dump` is a *dump filter*. The format of dump filters is
|
8
|
+
[documented][dump-filters], but in simple cases `:2` will be enough and will
|
9
|
+
give you everything.
|
10
|
+
|
11
|
+
[dump-filters]: https://github.com/oracle/graal/blob/master/compiler/src/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/doc-files/DumpHelp.txt
|
12
|
+
|
13
|
+
You may want to combine with `-XX:CompileOnly=Foo::foo` (you can omit the class
|
14
|
+
part) to restrict compilation to a single method to give smaller dumps, and to
|
15
|
+
some extent make graphs simpler by avoiding what you want to look at being
|
16
|
+
inlined, or other things being inlined into it.
|
17
|
+
|
18
|
+
Graal tends to be quite aggressive about loop unrolling, which can produce
|
19
|
+
massive graphs with the logic repeated. I often use these flags to simplify the
|
20
|
+
graph without significantly effecting too much how the logic in it is compiled.
|
21
|
+
|
22
|
+
```
|
23
|
+
-Dgraal.FullUnroll=false \
|
24
|
+
-Dgraal.PartialUnroll=false \
|
25
|
+
-Dgraal.LoopPeeling=false \
|
26
|
+
-Dgraal.LoopUnswitch=false \
|
27
|
+
-Dgraal.OptLoopTransform=false \
|
28
|
+
-Dgraal.OptScheduleOutOfLoops=false \
|
29
|
+
-Dgraal.VectorizeLoops=false
|
30
|
+
```
|
31
|
+
|
32
|
+
## TruffleRuby and other Truffle languages
|
33
|
+
|
34
|
+
Use the same options as for GraalVM for Java, except they're prefixed with
|
35
|
+
`--vm.`, for example `--vm.Dgraal.Dump=Truffle:2`.
|
36
|
+
|
37
|
+
Use with `--engine.CompileOnly=foo`.
|
38
|
+
|
39
|
+
A good filter to use for Truffle languages is `--vm.Dgraal.Dump=Truffle:1`,
|
40
|
+
which will only give you Truffle compilations if you don't care about the
|
41
|
+
whole Graal compilation pipeline.
|
42
|
+
|
43
|
+
You may want to disable on-stack-replacement and inlining with
|
44
|
+
`--engine.Inlining=false` and `--engine.OSR=false` in order to make graphs
|
45
|
+
easier to understand.
|
46
|
+
|
47
|
+
You may need to use `--experimental-options`.
|
data/examples/Fib.java
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
/*
|
2
|
+
* % javac Fib.java
|
3
|
+
* % java -XX:CompileOnly=::fib -Dgraal.Dump=:2 Fib 14
|
4
|
+
*/
|
5
|
+
|
6
|
+
class Fib {
|
7
|
+
|
8
|
+
public static void main(String[] args) {
|
9
|
+
while (true) {
|
10
|
+
for (String arg : args) {
|
11
|
+
fib(Integer.parseInt(args[0]));
|
12
|
+
}
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
public static int fib(int n) {
|
17
|
+
if (n <= 1) {
|
18
|
+
return n;
|
19
|
+
} else {
|
20
|
+
return fib(n - 1) + fib(n - 2);
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
/*
|
2
|
+
* % javac MatMult.java
|
3
|
+
* % java -XX:CompileOnly=::matmult -Dgraal.Dump=:2 MatMult 100
|
4
|
+
*/
|
5
|
+
|
6
|
+
class MatMult {
|
7
|
+
|
8
|
+
public static void main(String[] args) {
|
9
|
+
while (true) {
|
10
|
+
for (String arg : args) {
|
11
|
+
final int size = Integer.parseInt(args[0]);
|
12
|
+
final double[][] a = new double[size][];
|
13
|
+
final double[][] b = new double[size][];
|
14
|
+
final double[][] c = new double[size][];
|
15
|
+
for (int n = 0; n < size; n++) {
|
16
|
+
a[n] = new double[size];
|
17
|
+
b[n] = new double[size];
|
18
|
+
c[n] = new double[size];
|
19
|
+
for (int m = 0; m < size; m++) {
|
20
|
+
a[n][m] = Math.random();
|
21
|
+
b[n][m] = Math.random();
|
22
|
+
}
|
23
|
+
}
|
24
|
+
matmult(size, a, b, c);
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
public static void matmult(int size, double[][] a, double[][] b, double[][] c) {
|
30
|
+
for(int i = 0; i < size; i++) {
|
31
|
+
for (int j = 0; j < size; j++) {
|
32
|
+
for (int k = 0; k < size; k++) {
|
33
|
+
c[i][j] += a[i][k] * b[k][j];
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
}
|
Binary file
|
data/examples/fib-js.bgv
ADDED
Binary file
|
Binary file
|
data/examples/fib.js
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
// % node --experimental-options --engine.CompileOnly=fib --engine.Inlining=false --vm.Dgraal.Dump=Truffle:2 -f fib.js 14
|
2
|
+
|
3
|
+
function fib(n) {
|
4
|
+
if (n <= 1) {
|
5
|
+
return n;
|
6
|
+
} else {
|
7
|
+
return fib(n - 1) + fib(n - 2);
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
while (true) {
|
12
|
+
for (let n = 2; n < process.argv.length; n++) {
|
13
|
+
fib(parseInt(process.argv[n]));
|
14
|
+
}
|
15
|
+
}
|
data/examples/fib.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# % ruby --experimental-options --engine.CompileOnly=fib --engine.Inlining=false --engine.OSR=false --vm.Dgraal.Dump=Truffle:2 fib.rb 14
|
2
|
+
|
3
|
+
def fib(n)
|
4
|
+
if n <= 1
|
5
|
+
n
|
6
|
+
else
|
7
|
+
fib(n - 1) + fib(n - 2)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
loop do
|
12
|
+
ARGV.each do |arg|
|
13
|
+
fib(Integer(arg))
|
14
|
+
end
|
15
|
+
end
|
Binary file
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# % ruby --experimental-options --engine.CompileOnly=identity --engine.Inlining=false --engine.OSR=false --vm.Dgraal.Dump=Truffle:2 identity.rb 1 2 3
|
2
|
+
|
3
|
+
# The purpose of this identity function is to learn what the Truffle prelude looks like.
|
4
|
+
|
5
|
+
def identity(arg)
|
6
|
+
arg
|
7
|
+
end
|
8
|
+
|
9
|
+
loop do
|
10
|
+
ARGV.each do |arg|
|
11
|
+
identity(Integer(arg))
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
; https://github.com/Storyyeller/Krakatau
|
2
|
+
; Krakatau/assemble.py Irreducible.j
|
3
|
+
|
4
|
+
.class public Irreducible
|
5
|
+
.super java/lang/Object
|
6
|
+
.field private static volatile intField I
|
7
|
+
|
8
|
+
.method public static exampleIrreducible : (ZI)I
|
9
|
+
.code stack 1 locals 3
|
10
|
+
|
11
|
+
iload_1
|
12
|
+
istore_2
|
13
|
+
iload_0
|
14
|
+
ifeq L_start_of_loop
|
15
|
+
|
16
|
+
goto L_inside_loop
|
17
|
+
|
18
|
+
L_start_of_loop:
|
19
|
+
iload_2
|
20
|
+
ifle L_end_of_loop
|
21
|
+
iload_2
|
22
|
+
putstatic Field Irreducible intField I
|
23
|
+
|
24
|
+
L_inside_loop:
|
25
|
+
iinc 2 -1
|
26
|
+
goto L_start_of_loop
|
27
|
+
|
28
|
+
L_end_of_loop:
|
29
|
+
iload_1
|
30
|
+
ireturn
|
31
|
+
|
32
|
+
.end code
|
33
|
+
.end method
|
34
|
+
|
35
|
+
.end class
|
@@ -0,0 +1,21 @@
|
|
1
|
+
//
|
2
|
+
// Source code recreated from a .class file by IntelliJ IDEA
|
3
|
+
// (powered by Fernflower decompiler)
|
4
|
+
//
|
5
|
+
|
6
|
+
public class IrreducibleDecompiled {
|
7
|
+
private static volatile int intField;
|
8
|
+
|
9
|
+
public static int exampleIrreducible(boolean var0, int var1) {
|
10
|
+
int var2 = var1;
|
11
|
+
if (var0) {
|
12
|
+
var2 = var1 - 1;
|
13
|
+
}
|
14
|
+
|
15
|
+
while(var2 > 0) {
|
16
|
+
intField = var2--;
|
17
|
+
}
|
18
|
+
|
19
|
+
return var1;
|
20
|
+
}
|
21
|
+
}
|
@@ -0,0 +1,418 @@
|
|
1
|
+
/*
|
2
|
+
* % javac JavaExamples.java
|
3
|
+
* % java -XX:-UseOnStackReplacement '-XX:CompileCommand=dontinline,*::*' -XX:+PrintCompilation -Dgraal.Dump=:3 JavaExamples
|
4
|
+
*/
|
5
|
+
|
6
|
+
import java.lang.reflect.Field;
|
7
|
+
import java.util.Random;
|
8
|
+
import sun.misc.Unsafe;
|
9
|
+
|
10
|
+
class JavaExamples {
|
11
|
+
|
12
|
+
private final static Random RANDOM = new Random();
|
13
|
+
private final static Unsafe UNSAFE = getUnsafe();
|
14
|
+
private final static long UNSAFE_MEMORY = UNSAFE.allocateMemory(1024);
|
15
|
+
|
16
|
+
public static void main(String[] args) {
|
17
|
+
if (args.length != 0) {
|
18
|
+
throw new UnsupportedOperationException("not expecting any arguments");
|
19
|
+
}
|
20
|
+
|
21
|
+
while (true) {
|
22
|
+
exampleLocalVariables(RANDOM.nextInt(), RANDOM.nextInt());
|
23
|
+
exampleLocalVariablesState(RANDOM.nextInt(), RANDOM.nextInt());
|
24
|
+
exampleArithOperator(RANDOM.nextInt(), RANDOM.nextInt());
|
25
|
+
exampleCompareOperator(RANDOM.nextInt(), RANDOM.nextInt());
|
26
|
+
try {
|
27
|
+
exampleExactArith(RANDOM.nextInt(), RANDOM.nextInt());
|
28
|
+
} catch (ArithmeticException e) { }
|
29
|
+
examplePhi(RANDOM.nextBoolean(), RANDOM.nextInt());
|
30
|
+
exampleSimpleCall(new ExampleObject(RANDOM.nextInt()), RANDOM.nextInt());
|
31
|
+
exampleInterfaceCallOneImpl(new OneImpl());
|
32
|
+
exampleInterfaceCallManyImpls(RANDOM.nextBoolean() ? new ManyImplsA() : new ManyImplsB());
|
33
|
+
exampleStaticCall(RANDOM.nextInt());
|
34
|
+
exampleStamp(RANDOM.nextInt());
|
35
|
+
exampleFullEscape(RANDOM.nextInt());
|
36
|
+
exampleNoEscape(RANDOM.nextInt());
|
37
|
+
examplePartialEscape(RANDOM.nextBoolean(), RANDOM.nextInt());
|
38
|
+
exampleIf(RANDOM.nextBoolean(), RANDOM.nextInt(), RANDOM.nextInt());
|
39
|
+
exampleIfNeverTaken(false, RANDOM.nextInt(), RANDOM.nextInt());
|
40
|
+
exampleIntSwitch(RANDOM.nextInt(3), RANDOM.nextInt(), RANDOM.nextInt(), RANDOM.nextInt());
|
41
|
+
exampleStringSwitch(new String[]{"foo", "bar", "baz"}[RANDOM.nextInt(3)], RANDOM.nextInt(), RANDOM.nextInt(), RANDOM.nextInt());
|
42
|
+
exampleWhile(RANDOM.nextInt(10));
|
43
|
+
exampleFor(RANDOM.nextInt(10));
|
44
|
+
exampleReducible(RANDOM.nextBoolean(), RANDOM.nextInt(10));
|
45
|
+
Irreducible.exampleIrreducible(RANDOM.nextBoolean(), RANDOM.nextInt(10));
|
46
|
+
exampleNestedWhile(RANDOM.nextInt(10));
|
47
|
+
exampleWhileBreak(RANDOM.nextInt(10));
|
48
|
+
exampleNestedWhileBreak(RANDOM.nextInt(10));
|
49
|
+
try {
|
50
|
+
exampleThrow();
|
51
|
+
} catch (RuntimeException e) { }
|
52
|
+
exampleCatch();
|
53
|
+
exampleThrowCatch();
|
54
|
+
exampleObjectAllocation(RANDOM.nextInt());
|
55
|
+
exampleArrayAllocation(RANDOM.nextInt(), RANDOM.nextInt());
|
56
|
+
exampleFieldWrite(new ExampleObject(RANDOM.nextInt()), RANDOM.nextInt());
|
57
|
+
exampleFieldRead(new ExampleObject(RANDOM.nextInt()));
|
58
|
+
exampleArrayWrite(new int[]{RANDOM.nextInt(), RANDOM.nextInt(), RANDOM.nextInt()}, RANDOM.nextInt(3), RANDOM.nextInt());
|
59
|
+
exampleArrayRead(new int[]{RANDOM.nextInt(), RANDOM.nextInt(), RANDOM.nextInt()}, RANDOM.nextInt(3));
|
60
|
+
exampleUnsafeRead(UNSAFE_MEMORY + RANDOM.nextInt(4) * 4);
|
61
|
+
exampleUnsafeWrite(UNSAFE_MEMORY + RANDOM.nextInt(4) * 4, RANDOM.nextInt());
|
62
|
+
exampleInstanceOfOneImpl(new OneImpl());
|
63
|
+
exampleInstanceOfManyImpls(RANDOM.nextBoolean() ? new ManyImplsA() : new ManyImplsB());
|
64
|
+
exampleSynchronized(new Object(), RANDOM.nextInt());
|
65
|
+
exampleDoubleSynchronized(new Object(), RANDOM.nextInt());
|
66
|
+
exampleLocalSynchronized(RANDOM.nextInt());
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
private static int exampleLocalVariables(int x, int y) {
|
71
|
+
int a = x + y;
|
72
|
+
return a * 2 + a;
|
73
|
+
}
|
74
|
+
|
75
|
+
private static int exampleLocalVariablesState(int x, int y) {
|
76
|
+
int a = x + y;
|
77
|
+
opaqueCall();
|
78
|
+
return a * 2 + a;
|
79
|
+
}
|
80
|
+
|
81
|
+
private static int exampleArithOperator(int x, int y) {
|
82
|
+
return x + y;
|
83
|
+
}
|
84
|
+
|
85
|
+
private static boolean exampleCompareOperator(int x, int y) {
|
86
|
+
return x <= y;
|
87
|
+
}
|
88
|
+
|
89
|
+
private static int exampleExactArith(int x, int y) throws ArithmeticException {
|
90
|
+
return Math.addExact(x, y);
|
91
|
+
}
|
92
|
+
|
93
|
+
private static int examplePhi(boolean condition, int x) {
|
94
|
+
final int a;
|
95
|
+
if (condition) {
|
96
|
+
a = opaqueCall();
|
97
|
+
} else {
|
98
|
+
a = opaqueCall();
|
99
|
+
}
|
100
|
+
return a + x;
|
101
|
+
}
|
102
|
+
|
103
|
+
private static int exampleSimpleCall(ExampleObject object, int x) {
|
104
|
+
return object.instanceCall(x);
|
105
|
+
}
|
106
|
+
|
107
|
+
private static int exampleInterfaceCallOneImpl(InterfaceOneImpl x) {
|
108
|
+
return x.interfaceCall();
|
109
|
+
}
|
110
|
+
|
111
|
+
private static int exampleInterfaceCallManyImpls(InterfaceManyImpls x) {
|
112
|
+
return x.interfaceCall();
|
113
|
+
}
|
114
|
+
|
115
|
+
private static int exampleStaticCall(int x) {
|
116
|
+
return staticCall(x);
|
117
|
+
}
|
118
|
+
|
119
|
+
private static int exampleStamp(int x) {
|
120
|
+
return x & 0x1234;
|
121
|
+
}
|
122
|
+
|
123
|
+
private static int exampleFullEscape(int x) {
|
124
|
+
final int[] a = new int[]{x};
|
125
|
+
objectField = a;
|
126
|
+
return a[0];
|
127
|
+
}
|
128
|
+
|
129
|
+
private static int exampleNoEscape(int x) {
|
130
|
+
final int[] a = new int[]{x};
|
131
|
+
return a[0];
|
132
|
+
}
|
133
|
+
|
134
|
+
private static int examplePartialEscape(boolean condition, int x) {
|
135
|
+
final int[] a = new int[]{x};
|
136
|
+
if (condition) {
|
137
|
+
objectField = a;
|
138
|
+
return a[0];
|
139
|
+
} else {
|
140
|
+
return a[0];
|
141
|
+
}
|
142
|
+
}
|
143
|
+
|
144
|
+
private static int exampleIf(boolean condition, int x, int y) {
|
145
|
+
final int a;
|
146
|
+
if (condition) {
|
147
|
+
intField = x;
|
148
|
+
a = x;
|
149
|
+
} else {
|
150
|
+
intField = y;
|
151
|
+
a = y;
|
152
|
+
}
|
153
|
+
return a;
|
154
|
+
}
|
155
|
+
|
156
|
+
private static int exampleIfNeverTaken(boolean condition, int x, int y) {
|
157
|
+
final int a;
|
158
|
+
if (condition) {
|
159
|
+
intField = x;
|
160
|
+
a = x;
|
161
|
+
} else {
|
162
|
+
intField = y;
|
163
|
+
a = y;
|
164
|
+
}
|
165
|
+
return a;
|
166
|
+
}
|
167
|
+
|
168
|
+
private static int exampleIntSwitch(int value, int x, int y, int z) {
|
169
|
+
final int a;
|
170
|
+
switch (value) {
|
171
|
+
case 0:
|
172
|
+
intField = x;
|
173
|
+
a = x;
|
174
|
+
break;
|
175
|
+
case 1:
|
176
|
+
intField = y;
|
177
|
+
a = y;
|
178
|
+
break;
|
179
|
+
default:
|
180
|
+
intField = z;
|
181
|
+
a = z;
|
182
|
+
break;
|
183
|
+
}
|
184
|
+
return a;
|
185
|
+
}
|
186
|
+
|
187
|
+
private static int exampleStringSwitch(String value, int x, int y, int z) {
|
188
|
+
final int a;
|
189
|
+
switch (value) {
|
190
|
+
case "foo":
|
191
|
+
intField = x;
|
192
|
+
a = x;
|
193
|
+
break;
|
194
|
+
case "bar":
|
195
|
+
intField = y;
|
196
|
+
a = y;
|
197
|
+
break;
|
198
|
+
default:
|
199
|
+
intField = z;
|
200
|
+
a = z;
|
201
|
+
break;
|
202
|
+
}
|
203
|
+
return a;
|
204
|
+
}
|
205
|
+
|
206
|
+
private static int exampleWhile(int count) {
|
207
|
+
int a = count;
|
208
|
+
while (a > 0) {
|
209
|
+
intField = a;
|
210
|
+
a--;
|
211
|
+
}
|
212
|
+
return count;
|
213
|
+
}
|
214
|
+
|
215
|
+
private static int exampleReducible(boolean condition, int count) {
|
216
|
+
int a = count;
|
217
|
+
if (condition) {
|
218
|
+
a = count - 1;
|
219
|
+
}
|
220
|
+
while (a > 0) {
|
221
|
+
intField = a;
|
222
|
+
inner:
|
223
|
+
a--;
|
224
|
+
}
|
225
|
+
return count;
|
226
|
+
}
|
227
|
+
|
228
|
+
private static int exampleFor(int count) {
|
229
|
+
for (int a = count; a > 0; a--) {
|
230
|
+
intField = a;
|
231
|
+
}
|
232
|
+
return count;
|
233
|
+
}
|
234
|
+
|
235
|
+
private static int exampleNestedWhile(int count) {
|
236
|
+
int a = count;
|
237
|
+
while (a > 0) {
|
238
|
+
int y = count;
|
239
|
+
while (y > 0) {
|
240
|
+
intField = a;
|
241
|
+
y--;
|
242
|
+
}
|
243
|
+
a--;
|
244
|
+
}
|
245
|
+
return count;
|
246
|
+
}
|
247
|
+
|
248
|
+
private static int exampleWhileBreak(int count) {
|
249
|
+
int a = count;
|
250
|
+
while (a > 0) {
|
251
|
+
if (a == 4) {
|
252
|
+
break;
|
253
|
+
}
|
254
|
+
intField = a;
|
255
|
+
a--;
|
256
|
+
}
|
257
|
+
return count;
|
258
|
+
}
|
259
|
+
|
260
|
+
private static int exampleNestedWhileBreak(int count) {
|
261
|
+
int a = count;
|
262
|
+
outer: while (a > 0) {
|
263
|
+
int b = count;
|
264
|
+
while (b > 0) {
|
265
|
+
if (b == 4) {
|
266
|
+
break outer;
|
267
|
+
}
|
268
|
+
intField = a;
|
269
|
+
b--;
|
270
|
+
}
|
271
|
+
a--;
|
272
|
+
}
|
273
|
+
return count;
|
274
|
+
}
|
275
|
+
|
276
|
+
private static void exampleThrow() {
|
277
|
+
throw RUNTIME_EXCEPTION;
|
278
|
+
}
|
279
|
+
|
280
|
+
private static void exampleCatch() {
|
281
|
+
try {
|
282
|
+
exampleThrow();
|
283
|
+
} catch (RuntimeException e) {
|
284
|
+
objectField = e;
|
285
|
+
}
|
286
|
+
}
|
287
|
+
|
288
|
+
private static void exampleThrowCatch() {
|
289
|
+
try {
|
290
|
+
throw RUNTIME_EXCEPTION;
|
291
|
+
} catch (RuntimeException e) {
|
292
|
+
}
|
293
|
+
}
|
294
|
+
|
295
|
+
private static ExampleObject exampleObjectAllocation(int x) {
|
296
|
+
return new ExampleObject(x);
|
297
|
+
}
|
298
|
+
|
299
|
+
private static int[] exampleArrayAllocation(int x, int y) {
|
300
|
+
return new int[]{x, y};
|
301
|
+
}
|
302
|
+
|
303
|
+
private static void exampleFieldWrite(ExampleObject object, int x) {
|
304
|
+
object.x = x;
|
305
|
+
}
|
306
|
+
|
307
|
+
private static int exampleFieldRead(ExampleObject object) {
|
308
|
+
assert object != null; // otherwise this is a 'trivial' method and won't go past tier 1
|
309
|
+
return object.x;
|
310
|
+
}
|
311
|
+
|
312
|
+
private static void exampleArrayWrite(int[] array, int n, int x) {
|
313
|
+
array[n] = x;
|
314
|
+
}
|
315
|
+
|
316
|
+
private static int exampleArrayRead(int[] array, int n) {
|
317
|
+
return array[n];
|
318
|
+
}
|
319
|
+
|
320
|
+
private static int exampleUnsafeRead(long unsafeMemory) {
|
321
|
+
return UNSAFE.getInt(unsafeMemory);
|
322
|
+
}
|
323
|
+
|
324
|
+
private static void exampleUnsafeWrite(long unsafeMemory, int x) {
|
325
|
+
UNSAFE.putInt(unsafeMemory, x);
|
326
|
+
}
|
327
|
+
|
328
|
+
private static boolean exampleInstanceOfOneImpl(Object x) {
|
329
|
+
return x instanceof InterfaceOneImpl;
|
330
|
+
}
|
331
|
+
|
332
|
+
private static boolean exampleInstanceOfManyImpls(Object x) {
|
333
|
+
return x instanceof InterfaceManyImpls;
|
334
|
+
}
|
335
|
+
|
336
|
+
private static void exampleSynchronized(Object object, int x) {
|
337
|
+
synchronized (object) {
|
338
|
+
intField = x;
|
339
|
+
}
|
340
|
+
}
|
341
|
+
|
342
|
+
private static void exampleDoubleSynchronized(Object object, int x) {
|
343
|
+
synchronized (object) {
|
344
|
+
intField = x;
|
345
|
+
}
|
346
|
+
synchronized (object) {
|
347
|
+
intField = x;
|
348
|
+
}
|
349
|
+
}
|
350
|
+
|
351
|
+
private static void exampleLocalSynchronized(int x) {
|
352
|
+
final Object object = new Object();
|
353
|
+
synchronized (object) {
|
354
|
+
intField = x;
|
355
|
+
}
|
356
|
+
}
|
357
|
+
|
358
|
+
private static int opaqueCall() {
|
359
|
+
return RANDOM.nextInt();
|
360
|
+
}
|
361
|
+
|
362
|
+
private static int staticCall(int x) {
|
363
|
+
return x;
|
364
|
+
}
|
365
|
+
|
366
|
+
private static final RuntimeException RUNTIME_EXCEPTION = new RuntimeException();
|
367
|
+
private static volatile int intField;
|
368
|
+
private static volatile Object objectField;
|
369
|
+
|
370
|
+
private static class ExampleObject {
|
371
|
+
public int x;
|
372
|
+
|
373
|
+
public ExampleObject(int x) {
|
374
|
+
this.x = x;
|
375
|
+
}
|
376
|
+
|
377
|
+
public int instanceCall(int y) {
|
378
|
+
return x + y;
|
379
|
+
}
|
380
|
+
}
|
381
|
+
|
382
|
+
private interface InterfaceOneImpl {
|
383
|
+
int interfaceCall();
|
384
|
+
}
|
385
|
+
|
386
|
+
private static class OneImpl implements InterfaceOneImpl {
|
387
|
+
public int interfaceCall() {
|
388
|
+
return 14;
|
389
|
+
}
|
390
|
+
}
|
391
|
+
|
392
|
+
private interface InterfaceManyImpls {
|
393
|
+
int interfaceCall();
|
394
|
+
}
|
395
|
+
|
396
|
+
private static class ManyImplsA implements InterfaceManyImpls {
|
397
|
+
public int interfaceCall() {
|
398
|
+
return 14;
|
399
|
+
}
|
400
|
+
}
|
401
|
+
|
402
|
+
private static class ManyImplsB implements InterfaceManyImpls {
|
403
|
+
public int interfaceCall() {
|
404
|
+
return 14;
|
405
|
+
}
|
406
|
+
}
|
407
|
+
|
408
|
+
private static Unsafe getUnsafe() {
|
409
|
+
try {
|
410
|
+
final Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
|
411
|
+
theUnsafe.setAccessible(true);
|
412
|
+
return (Unsafe) theUnsafe.get(null);
|
413
|
+
} catch (NoSuchFieldException | IllegalAccessException e) {
|
414
|
+
throw new RuntimeException(e);
|
415
|
+
}
|
416
|
+
}
|
417
|
+
|
418
|
+
}
|