seafoam 0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
}
|