and to add to the history... the bug was reported with an asm version before it started to produce nop, athrow. I think I remember also that this was not long before the change asm did.

bye Jochen

On 21.11.18 17:27, Remi Forax wrote:
The history from the ASM point of view,
starting with Java 6, the VM starts to use a new bytecode verifier which is linear in time and not exponential like the previous one but it requires to annotate with a StackMap attribute the bytecode with the state of the local types and the stack types more or less at the start of each basic block. with Java 7, if you want to generate Java 7 bytecode (to access to invokedynamic by example), you have to use the new bytecode verifier, so you have no choice but to add those StackMap attributes.

ASM since Java 6 allows users to ask to generate the StackMap attributes by running a point fix algorithm (the exponential one) when you generate the bytecode so the VM can verify the bytecode linearly. The problem if that in order to compute the StackMap information, we need to information that comes from the "parameter" of the basic block, but if the code is never called, we do not have this information. A previous release of ASM (again a long time ago) was failing in that case, a lot of people ask us to find a way to generate something (you can not remove it) when there is a dead code given that it will be never called anyway. That's why ASM generates the infamous nop ... athrow sequence.

So you have several ways to fix the issue,
- ask Evgeny (in CC) that jacoco should recognize the nop ... athrow sequence and do not report it.
- fix the groovy compiler to not generate dead code

regards,
Rémi

------------------------------------------------------------------------

    *De: *"Jochen Theodorou" <blackd...@gmx.org>
    *À: *"dev" <dev@groovy.apache.org>
    *Envoyé: *Mercredi 21 Novembre 2018 15:02:49
    *Objet: *Aw: Groovy 2.5.4 generates dead code

    Hi Andres,
    there was at some point in the past (I think it was related to
    Java8) a problem with us doing entries into the exception table (I
    think it was that table). There was no fix to this on any simple or
    middle level. The entry was made like that because of how the data
    is processed in AsmClassGenerator. That is why we added an
    additional instruction at the end, which then gets compiled by asm
    as nop; athrow; even though we do something else here. I vagually
    remember it had to do with us using asm to create a label for
    marking a range, then not having any instructions anymore and then
    marking the end of the range, followed by no further instructions...
    take it with care, this was 3 or 4 years ago or so - and I do not
    remember any JIRA issue for this right now either, but I think the
    riginal issue mentioned VerificationErrors.
    It is possible that this original issue no longer exists.
    bye Jochen
    *Gesendet:* Mittwoch, 21. November 2018 um 11:19 Uhr
    *Von:* "Andres Almiray" <aalmi...@gmail.com>
    *An:* dev@groovy.apache.org
    *Betreff:* Groovy 2.5.4 generates dead code
    Hello everyone,
    Evgeny Mandrikov (from JaCoCo) sent me a message regarding dead code
    produced by Groovy 2.5.4 (see
    https://github.com/jacoco/jacoco/pull/733#issuecomment-440030323 in
    context).
    Reproducing full message:

    @aalmiray <https://github.com/aalmiray> while playing further with
    Groovy, I noticed that groovyc 2.5.4 generates dead bytecode for the
    following |Example.groovy|

    Closure  closure=  {
       println("Hello,")
       println("World!")
    }
    closure()

    here is corresponding part from |javap -v -p Example\$_run_closure1|
    output

    |public java.lang.Object doCall(java.lang.Object); descriptor:
    (Ljava/lang/Object;)Ljava/lang/Object; flags: ACC_PUBLIC Code:
    stack=3, locals=3, args_size=2 0: invokestatic #22 // Method
    $getCallSiteArray:()[Lorg/codehaus/groovy/runtime/callsite/CallSite;
    3: astore_2 4: aload_2 5: ldc #32 // int 0 7: aaload 8: aload_0 9:
    ldc #34 // String Hello, 11: invokeinterface #40, 3 //
    InterfaceMethod
    
org/codehaus/groovy/runtime/callsite/CallSite.callCurrent:(Lgroovy/lang/GroovyObject;Ljava/lang/Object;)Ljava/lang/Object;
    16: pop 17: aload_2 18: ldc #41 // int 1 20: aaload 21: aload_0 22:
    ldc #43 // String World! 24: invokeinterface #40, 3 //
    InterfaceMethod
    
org/codehaus/groovy/runtime/callsite/CallSite.callCurrent:(Lgroovy/lang/GroovyObject;Ljava/lang/Object;)Ljava/lang/Object;
    29: areturn 30: nop 31: athrow StackMapTable: number_of_entries = 1
    frame_type = 255 /* full_frame */ offset_delta = 30 locals = []
    stack = [ class java/lang/Throwable ] LineNumberTable: line 2: 4
    line 3: 17 LocalVariableTable: Start Length Slot Name Signature 0 30
    0 this LExample$_run_closure1; 0 30 1 it Ljava/lang/Object; |

    instructions at offsets |30| and |31| are not reachable, therefore
    line |3| that starts at instruction with offset |17| will always be
    marked as uncovered.

    Any ideas on what may be causing this behavior?
    Cheers,
    Andres
    -------------------------------------------
    Java Champion; Groovy Enthusiast
    JCP EC Associate Seat
    http://andresalmiray.com
    http://www.linkedin.com/in/aalmiray
    --
    What goes up, must come down. Ask any system administrator.
    There are 10 types of people in the world: Those who understand
    binary, and those who don't.
    To understand recursion, we must first understand recursion.


Reply via email to