[ 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)