proguard.evaluation.TracedVariables Java Examples

The following examples show how to use proguard.evaluation.TracedVariables. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 6 votes vote down vote up
/**
 * Evaluates the instruction block and the exception handlers covering the
 * given instruction range in the given code.
 */
private void evaluateInstructionBlockAndExceptionHandlers(Clazz           clazz,
                                                          Method          method,
                                                          CodeAttribute codeAttribute,
                                                          TracedVariables variables,
                                                          TracedStack     stack,
                                                          int             startOffset,
                                                          int             endOffset)
{
    evaluateInstructionBlock(clazz,
                             method,
                             codeAttribute,
                             variables,
                             stack,
                             startOffset);

    evaluateExceptionHandlers(clazz,
                              method,
                              codeAttribute,
                              startOffset,
                              endOffset);
}
 
Example #2
Source File: EvaluationShrinker.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
/**
 * Marks the variable and the corresponding producing instructions
 * of the consumer at the given offset.
 * @param consumerOffset the offset of the consumer.
 * @param variableIndex  the index of the variable to be marked.
 */
private void markVariableProducers(int consumerOffset,
                                   int variableIndex)
{
    TracedVariables tracedVariables =
        partialEvaluator.getVariablesBefore(consumerOffset);

    // Mark the producer of the loaded value.
    markVariableProducers(tracedVariables.getProducerValue(variableIndex).instructionOffsetValue(),
                          variableIndex);
}
 
Example #3
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
/**
 * Pushes block of instructions to be executed in the calling partial
 * evaluator.
 */
private void pushCallingInstructionBlock(TracedVariables variables,
                                         TracedStack     stack,
                                         int             startOffset)
{
    callingInstructionBlockStack.push(new MyInstructionBlock(variables,
                                                             stack,
                                                             startOffset));
}
 
Example #4
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
/**
 * Pushes block of instructions to be executed in this partial evaluator.
 */
private void pushInstructionBlock(TracedVariables variables,
                                  TracedStack     stack,
                                  int             startOffset)
{
    instructionBlockStack.push(new MyInstructionBlock(variables,
                                                      stack,
                                                      startOffset));
}
 
Example #5
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
/**
 * Evaluates a block of instructions, starting at the given offset and ending
 * at a branch instruction, a return instruction, or a throw instruction.
 */
private void evaluateInstructionBlock(Clazz           clazz,
                                      Method          method,
                                      CodeAttribute codeAttribute,
                                      TracedVariables variables,
                                      TracedStack     stack,
                                      int             startOffset)
{
    // Execute the initial instruction block.
    evaluateSingleInstructionBlock(clazz,
                                   method,
                                   codeAttribute,
                                   variables,
                                   stack,
                                   startOffset);

    // Execute all resulting instruction blocks on the execution stack.
    while (!instructionBlockStack.empty())
    {
        if (DEBUG) System.out.println("Popping alternative branch out of "+instructionBlockStack.size()+" blocks");

        MyInstructionBlock instructionBlock =
            (MyInstructionBlock)instructionBlockStack.pop();

        evaluateSingleInstructionBlock(clazz,
                                       method,
                                       codeAttribute,
                                       instructionBlock.variables,
                                       instructionBlock.stack,
                                       instructionBlock.startOffset);
    }
}
 
Example #6
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
/**
 * Initializes the data structures for the variables, stack, etc.
 */
private void initializeParameters(Clazz           clazz,
                                  Method          method,
                                  CodeAttribute codeAttribute,
                                  TracedVariables variables)
{
    // Create the method parameters.
    TracedVariables parameters = new TracedVariables(codeAttribute.u2maxLocals);

    // Remember this instruction's offset with any stored value.
    Value storeValue = new InstructionOffsetValue(AT_METHOD_ENTRY);
    parameters.setProducerValue(storeValue);

    // Initialize the method parameters.
    invocationUnit.enterMethod(clazz, method, parameters);

    if (DEBUG)
    {
        System.out.println("  Params: "+parameters);
    }

    // Initialize the variables with the parameters.
    variables.initialize(parameters);

    // Set the store value of each parameter variable.
    InstructionOffsetValue atMethodEntry = new InstructionOffsetValue(AT_METHOD_ENTRY);

    for (int index = 0; index < parameters.size(); index++)
    {
        variables.setProducerValue(index, atMethodEntry);
    }
}
 
Example #7
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 5 votes vote down vote up
private MyInstructionBlock(TracedVariables variables,
                           TracedStack     stack,
                           int             startOffset)
{
    this.variables   = variables;
    this.stack       = stack;
    this.startOffset = startOffset;
}
 
Example #8
Source File: EvaluationSimplifier.java    From bazel with Apache License 2.0 4 votes vote down vote up
/**
 * Replaces the double pushing instruction at the given offset by a simpler
 * push instruction, if possible.
 */
private void replaceDoublePushInstruction(Clazz       clazz,
                                          int         offset,
                                          Instruction instruction,
                                          int         maxVariableIndex)
{
    Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
    if (pushedValue.isParticular())
    {
        // Push a constant instead.
        // Make sure to distinguish between +0.0 and -0.0.
        double value = pushedValue.doubleValue().value();
        if (value == 0.0 && Double.doubleToLongBits(value) == POS_ZERO_DOUBLE_BITS ||
            value == 1.0)
        {
            replaceConstantPushInstruction(clazz,
                                           offset,
                                           instruction,
                                           InstructionConstants.OP_DCONST_0,
                                           (int)value);
        }
        else
        {
            ConstantPoolEditor constantPoolEditor =
                new ConstantPoolEditor((ProgramClass)clazz);

            Instruction replacementInstruction =
                new ConstantInstruction(InstructionConstants.OP_LDC2_W,
                                        constantPoolEditor.addDoubleConstant(value));

            replaceInstruction(clazz, offset, instruction, replacementInstruction);
        }
    }
    else if (pushedValue.isSpecific())
    {
        // Load an equivalent lower-numbered variable instead, if any.
        TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
        for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
        {
            // Note that we have to check the second part as well.
            if (pushedValue.equals(variables.load(variableIndex)) &&
                variables.load(variableIndex + 1) != null         &&
                variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP)
            {
                replaceVariablePushInstruction(clazz,
                                               offset,
                                               instruction,
                                               InstructionConstants.OP_DLOAD,
                                               variableIndex);
            }
        }
    }
}
 
Example #9
Source File: EvaluationSimplifier.java    From bazel with Apache License 2.0 4 votes vote down vote up
/**
 * Replaces the float pushing instruction at the given offset by a simpler
 * push instruction, if possible.
 */
private void replaceFloatPushInstruction(Clazz       clazz,
                                         int         offset,
                                         Instruction instruction,
                                         int         maxVariableIndex)
{
    Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
    if (pushedValue.isParticular())
    {
        // Push a constant instead.
        // Make sure to distinguish between +0.0 and -0.0.
        float value = pushedValue.floatValue().value();
        if (value == 0.0f && Float.floatToIntBits(value) == POS_ZERO_FLOAT_BITS ||
            value == 1.0f ||
            value == 2.0f)
        {
            replaceConstantPushInstruction(clazz,
                                           offset,
                                           instruction,
                                           InstructionConstants.OP_FCONST_0,
                                           (int)value);
        }
        else
        {
            ConstantPoolEditor constantPoolEditor =
                new ConstantPoolEditor((ProgramClass)clazz);

            Instruction replacementInstruction =
                new ConstantInstruction(InstructionConstants.OP_LDC,
                                        constantPoolEditor.addFloatConstant(value));

            replaceInstruction(clazz, offset, instruction, replacementInstruction);
        }
    }
    else if (pushedValue.isSpecific())
    {
        // Load an equivalent lower-numbered variable instead, if any.
        TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
        for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
        {
            if (pushedValue.equals(variables.load(variableIndex)))
            {
                replaceVariablePushInstruction(clazz,
                                               offset,
                                               instruction,
                                               InstructionConstants.OP_FLOAD,
                                               variableIndex);
            }
        }
    }
}
 
Example #10
Source File: EvaluationSimplifier.java    From bazel with Apache License 2.0 4 votes vote down vote up
/**
 * Replaces the long pushing instruction at the given offset by a simpler
 * push instruction, if possible.
 */
private void replaceLongPushInstruction(Clazz       clazz,
                                        int         offset,
                                        Instruction instruction,
                                        int         maxVariableIndex)
{
    Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
    if (pushedValue.isParticular())
    {
        // Push a constant instead.
        long value = pushedValue.longValue().value();
        if (value == 0L ||
            value == 1L)
        {
            replaceConstantPushInstruction(clazz,
                                   offset,
                                   instruction,
                                   InstructionConstants.OP_LCONST_0,
                                   (int)value);
        }
        else
        {
            ConstantPoolEditor constantPoolEditor =
                new ConstantPoolEditor((ProgramClass)clazz);

            Instruction replacementInstruction =
                new ConstantInstruction(InstructionConstants.OP_LDC2_W,
                                        constantPoolEditor.addLongConstant(value));

            replaceInstruction(clazz, offset, instruction, replacementInstruction);
        }
    }
    else if (pushedValue.isSpecific())
    {
        // Load an equivalent lower-numbered variable instead, if any.
        TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
        for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
        {
            // Note that we have to check the second part as well.
            if (pushedValue.equals(variables.load(variableIndex)) &&
                variables.load(variableIndex + 1) != null         &&
                variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP)
            {
                replaceVariablePushInstruction(clazz,
                                               offset,
                                               instruction,
                                               InstructionConstants.OP_LLOAD,
                                               variableIndex);
            }
        }
    }
}
 
Example #11
Source File: EvaluationSimplifier.java    From bazel with Apache License 2.0 4 votes vote down vote up
/**
 * Replaces the integer pushing instruction at the given offset by a simpler
 * push instruction, if possible.
 */
private void replaceIntegerPushInstruction(Clazz       clazz,
                                           int         offset,
                                           Instruction instruction,
                                           int         maxVariableIndex)
{
    Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
    if (pushedValue.isParticular())
    {
        // Push a constant instead.
        int value = pushedValue.integerValue().value();
        if ((short)value == value)
        {
            replaceConstantPushInstruction(clazz,
                                           offset,
                                           instruction,
                                           InstructionConstants.OP_SIPUSH,
                                           value);
        }
        else
        {
            ConstantPoolEditor constantPoolEditor =
                new ConstantPoolEditor((ProgramClass)clazz);

            Instruction replacementInstruction =
                new ConstantInstruction(InstructionConstants.OP_LDC,
                                        constantPoolEditor.addIntegerConstant(value));

            replaceInstruction(clazz, offset, instruction, replacementInstruction);
        }
    }
    else if (pushedValue.isSpecific())
    {
        // Load an equivalent lower-numbered variable instead, if any.
        TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
        for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
        {
            if (pushedValue.equals(variables.load(variableIndex)))
            {
                replaceVariablePushInstruction(clazz,
                                               offset,
                                               instruction,
                                               InstructionConstants.OP_ILOAD,
                                               variableIndex);
                break;
            }
        }
    }
}
 
Example #12
Source File: EvaluationSimplifier.java    From proguard with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Replaces the double pushing instruction at the given offset by a simpler
 * push instruction, if possible.
 */
private void replaceDoublePushInstruction(Clazz       clazz,
                                          int         offset,
                                          Instruction instruction,
                                          int         maxVariableIndex)
{
    Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
    if (pushedValue.isParticular())
    {
        // Push a constant instead.
        // Make sure to distinguish between +0.0 and -0.0.
        double value = pushedValue.doubleValue().value();
        if (value == 0.0 && Double.doubleToLongBits(value) == POS_ZERO_DOUBLE_BITS ||
            value == 1.0)
        {
            replaceConstantPushInstruction(clazz,
                                           offset,
                                           instruction,
                                           InstructionConstants.OP_DCONST_0,
                                           (int)value);
        }
        else
        {
            ConstantPoolEditor constantPoolEditor =
                new ConstantPoolEditor((ProgramClass)clazz);

            Instruction replacementInstruction =
                new ConstantInstruction(InstructionConstants.OP_LDC2_W,
                                        constantPoolEditor.addDoubleConstant(value));

            replaceInstruction(clazz, offset, instruction, replacementInstruction);
        }
    }
    else if (pushedValue.isSpecific())
    {
        // Load an equivalent lower-numbered variable instead, if any.
        TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
        for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
        {
            // Note that we have to check the second part as well.
            if (pushedValue.equals(variables.load(variableIndex)) &&
                variables.load(variableIndex + 1) != null         &&
                variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP)
            {
                replaceVariablePushInstruction(clazz,
                                               offset,
                                               instruction,
                                               InstructionConstants.OP_DLOAD,
                                               variableIndex);
            }
        }
    }
}
 
Example #13
Source File: EvaluationSimplifier.java    From proguard with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Replaces the float pushing instruction at the given offset by a simpler
 * push instruction, if possible.
 */
private void replaceFloatPushInstruction(Clazz       clazz,
                                         int         offset,
                                         Instruction instruction,
                                         int         maxVariableIndex)
{
    Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
    if (pushedValue.isParticular())
    {
        // Push a constant instead.
        // Make sure to distinguish between +0.0 and -0.0.
        float value = pushedValue.floatValue().value();
        if (value == 0.0f && Float.floatToIntBits(value) == POS_ZERO_FLOAT_BITS ||
            value == 1.0f ||
            value == 2.0f)
        {
            replaceConstantPushInstruction(clazz,
                                           offset,
                                           instruction,
                                           InstructionConstants.OP_FCONST_0,
                                           (int)value);
        }
        else
        {
            ConstantPoolEditor constantPoolEditor =
                new ConstantPoolEditor((ProgramClass)clazz);

            Instruction replacementInstruction =
                new ConstantInstruction(InstructionConstants.OP_LDC,
                                        constantPoolEditor.addFloatConstant(value));

            replaceInstruction(clazz, offset, instruction, replacementInstruction);
        }
    }
    else if (pushedValue.isSpecific())
    {
        // Load an equivalent lower-numbered variable instead, if any.
        TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
        for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
        {
            if (pushedValue.equals(variables.load(variableIndex)))
            {
                replaceVariablePushInstruction(clazz,
                                               offset,
                                               instruction,
                                               InstructionConstants.OP_FLOAD,
                                               variableIndex);
            }
        }
    }
}
 
Example #14
Source File: EvaluationSimplifier.java    From proguard with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Replaces the long pushing instruction at the given offset by a simpler
 * push instruction, if possible.
 */
private void replaceLongPushInstruction(Clazz       clazz,
                                        int         offset,
                                        Instruction instruction,
                                        int         maxVariableIndex)
{
    Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
    if (pushedValue.isParticular())
    {
        // Push a constant instead.
        long value = pushedValue.longValue().value();
        if (value == 0L ||
            value == 1L)
        {
            replaceConstantPushInstruction(clazz,
                                   offset,
                                   instruction,
                                   InstructionConstants.OP_LCONST_0,
                                   (int)value);
        }
        else
        {
            ConstantPoolEditor constantPoolEditor =
                new ConstantPoolEditor((ProgramClass)clazz);

            Instruction replacementInstruction =
                new ConstantInstruction(InstructionConstants.OP_LDC2_W,
                                        constantPoolEditor.addLongConstant(value));

            replaceInstruction(clazz, offset, instruction, replacementInstruction);
        }
    }
    else if (pushedValue.isSpecific())
    {
        // Load an equivalent lower-numbered variable instead, if any.
        TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
        for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
        {
            // Note that we have to check the second part as well.
            if (pushedValue.equals(variables.load(variableIndex)) &&
                variables.load(variableIndex + 1) != null         &&
                variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP)
            {
                replaceVariablePushInstruction(clazz,
                                               offset,
                                               instruction,
                                               InstructionConstants.OP_LLOAD,
                                               variableIndex);
            }
        }
    }
}
 
Example #15
Source File: EvaluationSimplifier.java    From proguard with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Replaces the integer pushing instruction at the given offset by a simpler
 * push instruction, if possible.
 */
private void replaceIntegerPushInstruction(Clazz       clazz,
                                           int         offset,
                                           Instruction instruction,
                                           int         maxVariableIndex)
{
    Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
    if (pushedValue.isParticular())
    {
        // Push a constant instead.
        int value = pushedValue.integerValue().value();
        if ((short)value == value)
        {
            replaceConstantPushInstruction(clazz,
                                           offset,
                                           instruction,
                                           InstructionConstants.OP_SIPUSH,
                                           value);
        }
        else
        {
            ConstantPoolEditor constantPoolEditor =
                new ConstantPoolEditor((ProgramClass)clazz);

            Instruction replacementInstruction =
                new ConstantInstruction(InstructionConstants.OP_LDC,
                                        constantPoolEditor.addIntegerConstant(value));

            replaceInstruction(clazz, offset, instruction, replacementInstruction);
        }
    }
    else if (pushedValue.isSpecific())
    {
        // Load an equivalent lower-numbered variable instead, if any.
        TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
        for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
        {
            if (pushedValue.equals(variables.load(variableIndex)))
            {
                replaceVariablePushInstruction(clazz,
                                               offset,
                                               instruction,
                                               InstructionConstants.OP_ILOAD,
                                               variableIndex);
                break;
            }
        }
    }
}
 
Example #16
Source File: EvaluationSimplifier.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Replaces the double pushing instruction at the given offset by a simpler
 * push instruction, if possible.
 */
private void replaceDoublePushInstruction(Clazz       clazz,
                                          int         offset,
                                          Instruction instruction,
                                          int         maxVariableIndex)
{
    Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
    if (pushedValue.isParticular())
    {
        // Make sure to distinguish between +0.0 and -0.0.
        double value = pushedValue.doubleValue().value();
        if (value == 0.0 && Double.doubleToLongBits(value) == POS_ZERO_DOUBLE_BITS ||
            value == 1.0)
        {
            replaceConstantPushInstruction(clazz,
                                           offset,
                                           instruction,
                                           InstructionConstants.OP_DCONST_0,
                                           (int)value);
        }
        else
        {
            ConstantPoolEditor constantPoolEditor =
                new ConstantPoolEditor((ProgramClass)clazz);

            Instruction replacementInstruction =
                new ConstantInstruction(InstructionConstants.OP_LDC2_W,
                                        constantPoolEditor.addDoubleConstant(value)).shrink();

            replaceInstruction(clazz, offset, instruction, replacementInstruction);
        }
    }
    else if (pushedValue.isSpecific())
    {
        TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
        for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
        {
            if (pushedValue.equals(variables.load(variableIndex)))
            {
                replaceVariablePushInstruction(clazz,
                                               offset,
                                               instruction,
                                               InstructionConstants.OP_DLOAD,
                                               variableIndex);
            }
        }
    }
}
 
Example #17
Source File: EvaluationSimplifier.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Replaces the float pushing instruction at the given offset by a simpler
 * push instruction, if possible.
 */
private void replaceFloatPushInstruction(Clazz       clazz,
                                         int         offset,
                                         Instruction instruction,
                                         int         maxVariableIndex)
{
    Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
    if (pushedValue.isParticular())
    {
        // Make sure to distinguish between +0.0 and -0.0.
        float value = pushedValue.floatValue().value();
        if (value == 0.0f && Float.floatToIntBits(value) == POS_ZERO_FLOAT_BITS ||
            value == 1.0f ||
            value == 2.0f)
        {
            replaceConstantPushInstruction(clazz,
                                           offset,
                                           instruction,
                                           InstructionConstants.OP_FCONST_0,
                                           (int)value);
        }
        else
        {
            ConstantPoolEditor constantPoolEditor =
                new ConstantPoolEditor((ProgramClass)clazz);

            Instruction replacementInstruction =
                new ConstantInstruction(InstructionConstants.OP_LDC,
                                        constantPoolEditor.addFloatConstant(value)).shrink();

            replaceInstruction(clazz, offset, instruction, replacementInstruction);
        }
    }
    else if (pushedValue.isSpecific())
    {
        TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
        for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
        {
            if (pushedValue.equals(variables.load(variableIndex)))
            {
                replaceVariablePushInstruction(clazz,
                                               offset,
                                               instruction,
                                               InstructionConstants.OP_FLOAD,
                                               variableIndex);
            }
        }
    }
}
 
Example #18
Source File: EvaluationSimplifier.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Replaces the long pushing instruction at the given offset by a simpler
 * push instruction, if possible.
 */
private void replaceLongPushInstruction(Clazz       clazz,
                                        int         offset,
                                        Instruction instruction,
                                        int         maxVariableIndex)
{
    Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
    if (pushedValue.isParticular())
    {
        long value = pushedValue.longValue().value();
        if (value == 0L ||
            value == 1L)
        {
            replaceConstantPushInstruction(clazz,
                                   offset,
                                   instruction,
                                   InstructionConstants.OP_LCONST_0,
                                   (int)value);
        }
        else
        {
            ConstantPoolEditor constantPoolEditor =
                new ConstantPoolEditor((ProgramClass)clazz);

            Instruction replacementInstruction =
                new ConstantInstruction(InstructionConstants.OP_LDC2_W,
                                        constantPoolEditor.addLongConstant(value)).shrink();

            replaceInstruction(clazz, offset, instruction, replacementInstruction);
        }
    }
    else if (pushedValue.isSpecific())
    {
        TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
        for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
        {
            if (pushedValue.equals(variables.load(variableIndex)))
            {
                replaceVariablePushInstruction(clazz,
                                               offset,
                                               instruction,
                                               InstructionConstants.OP_LLOAD,
                                               variableIndex);
            }
        }
    }
}
 
Example #19
Source File: EvaluationSimplifier.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Replaces the integer pushing instruction at the given offset by a simpler
 * push instruction, if possible.
 */
private void replaceIntegerPushInstruction(Clazz       clazz,
                                           int         offset,
                                           Instruction instruction,
                                           int         maxVariableIndex)
{
    Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0);
    if (pushedValue.isParticular())
    {
        int value = pushedValue.integerValue().value();
        if (value << 16 >> 16 == value)
        {
            replaceConstantPushInstruction(clazz,
                                           offset,
                                           instruction,
                                           InstructionConstants.OP_SIPUSH,
                                           value);
        }
        else
        {
            ConstantPoolEditor constantPoolEditor =
                new ConstantPoolEditor((ProgramClass)clazz);

            Instruction replacementInstruction =
                new ConstantInstruction(InstructionConstants.OP_LDC,
                                        constantPoolEditor.addIntegerConstant(value)).shrink();

            replaceInstruction(clazz, offset, instruction, replacementInstruction);
        }
    }
    else if (pushedValue.isSpecific())
    {
        TracedVariables variables = partialEvaluator.getVariablesBefore(offset);
        for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++)
        {
            if (pushedValue.equals(variables.load(variableIndex)))
            {
                replaceVariablePushInstruction(clazz,
                                               offset,
                                               instruction,
                                               InstructionConstants.OP_ILOAD,
                                               variableIndex);
            }
        }
    }
}
 
Example #20
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Initializes the data structures for the variables, stack, etc.
 */
private void initializeArrays(CodeAttribute codeAttribute)
{
    int codeLength = codeAttribute.u4codeLength;

    // Create new arrays for storing information at each instruction offset.
    if (variablesAfter.length < codeLength)
    {
        // Create new arrays.
        branchOriginValues  = new InstructionOffsetValue[codeLength];
        branchTargetValues  = new InstructionOffsetValue[codeLength];
        variablesBefore     = new TracedVariables[codeLength];
        stacksBefore        = new TracedStack[codeLength];
        variablesAfter      = new TracedVariables[codeLength];
        stacksAfter         = new TracedStack[codeLength];
        generalizedContexts = new boolean[codeLength];
        evaluationCounts    = new int[codeLength];
    }
    else
    {
        // Reset the arrays.
        for (int index = 0; index < codeLength; index++)
        {
            branchOriginValues[index]   = null;
            branchTargetValues[index]   = null;
            generalizedContexts[index]  = false;
            evaluationCounts[index]     = 0;

            if (variablesBefore[index] != null)
            {
                variablesBefore[index].reset(codeAttribute.u2maxLocals);
            }

            if (stacksBefore[index] != null)
            {
                stacksBefore[index].reset(codeAttribute.u2maxStack);
            }

            if (variablesAfter[index] != null)
            {
                variablesAfter[index].reset(codeAttribute.u2maxLocals);
            }

            if (stacksAfter[index] != null)
            {
                stacksAfter[index].reset(codeAttribute.u2maxStack);
            }
        }
    }
}
 
Example #21
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
    {
        int startPC = exceptionInfo.u2startPC;
        int endPC   = exceptionInfo.u2endPC;

        // Do we have to evaluate this exception catch block?
        if (isTraced(startPC, endPC))
        {
            int handlerPC = exceptionInfo.u2handlerPC;
            int catchType = exceptionInfo.u2catchType;

            if (DEBUG) System.out.println("Evaluating exception ["+startPC +" -> "+endPC +": "+handlerPC+"]:");

            // Reuse the existing variables and stack objects, ensuring the
            // right size.
            TracedVariables variables = new TracedVariables(codeAttribute.u2maxLocals);
            TracedStack     stack     = new TracedStack(codeAttribute.u2maxStack);

            // Initialize the trace values.
            Value storeValue = new InstructionOffsetValue(AT_CATCH_ENTRY);
            variables.setProducerValue(storeValue);
            stack.setProducerValue(storeValue);

            // Initialize the variables by generalizing the variables of the
            // try block. Make sure to include the results of the last
            // instruction for preverification.
            generalizeVariables(startPC,
                                endPC,
                                evaluateAllCode,
                                variables);

            // Initialize the the stack.
            //stack.push(valueFactory.createReference((ClassConstant)((ProgramClass)clazz).getConstant(exceptionInfo.u2catchType), false));
            String catchClassName = catchType != 0 ?
                 clazz.getClassName(catchType) :
                 ClassConstants.INTERNAL_NAME_JAVA_LANG_THROWABLE;

            Clazz catchClass = catchType != 0 ?
                ((ClassConstant)((ProgramClass)clazz).getConstant(catchType)).referencedClass :
                null;

            stack.push(valueFactory.createReferenceValue(catchClassName,
                                                         catchClass,
                                                         false));

            int evaluationCount = evaluationCounts[handlerPC];

            // Evaluate the instructions, starting at the entry point.
            evaluateInstructionBlock(clazz,
                                     method,
                                     codeAttribute,
                                     variables,
                                     stack,
                                     handlerPC);

            // Remember to evaluate all exception handlers once more.
            if (!evaluateExceptions)
            {
                evaluateExceptions = evaluationCount < evaluationCounts[handlerPC];
            }
        }
//        else if (evaluateAllCode)
//        {
//            if (DEBUG) System.out.println("No information for partial evaluation of exception ["+startPC +" -> "+endPC +": "+exceptionInfo.u2handlerPC+"] yet");
//
//            // We don't have any information on the try block yet, but we do
//            // have to evaluate the exception handler.
//            // Remember to evaluate all exception handlers once more.
//            evaluateExceptions = true;
//        }
        else
        {
            if (DEBUG) System.out.println("No information for partial evaluation of exception ["+startPC +" -> "+endPC +": "+exceptionInfo.u2handlerPC+"]");
        }
    }
 
Example #22
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Evaluates a subroutine and its exception handlers, starting at the given
 * offset and ending at a subroutine return instruction.
 */
private void evaluateSubroutine(Clazz           clazz,
                                Method          method,
                                CodeAttribute codeAttribute,
                                TracedVariables variables,
                                TracedStack     stack,
                                int             subroutineStart,
                                java.util.Stack instructionBlockStack)
{
    int subroutineEnd = branchTargetFinder.subroutineEnd(subroutineStart);

    if (DEBUG) System.out.println("Evaluating subroutine from "+subroutineStart+" to "+subroutineEnd);

    PartialEvaluator subroutinePartialEvaluator = this;

    // Create a temporary partial evaluator if necessary.
    if (evaluationCounts[subroutineStart] > 0)
    {
        if (DEBUG) System.out.println("Creating new partial evaluator for subroutine");

        subroutinePartialEvaluator = new PartialEvaluator(this);

        subroutinePartialEvaluator.initializeArrays(codeAttribute);
    }

    // Evaluate the subroutine.
    subroutinePartialEvaluator.evaluateInstructionBlockAndExceptionHandlers(clazz,
                                                                            method,
                                                                            codeAttribute,
                                                                            variables,
                                                                            stack,
                                                                            subroutineStart,
                                                                            subroutineEnd);

    // Merge back the temporary partial evaluator if necessary.
    if (subroutinePartialEvaluator != this)
    {
        generalize(subroutinePartialEvaluator, 0, codeAttribute.u4codeLength);
    }

    if (DEBUG) System.out.println("Ending subroutine from "+subroutineStart+" to "+subroutineEnd);
}
 
Example #23
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Returns the variables after execution of the instruction at the given
 * offset.
 */
public TracedVariables getVariablesAfter(int instructionOffset)
{
    return variablesAfter[instructionOffset];
}
 
Example #24
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
/**
 * Returns the variables before execution of the instruction at the given
 * offset.
 */
public TracedVariables getVariablesBefore(int instructionOffset)
{
    return variablesBefore[instructionOffset];
}
 
Example #25
Source File: PartialEvaluator.java    From java-n-IDE-for-Android with Apache License 2.0 4 votes vote down vote up
public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
    // Evaluate the instructions, starting at the entry point.
    if (DEBUG)
    {
        System.out.println();
        System.out.println("Partial evaluation: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
        System.out.println("  Max locals = "+codeAttribute.u2maxLocals);
        System.out.println("  Max stack  = "+codeAttribute.u2maxStack);
    }

    // Reuse the existing variables and stack objects, ensuring the right size.
    TracedVariables variables = new TracedVariables(codeAttribute.u2maxLocals);
    TracedStack     stack     = new TracedStack(codeAttribute.u2maxStack);

    // Initialize the reusable arrays and variables.
    initializeArrays(codeAttribute);
    initializeParameters(clazz, method, codeAttribute, variables);

    // Find all instruction offsets,...
    codeAttribute.accept(clazz, method, branchTargetFinder);

    // Start executing the first instruction block.
    evaluateInstructionBlockAndExceptionHandlers(clazz,
                                                 method,
                                                 codeAttribute,
                                                 variables,
                                                 stack,
                                                 0,
                                                 codeAttribute.u4codeLength);

    if (DEBUG_RESULTS)
    {
        System.out.println("Evaluation results:");

        int offset = 0;
        do
        {
            if (isBranchOrExceptionTarget(offset))
            {
                System.out.println("Branch target from ["+branchOriginValues[offset]+"]:");
                if (isTraced(offset))
                {
                    System.out.println("  Vars:  "+variablesBefore[offset]);
                    System.out.println("  Stack: "+stacksBefore[offset]);
                }
            }

            Instruction instruction = InstructionFactory.create(codeAttribute.code,
                                                                offset);
            System.out.println(instruction.toString(offset));

            if (isTraced(offset))
            {
                int initializationOffset = branchTargetFinder.initializationOffset(offset);
                if (initializationOffset != NONE)
                {
                    System.out.println("     is to be initialized at ["+initializationOffset+"]");
                }

                InstructionOffsetValue branchTargets = branchTargets(offset);
                if (branchTargets != null)
                {
                    System.out.println("     has overall been branching to "+branchTargets);
                }

                System.out.println("  Vars:  "+variablesAfter[offset]);
                System.out.println("  Stack: "+stacksAfter[offset]);
            }

            offset += instruction.length(offset);
        }
        while (offset < codeAttribute.u4codeLength);
    }
}