This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new c6a0d30195 Avoid finding same class member repeatedly
c6a0d30195 is described below

commit c6a0d30195facf297e5df61111c79965196f033f
Author: Daniel Sun <[email protected]>
AuthorDate: Thu Apr 3 21:57:14 2025 +0900

    Avoid finding same class member repeatedly
---
 .../groovy/classgen/VariableScopeVisitor.java      | 92 ++++++++++++++--------
 1 file changed, 61 insertions(+), 31 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java 
b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
index 2a610282fb..7c0b2f4bc9 100644
--- a/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/VariableScopeVisitor.java
@@ -193,46 +193,51 @@ public class VariableScopeVisitor extends 
ClassCodeVisitorSupport {
         currentScope.putDeclaredVariable(variable);
     }
 
+    private final Map<ClassMemberCacheKey, Variable> classMemberCache = new 
HashMap<>(64);
     private Variable findClassMember(final ClassNode node, final String name) {
-        final boolean abstractType = node.isAbstract();
-
-        for (ClassNode cn = node; cn != null && !ClassHelper.isObjectType(cn); 
cn = cn.getSuperClass()) {
-            for (FieldNode fn : cn.getFields()) {
-                if (name.equals(fn.getName())) return fn;
-            }
+        return classMemberCache.computeIfAbsent(new ClassMemberCacheKey(name, 
node), k -> {
+            final ClassNode classNode = k.node;
+            final String memberName = k.name;
+            final boolean abstractType = classNode.isAbstract();
+
+            for (ClassNode cn = classNode; cn != null && 
!ClassHelper.isObjectType(cn); cn = cn.getSuperClass()) {
+                for (FieldNode fn : cn.getFields()) {
+                    if (memberName.equals(fn.getName())) return fn;
+                }
 
-            for (PropertyNode pn : cn.getProperties()) {
-                if (name.equals(pn.getName())) return pn;
-            }
+                for (PropertyNode pn : cn.getProperties()) {
+                    if (memberName.equals(pn.getName())) return pn;
+                }
 
-            for (MethodNode mn : cn.getMethods()) {
-                if ((abstractType || !mn.isAbstract()) && 
name.equals(getPropertyName(mn))) {
-                    // check for super property before returning a 
pseudo-property
-                    for (PropertyNode pn : 
getAllProperties(cn.getSuperClass())) {
-                        if (name.equals(pn.getName())) return pn;
-                    }
+                for (MethodNode mn : cn.getMethods()) {
+                    if ((abstractType || !mn.isAbstract()) && 
memberName.equals(getPropertyName(mn))) {
+                        // check for super property before returning a 
pseudo-property
+                        for (PropertyNode pn : 
getAllProperties(cn.getSuperClass())) {
+                            if (memberName.equals(pn.getName())) return pn;
+                        }
 
-                    FieldNode fn = new FieldNode(name, mn.getModifiers() & 
0xF, ClassHelper.dynamicType(), cn, null);
-                    fn.setHasNoRealSourcePosition(true);
-                    fn.setDeclaringClass(cn);
-                    fn.setSynthetic(true);
+                        FieldNode fn = new FieldNode(memberName, 
mn.getModifiers() & 0xF, ClassHelper.dynamicType(), cn, null);
+                        fn.setHasNoRealSourcePosition(true);
+                        fn.setDeclaringClass(cn);
+                        fn.setSynthetic(true);
 
-                    PropertyNode pn = new PropertyNode(fn, fn.getModifiers(), 
null, null);
-                    pn.putNodeMetaData("access.method", mn);
-                    pn.setDeclaringClass(cn);
-                    return pn;
+                        PropertyNode pn = new PropertyNode(fn, 
fn.getModifiers(), null, null);
+                        pn.putNodeMetaData("access.method", mn);
+                        pn.setDeclaringClass(cn);
+                        return pn;
+                    }
                 }
-            }
 
-            for (ClassNode in : cn.getAllInterfaces()) {
-                FieldNode fn = in.getDeclaredField(name);
-                if (fn != null) return fn;
-                PropertyNode pn = in.getProperty(name);
-                if (pn != null) return pn;
+                for (ClassNode in : cn.getAllInterfaces()) {
+                    FieldNode fn = in.getDeclaredField(memberName);
+                    if (fn != null) return fn;
+                    PropertyNode pn = in.getProperty(memberName);
+                    if (pn != null) return pn;
+                }
             }
-        }
 
-        return null;
+            return null;
+        });
     }
 
     private final Map<VariableCacheKey, Variable> variableCache = new 
HashMap<>(64);
@@ -765,6 +770,31 @@ public class VariableScopeVisitor extends 
ClassCodeVisitorSupport {
         }
     }
 
+    private static class ClassMemberCacheKey {
+        private static final int DEFAULT_HASH = 0;
+        private final String name;
+        private final ClassNode node;
+        private int hash = DEFAULT_HASH;
+
+        ClassMemberCacheKey(final String name, final ClassNode node) {
+            this.name = name;
+            this.node = node;
+        }
+
+        @Override
+        public boolean equals(final Object obj) {
+            if (this == obj) return true;
+            if (!(obj instanceof ClassMemberCacheKey)) return false;
+            ClassMemberCacheKey that = (ClassMemberCacheKey) obj;
+            return name.equals(that.name) && node.equals(that.node);
+        }
+
+        @Override
+        public int hashCode() {
+            return DEFAULT_HASH != hash ? hash : (hash = Objects.hash(name, 
node));
+        }
+    }
+
     private static class VariableCacheKey {
         private static final int DEFAULT_HASH = 0;
         private final String name;

Reply via email to