[ 
https://issues.apache.org/jira/browse/GROOVY-10535?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17530934#comment-17530934
 ] 

Eric Milles commented on GROOVY-10535:
--------------------------------------

[~paulk] [~daniel_sun] [~blackdrag]
Here is my idea for creating a method handle that is null-safe and survives 
call site caching.  The commented-out statement is today's logic.  Instead of 
an argument-sensitive solution, I'm creating a method handle that checks for 
null and produces {{false}} or {{FALSE}} (depending on the target type of 
boolean or Boolean).  And for non-null, {{asBoolean}} is invoked, which handles 
boolean and Boolean as well.  Basically, Boolean#valueOf is no longer leveraged.
{code:java}
        private void handleBoolean() {
            if (handle != null) return;
            // boolean->boolean, Boolean->boolean, boolean->Boolean are handled 
by the compiler
            // which leaves (T)Z and (T)Boolean, where T is the static type but 
runtime type of T might be Boolean
            boolean primitive = (staticTargetType == boolean.class);
            if (!primitive && staticTargetType != Boolean.class) return;
            /*
            if (args[0] == null) {
                if (primitive) {
                    handle = MethodHandles.constant(boolean.class, 
Boolean.FALSE);
                    handle = MethodHandles.dropArguments(handle, 0, 
staticSourceType);
                } else {
                    handle = BOOLEAN_IDENTITY; // null of type Boolean
                }
            } else if (args[0] instanceof Boolean) {
                handle = BOOLEAN_IDENTITY;
            } else {
                // call asBoolean
                name = "asBoolean";
                super.setCallSiteTarget();
            }
            */
            name = "asBoolean";
            super.setCallSiteTarget();
            MethodHandle elseCallAsBoolean = handle;
            MethodHandle ifNull = IS_NULL.bindTo(staticSourceType);
            MethodHandle thenFalse = MethodHandles.constant(staticTargetType, 
Boolean.FALSE);
                         thenFalse = MethodHandles.dropArguments(thenFalse, 0, 
staticSourceType);

            handle = MethodHandles.guardWithTest(ifNull, thenFalse, 
elseCallAsBoolean);
        }
{code}

I'm not too familiar with all this {{MethodHandle}} stuff, so forgive me if I 
went down a strange path.

> IF condition on empty Collection has different behavior than null Collection
> ----------------------------------------------------------------------------
>
>                 Key: GROOVY-10535
>                 URL: https://issues.apache.org/jira/browse/GROOVY-10535
>             Project: Groovy
>          Issue Type: Bug
>    Affects Versions: 3.0.10
>         Environment: Groovy 3.0.10/OpenJDK 17.0.2 - Ubuntu 21.10
>            Reporter: Rodolfo Yanke
>            Assignee: Eric Milles
>            Priority: Major
>
> I believe this code should print "something" but doesn't work:
> {code:java}
> @CompileStatic
> class NotWorkingExample {
>   static void main(String[] args) {
>     Collection<String> values = null
>     for (i in 0..<200_000) {
>       printSomethingIfNotEmpty(values)
>     }
>     //never printed but it should
>     values = ['A']
>     printSomethingIfNotEmpty(values)
>   }
>   static printSomethingIfNotEmpty(Collection<String> values) {
>     if(values) {
>       println 'something'
>     }
>   }
> }
> {code}
> This one does print "something" because we pass an empty collection [] 
> instead of null:
> {code:java}
> @CompileStatic
> class ItWorks {
>   static void main(String[] args) {
>       Collection<String> values = []
>       for (i in 0..<200_000) {
>         printSomethingIfNotEmpty(values)
>       }
>     //it works because [] was passed in the previous 200k calls
>     values = ['A']
>     printSomethingIfNotEmpty(values)
>   }
>   static printSomethingIfNotEmpty(Collection<String> values) {
>     if(values) {
>       println 'something'
>     }
>   }
> }{code}
> Some optimization is done differently when the condition is skipped too many 
> times. Both classes should output "something" on the last method call.
> Thank you for the support.



--
This message was sent by Atlassian Jira
(v8.20.7#820007)

Reply via email to