summaryrefslogtreecommitdiff
path: root/src/proguard/optimize/peephole/BranchTargetFinder.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/proguard/optimize/peephole/BranchTargetFinder.java')
-rw-r--r--src/proguard/optimize/peephole/BranchTargetFinder.java85
1 files changed, 49 insertions, 36 deletions
diff --git a/src/proguard/optimize/peephole/BranchTargetFinder.java b/src/proguard/optimize/peephole/BranchTargetFinder.java
index 79499f1..507c1f8 100644
--- a/src/proguard/optimize/peephole/BranchTargetFinder.java
+++ b/src/proguard/optimize/peephole/BranchTargetFinder.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2013 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2014 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
@@ -50,9 +50,14 @@ implements AttributeVisitor,
private static boolean DEBUG = System.getProperty("btf") != null;
//*/
- public static final int NONE = -2;
- public static final int AT_METHOD_ENTRY = -1;
+ public static final int NONE = -1;
+ // We'll explicitly mark instructions that are not part of a subroutine,
+ // with NO_SUBROUTINE. Subroutines may just branch back into normal code
+ // (e.g. due to a break instruction in Java code), and we want to avoid
+ // marking such normal code as subroutine. The first mark wins, so we're
+ // assuming that such code is marked as normal code before it is marked
+ // as subroutine.
public static final int UNKNOWN = -1;
public static final int NO_SUBROUTINE = -2;
@@ -355,24 +360,17 @@ implements AttributeVisitor,
currentSubroutineStart = NO_SUBROUTINE;
recentCreationOffsetIndex = 0;
- // Initialize the stack of 'new' instruction offsets if this method
- // is an instance initializer.
- if (method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))
- {
- recentCreationOffsets[recentCreationOffsetIndex++] = AT_METHOD_ENTRY;
- }
-
// Mark branch targets by going over all instructions.
codeAttribute.instructionsAccept(clazz, method, this);
+
+ // Mark branch targets in the exception table.
+ codeAttribute.exceptionsAccept(clazz, method, this);
}
while (repeat);
// The end of the code is a branch target sentinel.
instructionMarks[codeLength] = BRANCH_TARGET;
- // Mark branch targets in the exception table.
- codeAttribute.exceptionsAccept(clazz, method, this);
-
if (containsSubroutines)
{
// Set the subroutine returning flag and the subroutine end at each
@@ -487,33 +485,39 @@ implements AttributeVisitor,
// Check if this is an instruction of a subroutine.
checkSubroutine(offset);
- // Check if the instruction is a 'new' instruction.
- if (constantInstruction.opcode == InstructionConstants.OP_NEW)
+ byte opcode = constantInstruction.opcode;
+ if (opcode == InstructionConstants.OP_NEW)
{
// Push the 'new' instruction offset on the stack.
recentCreationOffsets[recentCreationOffsetIndex++] = offset;
}
- else
+ else if (opcode == InstructionConstants.OP_INVOKESPECIAL)
{
- // Check if the instruction is an initializer invocation.
+ // Is it calling an instance initializer?
isInitializer = false;
clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
if (isInitializer)
{
- // Pop the 'new' instruction offset from the stack.
- int recentCreationOffset = recentCreationOffsets[--recentCreationOffsetIndex];
+ // Do we have any 'new' instruction offsets on the stack?
+ if (recentCreationOffsetIndex > 0)
+ {
+ // Pop the 'new' instruction offset from the stack.
+ int recentCreationOffset = recentCreationOffsets[--recentCreationOffsetIndex];
- // Fill it out in the creation offsets.
- creationOffsets[offset] = recentCreationOffset;
+ // Link the creation offset and the initialization offset.
+ // TODO: There could be multiple initialization offsets.
+ creationOffsets[offset] = recentCreationOffset;
- // Fill out the initialization offsets.
- if (recentCreationOffset == AT_METHOD_ENTRY)
- {
- superInitializationOffset = offset;
+ initializationOffsets[recentCreationOffset] = offset;
}
else
{
- initializationOffsets[recentCreationOffset] = offset;
+ // Remember the super initialization offset.
+ // TODO: There could be multiple initialization offsets.
+ // For instance, in the constructor of the generated class
+ // groovy.inspect.swingui.GeneratedBytecodeAwareGroovyClassLoader
+ // in groovy-all-2.2.1.jar.
+ superInitializationOffset = offset;
}
}
}
@@ -613,7 +617,8 @@ implements AttributeVisitor,
public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
{
- isInitializer = methodrefConstant.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT);
+ // Remember whether the method is an initializer.
+ isInitializer = methodrefConstant.getName(clazz).equals(ClassConstants.METHOD_NAME_INIT);
}
@@ -621,10 +626,24 @@ implements AttributeVisitor,
public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
{
+ int startPC = exceptionInfo.u2startPC;
+ int endPC = exceptionInfo.u2endPC;
+ int handlerPC = exceptionInfo.u2handlerPC;
+
// Mark the exception offsets.
- instructionMarks[exceptionInfo.u2startPC] |= EXCEPTION_START;
- instructionMarks[exceptionInfo.u2endPC] |= EXCEPTION_END;
- instructionMarks[exceptionInfo.u2handlerPC] |= EXCEPTION_HANDLER;
+ instructionMarks[startPC] |= EXCEPTION_START;
+ instructionMarks[endPC] |= EXCEPTION_END;
+ instructionMarks[handlerPC] |= EXCEPTION_HANDLER;
+
+ // Mark the handler as part of a subroutine if necessary.
+ if (subroutineStarts[handlerPC] == UNKNOWN &&
+ subroutineStarts[startPC] != UNKNOWN)
+ {
+ subroutineStarts[handlerPC] = subroutineStarts[startPC];
+
+ // We'll have to go over all instructions again.
+ repeat = true;
+ }
}
@@ -737,12 +756,6 @@ implements AttributeVisitor,
{
// Mark the subroutine start.
subroutineStarts[offset] = currentSubroutineStart;
-
- if (currentSubroutineStart >= 0)
- {
- // Mark the subroutine end at the subroutine start.
- subroutineEnds[currentSubroutineStart] = offset;
- }
}
}
}