/*
 * 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);
            }
        }
    }
}
