summaryrefslogtreecommitdiff
path: root/src/proguard/optimize/TailRecursionSimplifier.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/proguard/optimize/TailRecursionSimplifier.java')
-rw-r--r--src/proguard/optimize/TailRecursionSimplifier.java109
1 files changed, 67 insertions, 42 deletions
diff --git a/src/proguard/optimize/TailRecursionSimplifier.java b/src/proguard/optimize/TailRecursionSimplifier.java
index 0946b6a..f820566 100644
--- a/src/proguard/optimize/TailRecursionSimplifier.java
+++ b/src/proguard/optimize/TailRecursionSimplifier.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@@ -54,9 +54,9 @@ implements AttributeVisitor,
private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer();
+ private final MyRecursionChecker recursionChecker = new MyRecursionChecker();
private Method targetMethod;
- private boolean recursive;
private boolean inlinedAny;
@@ -105,38 +105,31 @@ implements AttributeVisitor,
// clazz.getName().equals("abc/Def") &&
// method.getName(clazz).equals("abc");
- targetMethod = method;
- inlinedAny = false;
+ targetMethod = method;
+ inlinedAny = false;
codeAttributeComposer.reset();
- // Append the body of the code.
- copyCode(clazz, method, codeAttribute);
+ // The code may expand, due to expanding constant and variable
+ // instructions.
+ codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
+
+ // Copy the instructions.
+ codeAttribute.instructionsAccept(clazz, method, this);
// Update the code attribute if any code has been inlined.
if (inlinedAny)
{
- codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);
- }
- }
- }
+ // Copy the exceptions.
+ codeAttribute.exceptionsAccept(clazz, method, this);
+ // Append a label just after the code.
+ codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
- /**
- * Appends the code of the given code attribute.
- */
- private void copyCode(Clazz clazz, Method method, CodeAttribute codeAttribute)
- {
- // The code may expand, due to expanding constant and variable
- // instructions.
- codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
-
- // Copy the instructions.
- codeAttribute.instructionsAccept(clazz, method, this);
+ codeAttributeComposer.endCodeFragment();
- // Append a label just after the code.
- codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
-
- codeAttributeComposer.endCodeFragment();
+ codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);
+ }
+ }
}
@@ -145,7 +138,7 @@ implements AttributeVisitor,
public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
{
// Copy the instruction.
- codeAttributeComposer.appendInstruction(offset, instruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, instruction);
}
@@ -159,9 +152,9 @@ implements AttributeVisitor,
case InstructionConstants.OP_INVOKESTATIC:
{
// Is it a recursive call?
- clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, recursionChecker);
- if (recursive)
+ if (recursionChecker.isRecursive())
{
// Is the next instruction a return?
int nextOffset =
@@ -180,13 +173,13 @@ implements AttributeVisitor,
case InstructionConstants.OP_RETURN:
{
// Isn't the recursive call inside a try/catch block?
- codeAttribute.exceptionsAccept(clazz, method, offset, this);
+ codeAttribute.exceptionsAccept(clazz, method, offset, recursionChecker);
- if (recursive)
+ if (recursionChecker.isRecursive())
{
if (DEBUG)
{
- System.out.println("TailRecursionSimplifier.visitConstantInstruction: ["+
+ System.out.println("TailRecursionSimplifier: ["+
clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"], inlining "+constantInstruction.toString(offset));
}
@@ -223,23 +216,56 @@ implements AttributeVisitor,
}
// Copy the instruction.
- codeAttributeComposer.appendInstruction(offset, constantInstruction.shrink());
+ codeAttributeComposer.appendInstruction(offset, constantInstruction);
}
- // Implementations for ConstantVisitor.
+ // Implementations for ExceptionInfoVisitor.
- public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
{
- recursive = targetMethod.equals(methodrefConstant.referencedMember);
+ codeAttributeComposer.appendException(new ExceptionInfo(exceptionInfo.u2startPC,
+ exceptionInfo.u2endPC,
+ exceptionInfo.u2handlerPC,
+ exceptionInfo.u2catchType));
}
- // Implementations for ExceptionInfoVisitor.
-
- public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ /**
+ * This ConstantVisitor and ExceptionInfoVisitor returns whether a method
+ * invocation can be treated as tail-recursive.
+ */
+ private class MyRecursionChecker
+ extends SimplifiedVisitor
+ implements ConstantVisitor,
+ ExceptionInfoVisitor
{
- recursive = false;
+ private boolean recursive;
+
+
+ /**
+ * Returns whether the method invocation can be treated as
+ * tail-recursive.
+ */
+ public boolean isRecursive()
+ {
+ return recursive;
+ }
+
+ // Implementations for ConstantVisitor.
+
+ public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
+ {
+ recursive = targetMethod.equals(methodrefConstant.referencedMember);
+ }
+
+
+ // Implementations for ExceptionInfoVisitor.
+
+ public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
+ {
+ recursive = false;
+ }
}
@@ -257,7 +283,6 @@ implements AttributeVisitor,
(method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0;
// Count the number of parameters, taking into account their categories.
- int parameterCount = ClassUtil.internalMethodParameterCount(descriptor);
int parameterSize = ClassUtil.internalMethodParameterSize(descriptor);
int parameterOffset = isStatic ? 0 : 1;
@@ -315,7 +340,7 @@ implements AttributeVisitor,
}
codeAttributeComposer.appendInstruction(parameterSize-parameterIndex-1,
- new VariableInstruction(opcode, parameterOffset + parameterIndex).shrink());
+ new VariableInstruction(opcode, parameterOffset + parameterIndex));
}
}
@@ -323,7 +348,7 @@ implements AttributeVisitor,
if (!isStatic)
{
codeAttributeComposer.appendInstruction(parameterSize,
- new VariableInstruction(InstructionConstants.OP_ASTORE, 0).shrink());
+ new VariableInstruction(InstructionConstants.OP_ASTORE, 0));
}
codeAttributeComposer.endCodeFragment();