diff options
author | Gary D. Gregory <ggregory@apache.org> | 2017-10-16 20:32:13 +0000 |
---|---|---|
committer | Gary D. Gregory <ggregory@apache.org> | 2017-10-16 20:32:13 +0000 |
commit | 0d33e877b1642b1bb630415304b8d01de2ce427e (patch) | |
tree | 1fc26ac758bf154159c1dfd995b91175613e1fc7 | |
parent | 90e94269f7d64684ac7dc3fcbee055eea866d370 (diff) | |
download | apache-commons-bcel-0d33e877b1642b1bb630415304b8d01de2ce427e.tar.gz |
[BCEL-295] Fix local variable live range length; add test case.
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/bcel/trunk@1812323 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | src/changes/changes.xml | 1 | ||||
-rw-r--r-- | src/main/java/org/apache/bcel/generic/LocalVariableGen.java | 28 | ||||
-rw-r--r-- | src/main/java/org/apache/bcel/generic/MethodGen.java | 6 | ||||
-rw-r--r-- | src/test/java/org/apache/bcel/PLSETestCase.java | 22 |
4 files changed, 47 insertions, 10 deletions
diff --git a/src/changes/changes.xml b/src/changes/changes.xml index caf7a95f..2923f760 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -65,6 +65,7 @@ The <action> type attribute can be add,update,fix,remove. <release version="6.2" date="tba" description="tba"> <action issue="BCEL-294" type="fix" dev="britter" due-to="Mark Roberts">Incorrect comment in StackMap.java</action> <action issue="BCEL-296" type="fix" dev="ggregory" due-to="Mark Roberts">Incorrect comment in several classes.</action> + <action issue="BCEL-295" type="fix" dev="ggregory" due-to="Mark Roberts">Fix local variable live range length; add test case.</action> </release> <release version="6.1" date="2017-09-14" description="Experimental Java 9 Support"> diff --git a/src/main/java/org/apache/bcel/generic/LocalVariableGen.java b/src/main/java/org/apache/bcel/generic/LocalVariableGen.java index d5ee8fcd..fb27a136 100644 --- a/src/main/java/org/apache/bcel/generic/LocalVariableGen.java +++ b/src/main/java/org/apache/bcel/generic/LocalVariableGen.java @@ -38,6 +38,7 @@ public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Clo private InstructionHandle start; private InstructionHandle end; private int orig_index; // never changes; used to match up with LocalVariableTypeTable entries + private boolean live_to_end; /** @@ -61,6 +62,11 @@ public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Clo setStart(start); setEnd(end); this.orig_index = index; + if (end == null) { + this.live_to_end = true; + } else { + this.live_to_end = false; + } } @@ -88,11 +94,11 @@ public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Clo * This relies on that the instruction list has already been dumped to byte code or * or that the `setPositions' methods has been called for the instruction list. * - * Note that for local variables whose scope end at the last - * instruction of the method's code, the JVM specification is ambiguous: - * both a start_pc+length ending at the last instruction and - * start_pc+length ending at first index beyond the end of the code are - * valid. + * Note that due to the conversion from byte code offset to InstructionHandle, + * it is impossible to tell the difference between a live range that ends BEFORE + * the last insturction of the method or a live range that ends AFTER the last + * instruction of the method. Hence the live_to_end flag to differentiate + * between these two cases. * * @param cp constant pool */ @@ -102,7 +108,7 @@ public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Clo if ((start != null) && (end != null)) { start_pc = start.getPosition(); length = end.getPosition() - start_pc; - if (end.getNext() == null) { + if ((end.getNext() == null) && live_to_end) { length += end.getInstruction().getLength(); } } @@ -128,6 +134,16 @@ public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Clo } + public void setLiveToEnd( final boolean live_to_end) { + this.live_to_end = live_to_end; + } + + + public boolean getLiveToEnd() { + return live_to_end; + } + + @Override public void setName( final String name ) { this.name = name; diff --git a/src/main/java/org/apache/bcel/generic/MethodGen.java b/src/main/java/org/apache/bcel/generic/MethodGen.java index 6833bc9e..5873adc0 100644 --- a/src/main/java/org/apache/bcel/generic/MethodGen.java +++ b/src/main/java/org/apache/bcel/generic/MethodGen.java @@ -133,7 +133,7 @@ public class MethodGen extends FieldGenOrMethodGen { InstructionHandle end = null; if (!abstract_) { start = il.getStart(); - end = il.getEnd(); + // end == null => live to end of method /* Add local variables, namely the implicit `this' and the arguments */ if (!isStatic() && (class_name != null)) { // Instance method -> `this' is local var 0 @@ -725,9 +725,7 @@ public class MethodGen extends FieldGenOrMethodGen { if (null == start) { start = il.getStart(); } - if (null == end) { - end = il.getEnd(); - } + // end == null => live to end of method // Since we are recreating the LocalVaraible, we must // propagate the orig_index to new copy. addLocalVariable(l.getName(), Type.getType(l.getSignature()), l diff --git a/src/test/java/org/apache/bcel/PLSETestCase.java b/src/test/java/org/apache/bcel/PLSETestCase.java index f3c00e23..71f01fb9 100644 --- a/src/test/java/org/apache/bcel/PLSETestCase.java +++ b/src/test/java/org/apache/bcel/PLSETestCase.java @@ -18,7 +18,9 @@ package org.apache.bcel; +import org.apache.bcel.classfile.ClassParser; import org.apache.bcel.classfile.JavaClass; +import org.apache.bcel.classfile.LocalVariable; import org.apache.bcel.classfile.LocalVariableTable; import org.apache.bcel.classfile.Method; import org.apache.bcel.generic.ClassGen; @@ -28,6 +30,7 @@ import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.InvokeInstruction; import org.apache.bcel.generic.MethodGen; import org.apache.bcel.generic.Type; +import java.io.FileInputStream; public class PLSETestCase extends AbstractTestCase { @@ -86,4 +89,23 @@ public class PLSETestCase extends AbstractTestCase final String cn = ii.getClassName(pool); assertEquals("[Lorg.apache.bcel.data.PLSETestEnum;", cn); } + + /** + * BCEL-295: + */ + public void testB295() throws Exception + { + final JavaClass clazz = getTestClass(PACKAGE_BASE_NAME+".data.PLSETestClass2"); + final ClassGen cg = new ClassGen(clazz); + final ConstantPoolGen pool = cg.getConstantPool(); + final Method m = cg.getMethodAt(1); // 'main' + final LocalVariableTable lvt = m.getLocalVariableTable(); + final LocalVariable lv = lvt.getLocalVariable(2, 4); // 'i' + //System.out.println(lv); + final MethodGen mg = new MethodGen(m, cg.getClassName(), pool); + final LocalVariableTable new_lvt = mg.getLocalVariableTable(mg.getConstantPool()); + final LocalVariable new_lv = new_lvt.getLocalVariable(2, 4); // 'i' + //System.out.println(new_lv); + assertEquals("live range length", lv.getLength(), new_lv.getLength()); + } } |