aboutsummaryrefslogtreecommitdiffstats
path: root/src/proguard/optimize/evaluation
diff options
context:
space:
mode:
authorYing Wang <wangying@google.com>2012-02-27 18:34:24 -0800
committerYing Wang <wangying@google.com>2012-02-27 18:34:24 -0800
commit9f606f95f03a75961498803e24bee6799a7c0885 (patch)
treea45f4d74feda9b76277a0c9ced55ad15d82248a1 /src/proguard/optimize/evaluation
parentcfead78069f3dc32998dc118ee08cab3867acea2 (diff)
downloadandroid_external_proguard-jellybean.tar.gz
android_external_proguard-jellybean.tar.bz2
android_external_proguard-jellybean.zip
This reverts commit cfead78069f3dc32998dc118ee08cab3867acea2. Bug: 6079915
Diffstat (limited to 'src/proguard/optimize/evaluation')
-rw-r--r--src/proguard/optimize/evaluation/EvaluationShrinker.java290
-rw-r--r--src/proguard/optimize/evaluation/EvaluationSimplifier.java15
-rw-r--r--src/proguard/optimize/evaluation/LivenessAnalyzer.java12
-rw-r--r--src/proguard/optimize/evaluation/LoadingInvocationUnit.java20
-rw-r--r--src/proguard/optimize/evaluation/PartialEvaluator.java141
-rw-r--r--src/proguard/optimize/evaluation/StoringInvocationUnit.java2
-rw-r--r--src/proguard/optimize/evaluation/TracedBranchUnit.java2
-rw-r--r--src/proguard/optimize/evaluation/VariableOptimizer.java127
8 files changed, 159 insertions, 450 deletions
diff --git a/src/proguard/optimize/evaluation/EvaluationShrinker.java b/src/proguard/optimize/evaluation/EvaluationShrinker.java
index bc5f658..1463feb 100644
--- a/src/proguard/optimize/evaluation/EvaluationShrinker.java
+++ b/src/proguard/optimize/evaluation/EvaluationShrinker.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2009 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
@@ -34,8 +34,6 @@ import proguard.evaluation.*;
import proguard.evaluation.value.*;
import proguard.optimize.info.*;
-import java.util.Arrays;
-
/**
* This AttributeVisitor simplifies the code attributes that it visits, based
* on partial evaluation.
@@ -57,14 +55,13 @@ implements AttributeVisitor
private final InstructionVisitor extraDeletedInstructionVisitor;
private final InstructionVisitor extraAddedInstructionVisitor;
- private final PartialEvaluator partialEvaluator;
- private final PartialEvaluator simplePartialEvaluator = new PartialEvaluator();
- private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true);
- private final MyUnusedParameterSimplifier unusedParameterSimplifier = new MyUnusedParameterSimplifier();
- private final MyProducerMarker producerMarker = new MyProducerMarker();
- private final MyVariableInitializationMarker variableInitializationMarker = new MyVariableInitializationMarker();
- private final MyStackConsistencyFixer stackConsistencyFixer = new MyStackConsistencyFixer();
- private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false);
+ private final PartialEvaluator partialEvaluator;
+ private final PartialEvaluator simplePartialEvaluator = new PartialEvaluator();
+ private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true);
+ private final MyUnusedParameterSimplifier unusedParameterSimplifier = new MyUnusedParameterSimplifier();
+ private final MyProducerMarker producerMarker = new MyProducerMarker();
+ private final MyStackConsistencyFixer stackConsistencyFixer = new MyStackConsistencyFixer();
+ private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false);
private boolean[][] variablesNecessaryAfter = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_VARIABLES_SIZE];
private boolean[][] stacksNecessaryAfter = new boolean[ClassConstants.TYPICAL_CODE_LENGTH][ClassConstants.TYPICAL_STACK_SIZE];
@@ -279,10 +276,18 @@ implements AttributeVisitor
if (partialEvaluator.isTraced(offset) &&
!isInstructionNecessary(offset))
{
- Instruction instruction = InstructionFactory.create(codeAttribute.code,
- offset);
-
- instruction.accept(clazz, method, codeAttribute, offset, variableInitializationMarker);
+ // Is the corresponding variable necessary anywhere in the code,
+ // accoriding to a simple partial evaluation?
+ int variableIndex = partialEvaluator.initializedVariable(offset);
+ if (variableIndex >= 0 &&
+ isVariableInitializationNecessary(clazz,
+ method,
+ codeAttribute,
+ offset,
+ variableIndex))
+ {
+ markInstruction(offset);
+ }
}
}
if (DEBUG) System.out.println();
@@ -462,9 +467,7 @@ implements AttributeVisitor
*/
private class MyUnusedParameterSimplifier
extends SimplifiedVisitor
- implements InstructionVisitor,
- ConstantVisitor,
- MemberVisitor
+ implements InstructionVisitor, ConstantVisitor, MemberVisitor
{
private int invocationOffset;
private ConstantInstruction invocationInstruction;
@@ -654,40 +657,6 @@ implements AttributeVisitor
/**
- * This InstructionVisitor marks variable initializations that are
- * necessary to appease the JVM.
- */
- private class MyVariableInitializationMarker
- extends SimplifiedVisitor
- implements InstructionVisitor
- {
- // Implementations for InstructionVisitor.
-
- public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
-
-
- public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
- {
- if (!variableInstruction.isLoad())
- {
- int variableIndex = variableInstruction.variableIndex;
-
- if (isVariableInitialization(offset,
- variableIndex) &&
- isVariableInitializationNecessary(clazz,
- method,
- codeAttribute,
- offset,
- variableIndex))
- {
- markInstruction(offset);
- }
- }
- }
- }
-
-
- /**
* This InstructionVisitor fixes instructions locally, popping any unused
* produced stack entries after marked instructions, and popping produced
* stack entries and pushing missing stack entries instead of unmarked
@@ -718,23 +687,12 @@ implements AttributeVisitor
int requiredPushCount = 0;
for (int stackIndex = 0; stackIndex < popCount; stackIndex++)
{
- InstructionOffsetValue producerOffsets =
- tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue();
-
- if (!isStackSimplifiedBefore(offset, top - stackIndex))
+ // Is the stack entry required by other consumers?
+ if (!isStackSimplifiedBefore(offset, top - stackIndex) &&
+ !isAnyStackEntryNecessaryAfter(tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(), top - stackIndex))
{
- // Is the stack entry pushed by any producer,
- // because it is required by other consumers?
- if (isAnyStackEntryNecessaryAfter(producerOffsets, top - stackIndex))
- {
- // Make sure it is pushed after all producers.
- markStackEntriesAfter(producerOffsets, top - stackIndex);
- }
- else
- {
- // Remember to push it.
- requiredPushCount++;
- }
+ // Remember to push it.
+ requiredPushCount++;
}
}
@@ -799,16 +757,9 @@ implements AttributeVisitor
int expectedPopCount = 0;
for (int stackIndex = 0; stackIndex < popCount; stackIndex++)
{
- InstructionOffsetValue producerOffsets =
- tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue();
-
- // Is the stack entry pushed by any producer,
- // because it is required by other consumers?
- if (isAnyStackEntryNecessaryAfter(producerOffsets, top - stackIndex))
+ // Is the stack entry required by other consumers?
+ if (isAnyStackEntryNecessaryAfter(tracedStack.getTopProducerValue(stackIndex).instructionOffsetValue(), top - stackIndex))
{
- // Make sure it is pushed after all producers.
- markStackEntriesAfter(producerOffsets, top - stackIndex);
-
// Remember to pop it.
expectedPopCount++;
}
@@ -1101,7 +1052,6 @@ implements AttributeVisitor
byte oldOpcode = instruction.opcode;
byte newOpcode = 0;
- byte addOpcode = 0;
// Simplify the popping instruction if possible.
switch (oldOpcode)
@@ -1282,20 +1232,9 @@ implements AttributeVisitor
stackEntryPresent1)
{
// Will both elements be present?
- if (!stackEntryPresent1)
- {
- // Pop the original top element (later bottom element).
- newOpcode = InstructionConstants.OP_POP;
- }
- else if (!stackEntryPresent0)
- {
- // Swap both elements and pop the top one.
- newOpcode = InstructionConstants.OP_SWAP;
- addOpcode = InstructionConstants.OP_POP;
- }
- else
+ if (stackEntryPresent0 &&
+ stackEntryPresent1)
{
- // Just swap both elements.
newOpcode = InstructionConstants.OP_SWAP;
}
}
@@ -1303,7 +1242,6 @@ implements AttributeVisitor
}
}
- // Is there a replacement opcode?
if (newOpcode == 0)
{
// Delete the instruction.
@@ -1332,21 +1270,6 @@ implements AttributeVisitor
if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(dupOffset)+" by "+replacementInstruction.toString());
}
-
- // Is there an additional opcode?
- if (addOpcode != 0)
- {
- // Add the instruction.
- Instruction additionalInstruction = new SimpleInstruction(addOpcode);
- codeAttributeEditor.insertAfterInstruction(dupOffset, additionalInstruction);
-
- if (extraAddedInstructionVisitor != null)
- {
- extraAddedInstructionVisitor.visitSimpleInstruction(null, null, null, dupOffset, null);
- }
-
- if (DEBUG) System.out.println(" Adding instruction "+additionalInstruction.toString(dupOffset));
- }
}
@@ -1673,7 +1596,10 @@ implements AttributeVisitor
{
for (int offset = 0; offset < codeLength; offset++)
{
- Arrays.fill(variablesNecessaryAfter[offset], 0, maxLocals, false);
+ for (int index = 0; index < maxLocals; index++)
+ {
+ variablesNecessaryAfter[offset][index] = false;
+ }
}
}
@@ -1686,7 +1612,10 @@ implements AttributeVisitor
{
for (int offset = 0; offset < codeLength; offset++)
{
- Arrays.fill(stacksNecessaryAfter[offset], 0, maxStack, false);
+ for (int index = 0; index < maxStack; index++)
+ {
+ stacksNecessaryAfter[offset][index] = false;
+ }
}
}
@@ -1699,7 +1628,10 @@ implements AttributeVisitor
{
for (int offset = 0; offset < codeLength; offset++)
{
- Arrays.fill(stacksSimplifiedBefore[offset], 0, maxStack, false);
+ for (int index = 0; index < maxStack; index++)
+ {
+ stacksSimplifiedBefore[offset][index] = false;
+ }
}
}
@@ -1709,7 +1641,10 @@ implements AttributeVisitor
}
else
{
- Arrays.fill(instructionsNecessary, 0, codeLength, false);
+ for (int index = 0; index < codeLength; index++)
+ {
+ instructionsNecessary[index] = false;
+ }
}
}
@@ -1735,34 +1670,6 @@ implements AttributeVisitor
/**
- * Returns whether the specified variable is initialized at the specified
- * offset.
- */
- private boolean isVariableInitialization(int instructionOffset,
- int variableIndex)
- {
- // Wasn't the variable set yet?
- Value valueBefore = partialEvaluator.getVariablesBefore(instructionOffset).getValue(variableIndex);
- if (valueBefore == null)
- {
- return true;
- }
-
- // Is the computational type different now?
- Value valueAfter = partialEvaluator.getVariablesAfter(instructionOffset).getValue(variableIndex);
- if (valueAfter.computationalType() != valueBefore.computationalType())
- {
- return true;
- }
-
- // Was the producer an argument (which may be removed)?
- Value producersBefore = partialEvaluator.getVariablesBefore(instructionOffset).getProducerValue(variableIndex);
- return producersBefore.instructionOffsetValue().instructionOffsetCount() == 1 &&
- producersBefore.instructionOffsetValue().instructionOffset(0) == PartialEvaluator.AT_METHOD_ENTRY;
- }
-
-
- /**
* Returns whether the specified variable must be initialized at the
* specified offset, according to the verifier of the JVM.
*/
@@ -1779,8 +1686,8 @@ implements AttributeVisitor
{
if (DEBUG) System.out.println("Simple partial evaluation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
- // Lazily perform simple partial evaluation, the way the JVM
- // verifier would do it.
+ // Lazily compute perform simple partial evaluation, the way the
+ // JVM preverifier would do it.
simplePartialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
if (DEBUG) System.out.println("End of simple partial evaluation for initialization of variable v"+variableIndex+" at ["+initializationOffset+"]");
@@ -1788,7 +1695,7 @@ implements AttributeVisitor
// Check if the variable is necessary elsewhere.
for (int offset = 0; offset < codeLength; offset++)
{
- if (partialEvaluator.isTraced(offset))
+ if (isInstructionNecessary(offset))
{
Value producer = partialEvaluator.getVariablesBefore(offset).getProducerValue(variableIndex);
if (producer != null)
@@ -1801,22 +1708,16 @@ implements AttributeVisitor
InstructionOffsetValue simpleProducerOffsets =
simpleProducer.instructionOffsetValue();
- if (DEBUG)
+ // Does the sophisticated partial evaluation have fewer
+ // producers than the simple one?
+ // And does the simple partial evaluation point to an
+ // initialization of the variable?
+ if (producerOffsets.instructionOffsetCount() <
+ simpleProducerOffsets.instructionOffsetCount() &&
+ isVariableNecessaryAfterAny(producerOffsets, variableIndex) &&
+ simpleProducerOffsets.contains(initializationOffset))
{
- System.out.println(" ["+offset+"] producers ["+producerOffsets+"], simple producers ["+simpleProducerOffsets+"]");
- }
-
- // Is the variable being used without all of its
- // immediate simple producers being marked?
- if (isVariableNecessaryAfterAny(producerOffsets, variableIndex) &&
- !isVariableNecessaryAfterAll(simpleProducerOffsets, variableIndex))
- {
- if (DEBUG)
- {
- System.out.println(" => initialization of variable v"+variableIndex+" at ["+initializationOffset+"] necessary");
- }
-
- // Then the initialization may be necessary.
+ // Then the initialization is necessary.
return true;
}
}
@@ -1825,11 +1726,6 @@ implements AttributeVisitor
}
}
- if (DEBUG)
- {
- System.out.println(" => initialization of variable v"+variableIndex+" at ["+initializationOffset+"] not necessary");
- }
-
return false;
}
@@ -1853,7 +1749,7 @@ implements AttributeVisitor
/**
* Returns whether the specified variable is ever necessary after any
- * instructions in the specified block.
+ * instruction in the specified block.
*/
private boolean isVariableNecessaryAfterAny(int startOffset,
int endOffset,
@@ -1873,7 +1769,7 @@ implements AttributeVisitor
/**
* Returns whether the specified variable is ever necessary after any
- * instructions in the specified set of instructions offsets.
+ * instruction in the specified set of instructions offsets.
*/
private boolean isVariableNecessaryAfterAny(InstructionOffsetValue instructionOffsetValue,
int variableIndex)
@@ -1893,28 +1789,6 @@ implements AttributeVisitor
}
- /**
- * Returns whether the specified variable is ever necessary after all
- * instructions in the specified set of instructions offsets.
- */
- private boolean isVariableNecessaryAfterAll(InstructionOffsetValue instructionOffsetValue,
- int variableIndex)
- {
- int count = instructionOffsetValue.instructionOffsetCount();
-
- for (int index = 0; index < count; index++)
- {
- if (!isVariableNecessaryAfter(instructionOffsetValue.instructionOffset(index),
- variableIndex))
- {
- return false;
- }
- }
-
- return true;
- }
-
-
private boolean isVariableNecessaryAfter(int instructionOffset,
int variableIndex)
{
@@ -1923,36 +1797,6 @@ implements AttributeVisitor
}
- /**
- * Marks the stack entries after the given offsets.
- * @param instructionOffsets the offsets of the stack entries to be marked.
- * @param stackIndex the index of the stack entries to be marked
- * (counting from the bottom).
- */
- private void markStackEntriesAfter(InstructionOffsetValue instructionOffsets,
- int stackIndex)
- {
- if (instructionOffsets != null)
- {
- int offsetCount = instructionOffsets.instructionOffsetCount();
- for (int offsetIndex = 0; offsetIndex < offsetCount; offsetIndex++)
- {
- // Make sure the stack entry and the instruction are marked
- // at the producing offset.
- int offset = instructionOffsets.instructionOffset(offsetIndex);
-
- markStackEntryAfter(offset, stackIndex);
- }
- }
- }
-
-
- /**
- * Marks the stack entry after the given offset.
- * @param instructionOffset the offset of the stack entry to be marked.
- * @param stackIndex the index of the stack entry to be marked
- * (counting from the bottom).
- */
private void markStackEntryAfter(int instructionOffset,
int stackIndex)
{
@@ -1970,13 +1814,6 @@ implements AttributeVisitor
}
- /**
- * Returns whether any of the stack entries after the given offsets are
- * necessary.
- * @param instructionOffsets the offsets of the stack entries to be checked.
- * @param stackIndex the index of the stack entries to be checked
- * (counting from the bottom).
- */
private boolean isAnyStackEntryNecessaryAfter(InstructionOffsetValue instructionOffsets,
int stackIndex)
{
@@ -1994,13 +1831,6 @@ implements AttributeVisitor
}
- /**
- * Returns whether any of the stack entries after the given offset are
- * necessary.
- * @param instructionOffset the offset of the stack entry to be checked.
- * @param stackIndex the index of the stack entry to be checked
- * (counting from the bottom).
- */
private boolean isStackEntryNecessaryAfter(int instructionOffset,
int stackIndex)
{
diff --git a/src/proguard/optimize/evaluation/EvaluationSimplifier.java b/src/proguard/optimize/evaluation/EvaluationSimplifier.java
index b207108..0c3a9c7 100644
--- a/src/proguard/optimize/evaluation/EvaluationSimplifier.java
+++ b/src/proguard/optimize/evaluation/EvaluationSimplifier.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2009 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
@@ -43,9 +43,6 @@ extends SimplifiedVisitor
implements AttributeVisitor,
InstructionVisitor
{
- private static int POS_ZERO_FLOAT_BITS = Float.floatToIntBits(0.0f);
- private static long POS_ZERO_DOUBLE_BITS = Double.doubleToLongBits(0.0);
-
//*
private static final boolean DEBUG = false;
/*/
@@ -562,11 +559,10 @@ implements AttributeVisitor,
Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
if (pushedValue.isParticular())
{
- // Make sure to distinguish between +0.0 and -0.0.
float value = pushedValue.floatValue().value();
- if (value == 0.0f && Float.floatToIntBits(value) == POS_ZERO_FLOAT_BITS ||
- value == 1.0f ||
- value == 2.0f)
+ if (value == 0f ||
+ value == 1f ||
+ value == 2f)
{
replaceConstantPushInstruction(clazz,
offset,
@@ -631,9 +627,8 @@ implements AttributeVisitor,
Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
if (pushedValue.isParticular())
{
- // Make sure to distinguish between +0.0 and -0.0.
double value = pushedValue.doubleValue().value();
- if (value == 0.0 && Double.doubleToLongBits(value) == POS_ZERO_DOUBLE_BITS ||
+ if (value == 0.0 ||
value == 1.0)
{
replaceConstantPushInstruction(clazz,
diff --git a/src/proguard/optimize/evaluation/LivenessAnalyzer.java b/src/proguard/optimize/evaluation/LivenessAnalyzer.java
index 747f993..9915027 100644
--- a/src/proguard/optimize/evaluation/LivenessAnalyzer.java
+++ b/src/proguard/optimize/evaluation/LivenessAnalyzer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2009 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
@@ -79,16 +79,6 @@ implements AttributeVisitor,
/**
- * Returns whether the instruction at the given offset has ever been
- * executed during the partial evaluation.
- */
- public boolean isTraced(int instructionOffset)
- {
- return partialEvaluator.isTraced(instructionOffset);
- }
-
-
- /**
* Returns whether the specified variable is alive before the instruction
* at the given offset.
*/
diff --git a/src/proguard/optimize/evaluation/LoadingInvocationUnit.java b/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
index 578ece5..8379c57 100644
--- a/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
+++ b/src/proguard/optimize/evaluation/LoadingInvocationUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2009 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
@@ -35,9 +35,9 @@ import proguard.evaluation.value.*;
public class LoadingInvocationUnit
extends BasicInvocationUnit
{
- private final boolean loadFieldValues;
- private final boolean loadMethodParameterValues;
- private final boolean loadMethodReturnValues;
+ private boolean loadFieldValues;
+ private boolean loadMethodParameterValues;
+ private boolean loadMethodReturnValues;
/**
@@ -84,6 +84,8 @@ extends BasicInvocationUnit
value.isParticular())
{
return value;
+// // Make sure the value is refreshed.
+// return refresh(value);
}
}
}
@@ -108,6 +110,8 @@ extends BasicInvocationUnit
value.isParticular())
{
return value;
+// // Make sure the value is refreshed.
+// return refresh(value);
}
}
}
@@ -130,6 +134,8 @@ extends BasicInvocationUnit
value.isParticular())
{
return value;
+// // Make sure the value is refreshed.
+// return refresh(value);
}
}
@@ -157,6 +163,8 @@ extends BasicInvocationUnit
value.isParticular())
{
return value;
+// // Make sure the value is refreshed.
+// return refresh(value);
}
}
}
@@ -165,8 +173,8 @@ extends BasicInvocationUnit
refConstant,
type);
}
-
-
+//
+//
// // Small utility methods.
//
// private Value refresh(Value value)
diff --git a/src/proguard/optimize/evaluation/PartialEvaluator.java b/src/proguard/optimize/evaluation/PartialEvaluator.java
index b2776d1..5790a36 100644
--- a/src/proguard/optimize/evaluation/PartialEvaluator.java
+++ b/src/proguard/optimize/evaluation/PartialEvaluator.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2009 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
@@ -31,8 +31,6 @@ import proguard.evaluation.*;
import proguard.evaluation.value.*;
import proguard.optimize.peephole.BranchTargetFinder;
-import java.util.Arrays;
-
/**
* This AttributeVisitor performs partial evaluation on the code attributes
* that it visits.
@@ -70,6 +68,7 @@ implements AttributeVisitor,
private TracedStack[] stacksAfter = new TracedStack[ClassConstants.TYPICAL_CODE_LENGTH];
private boolean[] generalizedContexts = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
private int[] evaluationCounts = new int[ClassConstants.TYPICAL_CODE_LENGTH];
+ private int[] initializedVariables = new int[ClassConstants.TYPICAL_CODE_LENGTH];
private boolean evaluateExceptions;
private final BasicBranchUnit branchUnit;
@@ -190,47 +189,6 @@ implements AttributeVisitor,
if (DEBUG)
{
method.accept(clazz, new ClassPrinter());
-
- System.out.println("Evaluation results:");
-
- int offset = 0;
- do
- {
- if (isBranchOrExceptionTarget(offset))
- {
- System.out.println("Branch target from ["+branchOriginValues[offset]+"]:");
- if (isTraced(offset))
- {
- System.out.println(" Vars: "+variablesBefore[offset]);
- System.out.println(" Stack: "+stacksBefore[offset]);
- }
- }
-
- Instruction instruction = InstructionFactory.create(codeAttribute.code,
- offset);
- System.out.println(instruction.toString(offset));
-
- if (isTraced(offset))
- {
- int initializationOffset = branchTargetFinder.initializationOffset(offset);
- if (initializationOffset != NONE)
- {
- System.out.println(" is to be initialized at ["+initializationOffset+"]");
- }
-
- InstructionOffsetValue branchTargets = branchTargets(offset);
- if (branchTargets != null)
- {
- System.out.println(" has overall been branching to "+branchTargets);
- }
-
- System.out.println(" Vars: "+variablesAfter[offset]);
- System.out.println(" Stack: "+stacksAfter[offset]);
- }
-
- offset += instruction.length(offset);
- }
- while (offset < codeAttribute.u4codeLength);
}
throw ex;
@@ -254,8 +212,7 @@ implements AttributeVisitor,
TracedStack stack = new TracedStack(codeAttribute.u2maxStack);
// Initialize the reusable arrays and variables.
- initializeArrays(codeAttribute);
- initializeParameters(clazz, method, codeAttribute, variables);
+ initializeVariables(clazz, method, codeAttribute, variables, stack);
// Find all instruction offsets,...
codeAttribute.accept(clazz, method, branchTargetFinder);
@@ -292,6 +249,12 @@ implements AttributeVisitor,
if (isTraced(offset))
{
+ int variableIndex = initializedVariable(offset);
+ if (variableIndex >= 0)
+ {
+ System.out.println(" is initializing variable v"+variableIndex);
+ }
+
int initializationOffset = branchTargetFinder.initializationOffset(offset);
if (initializationOffset != NONE)
{
@@ -516,6 +479,16 @@ implements AttributeVisitor,
}
+ /**
+ * Returns the variable that is initialized at the given instruction offset,
+ * or <code>NONE</code> if no variable was initialized.
+ */
+ public int initializedVariable(int instructionOffset)
+ {
+ return initializedVariables[instructionOffset];
+ }
+
+
// Utility methods to evaluate instruction blocks.
/**
@@ -729,6 +702,9 @@ implements AttributeVisitor,
// Reset the trace value.
InstructionOffsetValue traceValue = InstructionOffsetValue.EMPTY_VALUE;
+ // Reset the initialization flag.
+ variables.resetInitialization();
+
// Note that the instruction is only volatile.
Instruction instruction = InstructionFactory.create(code, instructionOffset);
@@ -767,6 +743,9 @@ implements AttributeVisitor,
throw ex;
}
+ // Collect the offsets of the instructions whose results were used.
+ initializedVariables[instructionOffset] = variables.getInitializationIndex();
+
// Collect the branch targets from the branch unit.
InstructionOffsetValue branchTargets = branchUnit.getTraceBranchTargets();
int branchTargetCount = branchTargets.instructionOffsetCount();
@@ -917,7 +896,11 @@ implements AttributeVisitor,
subroutinePartialEvaluator = new PartialEvaluator(this);
- subroutinePartialEvaluator.initializeArrays(codeAttribute);
+ subroutinePartialEvaluator.initializeVariables(clazz,
+ method,
+ codeAttribute,
+ variables,
+ stack);
}
// Evaluate the subroutine.
@@ -969,12 +952,13 @@ implements AttributeVisitor,
if (evaluationCounts[offset] == 0)
{
- variablesBefore[offset] = other.variablesBefore[offset];
- stacksBefore[offset] = other.stacksBefore[offset];
- variablesAfter[offset] = other.variablesAfter[offset];
- stacksAfter[offset] = other.stacksAfter[offset];
- generalizedContexts[offset] = other.generalizedContexts[offset];
- evaluationCounts[offset] = other.evaluationCounts[offset];
+ variablesBefore[offset] = other.variablesBefore[offset];
+ stacksBefore[offset] = other.stacksBefore[offset];
+ variablesAfter[offset] = other.variablesAfter[offset];
+ stacksAfter[offset] = other.stacksAfter[offset];
+ generalizedContexts[offset] = other.generalizedContexts[offset];
+ evaluationCounts[offset] = other.evaluationCounts[offset];
+ initializedVariables[offset] = other.initializedVariables[offset];
}
else
{
@@ -984,6 +968,7 @@ implements AttributeVisitor,
stacksAfter[offset] .generalize(other.stacksAfter[offset]);
//generalizedContexts[offset]
evaluationCounts[offset] += other.evaluationCounts[offset];
+ //initializedVariables[offset]
}
}
}
@@ -1109,7 +1094,11 @@ implements AttributeVisitor,
/**
* Initializes the data structures for the variables, stack, etc.
*/
- private void initializeArrays(CodeAttribute codeAttribute)
+ private void initializeVariables(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ TracedVariables variables,
+ TracedStack stack)
{
int codeLength = codeAttribute.u4codeLength;
@@ -1117,25 +1106,33 @@ implements AttributeVisitor,
if (variablesAfter.length < codeLength)
{
// Create new arrays.
- branchOriginValues = new InstructionOffsetValue[codeLength];
- branchTargetValues = new InstructionOffsetValue[codeLength];
- variablesBefore = new TracedVariables[codeLength];
- stacksBefore = new TracedStack[codeLength];
- variablesAfter = new TracedVariables[codeLength];
- stacksAfter = new TracedStack[codeLength];
- generalizedContexts = new boolean[codeLength];
- evaluationCounts = new int[codeLength];
+ branchOriginValues = new InstructionOffsetValue[codeLength];
+ branchTargetValues = new InstructionOffsetValue[codeLength];
+ variablesBefore = new TracedVariables[codeLength];
+ stacksBefore = new TracedStack[codeLength];
+ variablesAfter = new TracedVariables[codeLength];
+ stacksAfter = new TracedStack[codeLength];
+ generalizedContexts = new boolean[codeLength];
+ evaluationCounts = new int[codeLength];
+ initializedVariables = new int[codeLength];
+
+ // Reset the arrays.
+ for (int index = 0; index < codeLength; index++)
+ {
+ initializedVariables[index] = NONE;
+ }
}
else
{
// Reset the arrays.
- Arrays.fill(branchOriginValues, null);
- Arrays.fill(branchTargetValues, null);
- Arrays.fill(generalizedContexts, false);
- Arrays.fill(evaluationCounts, 0);
-
for (int index = 0; index < codeLength; index++)
{
+ branchOriginValues[index] = null;
+ branchTargetValues[index] = null;
+ generalizedContexts[index] = false;
+ evaluationCounts[index] = 0;
+ initializedVariables[index] = NONE;
+
if (variablesBefore[index] != null)
{
variablesBefore[index].reset(codeAttribute.u2maxLocals);
@@ -1157,17 +1154,7 @@ implements AttributeVisitor,
}
}
}
- }
-
- /**
- * Initializes the data structures for the variables, stack, etc.
- */
- private void initializeParameters(Clazz clazz,
- Method method,
- CodeAttribute codeAttribute,
- TracedVariables variables)
- {
// Create the method parameters.
TracedVariables parameters = new TracedVariables(codeAttribute.u2maxLocals);
diff --git a/src/proguard/optimize/evaluation/StoringInvocationUnit.java b/src/proguard/optimize/evaluation/StoringInvocationUnit.java
index 010dab0..bcbb69f 100644
--- a/src/proguard/optimize/evaluation/StoringInvocationUnit.java
+++ b/src/proguard/optimize/evaluation/StoringInvocationUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2009 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
diff --git a/src/proguard/optimize/evaluation/TracedBranchUnit.java b/src/proguard/optimize/evaluation/TracedBranchUnit.java
index b7dd469..fa5bb79 100644
--- a/src/proguard/optimize/evaluation/TracedBranchUnit.java
+++ b/src/proguard/optimize/evaluation/TracedBranchUnit.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2009 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
diff --git a/src/proguard/optimize/evaluation/VariableOptimizer.java b/src/proguard/optimize/evaluation/VariableOptimizer.java
index a824481..b3ae81c 100644
--- a/src/proguard/optimize/evaluation/VariableOptimizer.java
+++ b/src/proguard/optimize/evaluation/VariableOptimizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2009 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
@@ -21,10 +21,10 @@
package proguard.optimize.evaluation;
import proguard.classfile.*;
-import proguard.classfile.attribute.visitor.*;
-import proguard.classfile.editor.*;
import proguard.classfile.visitor.MemberVisitor;
import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.editor.VariableRemapper;
import proguard.classfile.util.*;
/**
@@ -35,9 +35,7 @@ import proguard.classfile.util.*;
*/
public class VariableOptimizer
extends SimplifiedVisitor
-implements AttributeVisitor,
- LocalVariableInfoVisitor,
- LocalVariableTypeInfoVisitor
+implements AttributeVisitor
{
//*
private static final boolean DEBUG = false;
@@ -53,7 +51,6 @@ implements AttributeVisitor,
private final LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer();
private final VariableRemapper variableRemapper = new VariableRemapper();
- private VariableCleaner variableCleaner = new VariableCleaner();
private int[] variableMap = new int[ClassConstants.TYPICAL_VARIABLES_SIZE];
@@ -104,11 +101,6 @@ implements AttributeVisitor,
// Analyze the liveness of the variables in the code.
livenessAnalyzer.visitCodeAttribute(clazz, method, codeAttribute);
- // Trim the variables in the local variable tables, because even
- // clipping the tables individually may leave some inconsistencies
- // between them.
- codeAttribute.attributesAccept(clazz, method, this);
-
int startIndex =
(method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ||
reuseThis ? 0 : 1;
@@ -150,19 +142,23 @@ implements AttributeVisitor,
}
}
- // Have we been able to remap any variables?
+ // Remap the variables.
if (remapping)
{
if (DEBUG)
{
- System.out.println("VariableOptimizer: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
- for (int index= 0; index < variableSize; index++)
+ System.out.println("Remapping variables:");
+ System.out.println(" Class "+ ClassUtil.externalClassName(clazz.getName()));
+ System.out.println(" Method "+ClassUtil.externalFullMethodDescription(clazz.getName(),
+ 0,
+ method.getName(clazz),
+ method.getDescriptor(clazz)));
+ for (int index = 0; index < variableSize; index++)
{
- System.out.println(" v"+index+" -> "+variableMap[index]);
+ System.out.println(" ["+index+"] -> ["+variableMap[index]+"]");
}
}
- // Remap the variables.
variableRemapper.setVariableMap(variableMap);
variableRemapper.visitCodeAttribute(clazz, method, codeAttribute);
@@ -172,59 +168,6 @@ implements AttributeVisitor,
method.accept(clazz, extraVariableMemberVisitor);
}
}
- else
- {
- // Just clean up any empty variables.
- variableCleaner.visitCodeAttribute(clazz, method, codeAttribute);
- }
- }
-
-
- public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
- {
- // Trim the variables in the local variable table.
- localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
- }
-
-
- public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
- {
- // Trim the variables in the local variable type table.
- localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
- }
-
-
- // Implementations for LocalVariableInfoVisitor.
-
- public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
- {
- // Trim the local variable to the instructions at which it is alive.
- int variable = localVariableInfo.u2index;
- int startPC = localVariableInfo.u2startPC;
- int endPC = startPC + localVariableInfo.u2length;
-
- startPC = firstLiveness(startPC, endPC, variable);
- endPC = lastLiveness(startPC, endPC, variable);
-
- localVariableInfo.u2startPC = startPC;
- localVariableInfo.u2length = endPC - startPC;
- }
-
-
- // Implementations for LocalVariableTypeInfoVisitor.
-
- public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
- {
- // Trim the local variable type to the instructions at which it is alive.
- int variable = localVariableTypeInfo.u2index;
- int startPC = localVariableTypeInfo.u2startPC;
- int endPC = startPC + localVariableTypeInfo.u2length;
-
- startPC = firstLiveness(startPC, endPC, variable);
- endPC = lastLiveness(startPC, endPC, variable);
-
- localVariableTypeInfo.u2startPC = startPC;
- localVariableTypeInfo.u2length = endPC - startPC;
}
@@ -298,48 +241,4 @@ implements AttributeVisitor,
}
}
}
-
-
- /**
- * Returns the first instruction offset between the given offsets at which
- * the given variable goes alive.
- */
- private int firstLiveness(int startOffset, int endOffset, int variableIndex)
- {
- for (int offset = startOffset; offset < endOffset; offset++)
- {
- if (livenessAnalyzer.isTraced(offset) &&
- livenessAnalyzer.isAliveBefore(offset, variableIndex))
- {
- return offset;
- }
- }
-
- return endOffset;
- }
-
-
- /**
- * Returns the last instruction offset between the given offsets before
- * which the given variable is still alive.
- */
- private int lastLiveness(int startOffset, int endOffset, int variableIndex)
- {
- int previousOffset = endOffset;
-
- for (int offset = endOffset-1; offset >= startOffset; offset--)
- {
- if (livenessAnalyzer.isTraced(offset))
- {
- if (livenessAnalyzer.isAliveBefore(offset, variableIndex))
- {
- return previousOffset;
- }
-
- previousOffset = offset;
- }
- }
-
- return endOffset;
- }
}