You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2022/05/14 12:54:25 UTC
[groovy] branch GROOVY_4_0_X updated: Tweak guards for receiver and parameters further
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_4_0_X by this push:
new d471d3d507 Tweak guards for receiver and parameters further
d471d3d507 is described below
commit d471d3d507a8c7c9ea95c8e93a1fe2dd878e85db
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sat May 14 20:34:44 2022 +0800
Tweak guards for receiver and parameters further
---
.../org/codehaus/groovy/vmplugin/v8/Selector.java | 37 +++++++-
src/test/groovy/bugs/Groovy10535.groovy | 101 +++++++++++----------
2 files changed, 88 insertions(+), 50 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java b/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
index 99a67ea3b5..12b45d4f3b 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
@@ -63,6 +63,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
@@ -85,6 +86,7 @@ import static org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.MOP
import static org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.MOP_INVOKE_CONSTRUCTOR;
import static org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.MOP_INVOKE_METHOD;
import static org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.NULL_REF;
+import static org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.SAME_CLASS;
import static org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.SAME_CLASSES;
import static org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.SAME_MC;
import static org.codehaus.groovy.vmplugin.v8.IndyGuardsFiltersAndSignatures.SAM_CONVERSION;
@@ -923,10 +925,37 @@ public abstract class Selector {
// guards for receiver and parameter
Class<?>[] pt = handle.type().parameterArray();
- MethodHandle test = SAME_CLASSES.bindTo(args)
- .asCollector(Object[].class, pt.length)
- .asType(MethodType.methodType(boolean.class, pt));
- handle = MethodHandles.guardWithTest(test, handle, fallback);
+ if (Arrays.stream(args).anyMatch(arg -> null == arg)) {
+ for (int i = 0; i < args.length; i++) {
+ Object arg = args[i];
+ Class<?> paramType = pt[i];
+ MethodHandle test;
+
+ if (arg == null) {
+ test = IS_NULL.asType(MethodType.methodType(boolean.class, paramType));
+ if (LOG_ENABLED) LOG.info("added null argument check at pos " + i);
+ } else {
+ if (Modifier.isFinal(paramType.getModifiers())) {
+ // primitive types are also `final`
+ continue;
+ }
+ test = SAME_CLASS.
+ bindTo(arg.getClass()).
+ asType(MethodType.methodType(boolean.class, paramType));
+ if (LOG_ENABLED) LOG.info("added same class check at pos " + i);
+ }
+ Class<?>[] drops = new Class[i];
+ System.arraycopy(pt, 0, drops, 0, drops.length);
+ test = MethodHandles.dropArguments(test, 0, drops);
+ handle = MethodHandles.guardWithTest(test, handle, fallback);
+ }
+ } else {
+ // Avoid guards as possible as we could
+ MethodHandle test = SAME_CLASSES.bindTo(args)
+ .asCollector(Object[].class, pt.length)
+ .asType(MethodType.methodType(boolean.class, pt));
+ handle = MethodHandles.guardWithTest(test, handle, fallback);
+ }
}
/**
diff --git a/src/test/groovy/bugs/Groovy10535.groovy b/src/test/groovy/bugs/Groovy10535.groovy
index 0e85c00f8b..3e989014f3 100644
--- a/src/test/groovy/bugs/Groovy10535.groovy
+++ b/src/test/groovy/bugs/Groovy10535.groovy
@@ -26,62 +26,71 @@ final class Groovy10535 {
@Test
void testBooleanTypecast_invokeDynamicOptimization1() {
- assertScript '''
- @groovy.transform.CompileStatic
- class C {
- static main(args) {
- Collection<String> strings = null
- for (int i = 0; i <= 200_000; i += 1) { // vs groovy.indy.optimize.threshold
- assert test(strings) === null
+ for (String stcAnn : ['@groovy.transform.CompileStatic', '']) {
+ assertScript(
+ stcAnn + '''
+ class C {
+ static main(args) {
+ Collection<String> strings = null
+ for (int i = 0; i <= 200_000; i += 1) { // vs groovy.indy.optimize.threshold
+ assert test(strings) === null
+ }
+ strings = ['x']
+ assert test(strings) !== null
+ }
+ static test(Collection<String> values) {
+ if (values) return 'thing'
+ }
}
- strings = ['x']
- assert test(strings) !== null
- }
- static test(Collection<String> values) {
- if (values) return 'thing'
- }
- }
- '''
+ '''
+ )
+ }
}
@Test
void testBooleanTypecast_invokeDynamicOptimization2() {
- assertScript '''
- @groovy.transform.CompileStatic
- class C {
- static main(args) {
- Collection<String> strings = ['x']
- for (int i = 0; i <= 200_000; i += 1) {
- assert test(strings) !== null
+ for (String stcAnn : ['@groovy.transform.CompileStatic', '']) {
+ assertScript (
+ stcAnn + '''
+ class C {
+ static main(args) {
+ Collection<String> strings = ['x']
+ for (int i = 0; i <= 200_000; i += 1) {
+ assert test(strings) !== null
+ }
+ strings = null
+ assert test(strings) === null
+ }
+ static test(Collection<String> values) {
+ if (values) return 'thing'
+ }
}
- strings = null
- assert test(strings) === null
- }
- static test(Collection<String> values) {
- if (values) return 'thing'
- }
- }
- '''
+ '''
+ )
+ }
}
@Test
void testBooleanTypecast_invokeDynamicOptimization3() {
- assertScript '''
- @groovy.transform.CompileStatic
- class C {
- static main(args) {
- Collection<String> strings
- for (int i = 0; i <= 200_000; i += 1) {
- strings = [i as String]
- assert test(strings) !== null
+ for (String stcAnn : ['@groovy.transform.CompileStatic', '']) {
+ assertScript (
+ stcAnn + '''
+ class C {
+ static main(args) {
+ Collection<String> strings
+ for (int i = 0; i <= 200_000; i += 1) {
+ strings = [i as String]
+ assert test(strings) !== null
+ }
+ strings = null
+ assert test(strings) === null
+ }
+ static test(Collection<String> values) {
+ if (values) return 'thing'
+ }
}
- strings = null
- assert test(strings) === null
- }
- static test(Collection<String> values) {
- if (values) return 'thing'
- }
- }
- '''
+ '''
+ )
+ }
}
}