I have these 2 codes in Java and C++, which are supposed to do the same thing.
My intuition was that the size (and also content) of object code would be the same for R1 and R2. It's the case for the C++ (difference of 4 bytes if compiled without -O1). There is a bigger difference for the Java bytecode (R2 is longer), which is surprising for me.
Maybe I'm not looking at the right things and my question might not be relevant, but is it normal that the Java bytecode is so "close" from the source code, and does it mean that it's always more "efficient"/"optimized" to write everything in one-line instead of using local variables ?
C++
int A(int a) { return 0; }
int B(int b) { return 0; }
int C(int c) { return 0; }
int D(int d) { return 0; }
int R1() {
return A(B(C(3)+D(3)));
}
int R2() {
int d = D(3);
int c = C(3);
int b = B(c + d);
return A(b);
}
// Then R1() and R2() are called in the main()
Java
class MyClass {
static int A(int a) { return 0; }
static int B(int b) { return 0; }
static int C(int c) { return 0; }
static int D(int d) { return 0; }
static int R1() {
return A(B(C(3)+D(3)));
}
static int R2() {
int d = D(3);
int c = C(3);
int b = B(c + d);
return A(b);
}
// Then R1 and R2 are called in the Main()
}
When I compiled both of them (g++ -O1 version 9.4 and javac version 11.0.17), and disassemble R1 and R2, I get this:
C++ (g++ -O1 prog.cpp)
R1:
1251: f3 0f 1e fa endbr64
1255: 53 push %rbx
1256: bf 03 00 00 00 mov $0x3,%edi
125b: e8 9d ff ff ff callq 11fd <_Z1Ci>
1260: 89 c3 mov %eax,%ebx
1262: bf 03 00 00 00 mov $0x3,%edi
1267: e8 bb ff ff ff callq 1227 <_Z1Di>
126c: 8d 3c 03 lea (%rbx,%rax,1),%edi
126f: e8 5f ff ff ff callq 11d3 <_Z1Bi>
1274: 89 c7 mov %eax,%edi
1276: e8 2e ff ff ff callq 11a9 <_Z1Ai>
127b: 5b pop %rbx
127c: c3 retq
R2:
<exact same as R1>
Java (javap -c MyClass)
javap -c Appel
static int R1();
Code:
0: iconst_3
1: invokestatic #8 // Method C:(I)I
4: iconst_3
5: invokestatic #9 // Method D:(I)I
8: iadd
9: invokestatic #10 // Method B:(I)I
12: invokestatic #11 // Method A:(I)I
15: ireturn
static int R2();
Code:
0: iconst_3
1: invokestatic #9 // Method D:(I)I
4: istore_0
5: iconst_3
6: invokestatic #8 // Method C:(I)I
9: istore_1
10: iload_1
11: iload_0
12: iadd
13: invokestatic #10 // Method B:(I)I
16: istore_2
17: iload_2
18: invokestatic #11 // Method A:(I)I
21: ireturn
Aand friends do and the output is identical. Well, almost identical. Good enough for me.