aboutsummaryrefslogtreecommitdiffstats
path: root/src/proguard/classfile/editor/CodeAttributeEditor.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/proguard/classfile/editor/CodeAttributeEditor.java')
-rw-r--r--src/proguard/classfile/editor/CodeAttributeEditor.java400
1 files changed, 218 insertions, 182 deletions
diff --git a/src/proguard/classfile/editor/CodeAttributeEditor.java b/src/proguard/classfile/editor/CodeAttributeEditor.java
index 9658c98..337e0d4 100644
--- a/src/proguard/classfile/editor/CodeAttributeEditor.java
+++ b/src/proguard/classfile/editor/CodeAttributeEditor.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 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
@@ -28,7 +28,9 @@ import proguard.classfile.attribute.visitor.*;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
-import proguard.classfile.visitor.ClassPrinter;
+import proguard.util.ArrayUtil;
+
+import java.util.Arrays;
/**
* This AttributeVisitor accumulates specified changes to code, and then applies
@@ -50,10 +52,12 @@ implements AttributeVisitor,
//*
private static final boolean DEBUG = false;
/*/
- private static boolean DEBUG = true;
+ public static boolean DEBUG = false;
//*/
- private boolean updateFrameSizes;
+
+ private final boolean updateFrameSizes;
+ private final boolean shrinkInstructions;
private int codeLength;
private boolean modified;
@@ -64,7 +68,7 @@ implements AttributeVisitor,
/*private*/public Instruction[] postInsertions = new Instruction[ClassConstants.TYPICAL_CODE_LENGTH];
/*private*/public boolean[] deleted = new boolean[ClassConstants.TYPICAL_CODE_LENGTH];
- private int[] instructionOffsetMap = new int[ClassConstants.TYPICAL_CODE_LENGTH];
+ private int[] newInstructionOffsets = new int[ClassConstants.TYPICAL_CODE_LENGTH];
private int newOffset;
private boolean lengthIncreased;
@@ -75,15 +79,28 @@ implements AttributeVisitor,
private final InstructionWriter instructionWriter = new InstructionWriter();
+ /**
+ * Creates a new CodeAttributeEditor that automatically updates frame
+ * sizes and shrinks instructions.
+ */
public CodeAttributeEditor()
{
- this(true);
+ this(true, true);
}
- public CodeAttributeEditor(boolean updateFrameSizes)
+ /**
+ * Creates a new CodeAttributeEditor.
+ * @param updateFrameSizes specifies whether frame sizes of edited code
+ * should be updated.
+ * @param shrinkInstructions specifies whether added instructions should
+ * automatically be shrunk before being written.
+ */
+ public CodeAttributeEditor(boolean updateFrameSizes,
+ boolean shrinkInstructions)
{
- this.updateFrameSizes = updateFrameSizes;
+ this.updateFrameSizes = updateFrameSizes;
+ this.shrinkInstructions = shrinkInstructions;
}
@@ -93,8 +110,6 @@ implements AttributeVisitor,
*/
public void reset(int codeLength)
{
- this.codeLength = codeLength;
-
// Try to reuse the previous arrays.
if (preInsertions.length < codeLength)
{
@@ -105,18 +120,42 @@ implements AttributeVisitor,
}
else
{
- for (int index = 0; index < codeLength; index++)
- {
- preInsertions[index] = null;
- replacements[index] = null;
- postInsertions[index] = null;
- deleted[index] = false;
- }
+ Arrays.fill(preInsertions, 0, codeLength, null);
+ Arrays.fill(replacements, 0, codeLength, null);
+ Arrays.fill(postInsertions, 0, codeLength, null);
+ Arrays.fill(deleted, 0, codeLength, false);
}
+ this.codeLength = codeLength;
+
modified = false;
simple = true;
+ }
+
+
+ /**
+ * Extends the size of the accumulated code changes.
+ * @param codeLength the length of the code that will be edited next.
+ */
+ public void extend(int codeLength)
+ {
+ // Try to reuse the previous arrays.
+ if (preInsertions.length < codeLength)
+ {
+ preInsertions = (Instruction[])ArrayUtil.extendArray(preInsertions, codeLength);
+ replacements = (Instruction[])ArrayUtil.extendArray(replacements, codeLength);
+ postInsertions = (Instruction[])ArrayUtil.extendArray(postInsertions, codeLength);
+ deleted = ArrayUtil.extendArray(deleted, codeLength);
+ }
+ else
+ {
+ Arrays.fill(preInsertions, this.codeLength, codeLength, null);
+ Arrays.fill(replacements, this.codeLength, codeLength, null);
+ Arrays.fill(postInsertions, this.codeLength, codeLength, null);
+ Arrays.fill(deleted, this.codeLength, codeLength, false);
+ }
+ this.codeLength = codeLength;
}
@@ -134,7 +173,9 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- preInsertions[instructionOffset] = instruction;
+ preInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
simple = false;
@@ -156,7 +197,12 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- preInsertions[instructionOffset] = new CompositeInstruction(instructions);
+ CompositeInstruction instruction =
+ new CompositeInstruction(instructions);
+
+ preInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
simple = false;
@@ -178,7 +224,9 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- replacements[instructionOffset] = instruction;
+ replacements[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
}
@@ -198,7 +246,12 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- replacements[instructionOffset] = new CompositeInstruction(instructions);
+ CompositeInstruction instruction =
+ new CompositeInstruction(instructions);
+
+ replacements[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
}
@@ -218,7 +271,9 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- postInsertions[instructionOffset] = instruction;
+ postInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
simple = false;
@@ -239,7 +294,12 @@ implements AttributeVisitor,
throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
}
- postInsertions[instructionOffset] = new CompositeInstruction(instructions);
+ CompositeInstruction instruction =
+ new CompositeInstruction(instructions);
+
+ postInsertions[instructionOffset] = shrinkInstructions ?
+ instruction.shrink() :
+ instruction;
modified = true;
simple = false;
@@ -282,6 +342,34 @@ implements AttributeVisitor,
/**
+ * Clears all modifications of the instruction at the given offset.
+ * @param instructionOffset the offset of the instruction to be deleted.
+ */
+ public void clearModifications(int instructionOffset)
+ {
+ if (instructionOffset < 0 ||
+ instructionOffset >= codeLength)
+ {
+ throw new IllegalArgumentException("Invalid instruction offset ["+instructionOffset+"] in code with length ["+codeLength+"]");
+ }
+
+ preInsertions[instructionOffset] = null;
+ replacements[instructionOffset] = null;
+ postInsertions[instructionOffset] = null;
+ deleted[instructionOffset] = false;
+ }
+
+
+ /**
+ * Returns whether the code has been modified in any way.
+ */
+ public boolean isModified()
+ {
+ return modified;
+ }
+
+
+ /**
* Returns whether the instruction at the given offset has been modified
* in any way.
*/
@@ -326,54 +414,53 @@ implements AttributeVisitor,
public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute)
{
- if (DEBUG)
- {
- System.out.println("CodeAttributeEditor: ["+clazz.getName()+"."+method.getName(clazz)+"]");
- }
-
- // Avoid doing any work if nothing is changing anyway.
- if (!modified)
+ // Do we have to update the code?
+ if (modified)
{
- return;
- }
+ if (DEBUG)
+ {
+ System.out.println("CodeAttributeEditor: "+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz));
+ }
- // Check if we can perform a faster simple replacement of instructions.
- if (canPerformSimpleReplacements(codeAttribute))
- {
- // Simply overwrite the instructions.
- performSimpleReplacements(codeAttribute);
+ // Can we perform a faster simple replacement of instructions?
+ if (canPerformSimpleReplacements(codeAttribute))
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Simple editing");
+ }
- // Update the maximum stack size and local variable frame size.
- updateFrameSizes(clazz, method, codeAttribute);
- }
- else
- {
- // Move and remap the instructions.
- codeAttribute.u4codeLength =
- updateInstructions(clazz, method, codeAttribute);
+ // Simply overwrite the instructions.
+ performSimpleReplacements(codeAttribute);
+ }
+ else
+ {
+ if (DEBUG)
+ {
+ System.out.println(" Full editing");
+ }
- // Remap the exception table.
- codeAttribute.exceptionsAccept(clazz, method, this);
+ // Move and remap the instructions.
+ codeAttribute.u4codeLength =
+ updateInstructions(clazz, method, codeAttribute);
- // Remove exceptions with empty code blocks.
- codeAttribute.u2exceptionTableLength =
- removeEmptyExceptions(codeAttribute.exceptionTable,
- codeAttribute.u2exceptionTableLength);
+ // Update the exception table.
+ codeAttribute.exceptionsAccept(clazz, method, this);
- // Update the maximum stack size and local variable frame size.
- updateFrameSizes(clazz, method, codeAttribute);
+ // Remove exceptions with empty code blocks.
+ codeAttribute.u2exceptionTableLength =
+ removeEmptyExceptions(codeAttribute.exceptionTable,
+ codeAttribute.u2exceptionTableLength);
- // Remap the line number table and the local variable table.
- codeAttribute.attributesAccept(clazz, method, this);
+ // Update the line number table and the local variable tables.
+ codeAttribute.attributesAccept(clazz, method, this);
+ }
// Make sure instructions are widened if necessary.
instructionWriter.visitCodeAttribute(clazz, method, codeAttribute);
}
- }
-
- private void updateFrameSizes(Clazz clazz, Method method, CodeAttribute codeAttribute)
- {
+ // Update the maximum stack size and local variable frame size.
if (updateFrameSizes)
{
stackSizeUpdater.visitCodeAttribute(clazz, method, codeAttribute);
@@ -384,7 +471,7 @@ implements AttributeVisitor,
public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
{
- // Remap all stack map entries.
+ // Update all stack map entries.
expectedStackMapFrameOffset = -1;
stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
}
@@ -392,7 +479,7 @@ implements AttributeVisitor,
public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
{
- // Remap all stack map table entries.
+ // Update all stack map table entries.
expectedStackMapFrameOffset = 0;
stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
}
@@ -400,7 +487,7 @@ implements AttributeVisitor,
public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
{
- // Remap all line number table entries.
+ // Update all line number table entries.
lineNumberTableAttribute.lineNumbersAccept(clazz, method, codeAttribute, this);
// Remove line numbers with empty code blocks.
@@ -413,27 +500,15 @@ implements AttributeVisitor,
public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
{
- // Remap all local variable table entries.
+ // Update all local variable table entries.
localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
-
- // Remove local variables with empty code blocks.
- localVariableTableAttribute.u2localVariableTableLength =
- removeEmptyLocalVariables(localVariableTableAttribute.localVariableTable,
- localVariableTableAttribute.u2localVariableTableLength,
- codeAttribute.u2maxLocals);
}
public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
{
- // Remap all local variable table entries.
+ // Update all local variable table entries.
localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
-
- // Remove local variables with empty code blocks.
- localVariableTypeTableAttribute.u2localVariableTypeTableLength =
- removeEmptyLocalVariableTypes(localVariableTypeTableAttribute.localVariableTypeTable,
- localVariableTypeTableAttribute.u2localVariableTypeTableLength,
- codeAttribute.u2maxLocals);
}
@@ -491,7 +566,7 @@ implements AttributeVisitor,
if (DEBUG)
{
- System.out.println(" Replaced "+replacementInstruction.toString(newOffset));
+ System.out.println(" Replaced "+replacementInstruction.toString(offset));
}
}
}
@@ -513,9 +588,9 @@ implements AttributeVisitor,
int oldLength = codeAttribute.u4codeLength;
// Make sure there is a sufficiently large instruction offset map.
- if (instructionOffsetMap.length < oldLength + 1)
+ if (newInstructionOffsets.length < oldLength + 1)
{
- instructionOffsetMap = new int[oldLength + 1];
+ newInstructionOffsets = new int[oldLength + 1];
}
// Fill out the instruction offset map.
@@ -574,7 +649,7 @@ implements AttributeVisitor,
while (oldOffset < oldLength);
// Also add an entry for the first offset after the code.
- instructionOffsetMap[oldOffset] = newOffset;
+ newInstructionOffsets[oldOffset] = newOffset;
return newOffset;
}
@@ -588,7 +663,7 @@ implements AttributeVisitor,
private void mapInstruction(int oldOffset,
Instruction instruction)
{
- instructionOffsetMap[oldOffset] = newOffset;
+ newInstructionOffsets[oldOffset] = newOffset;
// Account for the pre-inserted instruction, if any.
Instruction preInstruction = preInsertions[oldOffset];
@@ -670,52 +745,53 @@ implements AttributeVisitor,
int oldOffset,
Instruction instruction)
{
- // Remap and insert the pre-inserted instruction, if any.
+ // Update and insert the pre-inserted instruction, if any.
Instruction preInstruction = preInsertions[oldOffset];
if (preInstruction != null)
{
if (DEBUG)
{
- System.out.println(" Pre-inserted "+preInstruction.toString(newOffset));
+ System.out.println(" Pre-inserted ["+oldOffset+"] -> "+preInstruction.toString(newOffset));
}
- // Remap the instruction.
+ // Update the instruction.
preInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
- // Remap and insert the replacement instruction, or the current
+ // Update and insert the replacement instruction, or the current
// instruction, if it shouldn't be deleted.
Instruction replacementInstruction = replacements[oldOffset];
if (replacementInstruction != null)
{
if (DEBUG)
{
- System.out.println(" Replaced "+replacementInstruction.toString(newOffset));
+ System.out.println(" Replaced ["+oldOffset+"] -> "+replacementInstruction.toString(newOffset));
}
- // Remap the instruction.
+
+ // Update the instruction.
replacementInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
else if (!deleted[oldOffset])
{
if (DEBUG)
{
- System.out.println(" Copied "+instruction.toString(newOffset));
+ System.out.println(" Copied ["+oldOffset+"] -> "+instruction.toString(newOffset));
}
- // Remap the instruction.
+ // Update the instruction.
instruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
- // Remap and insert the post-inserted instruction, if any.
+ // Update and insert the post-inserted instruction, if any.
Instruction postInstruction = postInsertions[oldOffset];
if (postInstruction != null)
{
if (DEBUG)
{
- System.out.println(" Post-inserted "+postInstruction.toString(newOffset));
+ System.out.println(" Post-inserted ["+oldOffset+"] -> "+postInstruction.toString(newOffset));
}
- // Remap the instruction.
+ // Update the instruction.
postInstruction.accept(clazz, method, codeAttribute, oldOffset, this);
}
}
@@ -765,8 +841,8 @@ implements AttributeVisitor,
public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
{
// Adjust the branch offset.
- branchInstruction.branchOffset = remapBranchOffset(offset,
- branchInstruction.branchOffset);
+ branchInstruction.branchOffset = newBranchOffset(offset,
+ branchInstruction.branchOffset);
// Write out the instruction.
instructionWriter.visitBranchInstruction(clazz,
@@ -782,11 +858,11 @@ implements AttributeVisitor,
public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
{
// Adjust the default jump offset.
- tableSwitchInstruction.defaultOffset = remapBranchOffset(offset,
- tableSwitchInstruction.defaultOffset);
+ tableSwitchInstruction.defaultOffset = newBranchOffset(offset,
+ tableSwitchInstruction.defaultOffset);
// Adjust the jump offsets.
- remapJumpOffsets(offset,
+ newJumpOffsets(offset,
tableSwitchInstruction.jumpOffsets);
// Write out the instruction.
@@ -803,11 +879,11 @@ implements AttributeVisitor,
public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
{
// Adjust the default jump offset.
- lookUpSwitchInstruction.defaultOffset = remapBranchOffset(offset,
- lookUpSwitchInstruction.defaultOffset);
+ lookUpSwitchInstruction.defaultOffset = newBranchOffset(offset,
+ lookUpSwitchInstruction.defaultOffset);
// Adjust the jump offsets.
- remapJumpOffsets(offset,
+ newJumpOffsets(offset,
lookUpSwitchInstruction.jumpOffsets);
// Write out the instruction.
@@ -825,11 +901,11 @@ implements AttributeVisitor,
public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
{
- // Remap the code offsets. Note that the instruction offset map also has
+ // Update the code offsets. Note that the instruction offset map also has
// an entry for the first offset after the code, for u2endPC.
- exceptionInfo.u2startPC = remapInstructionOffset(exceptionInfo.u2startPC);
- exceptionInfo.u2endPC = remapInstructionOffset(exceptionInfo.u2endPC);
- exceptionInfo.u2handlerPC = remapInstructionOffset(exceptionInfo.u2handlerPC);
+ exceptionInfo.u2startPC = newInstructionOffset(exceptionInfo.u2startPC);
+ exceptionInfo.u2endPC = newInstructionOffset(exceptionInfo.u2endPC);
+ exceptionInfo.u2handlerPC = newInstructionOffset(exceptionInfo.u2handlerPC);
}
@@ -837,8 +913,8 @@ implements AttributeVisitor,
public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame)
{
- // Remap the stack map frame offset.
- int stackMapFrameOffset = remapInstructionOffset(offset);
+ // Update the stack map frame offset.
+ int stackMapFrameOffset = newInstructionOffset(offset);
int offsetDelta = stackMapFrameOffset;
@@ -857,30 +933,30 @@ implements AttributeVisitor,
public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
{
- // Remap the stack map frame offset.
+ // Update the stack map frame offset.
visitAnyStackMapFrame(clazz, method, codeAttribute, offset, sameOneFrame);
- // Remap the verification type offset.
+ // Update the verification type offset.
sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
}
public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
{
- // Remap the stack map frame offset.
+ // Update the stack map frame offset.
visitAnyStackMapFrame(clazz, method, codeAttribute, offset, moreZeroFrame);
- // Remap the verification type offsets.
+ // Update the verification type offsets.
moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
}
public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
{
- // Remap the stack map frame offset.
+ // Update the stack map frame offset.
visitAnyStackMapFrame(clazz, method, codeAttribute, offset, fullFrame);
- // Remap the verification type offsets.
+ // Update the verification type offsets.
fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
}
@@ -893,8 +969,8 @@ implements AttributeVisitor,
public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType)
{
- // Remap the offset of the 'new' instruction.
- uninitializedType.u2newInstructionOffset = remapInstructionOffset(uninitializedType.u2newInstructionOffset);
+ // Update the offset of the 'new' instruction.
+ uninitializedType.u2newInstructionOffset = newInstructionOffset(uninitializedType.u2newInstructionOffset);
}
@@ -902,8 +978,8 @@ implements AttributeVisitor,
public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo)
{
- // Remap the code offset.
- lineNumberInfo.u2startPC = remapInstructionOffset(lineNumberInfo.u2startPC);
+ // Update the code offset.
+ lineNumberInfo.u2startPC = newInstructionOffset(lineNumberInfo.u2startPC);
}
@@ -911,11 +987,13 @@ implements AttributeVisitor,
public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
{
- // Remap the code offset and length.
- // TODO: The local variable frame might not be strictly preserved.
- localVariableInfo.u2length = remapBranchOffset(localVariableInfo.u2startPC,
- localVariableInfo.u2length);
- localVariableInfo.u2startPC = remapInstructionOffset(localVariableInfo.u2startPC);
+ // Update the code offset and length.
+ int newStartPC = newInstructionOffset(localVariableInfo.u2startPC);
+ int newEndPC = newInstructionOffset(localVariableInfo.u2startPC +
+ localVariableInfo.u2length);
+
+ localVariableInfo.u2length = newEndPC - newStartPC;
+ localVariableInfo.u2startPC = newStartPC;
}
@@ -923,11 +1001,13 @@ implements AttributeVisitor,
public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
{
- // Remap the code offset and length.
- // TODO: The local variable frame might not be strictly preserved.
- localVariableTypeInfo.u2length = remapBranchOffset(localVariableTypeInfo.u2startPC,
- localVariableTypeInfo.u2length);
- localVariableTypeInfo.u2startPC = remapInstructionOffset(localVariableTypeInfo.u2startPC);
+ // Update the code offset and length.
+ int newStartPC = newInstructionOffset(localVariableTypeInfo.u2startPC);
+ int newEndPC = newInstructionOffset(localVariableTypeInfo.u2startPC +
+ localVariableTypeInfo.u2length);
+
+ localVariableTypeInfo.u2length = newEndPC - newStartPC;
+ localVariableTypeInfo.u2startPC = newStartPC;
}
@@ -936,11 +1016,11 @@ implements AttributeVisitor,
/**
* Adjusts the given jump offsets for the instruction at the given offset.
*/
- private void remapJumpOffsets(int offset, int[] jumpOffsets)
+ private void newJumpOffsets(int oldInstructionOffset, int[] oldJumpOffsets)
{
- for (int index = 0; index < jumpOffsets.length; index++)
+ for (int index = 0; index < oldJumpOffsets.length; index++)
{
- jumpOffsets[index] = remapBranchOffset(offset, jumpOffsets[index]);
+ oldJumpOffsets[index] = newBranchOffset(oldInstructionOffset, oldJumpOffsets[index]);
}
}
@@ -949,24 +1029,24 @@ implements AttributeVisitor,
* Computes the new branch offset for the instruction at the given offset
* with the given branch offset.
*/
- private int remapBranchOffset(int offset, int branchOffset)
+ private int newBranchOffset(int oldInstructionOffset, int oldBranchOffset)
{
- return remapInstructionOffset(offset + branchOffset) - newOffset;
+ return newInstructionOffset(oldInstructionOffset + oldBranchOffset) - newOffset;
}
/**
* Computes the new instruction offset for the instruction at the given offset.
*/
- private int remapInstructionOffset(int offset)
+ private int newInstructionOffset(int oldInstructionOffset)
{
- if (offset < 0 ||
- offset > codeLength)
+ if (oldInstructionOffset < 0 ||
+ oldInstructionOffset > codeLength)
{
- throw new IllegalArgumentException("Invalid instruction offset ["+offset+"] in code with length ["+codeLength+"]");
+ throw new IllegalArgumentException("Invalid instruction offset ["+oldInstructionOffset+"] in code with length ["+codeLength+"]");
}
- return instructionOffsetMap[offset];
+ return newInstructionOffsets[oldInstructionOffset];
}
@@ -1018,53 +1098,9 @@ implements AttributeVisitor,
/**
- * Returns the given list of local variables, without the ones that have empty
- * code blocks or that exceed the actual number of local variables.
+ * This instruction is a composite of other instructions, for local use
+ * inside the editor class only.
*/
- private int removeEmptyLocalVariables(LocalVariableInfo[] localVariableInfos,
- int localVariableInfoCount,
- int maxLocals)
- {
- // Overwrite all empty local variable entries.
- int newIndex = 0;
- for (int index = 0; index < localVariableInfoCount; index++)
- {
- LocalVariableInfo localVariableInfo = localVariableInfos[index];
- if (localVariableInfo.u2length > 0 &&
- localVariableInfo.u2index < maxLocals)
- {
- localVariableInfos[newIndex++] = localVariableInfo;
- }
- }
-
- return newIndex;
- }
-
-
- /**
- * Returns the given list of local variable types, without the ones that
- * have empty code blocks or that exceed the actual number of local variables.
- */
- private int removeEmptyLocalVariableTypes(LocalVariableTypeInfo[] localVariableTypeInfos,
- int localVariableTypeInfoCount,
- int maxLocals)
- {
- // Overwrite all empty local variable type entries.
- int newIndex = 0;
- for (int index = 0; index < localVariableTypeInfoCount; index++)
- {
- LocalVariableTypeInfo localVariableTypeInfo = localVariableTypeInfos[index];
- if (localVariableTypeInfo.u2length > 0 &&
- localVariableTypeInfo.u2index < maxLocals)
- {
- localVariableTypeInfos[newIndex++] = localVariableTypeInfo;
- }
- }
-
- return newIndex;
- }
-
-
private class CompositeInstruction
extends Instruction
{