You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/03/22 15:57:21 UTC
[groovy] branch master updated: minor refactor
This is an automated email from the ASF dual-hosted git repository.
emilles 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 bf681d1 minor refactor
bf681d1 is described below
commit bf681d1655a6a8154ba69547ce1a8406f5d2a711
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Mar 22 10:51:17 2022 -0500
minor refactor
---
.../org/codehaus/groovy/classgen/Verifier.java | 205 ++++++++++-----------
1 file changed, 93 insertions(+), 112 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/Verifier.java b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
index 86e7641..271a20e 100644
--- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
@@ -77,7 +77,6 @@ import org.objectweb.asm.Opcodes;
import java.beans.Transient;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -94,6 +93,7 @@ import static java.lang.reflect.Modifier.isPrivate;
import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isStatic;
import static java.util.stream.Collectors.joining;
+import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.hasAnnotation;
import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated;
import static org.apache.groovy.ast.tools.ConstructorNodeUtils.getFirstIfSpecialConstructorCall;
import static org.apache.groovy.ast.tools.ExpressionUtils.transformInlineConstants;
@@ -111,6 +111,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.bytecodeX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.castX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.getInterfacesAndSuperInterfaces;
@@ -152,22 +153,18 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
public static final String STATIC_METACLASS_BOOL = "__$stMC";
public static final String INITIAL_EXPRESSION = "INITIAL_EXPRESSION";
public static final String DEFAULT_PARAMETER_GENERATED = "DEFAULT_PARAMETER_GENERATED";
- private static final Parameter[] SET_METACLASS_PARAMS = {new Parameter(ClassHelper.METACLASS_TYPE, "mc")};
private static final Class<?> GENERATED_ANNOTATION = Generated.class;
- private static final Class<?> INTERNAL_ANNOTATION = Internal.class;
+ private static final Class<?> INTERNAL_ANNOTATION = Internal.class;
private static final Class<?> TRANSIENT_ANNOTATION = Transient.class;
// NOTE: timeStamp constants shouldn't belong to Verifier but kept here for binary compatibility
public static final String __TIMESTAMP = "__timeStamp";
public static final String __TIMESTAMP__ = "__timeStamp__239_neverHappen";
- @Deprecated
- public static final Class<Sealed> SEALED_CLASS = Sealed.class;
- @Deprecated
- public static final Class<NonSealed> NON_SEALED_CLASS = NonSealed.class;
private static final Class<Sealed> SEALED_TYPE = Sealed.class;
private static final Class<NonSealed> NON_SEALED_TYPE = NonSealed.class;
+ private static final Parameter[] SET_METACLASS_PARAMS = {new Parameter(ClassHelper.METACLASS_TYPE, "mc")};
private ClassNode classNode;
private MethodNode methodNode;
@@ -184,43 +181,46 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
return methodNode;
}
- private static FieldNode setMetaClassFieldIfNotExists(final ClassNode node, FieldNode metaClassField) {
- if (metaClassField != null) return metaClassField;
- final String classInternalName = BytecodeHelper.getClassInternalName(node);
- metaClassField =
- node.addField("metaClass", ACC_PRIVATE | ACC_TRANSIENT | ACC_SYNTHETIC, ClassHelper.METACLASS_TYPE,
- bytecodeX(ClassHelper.METACLASS_TYPE, mv -> {
- mv.visitVarInsn(ALOAD, 0);
- mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
- })
- );
- metaClassField.setSynthetic(true);
- return metaClassField;
- }
-
private static FieldNode getMetaClassField(final ClassNode node) {
- FieldNode ret = node.getDeclaredField("metaClass");
- if (ret != null) {
- ClassNode mcFieldType = ret.getType();
+ FieldNode metaClassField = node.getDeclaredField("metaClass");
+ if (metaClassField != null) {
+ ClassNode mcFieldType = metaClassField.getType();
if (!mcFieldType.equals(ClassHelper.METACLASS_TYPE)) {
throw new RuntimeParserException("The class " + node.getName() +
" cannot declare field 'metaClass' of type " + mcFieldType.getName() + " as it needs to be of " +
- "the type " + ClassHelper.METACLASS_TYPE.getName() + " for internal groovy purposes", ret);
+ "the type " + ClassHelper.METACLASS_TYPE.getName() + " for internal groovy purposes", metaClassField);
}
- return ret;
+ return metaClassField;
}
ClassNode current = node;
while (!isObjectType(current)) {
current = current.getSuperClass();
if (current == null) break;
- ret = current.getDeclaredField("metaClass");
- if (ret == null) continue;
- if (isPrivate(ret.getModifiers())) continue;
- return ret;
+ metaClassField = current.getDeclaredField("metaClass");
+ if (metaClassField == null) continue;
+ if (isPrivate(metaClassField.getModifiers())) continue;
+ return metaClassField;
}
return null;
}
+ private static FieldNode setMetaClassFieldIfNotExists(final ClassNode node, FieldNode metaClassField) {
+ if (metaClassField == null) {
+ String classInternalName = BytecodeHelper.getClassInternalName(node);
+ metaClassField =
+ node.addField("metaClass", ACC_PRIVATE | ACC_SYNTHETIC | ACC_TRANSIENT, ClassHelper.METACLASS_TYPE,
+ bytecodeX(ClassHelper.METACLASS_TYPE, mv -> {
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
+ })
+ );
+ metaClassField.setSynthetic(true);
+ }
+ return metaClassField;
+ }
+
+ //--------------------------------------------------------------------------
+
@Override
public void visitClass(final ClassNode node) {
this.classNode = node;
@@ -234,15 +234,13 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
checkForDuplicateInterfaces(node);
- if (classNode.isInterface()
- || Traits.isTrait(node)) { // maybe possible to have this true in joint compilation mode
- //interfaces have no constructors, but this code expects one,
- //so create a dummy and don't add it to the class node
- ConstructorNode dummy = new ConstructorNode(0, null);
- addInitialization(node, dummy);
+ if (classNode.isInterface() || Traits.isTrait(node)) {
+ // interfaces have no constructors but this expects one,
+ // so create a dummy but do not add it to the class node
+ addInitialization(node, new ConstructorNode(0, null));
node.visitContents(this);
if (classNode.getNodeMetaData(ClassNodeSkip.class) == null) {
- classNode.setNodeMetaData(ClassNodeSkip.class, true);
+ classNode.setNodeMetaData(ClassNodeSkip.class, Boolean.TRUE);
}
return;
}
@@ -250,18 +248,15 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
addDefaultParameterMethods(node);
addDefaultParameterConstructors(node);
- final String classInternalName = BytecodeHelper.getClassInternalName(node);
- boolean skipGroovify = !node.getAnnotations(ClassHelper.make(POJO.class)).isEmpty()
- && !node.getAnnotations(ClassHelper.make(CompileStatic.class)).isEmpty();
+ boolean skipGroovify = hasAnnotation(node, ClassHelper.make(POJO.class))
+ && hasAnnotation(node, ClassHelper.make(CompileStatic.class));
if (!skipGroovify) {
- addStaticMetaClassField(node, classInternalName);
+ String classInternalName = BytecodeHelper.getClassInternalName(node);
- boolean knownSpecialCase =
- node.isDerivedFrom(ClassHelper.GSTRING_TYPE)
- || node.isDerivedFrom(ClassHelper.GROOVY_OBJECT_SUPPORT_TYPE);
-
- addFastPathHelperFieldsAndHelperMethod(node, classInternalName, knownSpecialCase);
- if (!knownSpecialCase) addGroovyObjectInterfaceAndMethods(node, classInternalName);
+ addStaticMetaClassField(node, classInternalName);
+ addFastPathHelperFieldsAndHelperMethod(node, classInternalName);
+ if (!node.isDerivedFrom(ClassHelper.GROOVY_OBJECT_SUPPORT_TYPE))
+ addGroovyObjectInterfaceAndMethods(node, classInternalName);
addGetLookupMethod(node);
}
@@ -280,7 +275,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
private static final String[] INVALID_COMPONENTS = {"clone", "finalize", "getClass", "hashCode", "notify", "notifyAll", "toString", "wait"};
- private void detectInvalidRecordComponentNames(ClassNode node) {
+ private static void detectInvalidRecordComponentNames(final ClassNode node) {
for (FieldNode fn : node.getFields()) {
if (Arrays.binarySearch(INVALID_COMPONENTS, fn.getName()) >= 0) {
throw new RuntimeParserException("Illegal record component name '" + fn.getName() + "'", fn);
@@ -288,7 +283,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
}
- private void detectNonSealedClasses(ClassNode node) {
+ private static void detectNonSealedClasses(final ClassNode node) {
if (isFinal(node.getModifiers())) return;
if (Boolean.TRUE.equals(node.getNodeMetaData(SEALED_TYPE))) return;
if (Boolean.TRUE.equals(node.getNodeMetaData(NON_SEALED_TYPE))) return;
@@ -306,7 +301,6 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
}
-
private void checkFinalVariables(final ClassNode node) {
GroovyClassVisitor visitor = new FinalVariableAnalyzer(null, getFinalVariablesCallback());
visitor.visitClass(node);
@@ -420,8 +414,8 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
return null;
}
- private static void addFastPathHelperFieldsAndHelperMethod(final ClassNode node, final String classInternalName, final boolean knownSpecialCase) {
- if (node.getNodeMetaData(ClassNodeSkip.class) != null) return;
+ private static void addFastPathHelperFieldsAndHelperMethod(final ClassNode node, final String classInternalName) {
+ if (Boolean.TRUE.equals(node.getNodeMetaData(ClassNodeSkip.class))) return;
FieldNode stMCB = checkFieldDoesNotExist(node, STATIC_METACLASS_BOOL);
if (stMCB == null) {
stMCB = node.addField(
@@ -441,11 +435,10 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
node.addConstructor(constructor);
}
- private void addGetLookupMethod(final ClassNode node) {
+ private static void addGetLookupMethod(final ClassNode node) {
int modifiers = ACC_PUBLIC;
- boolean nonStaticInnerClass = null != node.getOuterClass() && !Modifier.isStatic(node.getModifiers());
- if (!nonStaticInnerClass) {
- // static method cannot be declared in non-static inner class util Java 16
+ if (isStatic(node.getModifiers()) || node.getOuterClass() == null) {
+ // static method cannot be declared in non-static inner class until Java 16
modifiers |= ACC_STATIC;
}
@@ -528,51 +521,47 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
boolean shouldAnnotate = classNode.getModule().getContext() != null;
AnnotationNode generatedAnnotation = shouldAnnotate ? new AnnotationNode(ClassHelper.make(GENERATED_ANNOTATION)) : null;
- AnnotationNode internalAnnotation = shouldAnnotate ? new AnnotationNode(ClassHelper.make(INTERNAL_ANNOTATION)) : null;
+ AnnotationNode internalAnnotation = shouldAnnotate ? new AnnotationNode(ClassHelper.make(INTERNAL_ANNOTATION)) : null;
AnnotationNode transientAnnotation = shouldAnnotate ? new AnnotationNode(ClassHelper.make(TRANSIENT_ANNOTATION)) : null;
if (!node.hasMethod("getMetaClass", Parameter.EMPTY_ARRAY)) {
metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
- MethodNode methodNode = addMethod(node, !shouldAnnotate,
- "getMetaClass",
- ACC_PUBLIC,
- ClassHelper.METACLASS_TYPE,
- Parameter.EMPTY_ARRAY,
- ClassNode.EMPTY_ARRAY,
- new BytecodeSequence(new BytecodeInstruction() {
- @Override
- public void visit(final MethodVisitor mv) {
- Label nullLabel = new Label();
- /*
- * the code is:
- * if (this.metaClass==null) {
- * this.metaClass = this.$getStaticMetaClass()
- * return this.metaClass
- * } else {
- * return this.metaClass
- * }
- * with the optimization that the result of the
- * first this.metaClass is duped on the operand
- * stack and reused for the return in the else part
- */
- mv.visitVarInsn(ALOAD, 0);
- mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
- mv.visitInsn(DUP);
- mv.visitJumpInsn(IFNULL, nullLabel);
- mv.visitInsn(ARETURN);
-
- mv.visitLabel(nullLabel);
- mv.visitInsn(POP);
- mv.visitVarInsn(ALOAD, 0);
- mv.visitInsn(DUP);
- mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
- mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
- mv.visitVarInsn(ALOAD, 0);
- mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
- mv.visitInsn(ARETURN);
- }
- })
- );
+ Statement getMetaClassCode = new BytecodeSequence(new BytecodeInstruction() {
+ @Override
+ public void visit(final MethodVisitor mv) {
+ Label nullLabel = new Label();
+ /*
+ * the code is:
+ * if (this.metaClass==null) {
+ * this.metaClass = this.$getStaticMetaClass()
+ * return this.metaClass
+ * } else {
+ * return this.metaClass
+ * }
+ * with the optimization that the result of the
+ * first this.metaClass is duped on the operand
+ * stack and reused for the return in the else part
+ */
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
+ mv.visitInsn(DUP);
+ mv.visitJumpInsn(IFNULL, nullLabel);
+ mv.visitInsn(ARETURN);
+
+ mv.visitLabel(nullLabel);
+ mv.visitInsn(POP);
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitInsn(DUP);
+ mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
+ mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
+ mv.visitInsn(ARETURN);
+ }
+ });
+
+ MethodNode methodNode = addMethod(node, !shouldAnnotate, "getMetaClass", ACC_PUBLIC,
+ ClassHelper.METACLASS_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getMetaClassCode);
if (shouldAnnotate) {
methodNode.addAnnotation(generatedAnnotation);
methodNode.addAnnotation(internalAnnotation);
@@ -580,14 +569,11 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
}
}
- Parameter[] parameters = new Parameter[]{new Parameter(ClassHelper.METACLASS_TYPE, "mc")};
- if (!node.hasMethod("setMetaClass", parameters)) {
+ if (!node.hasMethod("setMetaClass", SET_METACLASS_PARAMS)) {
metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
Statement setMetaClassCode;
if (isFinal(metaClassField.getModifiers())) {
- ConstantExpression text = new ConstantExpression("cannot set read-only meta class");
- ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
- setMetaClassCode = new ExpressionStatement(cce);
+ setMetaClassCode = stmt(ctorX(ClassHelper.make(IllegalArgumentException.class), constX("cannot set read-only meta class")));
} else {
setMetaClassCode = new BytecodeSequence(new BytecodeInstruction() {
@Override
@@ -598,19 +584,14 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
*/
mv.visitVarInsn(ALOAD, 0);
mv.visitVarInsn(ALOAD, 1);
- mv.visitFieldInsn(PUTFIELD, classInternalName,
- "metaClass", "Lgroovy/lang/MetaClass;");
+ mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
mv.visitInsn(RETURN);
}
});
}
- MethodNode methodNode = addMethod(node, !shouldAnnotate,
- "setMetaClass",
- ACC_PUBLIC, ClassHelper.VOID_TYPE,
- SET_METACLASS_PARAMS, ClassNode.EMPTY_ARRAY,
- setMetaClassCode
- );
+ MethodNode methodNode = addMethod(node, !shouldAnnotate, "setMetaClass", ACC_PUBLIC,
+ ClassHelper.VOID_TYPE, SET_METACLASS_PARAMS, ClassNode.EMPTY_ARRAY, setMetaClassCode);
if (shouldAnnotate) {
methodNode.addAnnotation(generatedAnnotation);
methodNode.addAnnotation(internalAnnotation);
@@ -784,7 +765,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
// no method found, we need to replace
if (m == null) return true;
// method is in current class, nothing to be done
- if (m.getDeclaringClass() == this.getClassNode()) return false;
+ if (m.getDeclaringClass() == getClassNode()) return false;
// do not overwrite final
if (isFinal(m.getModifiers())) return false;
return true;
@@ -862,7 +843,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
visitMethod(getter);
}
- private void copyMethodAnnotations(PropertyNode node, MethodNode accessor) {
+ private static void copyMethodAnnotations(final PropertyNode node, final MethodNode accessor) {
for (AnnotationNode annotationNode : node.getAnnotations()) {
if (annotationNode.isTargetAllowed(METHOD_TARGET)) {
accessor.addAnnotation(annotationNode);