groovy-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Remi Forax <fo...@univ-mlv.fr>
Subject Re: Aw: Groovy 2.5.4 generates dead code
Date Wed, 21 Nov 2018 16:27:38 GMT
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" <blackdrag@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" <aalmiray@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 |
> https://github.com/jacoco/jacoco/pull/733#issuecomment-440030323 ] in context).
> Reproducing full message:

> [ https://github.com/aalmiray | @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://andresalmiray.com ]
> [ http://www.linkedin.com/in/aalmiray | 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.

Mime
View raw message