diff options
author | Brian Carlstrom <bdc@google.com> | 2015-01-08 08:24:06 -0800 |
---|---|---|
committer | Brian Carlstrom <bdc@google.com> | 2015-01-08 09:27:15 -0800 |
commit | 2270795fbe0b277bfd49f40950ecaa78583175cc (patch) | |
tree | 9ac962825d41c4fb8ad1ec0fc2e8b441b42d3869 /src/proguard/evaluation | |
parent | 9961286c06c25cd03464d3e2b00bd9b9dedf96ba (diff) | |
download | proguard-2270795fbe0b277bfd49f40950ecaa78583175cc.tar.gz |
Upgrade Proguard to 5.1.
Downloaded from:
http://sourceforge.net/projects/proguard/files/proguard/5.1/
Bug: 17550647
Change-Id: I2b4eab16eb7821fc232b294ab7f433aae08f71e1
Diffstat (limited to 'src/proguard/evaluation')
63 files changed, 1951 insertions, 693 deletions
diff --git a/src/proguard/evaluation/BasicBranchUnit.java b/src/proguard/evaluation/BasicBranchUnit.java index 127e922..f10e4be 100644 --- a/src/proguard/evaluation/BasicBranchUnit.java +++ b/src/proguard/evaluation/BasicBranchUnit.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 diff --git a/src/proguard/evaluation/BasicInvocationUnit.java b/src/proguard/evaluation/BasicInvocationUnit.java index 474556c..f7cc902 100644 --- a/src/proguard/evaluation/BasicInvocationUnit.java +++ b/src/proguard/evaluation/BasicInvocationUnit.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 @@ -68,7 +68,7 @@ implements InvocationUnit, // Initialize the parameters. boolean isStatic = - (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0; + (method.getAccessFlags() & ClassConstants.ACC_STATIC) != 0; // Count the number of parameters, taking into account their categories. int parameterSize = ClassUtil.internalMethodParameterSize(descriptor, isStatic); @@ -225,7 +225,7 @@ implements InvocationUnit, // Push the return value, if applicable. String returnType = ClassUtil.internalMethodReturnType(type); - if (returnType.charAt(0) != ClassConstants.INTERNAL_TYPE_VOID) + if (returnType.charAt(0) != ClassConstants.TYPE_VOID) { stack.push(getMethodReturnValue(clazz, methodrefConstant, returnType)); } @@ -250,7 +250,7 @@ implements InvocationUnit, // Push the return value, if applicable. String returnType = ClassUtil.internalMethodReturnType(type); - if (returnType.charAt(0) != ClassConstants.INTERNAL_TYPE_VOID) + if (returnType.charAt(0) != ClassConstants.TYPE_VOID) { stack.push(getMethodReturnValue(clazz, invokeDynamicConstant, returnType)); } @@ -417,9 +417,4 @@ implements InvocationUnit, returnTypeClass = referencedClasses[referencedClasses.length - 1]; } } - - -// public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) -// { -// } } diff --git a/src/proguard/evaluation/BranchUnit.java b/src/proguard/evaluation/BranchUnit.java index a381da7..e81b61d 100644 --- a/src/proguard/evaluation/BranchUnit.java +++ b/src/proguard/evaluation/BranchUnit.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 diff --git a/src/proguard/evaluation/ClassConstantValueFactory.java b/src/proguard/evaluation/ClassConstantValueFactory.java index 1c418c2..62cc42c 100644 --- a/src/proguard/evaluation/ClassConstantValueFactory.java +++ b/src/proguard/evaluation/ClassConstantValueFactory.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 @@ -21,10 +21,8 @@ package proguard.evaluation; import proguard.classfile.*; -import proguard.classfile.constant.*; -import proguard.classfile.constant.visitor.ConstantVisitor; -import proguard.classfile.util.SimplifiedVisitor; -import proguard.evaluation.value.*; +import proguard.classfile.constant.ClassConstant; +import proguard.evaluation.value.ValueFactory; /** * This class creates java.lang.Class ReferenceValue instances that correspond @@ -46,7 +44,7 @@ extends ConstantValueFactory public void visitClassConstant(Clazz clazz, ClassConstant classConstant) { // Create a Class reference instead of a reference to the class. - value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_CLASS, + value = valueFactory.createReferenceValue(ClassConstants.NAME_JAVA_LANG_CLASS, classConstant.javaLangClassClass, false); } diff --git a/src/proguard/evaluation/ConstantValueFactory.java b/src/proguard/evaluation/ConstantValueFactory.java index 0afb20c..6875bde 100644 --- a/src/proguard/evaluation/ConstantValueFactory.java +++ b/src/proguard/evaluation/ConstantValueFactory.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 @@ -85,14 +85,14 @@ implements ConstantVisitor public void visitStringConstant(Clazz clazz, StringConstant stringConstant) { - value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_STRING, + value = valueFactory.createReferenceValue(ClassConstants.NAME_JAVA_LANG_STRING, stringConstant.javaLangStringClass, false); } public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) { - value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_HANDLE, + value = valueFactory.createReferenceValue(ClassConstants.NAME_JAVA_LANG_INVOKE_METHOD_HANDLE, methodHandleConstant.javaLangInvokeMethodHandleClass, false); } @@ -106,7 +106,7 @@ implements ConstantVisitor public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) { - value = valueFactory.createReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_INVOKE_METHOD_TYPE, + value = valueFactory.createReferenceValue(ClassConstants.NAME_JAVA_LANG_INVOKE_METHOD_TYPE, methodTypeConstant.javaLangInvokeMethodTypeClass, false); } diff --git a/src/proguard/evaluation/InvocationUnit.java b/src/proguard/evaluation/InvocationUnit.java index e526b35..0750894 100644 --- a/src/proguard/evaluation/InvocationUnit.java +++ b/src/proguard/evaluation/InvocationUnit.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 diff --git a/src/proguard/evaluation/Processor.java b/src/proguard/evaluation/Processor.java index 3bfc5f3..d03b853 100644 --- a/src/proguard/evaluation/Processor.java +++ b/src/proguard/evaluation/Processor.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 @@ -40,6 +40,7 @@ implements InstructionVisitor private final ValueFactory valueFactory; private final BranchUnit branchUnit; private final InvocationUnit invocationUnit; + private final boolean alwaysCast; private final ConstantValueFactory constantValueFactory; private final ClassConstantValueFactory classConstantValueFactory; @@ -51,18 +52,22 @@ implements InstructionVisitor * @param stack the local stack. * @param branchUnit the class that can affect the program counter. * @param invocationUnit the class that can access other program members. + * @param alwaysCast a flag that specifies whether downcasts or casts + * of null values should always be performed. */ public Processor(Variables variables, Stack stack, ValueFactory valueFactory, BranchUnit branchUnit, - InvocationUnit invocationUnit) + InvocationUnit invocationUnit, + boolean alwaysCast) { this.variables = variables; this.stack = stack; this.valueFactory = valueFactory; this.branchUnit = branchUnit; this.invocationUnit = invocationUnit; + this.alwaysCast = alwaysCast; constantValueFactory = new ConstantValueFactory(valueFactory); classConstantValueFactory = new ClassConstantValueFactory(valueFactory); @@ -114,70 +119,83 @@ implements InstructionVisitor case InstructionConstants.OP_BALOAD: case InstructionConstants.OP_CALOAD: case InstructionConstants.OP_SALOAD: - stack.ipop(); - stack.apop(); - stack.push(valueFactory.createIntegerValue()); + { + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + stack.push(arrayReference.integerArrayLoad(arrayIndex, valueFactory)); break; - + } case InstructionConstants.OP_LALOAD: - stack.ipop(); - stack.apop(); - stack.push(valueFactory.createLongValue()); + { + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + stack.push(arrayReference.longArrayLoad(arrayIndex, valueFactory)); break; - + } case InstructionConstants.OP_FALOAD: - stack.ipop(); - stack.apop(); - stack.push(valueFactory.createFloatValue()); + { + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + stack.push(arrayReference.floatArrayLoad(arrayIndex, valueFactory)); break; - + } case InstructionConstants.OP_DALOAD: - stack.ipop(); - stack.apop(); - stack.push(valueFactory.createDoubleValue()); + { + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + stack.push(arrayReference.doubleArrayLoad(arrayIndex, valueFactory)); break; - + } case InstructionConstants.OP_AALOAD: { IntegerValue arrayIndex = stack.ipop(); ReferenceValue arrayReference = stack.apop(); - stack.push(arrayReference.arrayLoad(arrayIndex, valueFactory)); + stack.push(arrayReference.referenceArrayLoad(arrayIndex, valueFactory)); break; } - case InstructionConstants.OP_IASTORE: case InstructionConstants.OP_BASTORE: case InstructionConstants.OP_CASTORE: case InstructionConstants.OP_SASTORE: - stack.ipop(); - stack.ipop(); - stack.apop(); + { + Value value = stack.ipop(); + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + arrayReference.arrayStore(arrayIndex, value); break; - + } case InstructionConstants.OP_LASTORE: - stack.lpop(); - stack.ipop(); - stack.apop(); + { + Value value = stack.lpop(); + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + arrayReference.arrayStore(arrayIndex, value); break; - + } case InstructionConstants.OP_FASTORE: - stack.fpop(); - stack.ipop(); - stack.apop(); + { + Value value = stack.fpop(); + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + arrayReference.arrayStore(arrayIndex, value); break; - + } case InstructionConstants.OP_DASTORE: - stack.dpop(); - stack.ipop(); - stack.apop(); + { + Value value = stack.dpop(); + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + arrayReference.arrayStore(arrayIndex, value); break; - + } case InstructionConstants.OP_AASTORE: - stack.apop(); - stack.ipop(); - stack.apop(); + { + Value value = stack.apop(); + IntegerValue arrayIndex = stack.ipop(); + ReferenceValue arrayReference = stack.apop(); + arrayReference.arrayStore(arrayIndex, value); break; - + } case InstructionConstants.OP_POP: stack.pop1(); break; @@ -527,8 +545,8 @@ implements InstructionVisitor break; case InstructionConstants.OP_ARRAYLENGTH: - stack.apop(); - stack.push(valueFactory.createIntegerValue()); + ReferenceValue referenceValue = stack.apop(); + stack.push(referenceValue.arrayLength(valueFactory)); break; case InstructionConstants.OP_ATHROW: @@ -591,6 +609,7 @@ implements InstructionVisitor // TODO: Check cast. ReferenceValue castValue = stack.apop(); ReferenceValue castResultValue = + !alwaysCast && castValue.isNull() == Value.ALWAYS ? castValue : castValue.isNull() == Value.NEVER ? constantValueFactory.constantValue(clazz, constantIndex).referenceValue() : constantValueFactory.constantValue(clazz, constantIndex).referenceValue().generalize(valueFactory.createReferenceValueNull()); diff --git a/src/proguard/evaluation/Stack.java b/src/proguard/evaluation/Stack.java index c449e86..9294853 100644 --- a/src/proguard/evaluation/Stack.java +++ b/src/proguard/evaluation/Stack.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 diff --git a/src/proguard/evaluation/TracedStack.java b/src/proguard/evaluation/TracedStack.java index 08778a1..08e30e9 100644 --- a/src/proguard/evaluation/TracedStack.java +++ b/src/proguard/evaluation/TracedStack.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 @@ -24,12 +24,13 @@ import proguard.evaluation.value.Value; /** * This Stack saves additional information with stack elements, to keep track - * of their origins and destinations. + * of their origins. * <p> * The stack stores a given producer Value along with each Value it stores. * It then generalizes a given collected Value with the producer Value * of each Value it loads. The producer Value and the initial collected Value - * can be set; the generalized collected Value can be retrieved. + * can be set. The generalized collected Value can be retrieved, either taking + * into account dup/swap instructions as proper instructions or ignoring them. * * @author Eric Lafortune */ @@ -37,6 +38,7 @@ public class TracedStack extends Stack { private Value producerValue; private Stack producerStack; + private Stack actualProducerStack; /** @@ -46,7 +48,8 @@ public class TracedStack extends Stack { super(maxSize); - producerStack = new Stack(maxSize); + producerStack = new Stack(maxSize); + actualProducerStack = new Stack(maxSize); } @@ -57,7 +60,8 @@ public class TracedStack extends Stack { super(tracedStack); - producerStack = new Stack(tracedStack.producerStack); + producerStack = new Stack(tracedStack.producerStack); + actualProducerStack = new Stack(tracedStack.actualProducerStack); } @@ -84,14 +88,15 @@ public class TracedStack extends Stack /** - * Sets the specified producer Value on the stack, without disturbing it. + * Gets the specified actual producer Value from the stack, ignoring + * dup/swap instructions, without disturbing it. * @param index the index of the stack element, counting from the bottom * of the stack. - * @param value the producer value to set. + * @return the producer value at the specified position. */ - public void setBottomProducerValue(int index, Value value) + public Value getBottomActualProducerValue(int index) { - producerStack.setBottom(index, value); + return actualProducerStack.getBottom(index); } @@ -108,14 +113,15 @@ public class TracedStack extends Stack /** - * Sets the specified producer Value on the stack, without disturbing it. + * Gets the specified actual producer Value from the stack, ignoring + * dup/swap instructions, without disturbing it. * @param index the index of the stack element, counting from the top * of the stack. - * @param value the producer value to set. + * @return the producer value at the specified position. */ - public void setTopProducerValue(int index, Value value) + public Value getTopActualProducerValue(int index) { - producerStack.setTop(index, value); + return actualProducerStack.getTop(index); } @@ -126,6 +132,7 @@ public class TracedStack extends Stack super.reset(size); producerStack.reset(size); + actualProducerStack.reset(size); } public void copy(TracedStack other) @@ -133,13 +140,15 @@ public class TracedStack extends Stack super.copy(other); producerStack.copy(other.producerStack); + actualProducerStack.copy(other.actualProducerStack); } public boolean generalize(TracedStack other) { return super.generalize(other) | - producerStack.generalize(other.producerStack); + producerStack.generalize(other.producerStack) | + actualProducerStack.generalize(other.actualProducerStack); } public void clear() @@ -147,6 +156,7 @@ public class TracedStack extends Stack super.clear(); producerStack.clear(); + actualProducerStack.clear(); } public void removeTop(int index) @@ -154,6 +164,7 @@ public class TracedStack extends Stack super.removeTop(index); producerStack.removeTop(index); + actualProducerStack.removeTop(index); } public void push(Value value) @@ -203,85 +214,99 @@ public class TracedStack extends Stack { super.dup(); - producerPop(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.dup(); } public void dup_x1() { super.dup_x1(); - producerPop(); - producerPop(); - producerPush(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.dup_x1(); } public void dup_x2() { super.dup_x2(); - producerPop(); - producerPop(); - producerPop(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.pop(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.dup_x2(); } public void dup2() { super.dup2(); - producerPop(); - producerPop(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.dup2(); } public void dup2_x1() { super.dup2_x1(); - producerPop(); - producerPop(); - producerPop(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.pop(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.dup2_x1(); } public void dup2_x2() { super.dup2_x2(); - producerPop(); - producerPop(); - producerPop(); - producerPop(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.pop(); + producerStack.pop(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.dup2_x2(); } public void swap() { super.swap(); - producerPop(); - producerPop(); - producerPush(); - producerPush(); + producerStack.pop(); + producerStack.pop(); + producerStack.push(producerValue); + producerStack.push(producerValue); + + actualProducerStack.swap(); } @@ -298,14 +323,16 @@ public class TracedStack extends Stack TracedStack other = (TracedStack)object; return super.equals(object) && - this.producerStack.equals(other.producerStack); + this.producerStack.equals(other.producerStack) && + this.actualProducerStack.equals(other.actualProducerStack); } public int hashCode() { - return super.hashCode() ^ - producerStack.hashCode(); + return super.hashCode() ^ + producerStack.hashCode() ^ + actualProducerStack.hashCode(); } @@ -315,10 +342,13 @@ public class TracedStack extends Stack for (int index = 0; index < this.size(); index++) { - Value value = this.values[index]; - Value producerValue = producerStack.getBottom(index); + Value value = this.values[index]; + Value producerValue = producerStack.getBottom(index); + Value actualProducerValue = actualProducerStack.getBottom(index); buffer = buffer.append('[') - .append(producerValue == null ? "empty:" : producerValue.toString()) + .append(producerValue == null ? "empty:" : + producerValue.equals(actualProducerValue) ? producerValue.toString() : + producerValue.toString() + actualProducerValue.toString()) .append(value == null ? "empty" : value.toString()) .append(']'); } @@ -332,11 +362,13 @@ public class TracedStack extends Stack private void producerPush() { producerStack.push(producerValue); + actualProducerStack.push(producerValue); } private void producerPop() { producerStack.pop(); + actualProducerStack.pop(); } } diff --git a/src/proguard/evaluation/TracedVariables.java b/src/proguard/evaluation/TracedVariables.java index fef54e1..23e3041 100644 --- a/src/proguard/evaluation/TracedVariables.java +++ b/src/proguard/evaluation/TracedVariables.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 diff --git a/src/proguard/evaluation/Variables.java b/src/proguard/evaluation/Variables.java index 16b39e7..4b3a2a4 100644 --- a/src/proguard/evaluation/Variables.java +++ b/src/proguard/evaluation/Variables.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 diff --git a/src/proguard/evaluation/value/ArrayReferenceValue.java b/src/proguard/evaluation/value/ArrayReferenceValue.java new file mode 100644 index 0000000..56f18ad --- /dev/null +++ b/src/proguard/evaluation/value/ArrayReferenceValue.java @@ -0,0 +1,165 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * 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 + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.evaluation.value; + +import proguard.classfile.Clazz; + +/** + * This ReferenceValue represents a partially evaluated array. It has an array + * length and possibly array values (up to a fixed maximum number). It is not + * immutable. + * + * @author Eric Lafortune + */ +class ArrayReferenceValue extends TypedReferenceValue +{ + protected final IntegerValue arrayLength; + + + /** + * Creates a new ArrayReferenceValue. + */ + public ArrayReferenceValue(String type, + Clazz referencedClass, + IntegerValue arrayLength) + { + super(type, referencedClass, false); + + this.arrayLength = arrayLength; + } + + + // Implementations for ReferenceValue. + + public IntegerValue arrayLength(ValueFactory valueFactory) + { + return arrayLength; + } + + + // Implementations of binary methods of ReferenceValue. + + public ReferenceValue generalize(ReferenceValue other) + { + return other.generalize(this); + } + + + public int equal(ReferenceValue other) + { + return other.equal(this); + } + + +// // Implementations of binary ReferenceValue methods with +// // IdentifiedReferenceValue arguments. +// +// public ReferenceValue generalize(IdentifiedReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } +// +// +// public int equal(IdentifiedReferenceValue other) +// { +// return equal((TypedReferenceValue)other); +// } + + + // Implementations of binary ReferenceValue methods with + // ArrayReferenceValue arguments. + + public ReferenceValue generalize(ArrayReferenceValue other) + { + return + this.equals(other) ? this : + this.type != null && + this.type.equals(other.type) && + this.referencedClass == other.referencedClass ? new ArrayReferenceValue(this.type, + this.referencedClass, + this.arrayLength.generalize(other.arrayLength)) : + generalize((TypedReferenceValue)other); + } + + + public int equal(ArrayReferenceValue other) + { + if (this.arrayLength.equal(other.arrayLength) == NEVER) + { + return NEVER; + } + + return equal((TypedReferenceValue)other); + } + + +// // Implementations of binary ReferenceValue methods with +// // IdentifiedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(IdentifiedArrayReferenceValue other) +// { +// return generalize((ArrayReferenceValue)other); +// } +// +// +// public int equal(IdentifiedArrayReferenceValue other) +// { +// return equal((ArrayReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // DetailedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(DetailedArrayReferenceValue other) +// { +// return generalize((IdentifiedArrayReferenceValue)other); +// } +// +// +// public int equal(DetailedArrayReferenceValue other) +// { +// return equal((IdentifiedArrayReferenceValue)other); +// } + + + // Implementations for Object. + + public boolean equals(Object object) + { + return this == object || + super.equals(object) && + this.arrayLength.equals(((ArrayReferenceValue)object).arrayLength); + } + + + public int hashCode() + { + return super.hashCode() ^ + arrayLength.hashCode(); + } + + + public String toString() + { + return super.toString() + '['+arrayLength+']'; + } +} diff --git a/src/proguard/evaluation/value/Category1Value.java b/src/proguard/evaluation/value/Category1Value.java index a5ebf86..777e3e3 100644 --- a/src/proguard/evaluation/value/Category1Value.java +++ b/src/proguard/evaluation/value/Category1Value.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 diff --git a/src/proguard/evaluation/value/Category2Value.java b/src/proguard/evaluation/value/Category2Value.java index 2be6e71..80c2183 100644 --- a/src/proguard/evaluation/value/Category2Value.java +++ b/src/proguard/evaluation/value/Category2Value.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 diff --git a/src/proguard/evaluation/value/ComparisonValue.java b/src/proguard/evaluation/value/ComparisonValue.java index abbf31c..e2cd94e 100644 --- a/src/proguard/evaluation/value/ComparisonValue.java +++ b/src/proguard/evaluation/value/ComparisonValue.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 diff --git a/src/proguard/evaluation/value/CompositeDoubleValue.java b/src/proguard/evaluation/value/CompositeDoubleValue.java index be739ed..85b606a 100644 --- a/src/proguard/evaluation/value/CompositeDoubleValue.java +++ b/src/proguard/evaluation/value/CompositeDoubleValue.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 diff --git a/src/proguard/evaluation/value/CompositeFloatValue.java b/src/proguard/evaluation/value/CompositeFloatValue.java index 0961068..35f160f 100644 --- a/src/proguard/evaluation/value/CompositeFloatValue.java +++ b/src/proguard/evaluation/value/CompositeFloatValue.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 diff --git a/src/proguard/evaluation/value/CompositeIntegerValue.java b/src/proguard/evaluation/value/CompositeIntegerValue.java index 97caa2f..de56452 100644 --- a/src/proguard/evaluation/value/CompositeIntegerValue.java +++ b/src/proguard/evaluation/value/CompositeIntegerValue.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 diff --git a/src/proguard/evaluation/value/CompositeLongValue.java b/src/proguard/evaluation/value/CompositeLongValue.java index 3b8a97f..70351c8 100644 --- a/src/proguard/evaluation/value/CompositeLongValue.java +++ b/src/proguard/evaluation/value/CompositeLongValue.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 diff --git a/src/proguard/evaluation/value/ConvertedByteValue.java b/src/proguard/evaluation/value/ConvertedByteValue.java index eb1a350..6fd96e4 100644 --- a/src/proguard/evaluation/value/ConvertedByteValue.java +++ b/src/proguard/evaluation/value/ConvertedByteValue.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 diff --git a/src/proguard/evaluation/value/ConvertedCharacterValue.java b/src/proguard/evaluation/value/ConvertedCharacterValue.java index a491bed..81f0500 100644 --- a/src/proguard/evaluation/value/ConvertedCharacterValue.java +++ b/src/proguard/evaluation/value/ConvertedCharacterValue.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 diff --git a/src/proguard/evaluation/value/ConvertedDoubleValue.java b/src/proguard/evaluation/value/ConvertedDoubleValue.java index 65fab84..bd20542 100644 --- a/src/proguard/evaluation/value/ConvertedDoubleValue.java +++ b/src/proguard/evaluation/value/ConvertedDoubleValue.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 diff --git a/src/proguard/evaluation/value/ConvertedFloatValue.java b/src/proguard/evaluation/value/ConvertedFloatValue.java index e74ec8d..83e1eb1 100644 --- a/src/proguard/evaluation/value/ConvertedFloatValue.java +++ b/src/proguard/evaluation/value/ConvertedFloatValue.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 diff --git a/src/proguard/evaluation/value/ConvertedIntegerValue.java b/src/proguard/evaluation/value/ConvertedIntegerValue.java index 273b5a1..c5d83b5 100644 --- a/src/proguard/evaluation/value/ConvertedIntegerValue.java +++ b/src/proguard/evaluation/value/ConvertedIntegerValue.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 diff --git a/src/proguard/evaluation/value/ConvertedLongValue.java b/src/proguard/evaluation/value/ConvertedLongValue.java index 5cb9104..944e8b6 100644 --- a/src/proguard/evaluation/value/ConvertedLongValue.java +++ b/src/proguard/evaluation/value/ConvertedLongValue.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 diff --git a/src/proguard/evaluation/value/ConvertedShortValue.java b/src/proguard/evaluation/value/ConvertedShortValue.java index cef2a20..7e0472f 100644 --- a/src/proguard/evaluation/value/ConvertedShortValue.java +++ b/src/proguard/evaluation/value/ConvertedShortValue.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 diff --git a/src/proguard/evaluation/value/DetailedArrayReferenceValue.java b/src/proguard/evaluation/value/DetailedArrayReferenceValue.java new file mode 100644 index 0000000..73ca067 --- /dev/null +++ b/src/proguard/evaluation/value/DetailedArrayReferenceValue.java @@ -0,0 +1,301 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * 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 + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.evaluation.value; + +import proguard.classfile.Clazz; +import proguard.classfile.util.ClassUtil; +import proguard.util.ArrayUtil; + +/** + * This IdentifiedArrayReferenceValue represents an identified array reference + * value with its elements. + * + * @author Eric Lafortune + */ +class DetailedArrayReferenceValue extends IdentifiedArrayReferenceValue +{ + private static final int MAXIMUM_STORED_ARRAY_LENGTH = 32; + + + private final Value[] values; + + + /** + * Creates a new array reference value with the given ID. + */ + public DetailedArrayReferenceValue(String type, + Clazz referencedClass, + IntegerValue arrayLength, + ValueFactory valuefactory, + int id) + { + super(type, referencedClass, arrayLength, valuefactory, id); + + // Is the array short enough to analyze? + if (arrayLength.isParticular() && + arrayLength.value() <= MAXIMUM_STORED_ARRAY_LENGTH) + { + // Initialize the values of the array. + InitialValueFactory initialValueFactory = + new InitialValueFactory(valuefactory); + + String elementType = ClassUtil.isInternalArrayType(type) ? + type.substring(1) : + type; + + this.values = new Value[arrayLength.value()]; + + for (int index = 0; index < values.length; index++) + { + values[index] = initialValueFactory.createValue(elementType); + } + } + else + { + // Just ignore the values of the array. + this.values = null; + } + } + + + // Implementations for ReferenceValue. + + public IntegerValue integerArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + Value value = arrayLoad(indexValue, valueFactory); + return value != null ? + value.integerValue() : + super.integerArrayLoad(indexValue, valueFactory); + } + + + public LongValue longArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + Value value = arrayLoad(indexValue, valueFactory); + return value != null ? + value.longValue() : + super.longArrayLoad(indexValue, valueFactory); + } + + + public FloatValue floatArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + Value value = arrayLoad(indexValue, valueFactory); + return value != null ? + value.floatValue() : + super.floatArrayLoad(indexValue, valueFactory); + } + + + public DoubleValue doubleArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + Value value = arrayLoad(indexValue, valueFactory); + return value != null ? + value.doubleValue() : + super.doubleArrayLoad(indexValue, valueFactory); + } + + + public ReferenceValue referenceArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + Value value = arrayLoad(indexValue, valueFactory); + return value != null ? + value.referenceValue() : + super.referenceArrayLoad(indexValue, valueFactory); + } + + + /** + * Returns the specified untyped value from the given array, or null if it + * is unknown. + */ + private Value arrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + if (values != null && + indexValue.isParticular()) + { + int index = indexValue.value(); + if (index >=0 && + index < values.length) + { + return values[index]; + } + } + + return null; + } + + + public void arrayStore(IntegerValue indexValue, Value value) + { + if (values != null) + { + if (indexValue.isParticular()) + { + int index = indexValue.value(); + if (index >=0 && + index < values.length) + { + values[index] = value; + } + } + else + { + for (int index = 0; index < values.length; index++) + { + values[index].generalize(value); + } + } + } + } + + + // Implementations of binary methods of ReferenceValue. + + public ReferenceValue generalize(ReferenceValue other) + { + return other.generalize(this); + } + + + public int equal(ReferenceValue other) + { + return other.equal(this); + } + + +// // Implementations of binary ReferenceValue methods with +// // IdentifiedReferenceValue arguments. +// +// public ReferenceValue generalize(IdentifiedReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } +// +// +// public int equal(IdentifiedReferenceValue other) +// { +// return equal((TypedReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // ArrayReferenceValue arguments. +// +// public ReferenceValue generalize(ArrayReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } +// +// +// public int equal(ArrayReferenceValue other) +// { +// return equal((TypedReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // IdentifiedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(IdentifiedArrayReferenceValue other) +// { +// return generalize((ArrayReferenceValue)other); +// } +// +// +// public int equal(IdentifiedArrayReferenceValue other) +// { +// return equal((ArrayReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // DetailedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(DetailedArrayReferenceValue other) +// { +// return generalize((IdentifiedArrayReferenceValue)other); +// } +// +// +// public int equal(DetailedArrayReferenceValue other) +// { +// return equal((IdentifiedArrayReferenceValue)other); +// } + + + // Implementations for Value. + + public boolean isParticular() + { + if (values == null) + { + return false; + } + + for (int index = 0; index < values.length; index++) + { + if (!values[index].isParticular()) + { + return false; + } + } + + return true; + } + + + // Implementations for Object. + + public boolean equals(Object object) + { + return this == object || + super.equals(object) && + ArrayUtil.equalOrNull(this.values, ((DetailedArrayReferenceValue)object).values); + } + + + public int hashCode() + { + return super.hashCode() ^ + ArrayUtil.hashCodeOrNull(values); + } + + + public String toString() + { + if (values == null) + { + return super.toString(); + } + + StringBuffer buffer = new StringBuffer(super.toString()); + + buffer.append('{'); + for (int index = 0; index < values.length; index++) + { + buffer.append(values[index]); + buffer.append(index < values.length-1 ? ',' : '}'); + } + + return buffer.toString(); + } +}
\ No newline at end of file diff --git a/src/proguard/evaluation/value/DetailedValueFactory.java b/src/proguard/evaluation/value/DetailedValueFactory.java new file mode 100644 index 0000000..d28b8ab --- /dev/null +++ b/src/proguard/evaluation/value/DetailedValueFactory.java @@ -0,0 +1,48 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * 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 + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.evaluation.value; + +import proguard.classfile.*; + +/** + * This identified value factory creates array reference values that also + * represent their elements, in as far as possible. + * + * @author Eric Lafortune + */ +public class DetailedValueFactory +extends IdentifiedValueFactory +{ + // Implementations for ReferenceValue. + + public ReferenceValue createArrayReferenceValue(String type, + Clazz referencedClass, + IntegerValue arrayLength) + { + return type == null ? + REFERENCE_VALUE_NULL : + new DetailedArrayReferenceValue(ClassConstants.TYPE_ARRAY + type, + referencedClass, + arrayLength, + this, + referenceID++); + } +}
\ No newline at end of file diff --git a/src/proguard/evaluation/value/DoubleValue.java b/src/proguard/evaluation/value/DoubleValue.java index 6630b2f..7587ed3 100644 --- a/src/proguard/evaluation/value/DoubleValue.java +++ b/src/proguard/evaluation/value/DoubleValue.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 @@ -354,6 +354,6 @@ public abstract class DoubleValue extends Category2Value public final String internalType() { - return String.valueOf(ClassConstants.INTERNAL_TYPE_DOUBLE); + return String.valueOf(ClassConstants.TYPE_DOUBLE); } } diff --git a/src/proguard/evaluation/value/FloatValue.java b/src/proguard/evaluation/value/FloatValue.java index 6dc8bee..ce7806e 100644 --- a/src/proguard/evaluation/value/FloatValue.java +++ b/src/proguard/evaluation/value/FloatValue.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 @@ -354,6 +354,6 @@ public abstract class FloatValue extends Category1Value public final String internalType() { - return String.valueOf(ClassConstants.INTERNAL_TYPE_FLOAT); + return String.valueOf(ClassConstants.TYPE_FLOAT); } } diff --git a/src/proguard/evaluation/value/IdentifiedArrayReferenceValue.java b/src/proguard/evaluation/value/IdentifiedArrayReferenceValue.java new file mode 100644 index 0000000..3b597a1 --- /dev/null +++ b/src/proguard/evaluation/value/IdentifiedArrayReferenceValue.java @@ -0,0 +1,159 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * 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 + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.evaluation.value; + +import proguard.classfile.Clazz; + +/** + * This ArrayReferenceValue represents an array reference value that is + * identified by a unique ID. + * + * @author Eric Lafortune + */ +class IdentifiedArrayReferenceValue extends ArrayReferenceValue +{ + private final ValueFactory valuefactory; + private final int id; + + + /** + * Creates a new array reference value with the given ID. + */ + public IdentifiedArrayReferenceValue(String type, + Clazz referencedClass, + IntegerValue arrayLength, + ValueFactory valuefactory, + int id) + { + super(type, referencedClass, arrayLength); + + this.valuefactory = valuefactory; + this.id = id; + } + + + // Implementations of binary methods of ReferenceValue. + + public ReferenceValue generalize(ReferenceValue other) + { + return other.generalize(this); + } + + + public int equal(ReferenceValue other) + { + return other.equal(this); + } + + +// // Implementations of binary ReferenceValue methods with +// // IdentifiedReferenceValue arguments. +// +// public ReferenceValue generalize(IdentifiedReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } +// +// +// public int equal(IdentifiedReferenceValue other) +// { +// return equal((TypedReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // ArrayReferenceValue arguments. +// +// public ReferenceValue generalize(ArrayReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } +// +// +// public int equal(ArrayReferenceValue other) +// { +// return equal((TypedReferenceValue)other); +// } +// +// + // Implementations of binary ReferenceValue methods with + // IdentifiedArrayReferenceValue arguments. + +// public ReferenceValue generalize(IdentifiedArrayReferenceValue other) +// { +// return generalize((ArrayReferenceValue)other); +// } + + + public int equal(IdentifiedArrayReferenceValue other) + { + return this.equals(other) ? ALWAYS : + this.equal((TypedReferenceValue)other); + } + + +// // Implementations of binary ReferenceValue methods with +// // DetailedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(DetailedArrayReferenceValue other) +// { +// return generalize((IdentifiedArrayReferenceValue)other); +// } +// +// +// public int equal(DetailedArrayReferenceValue other) +// { +// return equal((IdentifiedArrayReferenceValue)other); +// } + + + // Implementations for Value. + + public boolean isSpecific() + { + return true; + } + + + // Implementations for Object. + + public boolean equals(Object object) + { + return this == object || + super.equals(object) && + this.valuefactory.equals(((IdentifiedArrayReferenceValue)object).valuefactory) && + this.id == ((IdentifiedArrayReferenceValue)object).id; + } + + + public int hashCode() + { + return super.hashCode() ^ + valuefactory.hashCode() ^ + id; + } + + + public String toString() + { + return super.toString() + '#' + id; + } +}
\ No newline at end of file diff --git a/src/proguard/evaluation/value/IdentifiedDoubleValue.java b/src/proguard/evaluation/value/IdentifiedDoubleValue.java index 4ff2466..6740a2c 100644 --- a/src/proguard/evaluation/value/IdentifiedDoubleValue.java +++ b/src/proguard/evaluation/value/IdentifiedDoubleValue.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 diff --git a/src/proguard/evaluation/value/IdentifiedFloatValue.java b/src/proguard/evaluation/value/IdentifiedFloatValue.java index c8349bc..62e4b2b 100644 --- a/src/proguard/evaluation/value/IdentifiedFloatValue.java +++ b/src/proguard/evaluation/value/IdentifiedFloatValue.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 diff --git a/src/proguard/evaluation/value/IdentifiedIntegerValue.java b/src/proguard/evaluation/value/IdentifiedIntegerValue.java index 6c3ee5d..ac1d033 100644 --- a/src/proguard/evaluation/value/IdentifiedIntegerValue.java +++ b/src/proguard/evaluation/value/IdentifiedIntegerValue.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 diff --git a/src/proguard/evaluation/value/IdentifiedLongValue.java b/src/proguard/evaluation/value/IdentifiedLongValue.java index e0b68f2..b670ae6 100644 --- a/src/proguard/evaluation/value/IdentifiedLongValue.java +++ b/src/proguard/evaluation/value/IdentifiedLongValue.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 diff --git a/src/proguard/evaluation/value/IdentifiedReferenceValue.java b/src/proguard/evaluation/value/IdentifiedReferenceValue.java index 5cfbd60..7f0196b 100644 --- a/src/proguard/evaluation/value/IdentifiedReferenceValue.java +++ b/src/proguard/evaluation/value/IdentifiedReferenceValue.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 @@ -23,18 +23,19 @@ package proguard.evaluation.value; import proguard.classfile.Clazz; /** - * This LongValue represents a reference value that is identified by a unique ID. + * This TypedReferenceValue represents a reference value that is identified by a + * unique ID. * * @author Eric Lafortune */ -final class IdentifiedReferenceValue extends ReferenceValue +class IdentifiedReferenceValue extends TypedReferenceValue { private final ValueFactory valuefactory; private final int id; /** - * Creates a new long value with the given ID. + * Creates a new reference value with the given ID. */ public IdentifiedReferenceValue(String type, Clazz referencedClass, @@ -49,25 +50,81 @@ final class IdentifiedReferenceValue extends ReferenceValue } - // Implementations for ReferenceValue. + // Implementations of binary methods of ReferenceValue. + + public ReferenceValue generalize(ReferenceValue other) + { + return other.generalize(this); + } + public int equal(ReferenceValue other) { - return this.equals(other) ? ALWAYS : MAYBE; + return other.equal(this); } - // Implementations of binary methods of ReferenceValue. + // Implementations of binary ReferenceValue methods with + // IdentifiedReferenceValue arguments. - public ReferenceValue generalize(ReferenceValue other) +// public ReferenceValue generalize(IdentifiedReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } + + + public int equal(IdentifiedReferenceValue other) { - // Remove the ID if both values don't share the same ID. - return this.equals(other) ? - this : - new ReferenceValue(type, referencedClass, mayBeNull).generalize(other); + return this.equals(other) ? ALWAYS : + this.equal((TypedReferenceValue)other); } +// // Implementations of binary ReferenceValue methods with +// // ArrayReferenceValue arguments. +// +// public ReferenceValue generalize(ArrayReferenceValue other) +// { +// return generalize((TypedReferenceValue)other); +// } +// +// +// public int equal(ArrayReferenceValue other) +// { +// return equal((TypedReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // IdentifiedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(IdentifiedArrayReferenceValue other) +// { +// return generalize((ArrayReferenceValue)other); +// } +// +// +// public int equal(IdentifiedArrayReferenceValue other) +// { +// return equal((ArrayReferenceValue)other); +// } +// +// +// // Implementations of binary ReferenceValue methods with +// // DetailedArrayReferenceValue arguments. +// +// public ReferenceValue generalize(DetailedArrayReferenceValue other) +// { +// return generalize((IdentifiedArrayReferenceValue)other); +// } +// +// +// public int equal(DetailedArrayReferenceValue other) +// { +// return equal((IdentifiedArrayReferenceValue)other); +// } + + // Implementations for Value. public boolean isSpecific() diff --git a/src/proguard/evaluation/value/IdentifiedValueFactory.java b/src/proguard/evaluation/value/IdentifiedValueFactory.java index be5c885..6bd1d5d 100644 --- a/src/proguard/evaluation/value/IdentifiedValueFactory.java +++ b/src/proguard/evaluation/value/IdentifiedValueFactory.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 @@ -21,21 +21,20 @@ package proguard.evaluation.value; import proguard.classfile.*; -import proguard.classfile.util.ClassUtil; /** - * This class provides methods to create and reuse IntegerValue objects. + * This particular value factory attaches a unique ID to any unknown values. * * @author Eric Lafortune */ public class IdentifiedValueFactory -extends SpecificValueFactory +extends ParticularValueFactory { - private int integerID; - private int longID; - private int floatID; - private int doubleID; - private int referenceID; + protected int integerID; + protected int longID; + protected int floatID; + protected int doubleID; + protected int referenceID; // Implementations for ValueFactory. @@ -70,6 +69,24 @@ extends SpecificValueFactory { return type == null ? REFERENCE_VALUE_NULL : - new IdentifiedReferenceValue(type, referencedClass, mayBeNull, this, referenceID++); + new IdentifiedReferenceValue(type, + referencedClass, + mayBeNull, + this, + referenceID++); + } + + + public ReferenceValue createArrayReferenceValue(String type, + Clazz referencedClass, + IntegerValue arrayLength) + { + return type == null ? + REFERENCE_VALUE_NULL : + new IdentifiedArrayReferenceValue(ClassConstants.TYPE_ARRAY + type, + referencedClass, + arrayLength, + this, + referenceID++); } }
\ No newline at end of file diff --git a/src/proguard/evaluation/value/InitialValueFactory.java b/src/proguard/evaluation/value/InitialValueFactory.java new file mode 100644 index 0000000..4b2cf29 --- /dev/null +++ b/src/proguard/evaluation/value/InitialValueFactory.java @@ -0,0 +1,79 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * 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 + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.evaluation.value; + +import proguard.classfile.ClassConstants; + +/** + * This value factory creates initial values for fields and array elements, + * with the help of a given value factory. Note that this class itself doesn't + * implement ValueFactory. + * + * @author Eric Lafortune + */ +public class InitialValueFactory +{ + private final ValueFactory valueFactory; + + + /** + * Creates a new InitialValueFactory. + * @param valueFactory the value factory that will actually create the + * values. + */ + public InitialValueFactory(ValueFactory valueFactory) + { + this.valueFactory = valueFactory; + } + + + /** + * Creates an initial value (0, 0L, 0.0f, 0.0, null) of the given type. + */ + public Value createValue(String type) + { + switch (type.charAt(0)) + { + case ClassConstants.TYPE_BOOLEAN: + case ClassConstants.TYPE_BYTE: + case ClassConstants.TYPE_CHAR: + case ClassConstants.TYPE_SHORT: + case ClassConstants.TYPE_INT: + return valueFactory.createIntegerValue(0); + + case ClassConstants.TYPE_LONG: + return valueFactory.createLongValue(0L); + + case ClassConstants.TYPE_FLOAT: + return valueFactory.createFloatValue(0.0f); + + case ClassConstants.TYPE_DOUBLE: + return valueFactory.createDoubleValue(0.0); + + case ClassConstants.TYPE_CLASS_START: + case ClassConstants.TYPE_ARRAY: + return valueFactory.createReferenceValueNull(); + + default: + throw new IllegalArgumentException("Invalid type ["+type+"]"); + } + } +} diff --git a/src/proguard/evaluation/value/InstructionOffsetValue.java b/src/proguard/evaluation/value/InstructionOffsetValue.java index 07a44ee..7cb953e 100644 --- a/src/proguard/evaluation/value/InstructionOffsetValue.java +++ b/src/proguard/evaluation/value/InstructionOffsetValue.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 @@ -143,60 +143,73 @@ public class InstructionOffsetValue extends Category1Value */ public final Value generalize(InstructionOffsetValue other) { - // If the values array of either is null, return the other one. - if (this.values == null) + // If the values array of either is null, we can return the other one. + int[] thisValues = this.values; + if (thisValues == null) { return other; } - if (other.values == null) + int[] otherValues = other.values; + if (otherValues == null) { return this; } // Compute the length of the union of the arrays. - int newLength = this.values.length; - for (int index = 0; index < other.values.length; index++) + int newLength = thisValues.length; + for (int index = 0; index < otherValues.length; index++) { - if (!this.contains(other.values[index])) + if (!this.contains(otherValues[index])) { newLength++; } } - // If the length of the union array is equal to the length of the values - // array of either, return it. - if (newLength == other.values.length) + // If the length of the union array is equal to the length of the other + // values array, we can return it. + if (newLength == otherValues.length) { return other; } - // The ordering of the this array may not be right, so we can't just - // use it. - //if (newLength == this.values.length) - //{ - // return this; - //} + // If the length of the union array is equal to the length of this + // values array, we can return it. We have to make sure that the other + // values are at the end. We'll just test one special case, with a + // single other value. + if (newLength == this.values.length && + otherValues.length == 1 && + thisValues[thisValues.length-1] == otherValues[0]) + { + return this; + } // Create the union array. + int newIndex = 0; int[] newValues = new int[newLength]; - int newIndex = 0; + // Is the length of the union array is equal to the sum of the lengths? + if (newLength == thisValues.length + otherValues.length) + { + // We can just copy all values, because they are unique. + System.arraycopy(thisValues, 0, newValues, 0, thisValues.length); - // Copy the values that are different from the other array. - for (int index = 0; index < this.values.length; index++) + newIndex = thisValues.length; + } + else { - if (!other.contains(this.values[index])) + // Copy the values that are different from the other array. + for (int index = 0; index < thisValues.length; index++) { - newValues[newIndex++] = this.values[index]; + if (!other.contains(thisValues[index])) + { + newValues[newIndex++] = thisValues[index]; + } } } // Copy the values from the other array. - for (int index = 0; index < other.values.length; index++) - { - newValues[newIndex++] = other.values[index]; - } + System.arraycopy(otherValues, 0, newValues, newIndex, otherValues.length); return new InstructionOffsetValue(newValues); } @@ -231,7 +244,7 @@ public class InstructionOffsetValue extends Category1Value public final String internalType() { - return String.valueOf(ClassConstants.INTERNAL_TYPE_INT); + return String.valueOf(ClassConstants.TYPE_INT); } diff --git a/src/proguard/evaluation/value/IntegerValue.java b/src/proguard/evaluation/value/IntegerValue.java index b1824c6..148c0ea 100644 --- a/src/proguard/evaluation/value/IntegerValue.java +++ b/src/proguard/evaluation/value/IntegerValue.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 @@ -997,6 +997,6 @@ public abstract class IntegerValue extends Category1Value public final String internalType() { - return String.valueOf(ClassConstants.INTERNAL_TYPE_INT); + return String.valueOf(ClassConstants.TYPE_INT); } } diff --git a/src/proguard/evaluation/value/LongValue.java b/src/proguard/evaluation/value/LongValue.java index e23c13c..e8f9e12 100644 --- a/src/proguard/evaluation/value/LongValue.java +++ b/src/proguard/evaluation/value/LongValue.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 @@ -549,6 +549,6 @@ public abstract class LongValue extends Category2Value public final String internalType() { - return String.valueOf(ClassConstants.INTERNAL_TYPE_INT); + return String.valueOf(ClassConstants.TYPE_INT); } } diff --git a/src/proguard/evaluation/value/NegatedDoubleValue.java b/src/proguard/evaluation/value/NegatedDoubleValue.java index 7619be7..25de608 100644 --- a/src/proguard/evaluation/value/NegatedDoubleValue.java +++ b/src/proguard/evaluation/value/NegatedDoubleValue.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 diff --git a/src/proguard/evaluation/value/NegatedFloatValue.java b/src/proguard/evaluation/value/NegatedFloatValue.java index 51b5074..7a05579 100644 --- a/src/proguard/evaluation/value/NegatedFloatValue.java +++ b/src/proguard/evaluation/value/NegatedFloatValue.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 diff --git a/src/proguard/evaluation/value/NegatedIntegerValue.java b/src/proguard/evaluation/value/NegatedIntegerValue.java index 1729083..cbbabdd 100644 --- a/src/proguard/evaluation/value/NegatedIntegerValue.java +++ b/src/proguard/evaluation/value/NegatedIntegerValue.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 diff --git a/src/proguard/evaluation/value/NegatedLongValue.java b/src/proguard/evaluation/value/NegatedLongValue.java index 7510524..bb9f729 100644 --- a/src/proguard/evaluation/value/NegatedLongValue.java +++ b/src/proguard/evaluation/value/NegatedLongValue.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 diff --git a/src/proguard/evaluation/value/ParticularDoubleValue.java b/src/proguard/evaluation/value/ParticularDoubleValue.java index e8c5aa7..d97eb5f 100644 --- a/src/proguard/evaluation/value/ParticularDoubleValue.java +++ b/src/proguard/evaluation/value/ParticularDoubleValue.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 @@ -182,9 +182,9 @@ final class ParticularDoubleValue extends SpecificDoubleValue public IntegerValue compare(ParticularDoubleValue other) { - return this.value < other.value ? SpecificValueFactory.INTEGER_VALUE_M1 : - this.value == other.value ? SpecificValueFactory.INTEGER_VALUE_0 : - SpecificValueFactory.INTEGER_VALUE_1; + return this.value < other.value ? ParticularValueFactory.INTEGER_VALUE_M1 : + this.value == other.value ? ParticularValueFactory.INTEGER_VALUE_0 : + ParticularValueFactory.INTEGER_VALUE_1; } diff --git a/src/proguard/evaluation/value/ParticularFloatValue.java b/src/proguard/evaluation/value/ParticularFloatValue.java index cbdde31..9084b36 100644 --- a/src/proguard/evaluation/value/ParticularFloatValue.java +++ b/src/proguard/evaluation/value/ParticularFloatValue.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 @@ -182,9 +182,9 @@ final class ParticularFloatValue extends SpecificFloatValue public IntegerValue compare(ParticularFloatValue other) { - return this.value < other.value ? SpecificValueFactory.INTEGER_VALUE_M1 : - this.value == other.value ? SpecificValueFactory.INTEGER_VALUE_0 : - SpecificValueFactory.INTEGER_VALUE_1; + return this.value < other.value ? ParticularValueFactory.INTEGER_VALUE_M1 : + this.value == other.value ? ParticularValueFactory.INTEGER_VALUE_0 : + ParticularValueFactory.INTEGER_VALUE_1; } diff --git a/src/proguard/evaluation/value/ParticularIntegerValue.java b/src/proguard/evaluation/value/ParticularIntegerValue.java index 609e95f..86f8a22 100644 --- a/src/proguard/evaluation/value/ParticularIntegerValue.java +++ b/src/proguard/evaluation/value/ParticularIntegerValue.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 diff --git a/src/proguard/evaluation/value/ParticularLongValue.java b/src/proguard/evaluation/value/ParticularLongValue.java index 1903235..7e7cc20 100644 --- a/src/proguard/evaluation/value/ParticularLongValue.java +++ b/src/proguard/evaluation/value/ParticularLongValue.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 diff --git a/src/proguard/evaluation/value/SpecificValueFactory.java b/src/proguard/evaluation/value/ParticularValueFactory.java index f761938..f28c10e 100644 --- a/src/proguard/evaluation/value/SpecificValueFactory.java +++ b/src/proguard/evaluation/value/ParticularValueFactory.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 @@ -20,12 +20,14 @@ */ package proguard.evaluation.value; +import proguard.classfile.*; + /** - * This class provides methods to create and reuse IntegerValue objects. + * This value factory creates particular values. * * @author Eric Lafortune */ -public class SpecificValueFactory +public class ParticularValueFactory extends ValueFactory { // Shared copies of Value objects, to avoid creating a lot of objects. @@ -69,9 +71,9 @@ extends ValueFactory public LongValue createLongValue(long value) { - return value == 0 ? LONG_VALUE_0 : - value == 1 ? LONG_VALUE_1 : - new ParticularLongValue(value); + return value == 0L ? LONG_VALUE_0 : + value == 1L ? LONG_VALUE_1 : + new ParticularLongValue(value); } @@ -94,4 +96,16 @@ extends ValueFactory value == 1.0 ? DOUBLE_VALUE_1 : new ParticularDoubleValue(value); } + + + public ReferenceValue createArrayReferenceValue(String type, + Clazz referencedClass, + IntegerValue arrayLength) + { + return type == null ? + REFERENCE_VALUE_NULL : + new ArrayReferenceValue(ClassConstants.TYPE_ARRAY + type, + referencedClass, + arrayLength); + } } diff --git a/src/proguard/evaluation/value/ReferenceValue.java b/src/proguard/evaluation/value/ReferenceValue.java index 4a52e82..1f87382 100644 --- a/src/proguard/evaluation/value/ReferenceValue.java +++ b/src/proguard/evaluation/value/ReferenceValue.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 @@ -20,191 +20,110 @@ */ package proguard.evaluation.value; -import proguard.classfile.*; -import proguard.classfile.util.ClassUtil; -import proguard.classfile.visitor.ClassCollector; - -import java.util.*; +import proguard.classfile.Clazz; /** - * This class represents a partially evaluated reference value. It has a type - * and a flag that indicates whether the value could be <code>null</code>. If - * the type is <code>null</code>, the value is <code>null</code>. + * This class represents a partially evaluated reference value. * * @author Eric Lafortune */ -public class ReferenceValue extends Category1Value +public abstract class ReferenceValue extends Category1Value { - private static final boolean DEBUG = false; + /** + * Returns the type. + */ + public abstract String getType(); +; + /** + * Returns the class that is referenced by the type. + */ + public abstract Clazz getReferencedClass(); - protected final String type; - protected final Clazz referencedClass; - protected final boolean mayBeNull; + // Basic unary methods. /** - * Creates a new ReferenceValue. + * Returns whether the type is <code>null</code>. */ - public ReferenceValue(String type, - Clazz referencedClass, - boolean mayBeNull) - { - this.type = type; - this.referencedClass = referencedClass; - this.mayBeNull = mayBeNull; - } + public abstract int isNull(); /** - * Returns the type. + * Returns whether the type is an instance of the given type. + */ + public abstract int instanceOf(String otherType, Clazz otherReferencedClass); + + + /** + * Returns a generalization of this ReferenceValue that may be null, + * depending on the flag. + */ + public abstract ReferenceValue generalizeMayBeNull(boolean mayBeNull); + + + /** + * Returns the length of the array, assuming this type is an array. */ - public String getType() + public IntegerValue arrayLength(ValueFactory valueFactory) { - return type; + return valueFactory.createIntegerValue(); } /** - * Returns the class that is referenced by the type. + * Returns the value of the array at the given index, assuming this type + * is an integer array. */ - public Clazz getReferencedClass() + public IntegerValue integerArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) { - return referencedClass; + return valueFactory.createIntegerValue(); } - // Basic unary methods. - /** - * Returns whether the type is <code>null</code>. + * Returns the value of the array at the given index, assuming this type + * is an long array. */ - public int isNull() + public LongValue longArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) { - return type == null ? ALWAYS : - mayBeNull ? MAYBE : - NEVER; + return valueFactory.createLongValue(); } /** - * Returns whether the type is an instance of the given type. + * Returns the value of the array at the given index, assuming this type + * is an float array. */ - public int instanceOf(String otherType, Clazz otherReferencedClass) + public FloatValue floatArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) { - String thisType = this.type; - - // If this type is null, it is never an instance of any class. - if (thisType == null) - { - return NEVER; - } - - // Start taking into account the type dimensions. - int thisDimensionCount = ClassUtil.internalArrayTypeDimensionCount(thisType); - int otherDimensionCount = ClassUtil.internalArrayTypeDimensionCount(otherType); - int commonDimensionCount = Math.min(thisDimensionCount, otherDimensionCount); - - // Strip any common array prefixes. - thisType = thisType.substring(commonDimensionCount); - otherType = otherType.substring(commonDimensionCount); - - // If either stripped type is a primitive type, we can tell right away. - if (commonDimensionCount > 0 && - (ClassUtil.isInternalPrimitiveType(thisType.charAt(0)) || - ClassUtil.isInternalPrimitiveType(otherType.charAt(0)))) - { - return !thisType.equals(otherType) ? NEVER : - mayBeNull ? MAYBE : - ALWAYS; - } - - // Strip the class type prefix and suffix of this type, if any. - if (thisDimensionCount == commonDimensionCount) - { - thisType = ClassUtil.internalClassNameFromClassType(thisType); - } - - // Strip the class type prefix and suffix of the other type, if any. - if (otherDimensionCount == commonDimensionCount) - { - otherType = ClassUtil.internalClassNameFromClassType(otherType); - } - - // If this type is an array type, and the other type is not - // java.lang.Object, java.lang.Cloneable, or java.io.Serializable, - // this type can never be an instance. - if (thisDimensionCount > otherDimensionCount && - !ClassUtil.isInternalArrayInterfaceName(otherType)) - { - return NEVER; - } - - // If the other type is an array type, and this type is not - // java.lang.Object, java.lang.Cloneable, or java.io.Serializable, - // this type can never be an instance. - if (thisDimensionCount < otherDimensionCount && - !ClassUtil.isInternalArrayInterfaceName(thisType)) - { - return NEVER; - } - - // If this type may be null, it might not be an instance of any class. - if (mayBeNull) - { - return MAYBE; - } - - // If this type is equal to the other type, or if the other type is - // java.lang.Object, this type is always an instance. - if (thisType.equals(otherType) || - ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT.equals(otherType)) - { - return ALWAYS; - } - - // If this type is an array type, it's ok. - if (thisDimensionCount > otherDimensionCount) - { - return ALWAYS; - } - - // If the other type is an array type, it might be ok. - if (thisDimensionCount < otherDimensionCount) - { - return MAYBE; - } - - // If the value extends the type, we're sure. - return referencedClass != null && - otherReferencedClass != null && - referencedClass.extendsOrImplements(otherReferencedClass) ? - ALWAYS : - MAYBE; + return valueFactory.createFloatValue(); } /** - * Returns the length of the array, assuming this type is an array. + * Returns the value of the array at the given index, assuming this type + * is an double array. */ - public IntegerValue arrayLength(ValueFactory valueFactory) + public DoubleValue doubleArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) { - return valueFactory.createIntegerValue(); + return valueFactory.createDoubleValue(); } /** * Returns the value of the array at the given index, assuming this type - * is an array. + * is a reference array. + */ + public abstract ReferenceValue referenceArrayLoad(IntegerValue indexValue, ValueFactory valueFactory); + + + /** + * Stores the given value at the given index in the given array, assuming + * this type is an array. */ - public Value arrayLoad(IntegerValue integerValue, ValueFactory valueFactory) + public void arrayStore(IntegerValue indexValue, Value value) { - return - type == null ? ValueFactory.REFERENCE_VALUE_NULL : - !ClassUtil.isInternalArrayType(type) ? ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL : - valueFactory.createValue(type.substring(1), - referencedClass, - true); } @@ -214,327 +133,173 @@ public class ReferenceValue extends Category1Value * Returns the generalization of this ReferenceValue and the given other * ReferenceValue. */ - public ReferenceValue generalize(ReferenceValue other) + public abstract ReferenceValue generalize(ReferenceValue other); + + + /** + * Returns whether this ReferenceValue is equal to the given other + * ReferenceValue. + * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. + */ + public abstract int equal(ReferenceValue other); + + + // Derived unary methods. + + /** + * Returns whether this ReferenceValue is not <code>null</code>. + * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. + */ + public final int isNotNull() { - // If both types are identical, the generalization is the same too. - if (this.equals(other)) - { - return this; - } - - String thisType = this.type; - String otherType = other.type; - - // If both types are nul, the generalization is null too. - if (thisType == null && otherType == null) - { - return ValueFactory.REFERENCE_VALUE_NULL; - } - - // If this type is null, the generalization is the other type, maybe null. - if (thisType == null) - { - return other.generalizeMayBeNull(true); - } - - // If the other type is null, the generalization is this type, maybe null. - if (otherType == null) - { - return this.generalizeMayBeNull(true); - } - - boolean mayBeNull = this.mayBeNull || other.mayBeNull; - - // If the two types are equal, the generalization remains the same, maybe null. - if (thisType.equals(otherType)) - { - return this.generalizeMayBeNull(mayBeNull); - } - - // Start taking into account the type dimensions. - int thisDimensionCount = ClassUtil.internalArrayTypeDimensionCount(thisType); - int otherDimensionCount = ClassUtil.internalArrayTypeDimensionCount(otherType); - int commonDimensionCount = Math.min(thisDimensionCount, otherDimensionCount); - - if (thisDimensionCount == otherDimensionCount) - { - // See if we can take into account the referenced classes. - Clazz thisReferencedClass = this.referencedClass; - Clazz otherReferencedClass = other.referencedClass; - - if (thisReferencedClass != null && - otherReferencedClass != null) - { - if (thisReferencedClass.extendsOrImplements(otherReferencedClass)) - { - return other.generalizeMayBeNull(mayBeNull); - } - - if (otherReferencedClass.extendsOrImplements(thisReferencedClass)) - { - return this.generalizeMayBeNull(mayBeNull); - } - - // Collect the superclasses and interfaces of this class. - Set thisSuperClasses = new HashSet(); - thisReferencedClass.hierarchyAccept(false, true, true, false, - new ClassCollector(thisSuperClasses)); - - int thisSuperClassesCount = thisSuperClasses.size(); - if (thisSuperClassesCount == 0 && - thisReferencedClass.getSuperName() != null) - { - throw new IllegalArgumentException("Can't find any super classes of ["+thisType+"] (not even immediate super class ["+thisReferencedClass.getSuperName()+"])"); - } - - // Collect the superclasses and interfaces of the other class. - Set otherSuperClasses = new HashSet(); - otherReferencedClass.hierarchyAccept(false, true, true, false, - new ClassCollector(otherSuperClasses)); - - int otherSuperClassesCount = otherSuperClasses.size(); - if (otherSuperClassesCount == 0 && - otherReferencedClass.getSuperName() != null) - { - throw new IllegalArgumentException("Can't find any super classes of ["+otherType+"] (not even immediate super class ["+otherReferencedClass.getSuperName()+"])"); - } - - if (DEBUG) - { - System.out.println("ReferenceValue.generalize this ["+thisReferencedClass.getName()+"] with other ["+otherReferencedClass.getName()+"]"); - System.out.println(" This super classes: "+thisSuperClasses); - System.out.println(" Other super classes: "+otherSuperClasses); - } - - // Find the common superclasses. - thisSuperClasses.retainAll(otherSuperClasses); - - if (DEBUG) - { - System.out.println(" Common super classes: "+thisSuperClasses); - } - - // Find a class that is a subclass of all common superclasses, - // or that at least has the maximum number of common superclasses. - Clazz commonClass = null; - - int maximumSuperClassCount = -1; - - // Go over all common superclasses to find it. In case of - // multiple subclasses, keep the lowest one alphabetically, - // in order to ensure that the choice is deterministic. - Iterator commonSuperClasses = thisSuperClasses.iterator(); - while (commonSuperClasses.hasNext()) - { - Clazz commonSuperClass = (Clazz)commonSuperClasses.next(); - - int superClassCount = superClassCount(commonSuperClass, thisSuperClasses); - if (maximumSuperClassCount < superClassCount || - (maximumSuperClassCount == superClassCount && - commonClass != null && - commonClass.getName().compareTo(commonSuperClass.getName()) > 0)) - { - commonClass = commonSuperClass; - maximumSuperClassCount = superClassCount; - } - } - - if (commonClass == null) - { - throw new IllegalArgumentException("Can't find common super class of ["+ - thisType +"] (with "+thisSuperClassesCount +" known super classes) and ["+ - otherType+"] (with "+otherSuperClassesCount+" known super classes)"); - } - - if (DEBUG) - { - System.out.println(" Best common class: ["+commonClass.getName()+"]"); - } - - // TODO: Handle more difficult cases, with multiple global subclasses. - - return new ReferenceValue(commonDimensionCount == 0 ? - commonClass.getName() : - ClassUtil.internalArrayTypeFromClassName(commonClass.getName(), - commonDimensionCount), - commonClass, - mayBeNull); - } - } - else if (thisDimensionCount > otherDimensionCount) - { - // See if the other type is an interface type of arrays. - if (ClassUtil.isInternalArrayInterfaceName(ClassUtil.internalClassNameFromClassType(otherType))) - { - return other.generalizeMayBeNull(mayBeNull); - } - } - else if (thisDimensionCount < otherDimensionCount) - { - // See if this type is an interface type of arrays. - if (ClassUtil.isInternalArrayInterfaceName(ClassUtil.internalClassNameFromClassType(thisType))) - { - return this.generalizeMayBeNull(mayBeNull); - } - } - - // Reduce the common dimension count if either type is an array of - // primitives type of this dimension. - if (commonDimensionCount > 0 && - (ClassUtil.isInternalPrimitiveType(otherType.charAt(commonDimensionCount))) || - ClassUtil.isInternalPrimitiveType(thisType.charAt(commonDimensionCount))) - { - commonDimensionCount--; - } - - // Fall back on a basic Object or array of Objects type. - return commonDimensionCount == 0 ? - mayBeNull ? - ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL : - ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL : - new ReferenceValue(ClassUtil.internalArrayTypeFromClassName(ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT, - commonDimensionCount), - null, - mayBeNull); + return -isNull(); } + // Derived binary methods. + /** - * Returns if the number of superclasses of the given class in the given - * set of classes. + * Returns whether this ReferenceValue and the given ReferenceValue are different. + * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. */ - private int superClassCount(Clazz subClass, Set classes) + public final int notEqual(ReferenceValue other) { - int count = 0; + return -equal(other); + } - Iterator iterator = classes.iterator(); - while (iterator.hasNext()) - { - Clazz clazz = (Clazz)iterator.next(); - if (subClass.extendsOrImplements(clazz)) - { - count++; - } - } + // Similar binary methods, but this time with typed reference arguments. - return count; + /** + * Returns the generalization of this ReferenceValue and the given other + * TypedReferenceValue. + */ + public ReferenceValue generalize(TypedReferenceValue other) + { + return generalize((ReferenceValue)other); } /** * Returns whether this ReferenceValue is equal to the given other - * ReferenceValue. + * TypedReferenceValue. * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. */ - public int equal(ReferenceValue other) + public int equal(TypedReferenceValue other) { - return this.type == null && other.type == null ? ALWAYS : MAYBE; + return equal((ReferenceValue)other); } - // Derived unary methods. + // Similar binary methods, but this time with identified reference + // arguments. /** - * Returns whether this ReferenceValue is not <code>null</code>. + * Returns the generalization of this ReferenceValue and the given other + * IdentifiedReferenceValue. + */ + public ReferenceValue generalize(IdentifiedReferenceValue other) + { + return generalize((TypedReferenceValue)other); + } + + + /** + * Returns whether this ReferenceValue is equal to the given other + * IdentifiedReferenceValue. * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. */ - public final int isNotNull() + public int equal(IdentifiedReferenceValue other) { - return -isNull(); + return equal((TypedReferenceValue)other); } + // Similar binary methods, but this time with array reference arguments. + /** * Returns the generalization of this ReferenceValue and the given other - * ReferenceValue. + * ArrayReferenceValue. */ - private ReferenceValue generalizeMayBeNull(boolean mayBeNull) + public ReferenceValue generalize(ArrayReferenceValue other) { - return this.mayBeNull || !mayBeNull ? - this : - new ReferenceValue(this.type, this.referencedClass, true); + return generalize((TypedReferenceValue)other); } - // Derived binary methods. - /** - * Returns whether this ReferenceValue and the given ReferenceValue are different. + * Returns whether this ReferenceValue is equal to the given other + * ArrayReferenceValue. * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. */ - public final int notEqual(ReferenceValue other) + public int equal(ArrayReferenceValue other) { - return -equal(other); + return equal((TypedReferenceValue)other); } - // Implementations for Value. + // Similar binary methods, but this time with identified array reference + // arguments. - public final ReferenceValue referenceValue() + /** + * Returns the generalization of this ReferenceValue and the given other + * IdentifiedArrayReferenceValue. + */ + public ReferenceValue generalize(IdentifiedArrayReferenceValue other) { - return this; + return generalize((ArrayReferenceValue)other); } - public final Value generalize(Value other) - { - return this.generalize(other.referenceValue()); - } - public boolean isParticular() + /** + * Returns whether this ReferenceValue is equal to the given other + * IdentifiedArrayReferenceValue. + * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. + */ + public int equal(IdentifiedArrayReferenceValue other) { - return type == null; + return equal((ArrayReferenceValue)other); } - public final int computationalType() + + // Similar binary methods, but this time with detailed array reference + // arguments. + + /** + * Returns the generalization of this ReferenceValue and the given other + * DetailedArrayReferenceValue. + */ + public ReferenceValue generalize(DetailedArrayReferenceValue other) { - return TYPE_REFERENCE; + return generalize((IdentifiedArrayReferenceValue)other); } - public final String internalType() + + /** + * Returns whether this ReferenceValue is equal to the given other + * DetailedArrayReferenceValue. + * @return <code>NEVER</code>, <code>MAYBE</code>, or <code>ALWAYS</code>. + */ + public int equal(DetailedArrayReferenceValue other) { - return - type == null ? ClassConstants.INTERNAL_TYPE_JAVA_LANG_OBJECT : - ClassUtil.isInternalArrayType(type) ? type : - ClassConstants.INTERNAL_TYPE_CLASS_START + - type + - ClassConstants.INTERNAL_TYPE_CLASS_END; + return equal((IdentifiedArrayReferenceValue)other); } - // Implementations for Object. + // Implementations for Value. - public boolean equals(Object object) + public final ReferenceValue referenceValue() { - if (this == object) - { - return true; - } - - if (object == null || - this.getClass() != object.getClass()) - { - return false; - } - - ReferenceValue other = (ReferenceValue)object; - return this.type == null ? other.type == null : - (this.mayBeNull == other.mayBeNull && - this.type.equals(other.type)); + return this; } - - public int hashCode() + public final Value generalize(Value other) { - return this.getClass().hashCode() ^ - (type == null ? 0 : type.hashCode() ^ (mayBeNull ? 0 : 1)); + return this.generalize(other.referenceValue()); } - - public String toString() + public final int computationalType() { - return type == null ? - "null" : - type + (referencedClass == null ? "?" : "") + (mayBeNull ? "" : "!"); + return TYPE_REFERENCE; } } diff --git a/src/proguard/evaluation/value/SpecificDoubleValue.java b/src/proguard/evaluation/value/SpecificDoubleValue.java index 644f553..5ee2db2 100644 --- a/src/proguard/evaluation/value/SpecificDoubleValue.java +++ b/src/proguard/evaluation/value/SpecificDoubleValue.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 @@ -157,7 +157,7 @@ abstract class SpecificDoubleValue extends DoubleValue // Not handling NaN properly. //return this.equals(other) ? - // SpecificValueFactory.INTEGER_VALUE_0 : + // ParticularValueFactory.INTEGER_VALUE_0 : // new ComparisonValue(this, other); } diff --git a/src/proguard/evaluation/value/SpecificFloatValue.java b/src/proguard/evaluation/value/SpecificFloatValue.java index d88baa3..66e245a 100644 --- a/src/proguard/evaluation/value/SpecificFloatValue.java +++ b/src/proguard/evaluation/value/SpecificFloatValue.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 @@ -157,7 +157,7 @@ abstract class SpecificFloatValue extends FloatValue // Not handling NaN properly. //return this.equals(other) ? - // SpecificValueFactory.INTEGER_VALUE_0 : + // ParticularValueFactory.INTEGER_VALUE_0 : // new ComparisonValue(this, other); } diff --git a/src/proguard/evaluation/value/SpecificIntegerValue.java b/src/proguard/evaluation/value/SpecificIntegerValue.java index 81f8646..352e385 100644 --- a/src/proguard/evaluation/value/SpecificIntegerValue.java +++ b/src/proguard/evaluation/value/SpecificIntegerValue.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 @@ -208,14 +208,14 @@ abstract class SpecificIntegerValue extends IntegerValue public IntegerValue subtract(SpecificIntegerValue other) { return this.equals(other) ? - SpecificValueFactory.INTEGER_VALUE_0 : + ParticularValueFactory.INTEGER_VALUE_0 : new CompositeIntegerValue(this, CompositeIntegerValue.SUBTRACT, other); } public IntegerValue subtractFrom(SpecificIntegerValue other) { return this.equals(other) ? - SpecificValueFactory.INTEGER_VALUE_0 : + ParticularValueFactory.INTEGER_VALUE_0 : new CompositeIntegerValue(other, CompositeIntegerValue.SUBTRACT, this); } @@ -310,7 +310,7 @@ abstract class SpecificIntegerValue extends IntegerValue public IntegerValue xor(SpecificIntegerValue other) { return this.equals(other) ? - SpecificValueFactory.INTEGER_VALUE_0 : + ParticularValueFactory.INTEGER_VALUE_0 : new CompositeIntegerValue(other, CompositeIntegerValue.XOR, this); } diff --git a/src/proguard/evaluation/value/SpecificLongValue.java b/src/proguard/evaluation/value/SpecificLongValue.java index 15138b4..162f9fe 100644 --- a/src/proguard/evaluation/value/SpecificLongValue.java +++ b/src/proguard/evaluation/value/SpecificLongValue.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 @@ -153,14 +153,14 @@ abstract class SpecificLongValue extends LongValue public LongValue subtract(SpecificLongValue other) { return this.equals(other) ? - SpecificValueFactory.LONG_VALUE_0 : + ParticularValueFactory.LONG_VALUE_0 : new CompositeLongValue(this, CompositeLongValue.SUBTRACT, other); } public LongValue subtractFrom(SpecificLongValue other) { return this.equals(other) ? - SpecificValueFactory.LONG_VALUE_0 : + ParticularValueFactory.LONG_VALUE_0 : new CompositeLongValue(other, CompositeLongValue.SUBTRACT, this); } @@ -225,7 +225,7 @@ abstract class SpecificLongValue extends LongValue public LongValue xor(SpecificLongValue other) { return this.equals(other) ? - SpecificValueFactory.LONG_VALUE_0 : + ParticularValueFactory.LONG_VALUE_0 : new CompositeLongValue(other, CompositeLongValue.XOR, this); } diff --git a/src/proguard/evaluation/value/TopValue.java b/src/proguard/evaluation/value/TopValue.java index c7320fa..4422f69 100644 --- a/src/proguard/evaluation/value/TopValue.java +++ b/src/proguard/evaluation/value/TopValue.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 diff --git a/src/proguard/evaluation/value/TypedReferenceValue.java b/src/proguard/evaluation/value/TypedReferenceValue.java new file mode 100644 index 0000000..4f8629c --- /dev/null +++ b/src/proguard/evaluation/value/TypedReferenceValue.java @@ -0,0 +1,613 @@ +/* + * ProGuard -- shrinking, optimization, obfuscation, and preverification + * of Java bytecode. + * + * 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 + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package proguard.evaluation.value; + +import proguard.classfile.*; +import proguard.classfile.util.ClassUtil; +import proguard.classfile.visitor.ClassCollector; + +import java.util.*; + +/** + * This ReferenceValue represents a partially evaluated reference value. + * It has a type and a flag that indicates whether the value could be + * <code>null</code>. If the type is <code>null</code>, the value is + * <code>null</code>. + * + * @author Eric Lafortune + */ +public class TypedReferenceValue extends ReferenceValue +{ + private static final boolean DEBUG = false; + + + protected final String type; + protected final Clazz referencedClass; + protected final boolean mayBeNull; + + + /** + * Creates a new TypedReferenceValue. + */ + public TypedReferenceValue(String type, + Clazz referencedClass, + boolean mayBeNull) + { + this.type = type; + this.referencedClass = referencedClass; + this.mayBeNull = mayBeNull; + } + + + // Implementations for ReferenceValue. + + public String getType() + { + return type; + } + + + public Clazz getReferencedClass() + { + return referencedClass; + } + + + // Implementations of unary methods of ReferenceValue. + + public int isNull() + { + return type == null ? ALWAYS : + mayBeNull ? MAYBE : + NEVER; + } + + + public int instanceOf(String otherType, Clazz otherReferencedClass) + { + String thisType = this.type; + + // If this type is null, it is never an instance of any class. + if (thisType == null) + { + return NEVER; + } + + // Start taking into account the type dimensions. + int thisDimensionCount = ClassUtil.internalArrayTypeDimensionCount(thisType); + int otherDimensionCount = ClassUtil.internalArrayTypeDimensionCount(otherType); + int commonDimensionCount = Math.min(thisDimensionCount, otherDimensionCount); + + // Strip any common array prefixes. + thisType = thisType.substring(commonDimensionCount); + otherType = otherType.substring(commonDimensionCount); + + // If either stripped type is a primitive type, we can tell right away. + if (commonDimensionCount > 0 && + (ClassUtil.isInternalPrimitiveType(thisType.charAt(0)) || + ClassUtil.isInternalPrimitiveType(otherType.charAt(0)))) + { + return !thisType.equals(otherType) ? NEVER : + mayBeNull ? MAYBE : + ALWAYS; + } + + // Strip the class type prefix and suffix of this type, if any. + if (thisDimensionCount == commonDimensionCount) + { + thisType = ClassUtil.internalClassNameFromClassType(thisType); + } + + // Strip the class type prefix and suffix of the other type, if any. + if (otherDimensionCount == commonDimensionCount) + { + otherType = ClassUtil.internalClassNameFromClassType(otherType); + } + + // If this type is an array type, and the other type is not + // java.lang.Object, java.lang.Cloneable, or java.io.Serializable, + // this type can never be an instance. + if (thisDimensionCount > otherDimensionCount && + !ClassUtil.isInternalArrayInterfaceName(otherType)) + { + return NEVER; + } + + // If the other type is an array type, and this type is not + // java.lang.Object, java.lang.Cloneable, or java.io.Serializable, + // this type can never be an instance. + if (thisDimensionCount < otherDimensionCount && + !ClassUtil.isInternalArrayInterfaceName(thisType)) + { + return NEVER; + } + + // If this type may be null, it might not be an instance of any class. + if (mayBeNull) + { + return MAYBE; + } + + // If this type is equal to the other type, or if the other type is + // java.lang.Object, this type is always an instance. + if (thisType.equals(otherType) || + ClassConstants.NAME_JAVA_LANG_OBJECT.equals(otherType)) + { + return ALWAYS; + } + + // If this type is an array type, it's ok. + if (thisDimensionCount > otherDimensionCount) + { + return ALWAYS; + } + + // If the other type is an array type, it might be ok. + if (thisDimensionCount < otherDimensionCount) + { + return MAYBE; + } + + // If the value extends the type, we're sure. + return referencedClass != null && + otherReferencedClass != null && + referencedClass.extendsOrImplements(otherReferencedClass) ? + ALWAYS : + MAYBE; + } + + + public ReferenceValue generalizeMayBeNull(boolean mayBeNull) + { + return this.mayBeNull == mayBeNull ? + this : + new TypedReferenceValue(type, referencedClass, true); + } + + + public ReferenceValue referenceArrayLoad(IntegerValue indexValue, ValueFactory valueFactory) + { + return + type == null ? ValueFactory.REFERENCE_VALUE_NULL : + !ClassUtil.isInternalArrayType(type) ? ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL : + valueFactory.createValue(type.substring(1), + referencedClass, + true).referenceValue(); + } + + + // Implementations of binary methods of ReferenceValue. + + public ReferenceValue generalize(ReferenceValue other) + { + return other.generalize(this); + } + + + public int equal(ReferenceValue other) + { + return other.equal(this); + } + + + // Implementations of binary ReferenceValue methods with TypedReferenceValue + // arguments. + + public ReferenceValue generalize(TypedReferenceValue other) + { + // If both types are identical, the generalization is the same too. + if (this.equals(other)) + { + return this; + } + + String thisType = this.type; + String otherType = other.type; + + // If both types are nul, the generalization is null too. + if (thisType == null && otherType == null) + { + return ValueFactory.REFERENCE_VALUE_NULL; + } + + // If this type is null, the generalization is the other type, maybe null. + if (thisType == null) + { + return other.generalizeMayBeNull(true); + } + + // If the other type is null, the generalization is this type, maybe null. + if (otherType == null) + { + return this.generalizeMayBeNull(true); + } + + boolean mayBeNull = this.mayBeNull || other.mayBeNull; + + // If the two types are equal, the generalization remains the same, maybe null. + if (thisType.equals(otherType)) + { + return typedReferenceValue(this, mayBeNull); + } + + // Start taking into account the type dimensions. + int thisDimensionCount = ClassUtil.internalArrayTypeDimensionCount(thisType); + int otherDimensionCount = ClassUtil.internalArrayTypeDimensionCount(otherType); + int commonDimensionCount = Math.min(thisDimensionCount, otherDimensionCount); + + if (thisDimensionCount == otherDimensionCount) + { + // See if we can take into account the referenced classes. + Clazz thisReferencedClass = this.referencedClass; + Clazz otherReferencedClass = other.referencedClass; + + if (thisReferencedClass != null && + otherReferencedClass != null) + { + // Is one class simply an extension of the other one? + if (thisReferencedClass.extendsOrImplements(otherReferencedClass)) + { + return typedReferenceValue(other, mayBeNull); + } + + if (otherReferencedClass.extendsOrImplements(thisReferencedClass)) + { + return typedReferenceValue(this, mayBeNull); + } + + // Do the classes have a non-trivial common superclass? + Clazz commonClass = findCommonClass(thisReferencedClass, + otherReferencedClass, + false); + + if (commonClass.getName().equals(ClassConstants.NAME_JAVA_LANG_OBJECT)) + { + // Otherwise, do the classes have a common interface? + Clazz commonInterface = findCommonClass(thisReferencedClass, + otherReferencedClass, + true); + if (commonInterface != null) + { + commonClass = commonInterface; + } + } + + return new TypedReferenceValue(commonDimensionCount == 0 ? + commonClass.getName() : + ClassUtil.internalArrayTypeFromClassName(commonClass.getName(), + commonDimensionCount), + commonClass, + mayBeNull); + } + } + else if (thisDimensionCount > otherDimensionCount) + { + // See if the other type is an interface type of arrays. + if (ClassUtil.isInternalArrayInterfaceName(ClassUtil.internalClassNameFromClassType(otherType))) + { + return typedReferenceValue(other, mayBeNull); + } + } + else if (thisDimensionCount < otherDimensionCount) + { + // See if this type is an interface type of arrays. + if (ClassUtil.isInternalArrayInterfaceName(ClassUtil.internalClassNameFromClassType(thisType))) + { + return typedReferenceValue(this, mayBeNull); + } + } + + // Reduce the common dimension count if either type is an array of + // primitives type of this dimension. + if (commonDimensionCount > 0 && + (ClassUtil.isInternalPrimitiveType(otherType.charAt(commonDimensionCount))) || + ClassUtil.isInternalPrimitiveType(thisType.charAt(commonDimensionCount))) + { + commonDimensionCount--; + } + + // Fall back on a basic Object or array of Objects type. + return + commonDimensionCount != 0 ? + new TypedReferenceValue(ClassUtil.internalArrayTypeFromClassName(ClassConstants.NAME_JAVA_LANG_OBJECT, commonDimensionCount), + null, + mayBeNull) : + mayBeNull ? + ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL : + ValueFactory.REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL; + } + + + /** + * Returns the most specific common superclass or interface of the given + * classes. + * @param class1 the first class. + * @param class2 the second class. + * @param interfaces specifies whether to look for a superclass or for an + * interface. + * @return the common class. + */ + private Clazz findCommonClass(Clazz class1, + Clazz class2, + boolean interfaces) + { + // Collect the superclasses or the interfaces of this class. + Set superClasses1 = new HashSet(); + class1.hierarchyAccept(!interfaces, + !interfaces, + interfaces, + false, + new ClassCollector(superClasses1)); + + int superClasses1Count = superClasses1.size(); + if (superClasses1Count == 0) + { + if (interfaces) + { + return null; + } + else if (class1.getSuperName() != null) + { + throw new IllegalArgumentException("Can't find any super classes of ["+class1.getName()+"] (not even immediate super class ["+class1.getSuperName()+"])"); + } + } + + // Collect the superclasses or the interfaces of the other class. + Set superClasses2 = new HashSet(); + class2.hierarchyAccept(!interfaces, + !interfaces, + interfaces, + false, + new ClassCollector(superClasses2)); + + int superClasses2Count = superClasses2.size(); + if (superClasses2Count == 0) + { + if (interfaces) + { + return null; + } + else if (class2.getSuperName() != null) + { + throw new IllegalArgumentException("Can't find any super classes of ["+class2.getName()+"] (not even immediate super class ["+class2.getSuperName()+"])"); + } + } + + if (DEBUG) + { + System.out.println("ReferenceValue.generalize this ["+class1.getName()+"] with other ["+class2.getName()+"] (interfaces = "+interfaces+")"); + System.out.println(" This super classes: "+superClasses1); + System.out.println(" Other super classes: "+superClasses2); + } + + // Find the common superclasses. + superClasses1.retainAll(superClasses2); + + if (DEBUG) + { + System.out.println(" Common super classes: "+superClasses1); + } + + if (interfaces && superClasses1.isEmpty()) + { + return null; + } + + // Find a class that is a subclass of all common superclasses, + // or that at least has the maximum number of common superclasses. + Clazz commonClass = null; + + int maximumSuperClassCount = -1; + + // Go over all common superclasses to find it. In case of + // multiple subclasses, keep the lowest one alphabetically, + // in order to ensure that the choice is deterministic. + Iterator commonSuperClasses = superClasses1.iterator(); + while (commonSuperClasses.hasNext()) + { + Clazz commonSuperClass = (Clazz)commonSuperClasses.next(); + + int superClassCount = superClassCount(commonSuperClass, superClasses1); + if (maximumSuperClassCount < superClassCount || + (maximumSuperClassCount == superClassCount && + commonClass != null && + commonClass.getName().compareTo(commonSuperClass.getName()) > 0)) + { + commonClass = commonSuperClass; + maximumSuperClassCount = superClassCount; + } + } + + if (commonClass == null) + { + throw new IllegalArgumentException("Can't find common super class of ["+ + class1.getName() +"] (with "+superClasses1Count +" known super classes) and ["+ + class2.getName()+"] (with "+superClasses2Count+" known super classes)"); + } + + if (DEBUG) + { + System.out.println(" Best common class: ["+commonClass.getName()+"]"); + } + + return commonClass; + } + + + /** + * Returns the given reference value that may or may not be null, ensuring + * that it is a TypedReferenceValue, not a subclass. + */ + private static ReferenceValue typedReferenceValue(TypedReferenceValue referenceValue, + boolean mayBeNull) + { + return referenceValue.getClass() == TypedReferenceValue.class ? + referenceValue.generalizeMayBeNull(mayBeNull) : + new TypedReferenceValue(referenceValue.type, + referenceValue.referencedClass, + mayBeNull); + } + + + /** + * Returns if the number of superclasses of the given class in the given + * set of classes. + */ + private int superClassCount(Clazz subClass, Set classes) + { + int count = 0; + + Iterator iterator = classes.iterator(); + + while (iterator.hasNext()) + { + Clazz clazz = (Clazz)iterator.next(); + if (subClass.extendsOrImplements(clazz)) + { + count++; + } + } + + return count; + } + + + public int equal(TypedReferenceValue other) + { + return this.type == null && other.type == null ? ALWAYS : MAYBE; + } + + + // Implementations of binary ReferenceValue methods with + // IdentifiedReferenceValue arguments. + + public ReferenceValue generalize(IdentifiedReferenceValue other) + { + return generalize((TypedReferenceValue)other); + } + + + public int equal(IdentifiedReferenceValue other) + { + return equal((TypedReferenceValue)other); + } + + + // Implementations of binary ReferenceValue methods with + // ArrayReferenceValue arguments. + + public ReferenceValue generalize(ArrayReferenceValue other) + { + return generalize((TypedReferenceValue)other); + } + + + public int equal(ArrayReferenceValue other) + { + return equal((TypedReferenceValue)other); + } + + + // Implementations of binary ReferenceValue methods with + // IdentifiedArrayReferenceValue arguments. + + public ReferenceValue generalize(IdentifiedArrayReferenceValue other) + { + return generalize((ArrayReferenceValue)other); + } + + + public int equal(IdentifiedArrayReferenceValue other) + { + return equal((ArrayReferenceValue)other); + } + + + // Implementations of binary ReferenceValue methods with + // DetailedArrayReferenceValue arguments. + + public ReferenceValue generalize(DetailedArrayReferenceValue other) + { + return generalize((IdentifiedArrayReferenceValue)other); + } + + + public int equal(DetailedArrayReferenceValue other) + { + return equal((IdentifiedArrayReferenceValue)other); + } + + + // Implementations for Value. + + public boolean isParticular() + { + return type == null; + } + + + public final String internalType() + { + return + type == null ? ClassConstants.TYPE_JAVA_LANG_OBJECT : + ClassUtil.isInternalArrayType(type) ? type : + ClassConstants.TYPE_CLASS_START + + type + + ClassConstants.TYPE_CLASS_END; + } + + + // Implementations for Object. + + public boolean equals(Object object) + { + if (this == object) + { + return true; + } + + if (object == null || + this.getClass() != object.getClass()) + { + return false; + } + + TypedReferenceValue other = (TypedReferenceValue)object; + return this.type == null ? other.type == null : + (this.mayBeNull == other.mayBeNull && + this.type.equals(other.type)); + } + + + public int hashCode() + { + return this.getClass().hashCode() ^ + (type == null ? 0 : type.hashCode() ^ (mayBeNull ? 0 : 1)); + } + + + public String toString() + { + return type == null ? + "null" : + type + (referencedClass == null ? "?" : "") + (mayBeNull ? "" : "!"); + } +} diff --git a/src/proguard/evaluation/value/UnknownDoubleValue.java b/src/proguard/evaluation/value/UnknownDoubleValue.java index f8bad9a..ad2f511 100644 --- a/src/proguard/evaluation/value/UnknownDoubleValue.java +++ b/src/proguard/evaluation/value/UnknownDoubleValue.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 diff --git a/src/proguard/evaluation/value/UnknownFloatValue.java b/src/proguard/evaluation/value/UnknownFloatValue.java index 464ceed..f6f2047 100644 --- a/src/proguard/evaluation/value/UnknownFloatValue.java +++ b/src/proguard/evaluation/value/UnknownFloatValue.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 diff --git a/src/proguard/evaluation/value/UnknownIntegerValue.java b/src/proguard/evaluation/value/UnknownIntegerValue.java index b273b12..5c05721 100644 --- a/src/proguard/evaluation/value/UnknownIntegerValue.java +++ b/src/proguard/evaluation/value/UnknownIntegerValue.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 diff --git a/src/proguard/evaluation/value/UnknownLongValue.java b/src/proguard/evaluation/value/UnknownLongValue.java index ee315be..ced2d1f 100644 --- a/src/proguard/evaluation/value/UnknownLongValue.java +++ b/src/proguard/evaluation/value/UnknownLongValue.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 diff --git a/src/proguard/evaluation/value/Value.java b/src/proguard/evaluation/value/Value.java index f8d9327..5cfd02c 100644 --- a/src/proguard/evaluation/value/Value.java +++ b/src/proguard/evaluation/value/Value.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 @@ -45,7 +45,7 @@ public abstract class Value */ public Category1Value category1Value() { - throw new IllegalArgumentException("Value is not a Category 1 value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a Category 1 value [" + this.getClass().getName() + "]"); } /** @@ -53,7 +53,7 @@ public abstract class Value */ public Category2Value category2Value() { - throw new IllegalArgumentException("Value is not a Category 2 value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a Category 2 value [" + this.getClass().getName() + "]"); } @@ -62,7 +62,7 @@ public abstract class Value */ public IntegerValue integerValue() { - throw new IllegalArgumentException("Value is not an integer value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not an integer value [" + this.getClass().getName() + "]"); } /** @@ -70,7 +70,7 @@ public abstract class Value */ public LongValue longValue() { - throw new IllegalArgumentException("Value is not a long value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a long value [" + this.getClass().getName() + "]"); } /** @@ -78,7 +78,7 @@ public abstract class Value */ public FloatValue floatValue() { - throw new IllegalArgumentException("Value is not a float value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a float value [" + this.getClass().getName() + "]"); } /** @@ -86,7 +86,7 @@ public abstract class Value */ public DoubleValue doubleValue() { - throw new IllegalArgumentException("Value is not a double value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a double value [" + this.getClass().getName() + "]"); } /** @@ -94,7 +94,7 @@ public abstract class Value */ public ReferenceValue referenceValue() { - throw new IllegalArgumentException("Value is not a reference value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not a reference value [" + this.getClass().getName() + "]"); } /** @@ -102,7 +102,7 @@ public abstract class Value */ public InstructionOffsetValue instructionOffsetValue() { - throw new IllegalArgumentException("Value is not an instruction offset value [" + this.getClass().getName() + "]"); + throw new IllegalArgumentException("Value \"" + this.toString() + "\" is not an instruction offset value [" + this.getClass().getName() + "]"); } @@ -154,15 +154,15 @@ public abstract class Value /** * Returns the internal type of this Value. - * @return <code>ClassConstants.INTERNAL_TYPE_BOOLEAN</code>, - * <code>ClassConstants.INTERNAL_TYPE_BYTE</code>, - * <code>ClassConstants.INTERNAL_TYPE_CHAR</code>, - * <code>ClassConstants.INTERNAL_TYPE_SHORT</code>, - * <code>ClassConstants.INTERNAL_TYPE_INT</code>, - * <code>ClassConstants.INTERNAL_TYPE_LONG</code>, - * <code>ClassConstants.INTERNAL_TYPE_FLOAT</code>, - * <code>ClassConstants.INTERNAL_TYPE_DOUBLE</code>, - * <code>ClassConstants.INTERNAL_TYPE_CLASS_START ... ClassConstants.INTERNAL_TYPE_CLASS_END</code>, or + * @return <code>ClassConstants.TYPE_BOOLEAN</code>, + * <code>ClassConstants.TYPE_BYTE</code>, + * <code>ClassConstants.TYPE_CHAR</code>, + * <code>ClassConstants.TYPE_SHORT</code>, + * <code>ClassConstants.TYPE_INT</code>, + * <code>ClassConstants.TYPE_LONG</code>, + * <code>ClassConstants.TYPE_FLOAT</code>, + * <code>ClassConstants.TYPE_DOUBLE</code>, + * <code>ClassConstants.TYPE_CLASS_START ... ClassConstants.TYPE_CLASS_END</code>, or * an array type containing any of these types (always as String). */ public abstract String internalType(); diff --git a/src/proguard/evaluation/value/ValueFactory.java b/src/proguard/evaluation/value/ValueFactory.java index c94ac65..cb9e657 100644 --- a/src/proguard/evaluation/value/ValueFactory.java +++ b/src/proguard/evaluation/value/ValueFactory.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 @@ -36,9 +36,9 @@ public class ValueFactory static final FloatValue FLOAT_VALUE = new UnknownFloatValue(); static final DoubleValue DOUBLE_VALUE = new UnknownDoubleValue(); - static final ReferenceValue REFERENCE_VALUE_NULL = new ReferenceValue(null, null, true); - static final ReferenceValue REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL = new ReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT, null, true); - static final ReferenceValue REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL = new ReferenceValue(ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT, null, false); + static final ReferenceValue REFERENCE_VALUE_NULL = new TypedReferenceValue(null, null, true); + static final ReferenceValue REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL = new TypedReferenceValue(ClassConstants.NAME_JAVA_LANG_OBJECT, null, true); + static final ReferenceValue REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL = new TypedReferenceValue(ClassConstants.NAME_JAVA_LANG_OBJECT, null, false); /** @@ -50,20 +50,20 @@ public class ValueFactory { switch (type.charAt(0)) { - case ClassConstants.INTERNAL_TYPE_VOID: return null; - case ClassConstants.INTERNAL_TYPE_BOOLEAN: - case ClassConstants.INTERNAL_TYPE_BYTE: - case ClassConstants.INTERNAL_TYPE_CHAR: - case ClassConstants.INTERNAL_TYPE_SHORT: - case ClassConstants.INTERNAL_TYPE_INT: return createIntegerValue(); - case ClassConstants.INTERNAL_TYPE_LONG: return createLongValue(); - case ClassConstants.INTERNAL_TYPE_FLOAT: return createFloatValue(); - case ClassConstants.INTERNAL_TYPE_DOUBLE: return createDoubleValue(); - default: return createReferenceValue(ClassUtil.isInternalArrayType(type) ? - type : - ClassUtil.internalClassNameFromClassType(type), - referencedClass, - mayBeNull); + case ClassConstants.TYPE_VOID: return null; + case ClassConstants.TYPE_BOOLEAN: + case ClassConstants.TYPE_BYTE: + case ClassConstants.TYPE_CHAR: + case ClassConstants.TYPE_SHORT: + case ClassConstants.TYPE_INT: return createIntegerValue(); + case ClassConstants.TYPE_LONG: return createLongValue(); + case ClassConstants.TYPE_FLOAT: return createFloatValue(); + case ClassConstants.TYPE_DOUBLE: return createDoubleValue(); + default: return createReferenceValue(ClassUtil.isInternalArrayType(type) ? + type : + ClassUtil.internalClassNameFromClassType(type), + referencedClass, + mayBeNull); } } @@ -153,10 +153,10 @@ public class ValueFactory Clazz referencedClass, boolean mayBeNull) { - return type == null ? REFERENCE_VALUE_NULL : - !type.equals(ClassConstants.INTERNAL_NAME_JAVA_LANG_OBJECT) ? new ReferenceValue(type, referencedClass, mayBeNull) : - mayBeNull ? REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL : - REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL; + return type == null ? REFERENCE_VALUE_NULL : + !type.equals(ClassConstants.NAME_JAVA_LANG_OBJECT) ? new TypedReferenceValue(type, referencedClass, mayBeNull) : + mayBeNull ? REFERENCE_VALUE_JAVA_LANG_OBJECT_MAYBE_NULL : + REFERENCE_VALUE_JAVA_LANG_OBJECT_NOT_NULL; } @@ -169,24 +169,7 @@ public class ValueFactory Clazz referencedClass, IntegerValue arrayLength) { - return createArrayReferenceValue(type, - referencedClass, - arrayLength, - createValue(type, referencedClass, false)); - } - - - /** - * Creates a new ReferenceValue for arrays of the given type and length, - * containing the given element. The type must be a fully specified internal - * type for primitives, classes, or arrays. - */ - public ReferenceValue createArrayReferenceValue(String type, - Clazz referencedClass, - IntegerValue arrayLength, - Value elementValue) - { - return createReferenceValue(ClassConstants.INTERNAL_TYPE_ARRAY + type, + return createReferenceValue(ClassConstants.TYPE_ARRAY + type, referencedClass, false); } |