summaryrefslogtreecommitdiff
path: root/src/proguard/optimize/evaluation/SimpleEnumUseSimplifier.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/proguard/optimize/evaluation/SimpleEnumUseSimplifier.java')
-rw-r--r--src/proguard/optimize/evaluation/SimpleEnumUseSimplifier.java820
1 files changed, 0 insertions, 820 deletions
diff --git a/src/proguard/optimize/evaluation/SimpleEnumUseSimplifier.java b/src/proguard/optimize/evaluation/SimpleEnumUseSimplifier.java
deleted file mode 100644
index b5a2396..0000000
--- a/src/proguard/optimize/evaluation/SimpleEnumUseSimplifier.java
+++ /dev/null
@@ -1,820 +0,0 @@
-/*
- * 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.optimize.evaluation;
-
-import proguard.classfile.*;
-import proguard.classfile.attribute.*;
-import proguard.classfile.attribute.visitor.AttributeVisitor;
-import proguard.classfile.constant.*;
-import proguard.classfile.constant.visitor.ConstantVisitor;
-import proguard.classfile.editor.*;
-import proguard.classfile.instruction.*;
-import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.classfile.util.*;
-import proguard.classfile.visitor.*;
-import proguard.evaluation.value.*;
-import proguard.optimize.info.SimpleEnumMarker;
-
-/**
- * This AttributeVisitor simplifies the use of enums in the code attributes that
- * it visits.
- *
- * @see SimpleEnumMarker
- * @see MemberReferenceFixer
- * @author Eric Lafortune
- */
-public class SimpleEnumUseSimplifier
-extends SimplifiedVisitor
-implements AttributeVisitor,
- InstructionVisitor,
- ConstantVisitor,
- ParameterVisitor
-{
- //*
- private static final boolean DEBUG = false;
- /*/
- private static boolean DEBUG = System.getProperty("enum") != null;
- //*/
-
- private final InstructionVisitor extraInstructionVisitor;
-
- private final PartialEvaluator partialEvaluator;
- private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(true, true);
- private final ConstantVisitor nullParameterFixer = new ReferencedMemberVisitor(new AllParameterVisitor(this));
-
- // Fields acting as parameters and return values for the visitor methods.
- private Clazz invocationClazz;
- private Method invocationMethod;
- private CodeAttribute invocationCodeAttribute;
- private int invocationOffset;
- private boolean isSimpleEnum;
-
-
- /**
- * Creates a new SimpleEnumUseSimplifier.
- */
- public SimpleEnumUseSimplifier()
- {
- this(new PartialEvaluator(), null);
- }
-
-
- /**
- * Creates a new SimpleEnumDescriptorSimplifier.
- * @param partialEvaluator the partial evaluator that will
- * execute the code and provide
- * information about the results.
- * @param extraInstructionVisitor an optional extra visitor for all
- * simplified instructions.
- */
- public SimpleEnumUseSimplifier(PartialEvaluator partialEvaluator,
- InstructionVisitor extraInstructionVisitor)
- {
- this.partialEvaluator = partialEvaluator;
- this.extraInstructionVisitor = extraInstructionVisitor;
- }
-
-
- // Implementations for AttributeVisitor.
-
- public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
-
-
- public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
- {
- if (DEBUG)
- {
- System.out.println("SimpleEnumUseSimplifier: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
- }
-
- // Skip the non-static methods of simple enum classes.
- if (SimpleEnumMarker.isSimpleEnum(clazz) &&
- (method.getAccessFlags() & ClassConstants.ACC_STATIC) == 0)
- {
- return;
- }
-
- // Evaluate the method.
- partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
-
- int codeLength = codeAttribute.u4codeLength;
-
- // Reset the code changes.
- codeAttributeEditor.reset(codeLength);
-
- // Replace any instructions that can be simplified.
- for (int offset = 0; offset < codeLength; offset++)
- {
- if (partialEvaluator.isTraced(offset))
- {
- Instruction instruction = InstructionFactory.create(codeAttribute.code,
- offset);
-
- instruction.accept(clazz, method, codeAttribute, offset, this);
- }
- }
-
- // Apply all accumulated changes to the code.
- codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute);
- }
-
-
- // Implementations for InstructionVisitor.
-
- public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
- {
- switch (simpleInstruction.opcode)
- {
- case InstructionConstants.OP_AALOAD:
- {
- if (isPushingSimpleEnum(offset))
- {
- // Load a simple enum integer from an integer array.
- replaceInstruction(clazz,
- offset,
- simpleInstruction,
- new SimpleInstruction(
- InstructionConstants.OP_IALOAD));
- }
- break;
- }
- case InstructionConstants.OP_AASTORE:
- {
- if (isPoppingSimpleEnumArray(offset, 2))
- {
- // Store a simple enum integer in an integer array.
- replaceInstruction(clazz,
- offset,
- simpleInstruction,
- new SimpleInstruction(InstructionConstants.OP_IASTORE));
-
- // Replace any producers of null constants.
- replaceNullStackEntryProducers(clazz, method, codeAttribute, offset);
- }
- break;
- }
- case InstructionConstants.OP_ARETURN:
- {
- if (isReturningSimpleEnum(clazz, method))
- {
- // Return a simple enum integer instead of an enum.
- replaceInstruction(clazz,
- offset,
- simpleInstruction,
- new SimpleInstruction(InstructionConstants.OP_IRETURN));
-
- // Replace any producers of null constants.
- replaceNullStackEntryProducers(clazz, method, codeAttribute, offset);
- }
- break;
- }
- }
- }
-
-
- public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
- {
- int variableIndex = variableInstruction.variableIndex;
-
- switch (variableInstruction.opcode)
- {
- case InstructionConstants.OP_ALOAD:
- case InstructionConstants.OP_ALOAD_0:
- case InstructionConstants.OP_ALOAD_1:
- case InstructionConstants.OP_ALOAD_2:
- case InstructionConstants.OP_ALOAD_3:
- {
- if (isPushingSimpleEnum(offset))
- {
- // Load a simple enum integer instead of an enum.
- replaceInstruction(clazz,
- offset,
- variableInstruction,
- new VariableInstruction(InstructionConstants.OP_ILOAD,
- variableIndex));
-
- // Replace any producers of null constants.
- replaceNullVariableProducers(clazz,
- method,
- codeAttribute,
- offset,
- variableIndex);
- }
- break;
- }
- case InstructionConstants.OP_ASTORE:
- case InstructionConstants.OP_ASTORE_0:
- case InstructionConstants.OP_ASTORE_1:
- case InstructionConstants.OP_ASTORE_2:
- case InstructionConstants.OP_ASTORE_3:
- {
- if (!partialEvaluator.isSubroutineStart(offset) &&
- isPoppingSimpleEnum(offset))
- {
- // Store a simple enum integer instead of an enum.
- replaceInstruction(clazz,
- offset,
- variableInstruction,
- new VariableInstruction(InstructionConstants.OP_ISTORE,
- variableIndex));
-
- // Replace any producers of null constants.
- replaceNullStackEntryProducers(clazz, method, codeAttribute, offset);
- }
- break;
- }
- }
- }
-
-
- public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
- {
- switch (constantInstruction.opcode)
- {
- case InstructionConstants.OP_PUTSTATIC:
- case InstructionConstants.OP_PUTFIELD:
- {
- // Replace any producers of null constants.
- invocationClazz = clazz;
- invocationMethod = method;
- invocationCodeAttribute = codeAttribute;
- invocationOffset = offset;
- clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
- nullParameterFixer);
- break;
- }
- case InstructionConstants.OP_INVOKEVIRTUAL:
- {
- // Check if the instruction is calling a simple enum.
- String invokedMethodName =
- clazz.getRefName(constantInstruction.constantIndex);
- String invokedMethodType =
- clazz.getRefType(constantInstruction.constantIndex);
- int stackEntryIndex =
- ClassUtil.internalMethodParameterSize(invokedMethodType);
- if (isPoppingSimpleEnum(offset, stackEntryIndex))
- {
- replaceSupportedMethod(clazz,
- offset,
- constantInstruction,
- invokedMethodName,
- invokedMethodType);
- }
-
- // Fall through to check the parameters.
- }
- case InstructionConstants.OP_INVOKESPECIAL:
- case InstructionConstants.OP_INVOKESTATIC:
- case InstructionConstants.OP_INVOKEINTERFACE:
- {
- // Replace any producers of null constants.
- invocationClazz = clazz;
- invocationMethod = method;
- invocationCodeAttribute = codeAttribute;
- invocationOffset = offset;
- clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
- nullParameterFixer);
- break;
- }
- case InstructionConstants.OP_ANEWARRAY:
- {
- int constantIndex = constantInstruction.constantIndex;
-
- if (isReferencingSimpleEnum(clazz, constantIndex) &&
- !ClassUtil.isInternalArrayType(clazz.getClassName(constantIndex)))
- {
- // Create an integer array instead of an enum array.
- replaceInstruction(clazz,
- offset,
- constantInstruction,
- new SimpleInstruction(InstructionConstants.OP_NEWARRAY,
- InstructionConstants.ARRAY_T_INT));
- }
- break;
- }
- case InstructionConstants.OP_CHECKCAST:
- {
- if (isPoppingSimpleEnum(offset))
- {
- // Enum classes can only be simple if the checkcast
- // succeeds, so we can delete it.
- deleteInstruction(clazz,
- offset,
- constantInstruction);
-
- // Replace any producers of null constants.
- replaceNullStackEntryProducers(clazz, method, codeAttribute, offset);
- }
- break;
- }
- case InstructionConstants.OP_INSTANCEOF:
- {
- if (isPoppingSimpleEnum(offset))
- {
- // Enum classes can only be simple if the instanceof
- // succeeds, so we can push a constant result.
- replaceInstruction(clazz,
- offset,
- constantInstruction,
- new SimpleInstruction(InstructionConstants.OP_ICONST_1));
-
- // Replace any producers of null constants.
- replaceNullStackEntryProducers(clazz, method, codeAttribute, offset);
- }
- break;
- }
- }
- }
-
-
- public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
- {
- switch (branchInstruction.opcode)
- {
- case InstructionConstants.OP_IFACMPEQ:
- {
- if (isPoppingSimpleEnum(offset))
- {
- // Compare simple enum integers instead of enums.
- replaceInstruction(clazz,
- offset,
- branchInstruction,
- new BranchInstruction(InstructionConstants.OP_IFICMPEQ,
- branchInstruction.branchOffset));
- }
- break;
- }
- case InstructionConstants.OP_IFACMPNE:
- {
- if (isPoppingSimpleEnum(offset))
- {
- // Compare simple enum integers instead of enums.
- replaceInstruction(clazz,
- offset,
- branchInstruction,
- new BranchInstruction(InstructionConstants.OP_IFICMPNE,
- branchInstruction.branchOffset));
- }
- break;
- }
- case InstructionConstants.OP_IFNULL:
- {
- if (isPoppingSimpleEnum(offset))
- {
- // Compare with 0 instead of null.
- replaceInstruction(clazz,
- offset,
- branchInstruction,
- new BranchInstruction(
- InstructionConstants.OP_IFEQ,
- branchInstruction.branchOffset));
- }
- break;
- }
- case InstructionConstants.OP_IFNONNULL:
- {
- if (isPoppingSimpleEnum(offset))
- {
- // Compare with 0 instead of null.
- replaceInstruction(clazz,
- offset,
- branchInstruction,
- new BranchInstruction(InstructionConstants.OP_IFNE,
- branchInstruction.branchOffset));
- }
- break;
- }
- }
- }
-
-
- public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
- {
- }
-
-
- // Implementations for ConstantVisitor.
-
- public void visitAnyConstant(Clazz clazz, Constant constant) {}
-
-
- public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
- {
- // Does the constant refer to a simple enum type?
- isSimpleEnum = isSimpleEnum(stringConstant.referencedClass);
- }
-
-
- public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
- {
- // Does the constant refer to a simple enum type?
- isSimpleEnum = isSimpleEnum(classConstant.referencedClass);
- }
-
-
- // Implementations for ParameterVisitor.
-
- public void visitParameter(Clazz clazz, Member member, int parameterIndex, int parameterCount, int parameterOffset, int parameterSize, String parameterType, Clazz referencedClass)
- {
- // Check if the parameter is passing a simple enum as a more general
- // type.
- if (!ClassUtil.isInternalPrimitiveType(parameterType.charAt(0)) &&
- isSimpleEnum(referencedClass))
- {
- // Replace any producers of null constants for this parameter.
- int stackEntryIndex = parameterSize - parameterOffset - 1;
-
- replaceNullStackEntryProducers(invocationClazz,
- invocationMethod,
- invocationCodeAttribute,
- invocationOffset,
- stackEntryIndex);
- }
- }
-
-
- // Small utility methods.
-
- /**
- * Returns whether the constant at the given offset is referencing a
- * simple enum class.
- */
- private boolean isReferencingSimpleEnum(Clazz clazz, int constantIndex)
- {
- isSimpleEnum = false;
-
- clazz.constantPoolEntryAccept(constantIndex, this);
-
- return isSimpleEnum;
- }
-
-
- /**
- * Returns whether the given method is returning a simple enum class.
- */
- private boolean isReturningSimpleEnum(Clazz clazz, Method method)
- {
- String descriptor = method.getDescriptor(clazz);
- String returnType = ClassUtil.internalMethodReturnType(descriptor);
-
- if (ClassUtil.isInternalClassType(returnType) &&
- !ClassUtil.isInternalArrayType(returnType))
- {
- Clazz[] referencedClasses =
- ((ProgramMethod)method).referencedClasses;
-
- if (referencedClasses != null)
- {
- int returnedClassIndex =
- new DescriptorClassEnumeration(descriptor).classCount() - 1;
-
- Clazz returnedClass = referencedClasses[returnedClassIndex];
-
- return isSimpleEnum(returnedClass);
- }
- }
-
- return false;
- }
-
-
- /**
- * Returns whether the instruction at the given offset is pushing a simple
- * enum class.
- */
- private boolean isPushingSimpleEnum(int offset)
- {
- ReferenceValue referenceValue =
- partialEvaluator.getStackAfter(offset).getTop(0).referenceValue();
-
- Clazz referencedClass = referenceValue.getReferencedClass();
-
- return isSimpleEnum(referencedClass) &&
- !ClassUtil.isInternalArrayType(referenceValue.getType());
- }
-
-
- /**
- * Returns whether the instruction at the given offset is popping a simple
- * enum class.
- */
- private boolean isPoppingSimpleEnum(int offset)
- {
- return isPoppingSimpleEnum(offset, 0);
- }
-
-
- /**
- * Returns whether the instruction at the given offset is popping a simple
- * enum class.
- */
- private boolean isPoppingSimpleEnum(int offset, int stackEntryIndex)
- {
- ReferenceValue referenceValue =
- partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue();
-
- return isSimpleEnum(referenceValue.getReferencedClass()) &&
- !ClassUtil.isInternalArrayType(referenceValue.getType());
- }
-
-
- /**
- * Returns whether the instruction at the given offset is popping a simple
- * enum type. This includes simple enum arrays.
- */
- private boolean isPoppingSimpleEnumType(int offset, int stackEntryIndex)
- {
- ReferenceValue referenceValue =
- partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue();
-
- return isSimpleEnum(referenceValue.getReferencedClass());
- }
-
-
- /**
- * Returns whether the instruction at the given offset is popping a
- * one-dimensional simple enum array.
- */
- private boolean isPoppingSimpleEnumArray(int offset, int stackEntryIndex)
- {
- ReferenceValue referenceValue =
- partialEvaluator.getStackBefore(offset).getTop(stackEntryIndex).referenceValue();
-
- return isSimpleEnum(referenceValue.getReferencedClass()) &&
- ClassUtil.internalArrayTypeDimensionCount(referenceValue.getType()) == 1;
- }
-
-
- /**
- * Returns whether the given class is not null and a simple enum class.
- */
- private boolean isSimpleEnum(Clazz clazz)
- {
- return clazz != null &&
- SimpleEnumMarker.isSimpleEnum(clazz);
- }
-
-
- /**
- * Returns whether the specified enum method is supported for simple enums.
- */
- private void replaceSupportedMethod(Clazz clazz,
- int offset,
- Instruction instruction,
- String name,
- String type)
- {
- if (name.equals(ClassConstants.METHOD_NAME_ORDINAL) &&
- type.equals(ClassConstants.METHOD_TYPE_ORDINAL))
- {
- Instruction[] replacementInstructions = new Instruction[]
- {
- new SimpleInstruction(InstructionConstants.OP_ICONST_1),
- new SimpleInstruction(InstructionConstants.OP_ISUB),
- };
-
- replaceInstructions(clazz,
- offset,
- instruction,
- replacementInstructions);
- }
- }
-
-
- /**
- * Replaces the instruction at the given offset by the given instructions.
- */
- private void replaceInstructions(Clazz clazz,
- int offset,
- Instruction instruction,
- Instruction[] replacementInstructions)
- {
- if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(offset)+" -> "+replacementInstructions.length+" instructions");
-
- codeAttributeEditor.replaceInstruction(offset, replacementInstructions);
-
- // Visit the instruction, if required.
- if (extraInstructionVisitor != null)
- {
- // Note: we're not passing the right arguments for now, knowing that
- // they aren't used anyway.
- instruction.accept(clazz, null, null, offset, extraInstructionVisitor);
- }
- }
-
-
- /**
- * Replaces the instruction at the given offset by the given instruction,
- * popping any now unused stack entries.
- */
- private void replaceInstruction(Clazz clazz,
- int offset,
- Instruction instruction,
- Instruction replacementInstruction)
- {
- // Pop unneeded stack entries if necessary.
- int popCount =
- instruction.stackPopCount(clazz) -
- replacementInstruction.stackPopCount(clazz);
-
- insertPopInstructions(offset, popCount);
-
- if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(offset)+" -> "+replacementInstruction.toString()+(popCount == 0 ? "" : " ("+popCount+" pops)"));
-
- codeAttributeEditor.replaceInstruction(offset, replacementInstruction);
-
- // Visit the instruction, if required.
- if (extraInstructionVisitor != null)
- {
- // Note: we're not passing the right arguments for now, knowing that
- // they aren't used anyway.
- instruction.accept(clazz, null, null, offset, extraInstructionVisitor);
- }
- }
-
-
- /**
- * Deletes the instruction at the given offset, popping any now unused
- * stack entries.
- */
- private void deleteInstruction(Clazz clazz,
- int offset,
- Instruction instruction)
- {
- // Pop unneeded stack entries if necessary.
- //int popCount = instruction.stackPopCount(clazz);
- //
- //insertPopInstructions(offset, popCount);
- //
- //if (DEBUG) System.out.println(" Deleting instruction "+instruction.toString(offset)+(popCount == 0 ? "" : " ("+popCount+" pops)"));
-
- if (DEBUG) System.out.println(" Deleting instruction "+instruction.toString(offset));
-
- codeAttributeEditor.deleteInstruction(offset);
-
- // Visit the instruction, if required.
- if (extraInstructionVisitor != null)
- {
- // Note: we're not passing the right arguments for now, knowing that
- // they aren't used anyway.
- instruction.accept(clazz, null, null, offset, extraInstructionVisitor);
- }
- }
-
-
- /**
- * Pops the given number of stack entries before the instruction at the
- * given offset.
- */
- private void insertPopInstructions(int offset, int popCount)
- {
- switch (popCount)
- {
- case 0:
- {
- break;
- }
- case 1:
- {
- // Insert a single pop instruction.
- Instruction popInstruction =
- new SimpleInstruction(InstructionConstants.OP_POP);
-
- codeAttributeEditor.insertBeforeInstruction(offset,
- popInstruction);
- break;
- }
- case 2:
- {
- // Insert a single pop2 instruction.
- Instruction popInstruction =
- new SimpleInstruction(InstructionConstants.OP_POP2);
-
- codeAttributeEditor.insertBeforeInstruction(offset,
- popInstruction);
- break;
- }
- default:
- {
- // Insert the specified number of pop instructions.
- Instruction[] popInstructions =
- new Instruction[popCount / 2 + popCount % 2];
-
- Instruction popInstruction =
- new SimpleInstruction(InstructionConstants.OP_POP2);
-
- for (int index = 0; index < popCount / 2; index++)
- {
- popInstructions[index] = popInstruction;
- }
-
- if (popCount % 2 == 1)
- {
- popInstruction =
- new SimpleInstruction(InstructionConstants.OP_POP);
-
- popInstructions[popCount / 2] = popInstruction;
- }
-
- codeAttributeEditor.insertBeforeInstruction(offset,
- popInstructions);
- break;
- }
- }
- }
-
-
- /**
- * Replaces aconst_null producers of the consumer of the top stack entry
- * at the given offset by iconst_0.
- */
- private void replaceNullStackEntryProducers(Clazz clazz,
- Method method,
- CodeAttribute codeAttribute,
- int consumerOffset)
- {
- replaceNullStackEntryProducers(clazz, method, codeAttribute, consumerOffset, 0);
- }
-
-
- /**
- * Replaces aconst_null producers of the specified stack entry by
- * iconst_0.
- */
- private void replaceNullStackEntryProducers(Clazz clazz,
- Method method,
- CodeAttribute codeAttribute,
- int consumerOffset,
- int stackEntryIndex)
- {
- InstructionOffsetValue producerOffsets =
- partialEvaluator.getStackBefore(consumerOffset).getTopActualProducerValue(stackEntryIndex).instructionOffsetValue();
-
- for (int index = 0; index < producerOffsets.instructionOffsetCount(); index++)
- {
- int producerOffset = producerOffsets.instructionOffset(index);
-
- // TODO: A method might be pushing the null constant.
- if (producerOffset >= 0 &&
- codeAttribute.code[producerOffset] == InstructionConstants.OP_ACONST_NULL)
- {
- // Replace pushing null by pushing 0.
- replaceInstruction(clazz,
- producerOffset,
- new SimpleInstruction(InstructionConstants.OP_ACONST_NULL),
- new SimpleInstruction(InstructionConstants.OP_ICONST_0));
- }
- }
- }
-
-
- /**
- * Replaces aconst_null/astore producers of the specified reference variable by
- * iconst_0/istore.
- */
- private void replaceNullVariableProducers(Clazz clazz,
- Method method,
- CodeAttribute codeAttribute,
- int consumerOffset,
- int variableIndex)
- {
- InstructionOffsetValue producerOffsets =
- partialEvaluator.getVariablesBefore(consumerOffset).getProducerValue(variableIndex).instructionOffsetValue();
-
- for (int index = 0; index < producerOffsets.instructionOffsetCount(); index++)
- {
- int producerOffset = producerOffsets.instructionOffset(index);
-
- if (producerOffset >= 0 &&
- partialEvaluator.getVariablesAfter(producerOffset).getValue(variableIndex).referenceValue().isNull() == Value.ALWAYS)
- {
- // Replace loading null by loading 0.
- replaceInstruction(clazz,
- producerOffset,
- new VariableInstruction(InstructionConstants.OP_ASTORE, variableIndex),
- new VariableInstruction(InstructionConstants.OP_ISTORE, variableIndex));
-
- // Replace pushing null by pushing 0.
- replaceNullStackEntryProducers(clazz, method, codeAttribute, producerOffset);
- }
- }
- }
-}