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 2019/11/23 18:04:03 UTC
[groovy] branch master updated: organize members and other minor
edits
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 b51fe06 organize members and other minor edits
b51fe06 is described below
commit b51fe06dd9aa5d41489106d7a3047dbda76bb68e
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 23 11:55:04 2019 -0600
organize members and other minor edits
---
.../classgen/asm/OptimizingStatementWriter.java | 527 +++++++++++----------
1 file changed, 273 insertions(+), 254 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/OptimizingStatementWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/OptimizingStatementWriter.java
index fb07f94..5c4b50c 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/OptimizingStatementWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/OptimizingStatementWriter.java
@@ -60,8 +60,10 @@ import org.codehaus.groovy.syntax.Types;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
+import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
+import java.util.Optional;
import static org.codehaus.groovy.ast.ClassHelper.BigDecimal_TYPE;
import static org.codehaus.groovy.ast.ClassHelper.GROOVY_INTERCEPTABLE_TYPE;
@@ -85,40 +87,8 @@ import static org.objectweb.asm.Opcodes.IFEQ;
import static org.objectweb.asm.Opcodes.IFNE;
import static org.objectweb.asm.Opcodes.INVOKEINTERFACE;
-/**
- * A class to write out the optimized statements
- */
public class OptimizingStatementWriter extends StatementWriter {
- private static class FastPathData {
- private Label pathStart = new Label();
- private Label afterPath = new Label();
- }
-
- public static class ClassNodeSkip{}
-
- public static class StatementMeta {
- private boolean optimize=false;
- protected MethodNode target;
- protected ClassNode type;
- protected VariableExpression declaredVariableExpression;
- protected boolean[] involvedTypes = new boolean[typeMapKeyNames.length];
- public void chainInvolvedTypes(OptimizeFlagsCollector opt) {
- for (int i=0; i<typeMapKeyNames.length; i++) {
- if (opt.current.involvedTypes[i]) {
- this.involvedTypes[i] = true;
- }
- }
- }
- public String toString() {
- StringBuilder ret = new StringBuilder("optimize=" + optimize + " target=" + target + " type=" + type + " involvedTypes=");
- for (int i=0; i<typeMapKeyNames.length; i++) {
- if (involvedTypes[i]) ret.append(" ").append(typeMapKeyNames[i]);
- }
- return ret.toString();
- }
- }
-
private static final MethodCaller[] guards = {
null,
MethodCaller.newStatic(BytecodeInterface8.class, "isOrigInt"),
@@ -132,8 +102,8 @@ public class OptimizingStatementWriter extends StatementWriter {
};
private static final MethodCaller disabledStandardMetaClass = MethodCaller.newStatic(BytecodeInterface8.class, "disabledStandardMetaClass");
- private boolean fastPathBlocked = false;
private final WriterController controller;
+ private boolean fastPathBlocked;
public OptimizingStatementWriter(WriterController controller) {
super(controller);
@@ -475,27 +445,69 @@ public class OptimizingStatementWriter extends StatementWriter {
return meta;
}
+ //--------------------------------------------------------------------------
+
+ public static class ClassNodeSkip {
+ }
+
+ private static class FastPathData {
+ private Label pathStart = new Label();
+ private Label afterPath = new Label();
+ }
+
+ public static class StatementMeta {
+ private boolean optimize;
+ protected ClassNode type;
+ protected MethodNode target;
+ protected VariableExpression declaredVariableExpression;
+ protected boolean[] involvedTypes = new boolean[typeMapKeyNames.length];
+
+ public void chainInvolvedTypes(final OptimizeFlagsCollector opt) {
+ for (int i = 0, n = typeMapKeyNames.length; i < n; i += 1) {
+ if (opt.current.involvedTypes[i]) {
+ this.involvedTypes[i] = true;
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder ret = new StringBuilder("optimize=" + optimize + " target=" + target + " type=" + type + " involvedTypes=");
+ for (int i = 0, n = typeMapKeyNames.length; i < n; i += 1) {
+ if (involvedTypes[i]) ret.append(" ").append(typeMapKeyNames[i]);
+ }
+ return ret.toString();
+ }
+ }
+
private static class OptimizeFlagsCollector {
private static class OptimizeFlagsEntry {
- private boolean canOptimize = false;
- private boolean shouldOptimize = false;
+ private boolean canOptimize;
+ private boolean shouldOptimize;
private boolean[] involvedTypes = new boolean[typeMapKeyNames.length];
}
+
private OptimizeFlagsEntry current = new OptimizeFlagsEntry();
- private final LinkedList<OptimizeFlagsEntry> olderEntries = new LinkedList<OptimizeFlagsEntry>();
+ private final Deque<OptimizeFlagsEntry> previous = new LinkedList<>();
+
public void push() {
- olderEntries.addLast(current);
+ previous.addLast(current);
current = new OptimizeFlagsEntry();
}
- public void pop(boolean propagateFlags){
+
+ public void pop(final boolean propagateFlags) {
OptimizeFlagsEntry old = current;
- current = olderEntries.removeLast();
+ current = previous.removeLast();
if (propagateFlags) {
chainCanOptimize(old.canOptimize);
chainShouldOptimize(old.shouldOptimize);
- for (int i=0; i<typeMapKeyNames.length; i++) current.involvedTypes[i] |= old.involvedTypes[i];
+ for (int i = 0, n = typeMapKeyNames.length; i < n; i += 1) {
+ current.involvedTypes[i] |= old.involvedTypes[i];
+ }
}
}
+
+ @Override
public String toString() {
StringBuilder ret;
if (current.shouldOptimize) {
@@ -506,40 +518,46 @@ public class OptimizingStatementWriter extends StatementWriter {
ret = new StringBuilder("don't optimize");
}
ret.append(" involvedTypes =");
- for (int i=0; i<typeMapKeyNames.length; i++) {
+ for (int i = 0, n = typeMapKeyNames.length; i < n; i += 1) {
if (current.involvedTypes[i]) ret.append(" ").append(typeMapKeyNames[i]);
}
return ret.toString();
}
+
/**
* @return true iff we should Optimize - this is almost seen as must
*/
private boolean shouldOptimize() {
return current.shouldOptimize;
}
+
/**
* @return true iff we can optimize, but not have to
*/
private boolean canOptimize() {
return current.canOptimize || current.shouldOptimize;
}
+
/**
* set "should" to true, if not already
*/
- public void chainShouldOptimize(boolean opt) {
+ public void chainShouldOptimize(final boolean opt) {
current.shouldOptimize = shouldOptimize() || opt;
}
+
/**
* set "can" to true, if not already
*/
- public void chainCanOptimize(boolean opt) {
+ public void chainCanOptimize(final boolean opt) {
current.canOptimize = current.canOptimize || opt;
}
- public void chainInvolvedType(ClassNode type) {
+
+ public void chainInvolvedType(final ClassNode type) {
Integer res = typeMap.get(type);
- if (res==null) return;
+ if (res == null) return;
current.involvedTypes[res] = true;
}
+
public void reset() {
current.canOptimize = false;
current.shouldOptimize = false;
@@ -548,125 +566,115 @@ public class OptimizingStatementWriter extends StatementWriter {
}
private static class OptVisitor extends ClassCodeVisitorSupport {
+ private static final VariableScope nonStaticScope = new VariableScope();
+ private final OptimizeFlagsCollector opt = new OptimizeFlagsCollector();
+ private boolean optimizeMethodCall = true;
private final TypeChooser typeChooser;
+ private VariableScope scope;
+ private ClassNode node;
- public OptVisitor(final TypeChooser chooser) {
+ OptVisitor(final TypeChooser chooser) {
this.typeChooser = chooser;
}
- @Override protected SourceUnit getSourceUnit() {return null;}
-
- private ClassNode node;
- private OptimizeFlagsCollector opt = new OptimizeFlagsCollector();
- private boolean optimizeMethodCall = true;
- private VariableScope scope;
- private static final VariableScope nonStaticScope = new VariableScope();
+ @Override
+ protected SourceUnit getSourceUnit() {
+ return null;
+ }
@Override
- public void visitClass(ClassNode node) {
+ public void visitClass(final ClassNode node) {
this.optimizeMethodCall = !node.implementsInterface(GROOVY_INTERCEPTABLE_TYPE);
this.node = node;
this.scope = nonStaticScope;
super.visitClass(node);
- this.scope=null;
- this.node=null;
- }
-
- @Override
- public void visitMethod(MethodNode node) {
- scope = node.getVariableScope();
- super.visitMethod(node);
- opt.reset();
+ this.scope = null;
+ this.node = null;
}
@Override
- public void visitConstructor(ConstructorNode node) {
+ public void visitConstructor(final ConstructorNode node) {
scope = node.getVariableScope();
super.visitConstructor(node);
}
@Override
- public void visitReturnStatement(ReturnStatement statement) {
- opt.push();
- super.visitReturnStatement(statement);
- if (opt.shouldOptimize()) addMeta(statement,opt);
- opt.pop(opt.shouldOptimize());
+ public void visitMethod(final MethodNode node) {
+ scope = node.getVariableScope();
+ super.visitMethod(node);
+ opt.reset();
}
- @Override
- public void visitUnaryMinusExpression(UnaryMinusExpression expression) {
- //TODO: implement int operations for this
- super.visitUnaryMinusExpression(expression);
- StatementMeta meta = addMeta(expression);
- meta.type = OBJECT_TYPE;
- }
+ // statements:
@Override
- public void visitUnaryPlusExpression(UnaryPlusExpression expression) {
- //TODO: implement int operations for this
- super.visitUnaryPlusExpression(expression);
- StatementMeta meta = addMeta(expression);
- meta.type = OBJECT_TYPE;
+ public void visitBlockStatement(final BlockStatement statement) {
+ opt.push();
+ boolean optAll = true;
+ for (Statement stmt : statement.getStatements()) {
+ opt.push();
+ stmt.visit(this);
+ optAll = optAll && opt.canOptimize();
+ opt.pop(true);
+ }
+ if (statement.isEmpty()) {
+ opt.chainCanOptimize(true);
+ opt.pop(true);
+ } else {
+ opt.chainShouldOptimize(optAll);
+ if (optAll) {
+ addMeta(statement, opt);
+ }
+ opt.pop(optAll);
+ }
}
@Override
- public void visitBitwiseNegationExpression(BitwiseNegationExpression expression) {
- //TODO: implement int operations for this
- super.visitBitwiseNegationExpression(expression);
- StatementMeta meta = addMeta(expression);
- meta.type = OBJECT_TYPE;
- }
-
- private void addTypeInformation(Expression expression, Expression orig) {
- ClassNode type = typeChooser.resolveType(expression, node);
- if (isPrimitiveType(type)) {
- StatementMeta meta = addMeta(orig);
- meta.type = type;
- opt.chainShouldOptimize(true);
- opt.chainInvolvedType(type);
+ public void visitExpressionStatement(final ExpressionStatement statement) {
+ if (statement.getNodeMetaData(StatementMeta.class) != null) return;
+ opt.push();
+ super.visitExpressionStatement(statement);
+ if (opt.shouldOptimize()) {
+ addMeta(statement, opt);
}
+ opt.pop(opt.shouldOptimize());
}
@Override
- public void visitPrefixExpression(PrefixExpression expression) {
- super.visitPrefixExpression(expression);
- addTypeInformation(expression.getExpression(),expression);
+ public void visitForLoop(final ForStatement statement) {
+ opt.push();
+ super.visitForLoop(statement);
+ if (opt.shouldOptimize()) {
+ addMeta(statement, opt);
+ }
+ opt.pop(opt.shouldOptimize());
}
@Override
- public void visitPostfixExpression(PostfixExpression expression) {
- super.visitPostfixExpression(expression);
- addTypeInformation(expression.getExpression(),expression);
+ public void visitIfElse(final IfStatement statement) {
+ opt.push();
+ super.visitIfElse(statement);
+ if (opt.shouldOptimize()) {
+ addMeta(statement, opt);
+ }
+ opt.pop(opt.shouldOptimize());
}
@Override
- public void visitDeclarationExpression(DeclarationExpression expression) {
- Expression right = expression.getRightExpression();
- right.visit(this);
-
- ClassNode leftType = typeChooser.resolveType(expression.getLeftExpression(), node);
- Expression rightExpression = expression.getRightExpression();
- ClassNode rightType = optimizeDivWithIntOrLongTarget(rightExpression, leftType);
- if (rightType==null) rightType = typeChooser.resolveType(expression.getRightExpression(), node);
- if (isPrimitiveType(leftType) && isPrimitiveType(rightType)) {
- // if right is a constant, then we optimize only if it makes
- // a block complete, so we set a maybe
- if (right instanceof ConstantExpression) {
- opt.chainCanOptimize(true);
- } else {
- opt.chainShouldOptimize(true);
- }
- StatementMeta meta = addMeta(expression);
- ClassNode declarationType = typeChooser.resolveType(expression, node);
- meta.type = declarationType!=null?declarationType:leftType;
- opt.chainInvolvedType(leftType);
- opt.chainInvolvedType(rightType);
+ public void visitReturnStatement(final ReturnStatement statement) {
+ opt.push();
+ super.visitReturnStatement(statement);
+ if (opt.shouldOptimize()) {
+ addMeta(statement,opt);
}
+ opt.pop(opt.shouldOptimize());
}
+ // expressions:
+
@Override
- public void visitBinaryExpression(BinaryExpression expression) {
- if (expression.getNodeMetaData(StatementMeta.class)!=null) return;
+ public void visitBinaryExpression(final BinaryExpression expression) {
+ if (expression.getNodeMetaData(StatementMeta.class) != null) return;
super.visitBinaryExpression(expression);
ClassNode leftType = typeChooser.resolveType(expression.getLeftExpression(), node);
@@ -674,7 +682,7 @@ public class OptimizingStatementWriter extends StatementWriter {
ClassNode resultType = null;
int operation = expression.getOperation().getType();
- if (operation==Types.LEFT_SQUARE_BRACKET && leftType.isArray()) {
+ if (operation == Types.LEFT_SQUARE_BRACKET && leftType.isArray()) {
opt.chainShouldOptimize(true);
resultType = leftType.getComponentType();
} else {
@@ -696,8 +704,10 @@ public class OptimizingStatementWriter extends StatementWriter {
}
resultType = boolean_TYPE;
break;
- case Types.LOGICAL_AND: case Types.LOGICAL_AND_EQUAL:
- case Types.LOGICAL_OR: case Types.LOGICAL_OR_EQUAL:
+ case Types.LOGICAL_AND:
+ case Types.LOGICAL_AND_EQUAL:
+ case Types.LOGICAL_OR:
+ case Types.LOGICAL_OR_EQUAL:
if (boolean_TYPE.equals(leftType) && boolean_TYPE.equals(rightType)) {
opt.chainShouldOptimize(true);
} else {
@@ -706,7 +716,8 @@ public class OptimizingStatementWriter extends StatementWriter {
expression.setType(boolean_TYPE);
resultType = boolean_TYPE;
break;
- case Types.DIVIDE: case Types.DIVIDE_EQUAL:
+ case Types.DIVIDE:
+ case Types.DIVIDE_EQUAL:
if (isLongCategory(leftType) && isLongCategory(rightType)) {
resultType = BigDecimal_TYPE;
opt.chainShouldOptimize(true);
@@ -718,8 +729,9 @@ public class OptimizingStatementWriter extends StatementWriter {
opt.chainShouldOptimize(true);
}
break;
- case Types.POWER: case Types.POWER_EQUAL:
- //TODO: implement
+ case Types.POWER:
+ case Types.POWER_EQUAL:
+ // TODO: implement
break;
case Types.ASSIGN:
resultType = optimizeDivWithIntOrLongTarget(expression.getRightExpression(), leftType);
@@ -742,166 +754,189 @@ public class OptimizingStatementWriter extends StatementWriter {
}
}
- if (resultType!=null) {
- StatementMeta meta = addMeta(expression);
- meta.type = resultType;
+ if (resultType != null) {
+ addMeta(expression).type = resultType;
opt.chainInvolvedType(resultType);
opt.chainInvolvedType(leftType);
opt.chainInvolvedType(rightType);
}
}
- /**
- * method to optimize Z = X/Y with Z being int or long style
- * @returns null if the optimization cannot be applied, otherwise it
- * will return the new target type
- */
- private ClassNode optimizeDivWithIntOrLongTarget(Expression rhs, ClassNode assignmentTartgetType) {
- if (!(rhs instanceof BinaryExpression)) return null;
- BinaryExpression binExp = (BinaryExpression) rhs;
- int op = binExp.getOperation().getType();
- if (op!=Types.DIVIDE && op!=Types.DIVIDE_EQUAL) return null;
-
- ClassNode originalResultType = typeChooser.resolveType(binExp, node);
- if ( !originalResultType.equals(BigDecimal_TYPE) ||
- !(isLongCategory(assignmentTartgetType) || isFloatingCategory(assignmentTartgetType))
- ) {
- return null;
- }
+ @Override
+ public void visitBitwiseNegationExpression(final BitwiseNegationExpression expression) {
+ // TODO: implement int operations for this
+ super.visitBitwiseNegationExpression(expression);
+ addMeta(expression).type = OBJECT_TYPE;
+ }
- ClassNode leftType = typeChooser.resolveType(binExp.getLeftExpression(), node);
- if (!isLongCategory(leftType)) return null;
- ClassNode rightType = typeChooser.resolveType(binExp.getRightExpression(), node);
- if (!isLongCategory(rightType)) return null;
+ @Override
+ public void visitClosureExpression(final ClosureExpression expression) {
+ }
- ClassNode target;
- if (isIntCategory(leftType) && isIntCategory(rightType)) {
- target = int_TYPE;
- } else if (isLongCategory(leftType) && isLongCategory(rightType)) {
- target = long_TYPE;
- } else if (isDoubleCategory(leftType) && isDoubleCategory(rightType)) {
- target = double_TYPE;
- } else {
- return null;
- }
- StatementMeta meta = addMeta(rhs);
- meta.type = target;
- opt.chainInvolvedType(target);
- return target;
+ @Override
+ public void visitConstructorCallExpression(final ConstructorCallExpression expression) {
+ if (expression.getNodeMetaData(StatementMeta.class) != null) return;
+ super.visitConstructorCallExpression(expression);
+ // we cannot set a target for the constructor call, since we cannot easily check the meta class of the other class
+ //setMethodTarget(call, "<init>", call.getArguments(), false);
}
@Override
- public void visitExpressionStatement(ExpressionStatement statement) {
- if (statement.getNodeMetaData(StatementMeta.class)!=null) return;
- opt.push();
- super.visitExpressionStatement(statement);
- if (opt.shouldOptimize()) addMeta(statement,opt);
- opt.pop(opt.shouldOptimize());
+ public void visitDeclarationExpression(final DeclarationExpression expression) {
+ Expression right = expression.getRightExpression();
+ right.visit(this);
+
+ ClassNode leftType = typeChooser.resolveType(expression.getLeftExpression(), node);
+ Expression rightExpression = expression.getRightExpression();
+ ClassNode rightType = optimizeDivWithIntOrLongTarget(rightExpression, leftType);
+ if (rightType == null) rightType = typeChooser.resolveType(expression.getRightExpression(), node);
+ if (isPrimitiveType(leftType) && isPrimitiveType(rightType)) {
+ // if right is a constant, then we optimize only if it makes a block complete, so we set a maybe
+ if (right instanceof ConstantExpression) {
+ opt.chainCanOptimize(true);
+ } else {
+ opt.chainShouldOptimize(true);
+ }
+ addMeta(expression).type = Optional.ofNullable(typeChooser.resolveType(expression, node)).orElse(leftType);
+ opt.chainInvolvedType(leftType);
+ opt.chainInvolvedType(rightType);
+ }
}
@Override
- public void visitBlockStatement(BlockStatement block) {
- opt.push();
- boolean optAll = true;
- for (Statement statement : block.getStatements()) {
- opt.push();
- statement.visit(this);
- optAll = optAll && opt.canOptimize();
- opt.pop(true);
+ public void visitMethodCallExpression(final MethodCallExpression expression) {
+ if (expression.getNodeMetaData(StatementMeta.class) != null) return;
+ super.visitMethodCallExpression(expression);
+
+ Expression objectExpression = expression.getObjectExpression();
+ boolean setTarget = AsmClassGenerator.isThisExpression(objectExpression);
+ if (!setTarget) {
+ if (!(objectExpression instanceof ClassExpression)) return;
+ setTarget = objectExpression.equals(node); // XXX: comparing Expression and ClassNode
}
- if (block.isEmpty()) {
- opt.chainCanOptimize(true);
- opt.pop(true);
- } else {
- opt.chainShouldOptimize(optAll);
- if (optAll) addMeta(block,opt);
- opt.pop(optAll);
+ if (setTarget) {
+ setMethodTarget(expression, expression.getMethodAsString(), expression.getArguments(), true);
}
}
@Override
- public void visitIfElse(IfStatement statement) {
- opt.push();
- super.visitIfElse(statement);
- if (opt.shouldOptimize()) addMeta(statement,opt);
- opt.pop(opt.shouldOptimize());
+ public void visitPostfixExpression(final PostfixExpression expression) {
+ super.visitPostfixExpression(expression);
+ addTypeInformation(expression.getExpression(), expression);
}
- /*@Override
- public void visitConstantExpression(ConstantExpression expression) {
- super.visitConstantExpression(expression);
- opt.chainShouldOptimize(true);
- }*/
+ @Override
+ public void visitPrefixExpression(final PrefixExpression expression) {
+ super.visitPrefixExpression(expression);
+ addTypeInformation(expression.getExpression(), expression);
+ }
@Override
- public void visitStaticMethodCallExpression(StaticMethodCallExpression expression) {
- if (expression.getNodeMetaData(StatementMeta.class)!=null) return;
+ public void visitStaticMethodCallExpression(final StaticMethodCallExpression expression) {
+ if (expression.getNodeMetaData(StatementMeta.class) != null) return;
super.visitStaticMethodCallExpression(expression);
+ setMethodTarget(expression, expression.getMethod(), expression.getArguments(), true);
+ }
- setMethodTarget(expression,expression.getMethod(), expression.getArguments(), true);
+ @Override
+ public void visitUnaryMinusExpression(final UnaryMinusExpression expression) {
+ // TODO: implement int operations for this
+ super.visitUnaryMinusExpression(expression);
+ addMeta(expression).type = OBJECT_TYPE;
}
@Override
- public void visitMethodCallExpression(MethodCallExpression expression) {
- if (expression.getNodeMetaData(StatementMeta.class)!=null) return;
- super.visitMethodCallExpression(expression);
+ public void visitUnaryPlusExpression(final UnaryPlusExpression expression) {
+ // TODO: implement int operations for this
+ super.visitUnaryPlusExpression(expression);
+ addMeta(expression).type = OBJECT_TYPE;
+ }
- Expression object = expression.getObjectExpression();
- boolean setTarget = AsmClassGenerator.isThisExpression(object);
- if (!setTarget) {
- if (!(object instanceof ClassExpression)) return;
- setTarget = object.equals(node);
- }
+ //
- if (!setTarget) return;
- setMethodTarget(expression, expression.getMethodAsString(), expression.getArguments(), true);
+ private void addTypeInformation(final Expression expression, final Expression orig) {
+ ClassNode type = typeChooser.resolveType(expression, node);
+ if (isPrimitiveType(type)) {
+ addMeta(orig).type = type;
+ opt.chainShouldOptimize(true);
+ opt.chainInvolvedType(type);
+ }
}
- @Override
- public void visitConstructorCallExpression(ConstructorCallExpression call) {
- if (call.getNodeMetaData(StatementMeta.class)!=null) return;
- super.visitConstructorCallExpression(call);
+ /**
+ * Optimizes "Z = X/Y" with Z being int or long style.
+ *
+ * @returns null if the optimization cannot be applied, otherwise it will return the new target type
+ */
+ private ClassNode optimizeDivWithIntOrLongTarget(final Expression rhs, final ClassNode assignmentTartgetType) {
+ if (!(rhs instanceof BinaryExpression)) return null;
+ BinaryExpression binExp = (BinaryExpression) rhs;
+ int op = binExp.getOperation().getType();
+ if (op != Types.DIVIDE && op != Types.DIVIDE_EQUAL) return null;
- // we cannot a target for the constructor call, since we cannot easily
- // check the meta class of the other class
- // setMethodTarget(call, "<init>", call.getArguments(), false);
+ ClassNode originalResultType = typeChooser.resolveType(binExp, node);
+ if (!originalResultType.equals(BigDecimal_TYPE)
+ || !(isLongCategory(assignmentTartgetType)
+ || isFloatingCategory(assignmentTartgetType))) {
+ return null;
+ }
+
+ ClassNode leftType = typeChooser.resolveType(binExp.getLeftExpression(), node);
+ if (!isLongCategory(leftType)) return null;
+ ClassNode rightType = typeChooser.resolveType(binExp.getRightExpression(), node);
+ if (!isLongCategory(rightType)) return null;
+
+ ClassNode target;
+ if (isIntCategory(leftType) && isIntCategory(rightType)) {
+ target = int_TYPE;
+ } else if (isLongCategory(leftType) && isLongCategory(rightType)) {
+ target = long_TYPE;
+ } else if (isDoubleCategory(leftType) && isDoubleCategory(rightType)) {
+ target = double_TYPE;
+ } else {
+ return null;
+ }
+ addMeta(rhs).type = target;
+ opt.chainInvolvedType(target);
+ return target;
}
- private void setMethodTarget(Expression expression, String name, Expression callArgs, boolean isMethod) {
- if (name==null) return;
+ private void setMethodTarget(final Expression expression, final String name, final Expression callArgs, final boolean isMethod) {
+ if (name == null) return;
if (!optimizeMethodCall) return;
if (AsmClassGenerator.containsSpreadExpression(callArgs)) return;
+
// find method call target
Parameter[] paraTypes = null;
if (callArgs instanceof ArgumentListExpression) {
ArgumentListExpression args = (ArgumentListExpression) callArgs;
int size = args.getExpressions().size();
paraTypes = new Parameter[size];
- int i=0;
- for (Expression exp: args.getExpressions()) {
+ int i = 0;
+ for (Expression exp : args.getExpressions()) {
ClassNode type = typeChooser.resolveType(exp, node);
if (!validTypeForCall(type)) return;
- paraTypes[i] = new Parameter(type,"");
- i++;
+ paraTypes[i] = new Parameter(type, "");
+ i += 1;
}
} else {
ClassNode type = typeChooser.resolveType(callArgs, node);
if (!validTypeForCall(type)) return;
- paraTypes = new Parameter[]{new Parameter(type,"")};
+ paraTypes = new Parameter[]{new Parameter(type, "")};
}
MethodNode target;
ClassNode type;
if (isMethod) {
target = node.getMethod(name, paraTypes);
- if (target==null) return;
+ if (target == null) return;
if (!target.getDeclaringClass().equals(node)) return;
if (scope.isInStaticContext() && !target.isStatic()) return;
type = target.getReturnType().redirect();
} else {
type = expression.getType();
target = selectConstructor(type, paraTypes);
- if (target==null) return;
+ if (target == null) return;
}
StatementMeta meta = addMeta(expression);
@@ -910,37 +945,21 @@ public class OptimizingStatementWriter extends StatementWriter {
opt.chainShouldOptimize(true);
}
- private static MethodNode selectConstructor(ClassNode node, Parameter[] paraTypes) {
- List<ConstructorNode> cl = node.getDeclaredConstructors();
- MethodNode res = null;
- for (ConstructorNode cn : cl) {
- if (ParameterUtils.parametersEqual(cn.getParameters(), paraTypes)) {
- res = cn;
+ private static MethodNode selectConstructor(final ClassNode node, final Parameter[] parameters) {
+ List<ConstructorNode> ctors = node.getDeclaredConstructors();
+ MethodNode result = null;
+ for (ConstructorNode ctor : ctors) {
+ if (ParameterUtils.parametersEqual(ctor.getParameters(), parameters)) {
+ result = ctor;
break;
}
}
- if (res !=null && res.isPublic()) return res;
- return null;
+ return (result != null && result.isPublic() ? result : null);
}
- private static boolean validTypeForCall(ClassNode type) {
+ private static boolean validTypeForCall(final ClassNode type) {
// do call only for final classes and primitive types
- if (isPrimitiveType(type)) return true;
- return (type.getModifiers() & ACC_FINAL) > 0;
- }
-
- @Override
- public void visitClosureExpression(ClosureExpression expression) {
- }
-
- @Override
- public void visitForLoop(ForStatement statement) {
- opt.push();
- super.visitForLoop(statement);
- if (opt.shouldOptimize()) addMeta(statement,opt);
- opt.pop(opt.shouldOptimize());
+ return isPrimitiveType(type) || (type.getModifiers() & ACC_FINAL) > 0;
}
}
-
-
}