Skip to content

Instantly share code, notes, and snippets.

@franz1981
Created February 28, 2024 16:46
Show Gist options
  • Save franz1981/d9db204244be173856a87c3780fcf426 to your computer and use it in GitHub Desktop.
Save franz1981/d9db204244be173856a87c3780fcf426 to your computer and use it in GitHub Desktop.

Weird ASM produced around type guards

With

# VM version: JDK 17.0.7, Java HotSpot(TM) 64-Bit Server VM, 17.0.7+8-LTS-224

red.hat.puzzles.polymorphism.InstanceOfScalabilityBenchmark.encodeFullType -pencoderType=a -ppollutionCases=20000 -t 16 -f 4 -prof perfasm

where

# Benchmark: red.hat.puzzles.polymorphism.InstanceOfScalabilityBenchmark.encodeFullType
# Parameters: (encoderType = a, polluteExistingTypes = true, pollutionCases = 20000)

reports:

....[Hottest Region 1]..............................................................................
c2, level 4, red.hat.puzzles.polymorphism.jmh_generated.InstanceOfScalabilityBenchmark_encodeFullType_jmhTest::encodeFullType_avgt_jmhStub, version 858 (22 bytes) 

            0x00007f66fd0309fa:   mov    %r11d,0x4(%rsp)
            0x00007f66fd0309ff:   call   0x00007f66fc86c480           ; ImmutableOopMap {[48]=Oop [56]=Oop [64]=Oop [0]=NarrowOop }
                                                                      ;*ifeq {reexecute=1 rethrow=0 return_oop=0}
                                                                      ; - (reexecute) red.hat.puzzles.polymorphism.ReferenceCounted::release@4 (line 8)
                                                                      ; - red.hat.puzzles.polymorphism.HttpObjectEncoderA::encode@51 (line 25)
                                                                      ; - red.hat.puzzles.polymorphism.InstanceOfScalabilityBenchmark::encodeFullType@8 (line 126)
                                                                      ; - red.hat.puzzles.polymorphism.jmh_generated.InstanceOfScalabilityBenchmark_encodeFullType_jmhTest::encodeFullType_avgt_jmhStub@15 (line 186)
                                                                      ;   {runtime_call UncommonTrapBlob}
            0x00007f66fd030a04:   movabs $0x800c27058,%rax            ;   {metadata('red/hat/puzzles/polymorphism/Encoder$HttpMessage')}
            0x00007f66fd030a0e:   mov    0x28(%rsi),%rdi
 35.85%     0x00007f66fd030a12:   mov    (%rdi),%ecx
  0.01%     0x00007f66fd030a14:   add    $0x8,%rdi
            0x00007f66fd030a18:   test   %rax,%rax
            0x00007f66fd030a1b:   repnz scas %es:(%rdi),%rax
         ╭  0x00007f66fd030a1e:   jne    0x00007f66fd030a28
         │  0x00007f66fd030a24:   mov    %rax,0x20(%rsi)
  0.53%  ↘  0x00007f66fd030a28:   je     0x00007f66fd030983
            0x00007f66fd030a2e:   mov    $0xffffff45,%esi
            0x00007f66fd030a33:   mov    %r9,0x30(%rsp)
            0x00007f66fd030a38:   mov    %r11,(%rsp)
            0x00007f66fd030a3c:   mov    %r10d,0x8(%rsp)
            0x00007f66fd030a41:   xchg   %ax,%ax
            0x00007f66fd030a43:   call   0x00007f66fc86c480           ; ImmutableOopMap {[48]=Oop [56]=Oop [64]=Oop [0]=Oop [8]=NarrowOop }
                                                                      ;*ifeq {reexecute=1 rethrow=0 return_oop=0}
                                                                      ; - (reexecute) red.hat.puzzles.polymorphism.HttpObjectEncoderA::encode@4 (line 13)
                                                                      ; - red.hat.puzzles.polymorphism.InstanceOfScalabilityBenchmark::encodeFullType@8 (line 126)
                                                                      ; - red.hat.puzzles.polymorphism.jmh_generated.InstanceOfScalabilityBenchmark_encodeFullType_jmhTest::encodeFullType_avgt_jmhStub@15 (line 186)
....................................................................................................
 36.38%  <total for region 1>

Where

    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
    @Override
    public void encode(Object o) {
        try {
            if (o instanceof HttpMessage) {         
                H msg = (H) o;                  // <---------- this check here vs HttpMessage
                encodeHttpMessage(msg);
            }
            if (o instanceof HttpContent) {
                if (o instanceof HttpLastContent) {
                    encodeLastHttpContent((HttpLastContent) o);
                } else {
                    encodeHttpNotLastContent((HttpContent) o);
                }
            }
        } finally {
            release(o);
        }
    }

While on jdk main :

....[Hottest Region 1]..............................................................................
c2, level 4, red.hat.puzzles.polymorphism.HttpObjectEncoderA::encode, version 1176 (19 bytes) 

             #           [sp+0x40]  (sp of caller)
             0x00007f6160a57ae0:   mov    0x8(%rsi),%r10d
             0x00007f6160a57ae4:   cmp    %r10,%rax
             0x00007f6160a57ae7:   jne    0x00007f6160265280           ;   {runtime_call ic_miss_stub}
             0x00007f6160a57aed:   data16 xchg %ax,%ax
           [Verified Entry Point]
             0x00007f6160a57af0:   mov    %eax,-0x14000(%rsp)
             0x00007f6160a57af7:   push   %rbp
             0x00007f6160a57af8:   sub    $0x30,%rsp
             0x00007f6160a57afc:   cmpl   $0x1,0x20(%r15)
  0.03%      0x00007f6160a57b04:   jne    0x00007f6160a57d66           ;*synchronization entry
                                                                       ; - red.hat.puzzles.polymorphism.HttpObjectEncoderA::encode@-1 (line 13)
  0.01%      0x00007f6160a57b0a:   mov    %rsi,(%rsp)
  0.01%      0x00007f6160a57b0e:   mov    0x8(%rdx),%ebp               ; implicit exception: dispatches to 0x00007f6160a57d19
             0x00007f6160a57b11:   mov    %ebp,%esi
             0x00007f6160a57b13:   mov    0x20(%rsi),%r10
 80.23%      0x00007f6160a57b17:   cmp    $0xbb13c240,%ebp             ;   {metadata(&apos;red/hat/puzzles/polymorphism/InstanceOfScalabilityBenchmark$DefaultFullHttpResponse&apos;)}
         ?   0x00007f6160a57b1d:   je     0x00007f6160a57b3a
         ?   0x00007f6160a57b1f:   cmp    $0xbb13c000,%ebp             ;   {metadata(&apos;red/hat/puzzles/polymorphism/InstanceOfScalabilityBenchmark$DefaultHttpResponse&apos;)}
         ??  0x00007f6160a57b25:   je     0x00007f6160a57b3a
         ??  0x00007f6160a57b27:   movabs $0xbb112d50,%rax             ;   {metadata(&apos;red/hat/puzzles/polymorphism/Encoder$HttpMessage&apos;)}
         ??  0x00007f6160a57b31:   cmp    %rax,%r10
         ??  0x00007f6160a57b34:   jne    0x00007f6160a57cd0           ;*instanceof {reexecute=0 rethrow=0 return_oop=0}
         ??                                                            ; - red.hat.puzzles.polymorphism.HttpObjectEncoderA::encode@1 (line 13)
         ??  0x00007f6160a57b3a:   mov    %r10,0x18(%rsp)
             0x00007f6160a57b3f:   mov    %rsi,0x10(%rsp)
             0x00007f6160a57b44:   mov    %rdx,0x8(%rsp)               ;*checkcast {reexecute=0 rethrow=0 return_oop=0}
....................................................................................................
 80.27%  <total for region 1>

which refer to the same encode method shown before but the present a weird order while loading secondary_super_cache and guards, which is:

  1. 0x00007f6160a57b13: mov 0x20(%rsi),%r10 i.e. load current Klass::secondary_super_cache
  2. compare against 2 known types (which were ones with highest frequency) i.e. DefaultHttpResponse, DefaultFullHttpResponse
  3. if not any of the previous concrete types, compare the previous load secondary_super with HttpMessage

I would have expected the guards to happen before and the load + cmp secondary_super, after, instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment