0

I am sure almost everybody is familiar with the most downvoted question(java tagged) on SO. Copy pasting the snippet for completeness:

k = (j = (i = 0) + 2) + 1;
return i|= j|= k|= (j+= i) - - (k+++k) - - (i =+j);

Above snippet always returns 11 no matter what. So my question is: will jvm evaluate this/similar madness on each invocation?

Naman
  • 27,789
  • 26
  • 218
  • 353
  • did you try looking at the byte code generated for the block to start off with? – Naman Jul 24 '20 at 16:39
  • You yourself said it always returns 11, why should it not all of a sudden? It's not possible to know a priori how a similar madness will be evaluated either. I hope your question will also become the most down-voted question on Java. – Dennis Kozevnikoff Jul 24 '20 at 16:48
  • 1
    @Naman FYI byte code lies. Byte code can be optimized by jvm – Concurrent Bhai Jul 24 '20 at 16:49
  • @ConcurrentBhai Ofcourse it does, that's why I was asking if you have *started off* by looking at it. Some research or work done related to the question you're asking is always good. – Naman Jul 24 '20 at 17:16
  • @Naman Yes but it doesn't provide the answer I am looking for. There is no optimization by the compiler. – Concurrent Bhai Jul 24 '20 at 17:17
  • The answer is that it will depend on the JVM. – Stephen C Jul 25 '20 at 08:18

1 Answers1

2

I don't know if this counts as an answer, but it seems that the JVM can prove that no evaluation is needed:

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 20, time = 20)
@Measurement(iterations = 20, time = 20)
public class MostDownVoted {

    public static void main(String[] args) throws Exception {
        Options opt = new OptionsBuilder()
            .include(MostDownVoted.class.getSimpleName())
            .build();

        new Runner(opt).run();
    }

    @State(Scope.Benchmark)
    public static class Holder {

        int k;
        int i;
        int j;

        @Setup(Level.Iteration)
        public void setUp() {
            k = ThreadLocalRandom.current().nextInt();
            i = ThreadLocalRandom.current().nextInt();
            j = ThreadLocalRandom.current().nextInt();
        }

    }

    @Fork(1)
    @Benchmark
    public int test1(Holder h) {
        h.k = (h.j = (h.i = 0) + 2) + 1;
        return h.i |= h.j |= h.k |= (h.j += h.i) - -(h.k++ + h.k) - -(h.i = +h.j);
    }

    @Fork(1)
    @Benchmark
    public int test2(Holder h) {
        return 11;
    }

    @Benchmark
    @Fork(value = 1, jvmArgsAppend = "-XX:TieredStopAtLevel=1")
    public int test3(Holder h) {
        h.k = (h.j = (h.i = 0) + 2) + 1;
        return h.i |= h.j |= h.k |= (h.j += h.i) - -(h.k++ + h.k) - -(h.i = +h.j);
    }

}

The results show that once C2 compiler kicks in, the results with return 11 are on par with what you have :

MostDownVoted.test1  avgt   20  2.816 ± 0.003  ns/op
MostDownVoted.test2  avgt   20  2.122 ± 0.016  ns/op
MostDownVoted.test3  avgt   20  3.979 ± 0.758  ns/op
Eugene
  • 117,005
  • 15
  • 201
  • 306