Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 19 additions & 13 deletions src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.codehaus.groovy.ast.GenericsType;
import org.codehaus.groovy.ast.InnerClassNode;
import org.codehaus.groovy.ast.InterfaceHelperClassNode;
import org.codehaus.groovy.ast.IntersectionTypeClassNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.ast.PackageNode;
Expand All @@ -56,7 +57,6 @@
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.FieldExpression;
import org.codehaus.groovy.ast.expr.GStringExpression;
import org.codehaus.groovy.ast.IntersectionTypeClassNode;
import org.codehaus.groovy.ast.expr.LambdaExpression;
import org.codehaus.groovy.ast.expr.ListExpression;
import org.codehaus.groovy.ast.expr.MapEntryExpression;
Expand Down Expand Up @@ -103,6 +103,7 @@
import org.codehaus.groovy.classgen.asm.MopWriter;
import org.codehaus.groovy.classgen.asm.OperandStack;
import org.codehaus.groovy.classgen.asm.OptimizingStatementWriter;
import org.codehaus.groovy.classgen.asm.PeepholeOptimizingMethodVisitor;
import org.codehaus.groovy.classgen.asm.WriterController;
import org.codehaus.groovy.classgen.asm.WriterControllerFactory;
import org.codehaus.groovy.control.SourceUnit;
Expand Down Expand Up @@ -350,7 +351,7 @@
* {@inheritDoc}
*/
@Override
public void visitClass(final ClassNode classNode) {

Check warning on line 354 in src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

A "Brain Method" was detected. Refactor it to reduce at least one of the following metrics: LOC from 104 to 64, Complexity from 20 to 14, Nesting Level from 4 to 2, Number of Variables from 20 to 6.

See more on https://sonarcloud.io/project/issues?id=apache_groovy&issues=AZ6dYD-q1lza7NKJnwoC&open=AZ6dYD-q1lza7NKJnwoC&pullRequest=2591
referencedClasses.clear();

WriterControllerFactory factory = classNode.getNodeMetaData(WriterControllerFactory.class);
Expand Down Expand Up @@ -615,18 +616,22 @@
* {@inheritDoc}
*/
@Override
protected void visitConstructorOrMethod(final MethodNode node, final boolean isConstructor) {

Check warning on line 619 in src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

A "Brain Method" was detected. Refactor it to reduce at least one of the following metrics: LOC from 80 to 64, Complexity from 21 to 14, Nesting Level from 3 to 2, Number of Variables from 19 to 6.

See more on https://sonarcloud.io/project/issues?id=apache_groovy&issues=AZ6dYD-q1lza7NKJnwoD&open=AZ6dYD-q1lza7NKJnwoD&pullRequest=2591
Parameter[] parameters = node.getParameters();
Parameter receiver = null; // JSR 308 "this" parameter
if (parameters.length > 0 && parameters[0].isReceiver()) {
receiver = parameters[0]; // non-static method or inner class ctor
parameters = Arrays.copyOfRange(parameters, 1, parameters.length);
}
MethodVisitor mv = classVisitor.visitMethod(
node.getModifiers() | (isVargs(parameters) ? ACC_VARARGS : 0), node.getName(),
BytecodeHelper.getMethodDescriptor(node.getReturnType(), parameters),
BytecodeHelper.getGenericsMethodSignature(node),
buildExceptions(node.getExceptions()));

MethodVisitor mv = new PeepholeOptimizingMethodVisitor(
classVisitor.visitMethod(
node.getModifiers() | (isVargs(parameters) ? ACC_VARARGS : 0),
node.getName(),
BytecodeHelper.getMethodDescriptor(node.getReturnType(), parameters),
BytecodeHelper.getGenericsMethodSignature(node),
buildExceptions(node.getExceptions())));

controller.setMethodVisitor(mv);
controller.resetLineNumber();

Expand Down Expand Up @@ -678,10 +683,10 @@
mv.visitMaxs(0, 0);
} catch (Throwable t) {
Writer writer = null;
if (mv instanceof TraceMethodVisitor) {
if (mv instanceof TraceMethodVisitor tmv) {
writer = new StringBuilderWriter();
PrintWriter p = new PrintWriter(writer);
((TraceMethodVisitor) mv).p.print(p);
tmv.p.print(p);
p.flush();
}
StringBuilder message = new StringBuilder(64);
Expand Down Expand Up @@ -1971,7 +1976,7 @@
* {@inheritDoc}
*/
@Override
public void visitArrayExpression(final ArrayExpression expression) {

Check warning on line 1979 in src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

A "Brain Method" was detected. Refactor it to reduce at least one of the following metrics: LOC from 106 to 64, Complexity from 19 to 14, Nesting Level from 3 to 2, Number of Variables from 14 to 6.

See more on https://sonarcloud.io/project/issues?id=apache_groovy&issues=AZ6dYD-q1lza7NKJnwoE&open=AZ6dYD-q1lza7NKJnwoE&pullRequest=2591
MethodVisitor mv = controller.getMethodVisitor();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
Expand Down Expand Up @@ -2329,11 +2334,12 @@
while (index<size) {
String methodName = "$createListEntry_" + controller.getNextHelperMethodIndex();
methods.add(methodName);
mv = controller.getClassVisitor().visitMethod(
ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC,
methodName,
"([Ljava/lang/Object;)V",
null, null);
mv = new PeepholeOptimizingMethodVisitor(
controller.getClassVisitor().visitMethod(
ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC,
methodName,
"([Ljava/lang/Object;)V",
null, null));
controller.setMethodVisitor(mv);
mv.visitCode();
int methodBlockSize = Math.min(size-index, maxInit);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import static org.objectweb.asm.Opcodes.ICONST_3;
import static org.objectweb.asm.Opcodes.ICONST_4;
import static org.objectweb.asm.Opcodes.ICONST_5;
import static org.objectweb.asm.Opcodes.ICONST_M1;
import static org.objectweb.asm.Opcodes.IFEQ;
import static org.objectweb.asm.Opcodes.IFNE;
import static org.objectweb.asm.Opcodes.ILOAD;
Expand Down Expand Up @@ -249,6 +250,9 @@ public static String[] getClassInternalNames(ClassNode[] names) {
*/
public static void pushConstant(MethodVisitor mv, int value) {
switch (value) {
case -1:
mv.visitInsn(ICONST_M1);
break;
case 0:
mv.visitInsn(ICONST_0);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ protected void generateMopCalls(final LinkedList<MethodNode> methods, final bool
Parameter[] parameters = method.getParameters();
String mopName = getMopMethodName(method, useThis);
String signature = BytecodeHelper.getMethodDescriptor(returnType, parameters);
MethodVisitor mv = controller.getClassVisitor().visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, mopName, signature, null, null);
MethodVisitor mv = new PeepholeOptimizingMethodVisitor(
controller.getClassVisitor().visitMethod(
ACC_PUBLIC | ACC_SYNTHETIC, mopName, signature, null, null));
controller.setMethodVisitor(mv);

int stackIndex = 0;
Expand Down
57 changes: 6 additions & 51 deletions src/main/java/org/codehaus/groovy/classgen/asm/OperandStack.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,10 @@
import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
import static org.objectweb.asm.Opcodes.ACONST_NULL;
import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.BIPUSH;
import static org.objectweb.asm.Opcodes.CHECKCAST;
import static org.objectweb.asm.Opcodes.D2F;
import static org.objectweb.asm.Opcodes.D2I;
import static org.objectweb.asm.Opcodes.D2L;
import static org.objectweb.asm.Opcodes.DCONST_0;
import static org.objectweb.asm.Opcodes.DCONST_1;
import static org.objectweb.asm.Opcodes.DUP;
import static org.objectweb.asm.Opcodes.DUP2;
import static org.objectweb.asm.Opcodes.DUP2_X1;
Expand All @@ -64,25 +61,18 @@
import static org.objectweb.asm.Opcodes.F2D;
import static org.objectweb.asm.Opcodes.F2I;
import static org.objectweb.asm.Opcodes.F2L;
import static org.objectweb.asm.Opcodes.FCONST_0;
import static org.objectweb.asm.Opcodes.FCONST_1;
import static org.objectweb.asm.Opcodes.FCONST_2;
import static org.objectweb.asm.Opcodes.GETSTATIC;
import static org.objectweb.asm.Opcodes.I2B;
import static org.objectweb.asm.Opcodes.I2C;
import static org.objectweb.asm.Opcodes.I2D;
import static org.objectweb.asm.Opcodes.I2F;
import static org.objectweb.asm.Opcodes.I2L;
import static org.objectweb.asm.Opcodes.I2S;
import static org.objectweb.asm.Opcodes.ICONST_0;
import static org.objectweb.asm.Opcodes.ICONST_1;
import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
import static org.objectweb.asm.Opcodes.L2D;
import static org.objectweb.asm.Opcodes.L2F;
import static org.objectweb.asm.Opcodes.L2I;
import static org.objectweb.asm.Opcodes.LCONST_0;
import static org.objectweb.asm.Opcodes.LCONST_1;
import static org.objectweb.asm.Opcodes.NEW;
import static org.objectweb.asm.Opcodes.POP;
import static org.objectweb.asm.Opcodes.POP2;
Expand Down Expand Up @@ -165,11 +155,7 @@
MethodVisitor mv = controller.getMethodVisitor();
if (mark == size) {
// no element, so use emptyDefault
if (emptyDefault) {
mv.visitIntInsn(BIPUSH, 1);
} else {
mv.visitIntInsn(BIPUSH, 0);
}
mv.visitLdcInsn(emptyDefault ? 1 : 0);
stack.add(null);
} else if (mark == size - 1) {
ClassNode last = stack.get(size - 1);
Expand Down Expand Up @@ -585,42 +571,11 @@
boolean isChar = isPrimitiveChar(type);
if (isInt || isShort || isByte || isChar) {
int val = isInt ? (Integer) value : isShort ? (Short) value : isChar ? (Character) value : (Byte) value;
BytecodeHelper.pushConstant(mv, val);
} else if (isPrimitiveLong(type)) {
if ((Long) value == 0L) {
mv.visitInsn(LCONST_0);
} else if ((Long) value == 1L) {
mv.visitInsn(LCONST_1);
} else {
mv.visitLdcInsn(value);
}
} else if (isPrimitiveFloat(type)) {
// GROOVY-9797: Use Float.equals to differentiate between positive and negative zero
if (value.equals(0f)) {
mv.visitInsn(FCONST_0);
} else if ((Float) value == 1f) {
mv.visitInsn(FCONST_1);
} else if ((Float) value == 2f) {
mv.visitInsn(FCONST_2);
} else {
mv.visitLdcInsn(value);
}
} else if (isPrimitiveDouble(type)) {
// GROOVY-9797: Use Double.equals to differentiate between positive and negative zero
if (value.equals(0d)) {
mv.visitInsn(DCONST_0);
} else if ((Double) value == 1d) {
mv.visitInsn(DCONST_1);
} else {
mv.visitLdcInsn(value);
}
mv.visitLdcInsn(val);
} else if (isPrimitiveLong(type) || isPrimitiveFloat(type) || isPrimitiveDouble(type)) {
mv.visitLdcInsn(value);
Comment on lines +575 to +576

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this require LCONST_0 and so on so the operand stack type is correct?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it was different when most of the bytecode code was written, but current version of asm actually handle the special case internally: https://asm.ow2.io/javadoc/org/objectweb/asm/MethodVisitor.html#visitLdcInsn(java.lang.Object) - AFAIK

} else if (isPrimitiveBoolean(type)) {
boolean b = (Boolean) value;
if (b) {
mv.visitInsn(ICONST_1);
} else {
mv.visitInsn(ICONST_0);
}
mv.visitLdcInsn((Boolean) value ? 1 : 0);

Check warning on line 578 in src/main/java/org/codehaus/groovy/classgen/asm/OperandStack.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a primitive boolean expression here.

See more on https://sonarcloud.io/project/issues?id=apache_groovy&issues=AZ6dYD-E1lza7NKJnwoB&open=AZ6dYD-E1lza7NKJnwoB&pullRequest=2591
} else {
mv.visitLdcInsn(value);
}
Expand Down Expand Up @@ -729,7 +684,7 @@
*/
public void pushBool(final boolean value) {
MethodVisitor mv = controller.getMethodVisitor();
mv.visitInsn(value ? ICONST_1 : ICONST_0);
mv.visitLdcInsn(value ? 1 : 0);
push(ClassHelper.boolean_TYPE);
}

Expand Down
Loading
Loading