P
P copied to clipboard
Implement copy propagation optimisation pass?
In the following event handler (part of the ClientServer tutorial),
103 on eWithDrawResp do (resp: tWithDrawResp) {
104 assert resp.rId in pendingWDReqs,
105 format ("unexpected rId: {0} received, expected one of {1}", resp.rId, pendingWDReqs);
106 pendingWDReqs -= (resp.rId);
107 ...
The following backend code is generated:
TMP_tmp0_3 = ((Integer)resp_1.get("rId"));
TMP_tmp1_2 = pendingWDReqs.contains(TMP_tmp0_3);
TMP_tmp2_2 = ((Integer)resp_1.get("rId"));
TMP_tmp3_2 = (HashSet<Integer>)Values.clone(pendingWDReqs);
TMP_tmp4_2 = MessageFormat.format("unexpected rId: {0} received, expected one of {1}", TMP_tmp2_2, TMP_tmp3_2);
tryAssert(TMP_tmp1_2, TMP_tmp4_2);
TMP_tmp5_2 = ((Integer)resp_1.get("rId"));
pendingWDReqs.remove(TMP_tmp5_2);
Of course, TMP_tmp0_3
, TMP_tmp2_2
, and TMP_tmp5_2
are all redundant accesses. I wonder how feasible it would be to implement copy propagation or common subexpression elimination as an IR transformer?
Good point! I have always been scared of adding any optimization into the compiler until really needed. Performance has never been a concern for the generated code so far (not any more as we start using P generated code outside testing).
But correctness would need to be thoroughly tested if we add optimizations.
Do you have a plan or design?
Yep, strong agree that adding an optimisation that breaks the compiler would be a bad idea!
I also wonder whether the CLR and JVM's JITs (or even javac
) are smart enough to elide those redundant accesses; running a quick experiment there might be the first thing to try before we try anything fancy on our end.
But, given that the IR is already in SSA, I think there are straightforward procedures for doing this? Let me investigate and come up with a concrete proposal if they're not elided at runtime.
Thank you!
OK, I did some splunking with the following P example from the Tutorial:
19 state WaitForEvents {
20 on ePrepareResp do (resp: tPrepareResp){
21 var transId: int;
22 transId = resp.transId;
23
24 if(!(transId in participantsResponse))
25 {
26 participantsResponse[transId] = default(map[tTransStatus, int]);
27 participantsResponse[transId][SUCCESS] = 0;
28 participantsResponse[transId][ERROR] = 0;
29 }
30 participantsResponse[transId][resp.status] = participantsResponse[transId][resp.status] + 1;
31 }
The P IR emits a bunch of extraneous SSA nodes for map[tTransStatus, int]
, which in the Java extracted code appear as HashMap<Integer, Integer>
types:
private void Anon_2(eWriteTransResp pEvent) {
Gen_PTuple_2 resp_1 = pEvent.payload;
int TMP_tmp0_1 = 0;
boolean TMP_tmp1_1 = false;
int TMP_tmp2_1 = 0;
boolean TMP_tmp3_1 = false;
boolean TMP_tmp4_1 = false;
String TMP_tmp5_1 = "";
int TMP_tmp6_1 = 0;
boolean TMP_tmp7_1 = false;
int TMP_tmp8_1 = 0;
HashMap<Integer,Integer> TMP_tmp9_1 = new HashMap<Integer,Integer>();
int TMP_tmp10 = 0;
boolean TMP_tmp11 = false;
String TMP_tmp12 = "";
int TMP_tmp13 = 0;
HashMap<Integer,Integer> TMP_tmp14 = new HashMap<Integer,Integer>();
int TMP_tmp15 = 0;
int TMP_tmp16 = 0;
HashMap<Integer,Integer> TMP_tmp17 = new HashMap<Integer,Integer>();
int TMP_tmp18 = 0;
String TMP_tmp19 = "";
String TMP_tmp20 = "";
int TMP_tmp21 = 0;
boolean TMP_tmp22 = false;
int TMP_tmp23 = 0;
HashMap<Integer,Integer> TMP_tmp24 = new HashMap<Integer,Integer>();
int TMP_tmp25 = 0;
boolean TMP_tmp26 = false;
int TMP_tmp27 = 0;
String TMP_tmp28 = "";
int TMP_tmp29 = 0;
HashMap<Integer,Integer> TMP_tmp30 = new HashMap<Integer,Integer>();
int TMP_tmp31 = 0;
int TMP_tmp32 = 0;
HashMap<Integer,Integer> TMP_tmp33 = new HashMap<Integer,Integer>();
int TMP_tmp34 = 0;
String TMP_tmp35 = "";
String TMP_tmp36 = "";
int TMP_tmp37 = 0;
TMP_tmp0_1 = resp_1.transId;
TMP_tmp1_1 = participantsResponse.containsKey(TMP_tmp0_1);
TMP_tmp4_1 = TMP_tmp1_1;
if (TMP_tmp4_1) {} else
{
TMP_tmp2_1 = resp_1.status;
TMP_tmp3_1 = (TMP_tmp2_1 == tTransStatus.TIMEOUT);
TMP_tmp4_1 = TMP_tmp3_1;
}
...
Briefly: we have to check three compilers to see if these unnecessary allocations disappear. The first is of course the javac
bytecode output, but also HotSpot has two JIT compilers: the Client Compiler (called "c1" internally) and the Server Compiler ("c2"). Both are used at runtime to generate native assembly with the so-called "tiered compilation" approach: C1 is optimised for compilation speed and C2 is optimised for code quality, so C2 is used for hot code; infrequently-called code may not ever hit the server compiler (though this is configurable of course). To dump JIT output, the -XX:+UnlockDiagnosticVMOptions -XX:CompileCommand=print,*.Anon_2
flags were passed to Java.
The thing we'd like to see from all this output is assembly for Anon_2
that basically just calls containsKey()
right away and avoids all the Hashmap.init()
calls.
javac bytecode
No dice.
private void Anon_2(TutorialIntegrationTests.TwoPhaseCommit$eWriteTransResp);
Code:
0: aload_1
1: getfield #69 // Field TutorialIntegrationTests/TwoPhaseCommit$eWriteTransResp.payload:LTutorialIntegrationTests/TwoPhaseCommit$Gen_PTup
le_2;
...
54: new #21 // class java/util/HashMap
57: dup
58: invokespecial #23 // Method java/util/HashMap."<init>":()V
61: astore 17
63: iconst_0
64: istore 18
66: iconst_0
67: istore 19
69: new #21 // class java/util/HashMap
72: dup
73: invokespecial #23 // Method java/util/HashMap."<init>":()V
76: astore 20
78: iconst_0
79: istore 21
81: ldc #74 // String
83: astore 22
85: ldc #74 // String
87: astore 23
89: iconst_0
90: istore 24
92: iconst_0
93: istore 25
95: iconst_0
96: istore 26
98: new #21 // class java/util/HashMap
101: dup
102: invokespecial #23 // Method java/util/HashMap."<init>":()V
C1
No dice.
============================= C1-compiled nmethod ==============================
----------------------------------- Assembly -----------------------------------
Compiled method (c1) 14044 13335 3 TutorialIntegrationTests.TwoPhaseCommit$AtomicityInvariant::Anon_2 (685 bytes)
total in heap [0x000000011899c510,0x00000001189a2028] = 23320
relocation [0x000000011899c670,0x000000011899cb68] = 1272
main code [0x000000011899cb80,0x00000001189a0460] = 14560
stub code [0x00000001189a0460,0x00000001189a0780] = 800
oops [0x00000001189a0780,0x00000001189a07a8] = 40
metadata [0x00000001189a07a8,0x00000001189a07f0] = 72
scopes data [0x00000001189a07f0,0x00000001189a1538] = 3400
scopes pcs [0x00000001189a1538,0x00000001189a1ef8] = 2496
dependencies [0x00000001189a1ef8,0x00000001189a1f08] = 16
nul chk table [0x00000001189a1f08,0x00000001189a2028] = 288
[Constant Pool (empty)]
[MachCode]
[Entry Point]
# {method} {0x000000010d89e528} 'Anon_2' '(LTutorialIntegrationTests/TwoPhaseCommit$eWriteTransResp;)V' in 'TutorialIntegrationTests/TwoPhaseCommit$AtomicityInvariant'
# this: rsi:rsi = 'TutorialIntegrationTests/TwoPhaseCommit$AtomicityInvariant'
# parm0: rdx:rdx = 'TutorialIntegrationTests/TwoPhaseCommit$eWriteTransResp'
# [sp+0x150] (sp of caller)
0x000000011899cb80: 448b 5608 | 49bb 0000 | 0000 0800 | 0000 4d03 | d34c 3bd0
0x000000011899cb94: ; {runtime_call ic_miss_stub}
0x000000011899cb94: 0f85 e6ab | 9fff 660f | 1f44 0000
[Verified Entry Point]
0x000000011899cba0: 8984 2400 | c0fe ff55 | 4881 ec40 | 0100 0048 | 8974 2470
0x000000011899cbb4: ; {metadata(method data for {method} {0x000000010d89e528} 'Anon_2' '(LTutorialIntegrationTests/TwoPhaseCommit$eWriteTransResp;)V' in 'TutorialIntegrationTests/TwoPhaseCommit$AtomicityInvariant')}
0x000000011899cbb4: 48bf 5853 | b60d 0100 | 0000 8b87 | ac00 0000 | 83c0 0289 | 87ac 0000 | 00e9 bf30 | 0000 4883
0x000000011899cbd4: fa00 0f84 | d630 0000 | 0f1f 4000
0x000000011899cbe0: ; implicit exception: dispatches to 0x000000011899fcbf
0x000000011899cbe0: e9ea 3000 | 0090 48c1 | e303 4889
0x000000011899cbec: ; {metadata('java/util/HashMap')}
0x000000011899cbec: 5c24 6848 | bab8 800f | 0008 0000 | 004c 8bc6 | 498b 8708 | 0100 0048 | 8d78 3049 | 3bbf 1801
0x000000011899cc0c: 0000 0f87 | c530 0000 | 4989 bf08 | 0100 0048 | c700 0100 | 0000 488b | ca49 ba00 | 0000 0008
0x000000011899cc2c: 0000 0049 | 2bca 8948 | 0848 33c9 | 8948 0c48 | 33c9 4889 | 4810 4889 | 4818 4889 | 4820 4889
0x000000011899cc4c: 4828 488b
0x000000011899cc50: ; {metadata(method data for {method} {0x000000010d89e528} 'Anon_2' '(LTutorialIntegrationTests/TwoPhaseCommit$eWriteTransResp;)V' in 'TutorialIntegrationTests/TwoPhaseCommit$AtomicityInvariant')}
0x000000011899cc50: d048 be58 | 53b6 0d01 | 0000 0048 | 8386 f000
0x000000011899cc60: ; {metadata(method data for {method} {0x000000080037d5e8} '<init>' '()V' in 'java/util/HashMap')}
0x000000011899cc60: 0000 0148 | ba20 8341 | 0d01 0000 | 008b b2ac | 0000 0083 | c602 89b2 | ac00 0000 | 81e6 feff
0x000000011899cc80: 1f00 83fe | 000f 845b | 3000 0048
0x000000011899cc8c: ; {metadata(method data for {method} {0x000000080037d5e8} '<init>' '()V' in 'java/util/HashMap')}
0x000000011899cc8c: 8bd0 48be | 2083 410d | 0100 0000 | 4883 86f0 | 0000 0001
0x000000011899cca0: ; {metadata(method data for {method} {0x00000008003d11f8} '<init>' '()V' in 'java/util/AbstractMap')}
0x000000011899cca0: 48ba 5084 | 410d 0100 | 0000 8bb2 | ac00 0000 | 83c6 0289 | b2ac 0000 | 0081 e6fe | ff1f 0083
0x000000011899ccc0: fe00 0f84 | 3f30 0000
0x000000011899ccc8: ; {metadata(method data for {method} {0x00000008003d11f8} '<init>' '()V' in 'java/util/AbstractMap')}
0x000000011899ccc8: 488b d048 | be50 8441 | 0d01 0000 | 0048 8386 | f000 0000
0x000000011899ccdc: ; {metadata(method data for {method} {0x0000000800444540} '<init>' '()V' in 'java/lang/Object')}
0x000000011899ccdc: 0148 bab8 | 3640 0d01 | 0000 008b | b2ac 0000 | 0083 c602 | 89b2 ac00 | 0000 81e6 | feff 1f00
0x000000011899ccfc: 83fe 000f | 8423 3000 | 00c7 4020 | 0000 403f
0x000000011899cd0c: ; {metadata('java/util/HashMap')}
0x000000011899cd0c: 48ba b880 | 0f00 0800 | 0000 498b | 8708 0100 | 0048 8d78 | 3049 3bbf | 1801 0000 | 0f87 1b30
0x000000011899cd2c: 0000 4989 | bf08 0100 | 0048 c700 | 0100 0000 | 488b ca49 | ba00 0000 | 0008 0000 | 0049 2bca
0x000000011899cd4c: 8948 0848 | 33c9 8948 | 0c48 33c9 | 4889 4810 | 4889 4818 | 4889 4820 | 4889 4828
0x000000011899cd68: ; {metadata(method data for {method} {0x000000010d89e528} 'Anon_2' '(LTutorialIntegrationTests/TwoPhaseCommit$eWriteTransResp;)V' in 'TutorialIntegrationTests/TwoPhaseCommit$AtomicityInvariant')}
0x000000011899cd68: 488b d048 | be58 53b6 | 0d01 0000 | 0048 8386 | 0001 0000
0x000000011899cd7c: ; {metadata(method data for {method} {0x000000080037d5e8} '<init>' '()V' in 'java/util/HashMap')}
0x000000011899cd7c: 0148 ba20 | 8341 0d01 | 0000 008b | b2ac 0000 | 0083 c602 | 89b2 ac00 | 0000 81e6 | feff 1f00
0x000000011899cd9c: 83fe 000f | 84b1 2f00 | 0048 8bd0
0x000000011899cda8: ; {metadata(method data for {method} {0x000000080037d5e8} '<init>' '()V' in 'java/util/HashMap')}
0x000000011899cda8: 48be 2083 | 410d 0100 | 0000 4883 | 86f0 0000
0x000000011899cdb8: ; {metadata(method data for {method} {0x00000008003d11f8} '<init>' '()V' in 'java/util/AbstractMap')}
0x000000011899cdb8: 0001 48ba | 5084 410d | 0100 0000 | 8bb2 ac00 | 0000 83c6 | 0289 b2ac | 0000 0081 | e6fe ff1f
0x000000011899cdd8: 0083 fe00 | 0f84 952f | 0000 488b
0x000000011899cde4: ; {metadata(method data for {method} {0x00000008003d11f8} '<init>' '()V' in 'java/util/AbstractMap')}
0x000000011899cde4: d048 be50 | 8441 0d01 | 0000 0048 | 8386 f000
0x000000011899cdf4: ; {metadata(method data for {method} {0x0000000800444540} '<init>' '()V' in 'java/lang/Object')}
0x000000011899cdf4: 0000 0148 | bab8 3640 | 0d01 0000 | 008b b2ac | 0000 0083 | c602 89b2 | ac00 0000 | 81e6 feff
0x000000011899ce14: 1f00 83fe | 000f 8479 | 2f00 00c7 | 4020 0000
0x000000011899ce24: ; {metadata('java/util/HashMap')}
0x000000011899ce24: 403f 48ba | b880 0f00 | 0800 0000 | 498b 8708 | 0100 0048 | 8d78 3049 | 3bbf 1801 | 0000 0f87
0x000000011899ce44: 712f 0000 | 4989 bf08 | 0100 0048 | c700 0100 | 0000 488b | ca49 ba00 | 0000 0008 | 0000 0049
0x000000011899ce64: 2bca 8948 | 0848 33c9 | 8948 0c48 | 33c9 4889 | 4810 4889 | 4818 4889 | 4820 4889 | 4828 488b
0x000000011899ce84: ; {metadata(method data for {method} {0x000000010d89e528} 'Anon_2' '(LTutorialIntegrationTests/TwoPhaseCommit$eWriteTransResp;)V' in 'TutorialIntegrationTests/TwoPhaseCommit$AtomicityInvariant')}
0x000000011899ce84: d048 be58 | 53b6 0d01 | 0000 0048 | 8386 1001
0x000000011899ce94: ; {metadata(method data for {method} {0x000000080037d5e8} '<init>' '()V' in 'java/util/HashMap')}
0x000000011899ce94: 0000 0148 | ba20 8341 | 0d01 0000 | 008b b2ac | 0000 0083 | c602 89b2 | ac00 0000 | 81e6 feff
0x000000011899ceb4: 1f00 83fe | 000f 8407 | 2f00 0048
0x000000011899cec0: ; {metadata(method data for {method} {0x000000080037d5e8} '<init>' '()V' in 'java/util/HashMap')}
0x000000011899cec0: 8bd0 48be | 2083 410d | 0100 0000 | 4883 86f0 | 0000 0001
0x000000011899ced4: ; {metadata(method data for {method} {0x00000008003d11f8} '<init>' '()V' in 'java/util/AbstractMap')}
0x000000011899ced4: 48ba 5084 | 410d 0100 | 0000 8bb2 | ac00 0000 | 83c6 0289 | b2ac 0000 | 0081 e6fe | ff1f 0083
0x000000011899cef4: fe00 0f84 | eb2e 0000
0x000000011899cefc: ; {metadata(method data for {method} {0x00000008003d11f8} '<init>' '()V' in 'java/util/AbstractMap')}
0x000000011899cefc: 488b d048 | be50 8441 | 0d01 0000 | 0048 8386 | f000 0000
0x000000011899cf10: ; {metadata(method data for {method} {0x0000000800444540} '<init>' '()V' in 'java/lang/Object')}
0x000000011899cf10: 0148 bab8 | 3640 0d01 | 0000 008b | b2ac 0000 | 0083 c602 | 89b2 ac00 | 0000 81e6 | feff 1f00
0x000000011899cf30: 83fe 000f | 84cf 2e00 | 00c7 4020 | 0000 403f
0x000000011899cf40: ; {metadata('java/util/HashMap')}
0x000000011899cf40: 48ba b880 | 0f00 0800 | 0000 498b | 8708 0100 | 0048 8d78 | 3049 3bbf | 1801 0000 | 0f87 c72e
0x000000011899cf60: 0000 4989 | bf08 0100 | 0048 c700 | 0100 0000 | 488b ca49 | ba00 0000 | 0008 0000 | 0049 2bca
0x000000011899cf80: 8948 0848 | 33c9 8948 | 0c48 33c9 | 4889 4810 | 4889 4818 | 4889 4820 | 4889 4828
0x000000011899cf9c: ; {metadata(method data for {method} {0x000000010d89e528} 'Anon_2' '(LTutorialIntegrationTests/TwoPhaseCommit$eWriteTransResp;)V' in 'TutorialIntegrationTests/TwoPhaseCommit$AtomicityInvariant')}
0x000000011899cf9c: 488b d048 | be58 53b6 | 0d01 0000 | 0048 8386 | 2001 0000
0x000000011899cfb0: ; {metadata(method data for {method} {0x000000080037d5e8} '<init>' '()V' in 'java/util/HashMap')}
0x000000011899cfb0: 0148 ba20 | 8341 0d01 | 0000 008b | b2ac 0000 | 0083 c602 | 89b2 ac00 | 0000 81e6 | feff 1f00
0x000000011899cfd0: 83fe 000f | 845d 2e00 | 0048 8bd0
0x000000011899cfdc: ; {metadata(method data for {method} {0x000000080037d5e8} '<init>' '()V' in 'java/util/HashMap')}
0x000000011899cfdc: 48be 2083 | 410d 0100 | 0000 4883 | 86f0 0000
0x000000011899cfec: ; {metadata(method data for {method} {0x00000008003d11f8} '<init>' '()V' in 'java/util/AbstractMap')}
0x000000011899cfec: 0001 48ba | 5084 410d | 0100 0000 | 8bb2 ac00 | 0000 83c6 | 0289 b2ac | 0000 0081 | e6fe ff1f
0x000000011899d00c: 0083 fe00 | 0f84 412e | 0000 488b
0x000000011899d018: ; {metadata(method data for {method} {0x00000008003d11f8} '<init>' '()V' in 'java/util/AbstractMap')}
0x000000011899d018: d048 be50 | 8441 0d01 | 0000 0048 | 8386 f000
0x000000011899d028: ; {metadata(method data for {method} {0x0000000800444540} '<init>' '()V' in 'java/lang/Object')}
0x000000011899d028: 0000 0148 | bab8 3640 | 0d01 0000 | 008b b2ac | 0000 0083 | c602 89b2 | ac00 0000 | 81e6 feff
0x000000011899d048: 1f00 83fe | 000f 8425 | 2e00 00c7 | 4020 0000
0x000000011899d058: ; {metadata('java/util/HashMap')}
0x000000011899d058: 403f 48ba | b880 0f00 | 0800 0000 | 498b 8708 | 0100 0048 | 8d78 3049 | 3bbf 1801 | 0000 0f87
0x000000011899d078: 1d2e 0000 | 4989 bf08 | 0100 0048 | c700 0100 | 0000 488b | ca49 ba00 | 0000 0008 | 0000 0049
0x000000011899d098: 2bca 8948 | 0848 33c9 | 8948 0c48 | 33c9 4889 | 4810 4889 | 4818 4889 | 4820 4889 | 4828 488b
0x000000011899d0b8: ; {metadata(method data for {method} {0x000000010d89e528} 'Anon_2' '(LTutorialIntegrationTests/TwoPhaseCommit$eWriteTransResp;)V' in 'TutorialIntegrationTests/TwoPhaseCommit$AtomicityInvariant')}
0x000000011899d0b8: d048 be58 | 53b6 0d01 | 0000 0048 | 8386 3001
0x000000011899d0c8: ; {metadata(method data for {method} {0x000000080037d5e8} '<init>' '()V' in 'java/util/HashMap')}
0x000000011899d0c8: 0000 0148 | ba20 8341 | 0d01 0000 | 008b b2ac | 0000 0083 | c602 89b2 | ac00 0000 | 81e6 feff
0x000000011899d0e8: 1f00 83fe | 000f 84b3 | 2d00 0048
0x000000011899d0f4: ; {metadata(method data for {method} {0x000000080037d5e8} '<init>' '()V' in 'java/util/HashMap')}
0x000000011899d0f4: 8bd0 48be | 2083 410d | 0100 0000 | 4883 86f0 | 0000 0001
0x000000011899d108: ; {metadata(method data for {method} {0x00000008003d11f8} '<init>' '()V' in 'java/util/AbstractMap')}
0x000000011899d108: 48ba 5084 | 410d 0100 | 0000 8bb2 | ac00 0000 | 83c6 0289 | b2ac 0000 | 0081 e6fe | ff1f 0083
0x000000011899d128: fe00 0f84 | 972d 0000
0x000000011899d130: ; {metadata(method data for {method} {0x00000008003d11f8} '<init>' '()V' in 'java/util/AbstractMap')}
0x000000011899d130: 488b d048 | be50 8441 | 0d01 0000 | 0048 8386 | f000 0000
0x000000011899d144: ; {metadata(method data for {method} {0x0000000800444540} '<init>' '()V' in 'java/lang/Object')}
0x000000011899d144: 0148 bab8 | 3640 0d01 | 0000 008b | b2ac 0000 | 0083 c602 | 89b2 ac00 | 0000 81e6 | feff 1f00
0x000000011899d164: 83fe 000f | 847b 2d00 | 00c7 4020 | 0000 403f
0x000000011899d174: ; {metadata('java/util/HashMap')}
0x000000011899d174: 48ba b880 | 0f00 0800 | 0000 498b | 8708 0100 | 0048 8d78 | 3049 3bbf | 1801 0000 | 0f87 732d
0x000000011899d194: 0000 4989 | bf08 0100 | 0048 c700 | 0100 0000 | 488b ca49 | ba00 0000 | 0008 0000 | 0049 2bca
0x000000011899d1b4: 8948 0848 | 33c9 8948 | 0c48 33c9 | 4889 4810 | 4889 4818 | 4889 4820 | 4889 4828
0x000000011899d1d0: ; {metadata(method data for {method} {0x000000010d89e528} 'Anon_2' '(LTutorialIntegrationTests/TwoPhaseCommit$eWriteTransResp;)V' in 'TutorialIntegrationTests/TwoPhaseCommit$AtomicityInvariant')}
0x000000011899d1d0: 488b f048 | bf58 53b6 | 0d01 0000 | 0048 8387 | 4001 0000
0x000000011899d1e4: ; {metadata(method data for {method} {0x000000080037d5e8} '<init>' '()V' in 'java/util/HashMap')}
0x000000011899d1e4: 0148 be20 | 8341 0d01 | 0000 008b | beac 0000 | 0083 c702 | 89be ac00 | 0000 81e7 | feff 1f00
0x000000011899d204: 83ff 000f | 8409 2d00 | 0048 8bf0
0x000000011899d210: ; {metadata(method data for {method} {0x000000080037d5e8} '<init>' '()V' in 'java/util/HashMap')}
0x000000011899d210: 48bf 2083 | 410d 0100 | 0000 4883 | 87f0 0000
0x000000011899d220: ; {metadata(method data for {method} {0x00000008003d11f8} '<init>' '()V' in 'java/util/AbstractMap')}
0x000000011899d220: 0001 48be | 5084 410d | 0100 0000 | 8bbe ac00 | 0000 83c7 | 0289 beac | 0000 0081 | e7fe ff1f
0x000000011899d240: 0083 ff00 | 0f84 ed2c | 0000 488b
0x000000011899d24c: ; {metadata(method data for {method} {0x00000008003d11f8} '<init>' '()V' in 'java/util/AbstractMap')}
0x000000011899d24c: f048 bf50 | 8441 0d01 | 0000 0048 | 8387 f000
0x000000011899d25c: ; {metadata(method data for {method} {0x0000000800444540} '<init>' '()V' in 'java/lang/Object')}
0x000000011899d25c: 0000 0148 | beb8 3640 | 0d01 0000 | 008b beac | 0000 0083 | c702 89be | ac00 0000 | 81e7 feff
0x000000011899d27c: 1f00 83ff | 000f 84d1 | 2c00 00c7 | 4020 0000 | 403f 4883 | fb00 0f84 | e12c 0000
C2:
Aha!
============================= C2-compiled nmethod ==============================
----------------------------------- Assembly -----------------------------------
Compiled method (c2) 15255 14110 4 TutorialIntegrationTests.TwoPhaseCommit$AtomicityInvariant::Anon_2 (685 bytes)
total in heap [0x000000012025b910,0x000000012025d428] = 6936
relocation [0x000000012025ba70,0x000000012025bb68] = 248
main code [0x000000012025bb80,0x000000012025c6a0] = 2848
stub code [0x000000012025c6a0,0x000000012025c6d8] = 56
oops [0x000000012025c6d8,0x000000012025c708] = 48
metadata [0x000000012025c708,0x000000012025c748] = 64
scopes data [0x000000012025c748,0x000000012025cf38] = 2032
scopes pcs [0x000000012025cf38,0x000000012025d1f8] = 704
dependencies [0x000000012025d1f8,0x000000012025d208] = 16
handler table [0x000000012025d208,0x000000012025d3d0] = 456
nul chk table [0x000000012025d3d0,0x000000012025d428] = 88
[Constant Pool (empty)]
[MachCode]
[Entry Point]
# {method} {0x000000010d89e528} 'Anon_2' '(LTutorialIntegrationTests/TwoPhaseCommit$eWriteTransResp;)V' in 'TutorialIntegrationTests/TwoPhaseCommit$AtomicityInvariant'
# this: rsi:rsi = 'TutorialIntegrationTests/TwoPhaseCommit$AtomicityInvariant'
# parm0: rdx:rdx = 'TutorialIntegrationTests/TwoPhaseCommit$eWriteTransResp'
# [sp+0x50] (sp of caller)
0x000000012025bb80: 448b 5608 | 49bb 0000 | 0000 0800 | 0000 4d03 | d349 3bc2
0x000000012025bb94: ; {runtime_call ic_miss_stub}
0x000000012025bb94: 0f85 e6bb | 13f8 6690 | 0f1f 4000
[Verified Entry Point]
0x000000012025bba0: 8984 2400 | c0fe ff55 | 4883 ec40
0x000000012025bbac: ; implicit exception: dispatches to 0x000000012025c5a0
0x000000012025bbac: 448b 420c
0x000000012025bbb0: ; implicit exception: dispatches to 0x000000012025c5ac
0x000000012025bbb0: 438b 4cc4 | 0c44 8b4e | 2044 8bd9 | 4181 c380 | 0000 004b | 8d1c c441 | 81fb 0001 | 0000 0f83
0x000000012025bbd0: 6003 0000
0x000000012025bbd4: ; {oop(a 'java/lang/Integer'[256] {0x00000007ffc77a00})}
0x000000012025bbd4: 4c63 d149 | bb00 7ac7 | ff07 0000 | 0047 8b9c | 9310 0200 | 004b 8d14 | dc45 85c9 | 0f84 5c08
0x000000012025bbf4: 0000 4889 | 5c24 0844 | 8904 2448 | 8bee 4b8d
0x000000012025bc04: ; {optimized virtual_call}
0x000000012025bc04: 34cc 90e8
0x000000012025bc08: ; ImmutableOopMap {rbp=Oop [0]=NarrowOop [8]=Oop }
;*invokevirtual getNode {reexecute=0 rethrow=0 return_oop=1}
; - java.util.HashMap::containsKey@2 (line 594)
; - TutorialIntegrationTests.TwoPhaseCommit$AtomicityInvariant::Anon_2@174 (line 409)
0x000000012025bc08: 74be 13f8 | 448b 0c24 | 438b 4ccc | 1048 85c0 | 0f84 7f04 | 0000 4885 | c041 0f95 | c245 0fb6
0x000000012025bc28: d245 85d2 | 0f84 2e08 | 0000 4c8b | c545 8b58 | 2043 8b6c | cc0c 498b | fb48 c1e7 | 034c 63d5
0x000000012025bc48: 8bdd 81c3 | 8000 0000 | 85c9 0f85 | 5604 0000 | 81fb 0001 | 0000 0f83 | 1003 0000
So, we have to hit the highest-optimising compiler for these allocations to disappear. C2 does some pretty aggressive dataflow analysis so I would have been surprised if it didn't elide those allocations, but I'm a bit surprised C1 didn't.
This is so cool! thanks for the study @dijkstracula, love it!
Are there similar optimization flags that we can use for C# compiler as well?