diff options
author | acolyer <acolyer> | 2005-09-27 21:08:24 +0000 |
---|---|---|
committer | acolyer <acolyer> | 2005-09-27 21:08:24 +0000 |
commit | 97520cf015afa87263c9497b4a60888ba2ada177 (patch) | |
tree | e0f226881520969d3afdcda2966db705f82a0ba2 | |
parent | fb428d0e5ad8adabc14049f8a170b30d57044588 (diff) | |
download | aspectj-97520cf015afa87263c9497b4a60888ba2ada177.tar.gz aspectj-97520cf015afa87263c9497b4a60888ba2ada177.zip |
fix for pr101407 - weaver produces wrong local variable table bytecode.
-rw-r--r-- | bcel-builder/src/org/aspectj/apache/bcel/generic/LocalVariableGen.java | 11 | ||||
-rw-r--r-- | lib/bcel/bcel-src.zip | bin | 871079 -> 871248 bytes | |||
-rw-r--r-- | lib/bcel/bcel.jar | bin | 594005 -> 594017 bytes | |||
-rw-r--r-- | weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java | 221 | ||||
-rw-r--r-- | weaver/src/org/aspectj/weaver/bcel/LocalVariableTag.java | 9 |
5 files changed, 136 insertions, 105 deletions
diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/LocalVariableGen.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/LocalVariableGen.java index 7791e6662..f181e8c9d 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/LocalVariableGen.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/LocalVariableGen.java @@ -63,7 +63,7 @@ import org.aspectj.apache.bcel.classfile.LocalVariable; * with getLocalVariable which needs the instruction list and the constant * pool as parameters. * - * @version $Id: LocalVariableGen.java,v 1.3 2004/11/22 08:31:27 aclement Exp $ + * @version $Id: LocalVariableGen.java,v 1.4 2005/09/27 21:08:24 acolyer Exp $ * @author <A HREF="mailto:markus.dahm@berlin.de">M. Dahm</A> * @see LocalVariable * @see MethodGen @@ -118,8 +118,15 @@ public class LocalVariableGen int start_pc = start.getPosition(); int length = end.getPosition() - start_pc; - if(length > 0) + if(length > 0) { length += end.getInstruction().getLength(); + // AMC - the above calculation is off by one. The spec says that the variable + // must have a range from start pos to start pos + length INCLUSIVE. + // but the calculation above puts start pos + length as the address of + // the first instruction outside of the range. + // So we need to subtract 1... which gives the very end of the last inst in the range + length = length - 1; + } int name_index = cp.addUtf8(name); int signature_index = cp.addUtf8(type.getSignature()); diff --git a/lib/bcel/bcel-src.zip b/lib/bcel/bcel-src.zip Binary files differindex 59543ed9b..3e83e735a 100644 --- a/lib/bcel/bcel-src.zip +++ b/lib/bcel/bcel-src.zip diff --git a/lib/bcel/bcel.jar b/lib/bcel/bcel.jar Binary files differindex 0d2474e5f..6d3a5ac7f 100644 --- a/lib/bcel/bcel.jar +++ b/lib/bcel/bcel.jar diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java index 92cd5b45c..b6450fc22 100644 --- a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java +++ b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java @@ -373,7 +373,7 @@ public final class LazyMethodGen { InstructionTargeter targeter = targeters[i]; if (targeter instanceof LocalVariableGen) { LocalVariableGen lng = (LocalVariableGen) targeter; - LocalVariableTag lr = new LocalVariableTag(BcelWorld.fromBcel(lng.getType()), lng.getName(), lng.getIndex()); + LocalVariableTag lr = new LocalVariableTag(BcelWorld.fromBcel(lng.getType()), lng.getName(), lng.getIndex(), lng.getStart().getPosition()); if (lng.getStart() == ih) { locals.add(lr); } else { @@ -896,35 +896,18 @@ public final class LazyMethodGen { * inspired by InstructionList.copy() */ public void packBody(MethodGen gen) { - HashMap map = new HashMap(); InstructionList fresh = gen.getInstructionList(); + Map map = copyAllInstructionsExceptRangeInstructionsInto(fresh); - /* Make copies of all instructions, append them to the new list - * and associate old instruction references with the new ones, i.e., - * a 1:1 mapping. - */ - for (InstructionHandle ih = getBody().getStart(); ih != null; ih = ih.getNext()) { - if (Range.isRangeHandle(ih)) { - continue; - } - Instruction i = ih.getInstruction(); - Instruction c = Utility.copyInstruction(i); - - if (c instanceof BranchInstruction) - map.put(ih, fresh.append((BranchInstruction) c)); - else - map.put(ih, fresh.append(c)); - } // at this point, no rangeHandles are in fresh. Let's use that... /* Update branch targets and insert various attributes. * Insert our exceptionHandlers * into a sorted list, so they can be added in order later. */ - InstructionHandle ih = getBody().getStart(); - InstructionHandle jh = fresh.getStart(); - - LinkedList exnList = new LinkedList(); + InstructionHandle oldInstructionHandle = getBody().getStart(); + InstructionHandle newInstructionHandle = fresh.getStart(); + LinkedList exceptionList = new LinkedList(); // map from localvariabletag to instruction handle Map localVariableStarts = new HashMap(); @@ -932,102 +915,64 @@ public final class LazyMethodGen { int currLine = -1; - while (ih != null) { - if (map.get(ih) == null) { - // we're a range instruction - Range r = Range.getRange(ih); - if (r instanceof ExceptionRange) { - ExceptionRange er = (ExceptionRange) r; - if (er.getStart() == ih) { - //System.err.println("er " + er); - if (!er.isEmpty()){ - // order is important, insert handlers in order of start - insertHandler(er, exnList); - } - } - } else { - // we must be a shadow range or something equally useless, - // so forget about doing anything - } + while (oldInstructionHandle != null) { + if (map.get(oldInstructionHandle) == null) { + // must be a range instruction since they're the only things we didn't copy across + handleRangeInstruction(oldInstructionHandle, exceptionList); // just increment ih. - ih = ih.getNext(); + oldInstructionHandle = oldInstructionHandle.getNext(); } else { // assert map.get(ih) == jh - Instruction i = ih.getInstruction(); - Instruction j = jh.getInstruction(); - - if (i instanceof BranchInstruction) { - BranchInstruction bi = (BranchInstruction) i; - BranchInstruction bj = (BranchInstruction) j; - InstructionHandle itarget = bi.getTarget(); // old target - -// try { - // New target is in hash map - bj.setTarget(remap(itarget, map)); -// } catch (NullPointerException e) { -// print(); -// System.out.println("Was trying to remap " + bi); -// System.out.println("who's target was supposedly " + itarget); -// throw e; -// } - - if (bi instanceof Select) { - // Either LOOKUPSWITCH or TABLESWITCH - InstructionHandle[] itargets = ((Select) bi).getTargets(); - InstructionHandle[] jtargets = ((Select) bj).getTargets(); + Instruction oldInstruction = oldInstructionHandle.getInstruction(); + Instruction newInstruction = newInstructionHandle.getInstruction(); - for (int k = itargets.length - 1; k >= 0; k--) { - // Update all targets - jtargets[k] = remap(itargets[k], map); - jtargets[k].addTargeter(bj); - } - } - } + if (oldInstruction instanceof BranchInstruction) { + handleBranchInstruction(map, oldInstruction, newInstruction); + } // now deal with line numbers // and store up info for local variables - InstructionTargeter[] targeters = ih.getTargeters(); - int lineNumberOffset = - (fromFilename == null) - ? 0 - : getEnclosingClass().getSourceDebugExtensionOffset(fromFilename); + InstructionTargeter[] targeters = oldInstructionHandle.getTargeters(); + int lineNumberOffset = (fromFilename == null) ? 0: getEnclosingClass().getSourceDebugExtensionOffset(fromFilename); if (targeters != null) { for (int k = targeters.length - 1; k >= 0; k--) { InstructionTargeter targeter = targeters[k]; if (targeter instanceof LineNumberTag) { int line = ((LineNumberTag)targeter).getLineNumber(); if (line != currLine) { - gen.addLineNumber(jh, line + lineNumberOffset); + gen.addLineNumber(newInstructionHandle, line + lineNumberOffset); currLine = line; } } else if (targeter instanceof LocalVariableTag) { LocalVariableTag lvt = (LocalVariableTag) targeter; - if (localVariableStarts.get(lvt) == null) { - localVariableStarts.put(lvt, jh); - } - localVariableEnds.put(lvt, jh); + if (localVariableStarts.get(lvt) == null) { + localVariableStarts.put(lvt, newInstructionHandle); + } + localVariableEnds.put(lvt, newInstructionHandle); } } } + // now continue - ih = ih.getNext(); - jh = jh.getNext(); + oldInstructionHandle = oldInstructionHandle.getNext(); + newInstructionHandle = newInstructionHandle.getNext(); } } - // now add exception handlers - for (Iterator iter = exnList.iterator(); iter.hasNext();) { - ExceptionRange r = (ExceptionRange) iter.next(); - if (r.isEmpty()) continue; - gen.addExceptionHandler( - remap(r.getRealStart(), map), - remap(r.getRealEnd(), map), - remap(r.getHandler(), map), - (r.getCatchType() == null) - ? null - : (ObjectType) BcelWorld.makeBcelType(r.getCatchType())); + addExceptionHandlers(gen, map, exceptionList); + addLocalVariables(gen, localVariableStarts, localVariableEnds); + + // JAVAC adds line number tables (with just one entry) to generated accessor methods - this + // keeps some tools that rely on finding at least some form of linenumbertable happy. + // Let's check if we have one - if we don't then let's add one. + // TODO Could be made conditional on whether line debug info is being produced + if (gen.getLineNumbers().length==0) { + gen.addLineNumber(gen.getInstructionList().getStart(),1); } - // now add local variables + } + + private void addLocalVariables(MethodGen gen, Map localVariableStarts, Map localVariableEnds) { + // now add local variables gen.removeLocalVariables(); // this next iteration _might_ be overkill, but we had problems with @@ -1061,16 +1006,90 @@ public final class LazyMethodGen { (InstructionHandle) localVariableStarts.get(tag), (InstructionHandle) localVariableEnds.get(tag)); } - - // JAVAC adds line number tables (with just one entry) to generated accessor methods - this - // keeps some tools that rely on finding at least some form of linenumbertable happy. - // Let's check if we have one - if we don't then let's add one. - // TODO Could be made conditional on whether line debug info is being produced - if (gen.getLineNumbers().length==0) { - gen.addLineNumber(gen.getInstructionList().getStart(),1); + } + + private void addExceptionHandlers(MethodGen gen, Map map, LinkedList exnList) { + // now add exception handlers + for (Iterator iter = exnList.iterator(); iter.hasNext();) { + ExceptionRange r = (ExceptionRange) iter.next(); + if (r.isEmpty()) continue; + gen.addExceptionHandler( + remap(r.getRealStart(), map), + remap(r.getRealEnd(), map), + remap(r.getHandler(), map), + (r.getCatchType() == null) + ? null + : (ObjectType) BcelWorld.makeBcelType(r.getCatchType())); } - } + } + private void handleBranchInstruction(Map map, Instruction oldInstruction, Instruction newInstruction) { + BranchInstruction oldBranchInstruction = (BranchInstruction) oldInstruction; + BranchInstruction newBranchInstruction = (BranchInstruction) newInstruction; + InstructionHandle oldTarget = oldBranchInstruction.getTarget(); // old target + +// try { + // New target is in hash map + newBranchInstruction.setTarget(remap(oldTarget, map)); +// } catch (NullPointerException e) { +// print(); +// System.out.println("Was trying to remap " + bi); +// System.out.println("who's target was supposedly " + itarget); +// throw e; +// } + + if (oldBranchInstruction instanceof Select) { + // Either LOOKUPSWITCH or TABLESWITCH + InstructionHandle[] oldTargets = ((Select) oldBranchInstruction).getTargets(); + InstructionHandle[] newTargets = ((Select) newBranchInstruction).getTargets(); + + for (int k = oldTargets.length - 1; k >= 0; k--) { + // Update all targets + newTargets[k] = remap(oldTargets[k], map); + newTargets[k].addTargeter(newBranchInstruction); + } + } + } + + private void handleRangeInstruction(InstructionHandle ih, LinkedList exnList) { + // we're a range instruction + Range r = Range.getRange(ih); + if (r instanceof ExceptionRange) { + ExceptionRange er = (ExceptionRange) r; + if (er.getStart() == ih) { + //System.err.println("er " + er); + if (!er.isEmpty()){ + // order is important, insert handlers in order of start + insertHandler(er, exnList); + } + } + } else { + // we must be a shadow range or something equally useless, + // so forget about doing anything + } + } + + /* Make copies of all instructions, append them to the new list + * and associate old instruction references with the new ones, i.e., + * a 1:1 mapping. + */ + private Map copyAllInstructionsExceptRangeInstructionsInto(InstructionList intoList) { + HashMap map = new HashMap(); + for (InstructionHandle ih = getBody().getStart(); ih != null; ih = ih.getNext()) { + if (Range.isRangeHandle(ih)) { + continue; + } + Instruction i = ih.getInstruction(); + Instruction c = Utility.copyInstruction(i); + + if (c instanceof BranchInstruction) + map.put(ih, intoList.append((BranchInstruction) c)); + else + map.put(ih, intoList.append(c)); + } + return map; + } + /** This procedure should not currently be used. */ // public void killNops() { diff --git a/weaver/src/org/aspectj/weaver/bcel/LocalVariableTag.java b/weaver/src/org/aspectj/weaver/bcel/LocalVariableTag.java index 36a3179d5..109211329 100644 --- a/weaver/src/org/aspectj/weaver/bcel/LocalVariableTag.java +++ b/weaver/src/org/aspectj/weaver/bcel/LocalVariableTag.java @@ -19,11 +19,15 @@ public final class LocalVariableTag extends Tag { private final UnresolvedType type; private final String name; private final int slot; + private final int startPos; - public LocalVariableTag(UnresolvedType type, String name, int slot) { + // AMC - pr101047, two local vars with the same name can share the same slot, but must in that case + // have different start positions. + public LocalVariableTag(UnresolvedType type, String name, int slot, int startPosition) { this.type = type; this.name = name; this.slot = slot; + this.startPos = startPosition; } public String getName() { @@ -44,7 +48,7 @@ public final class LocalVariableTag extends Tag { public boolean equals(Object other) { if (!(other instanceof LocalVariableTag)) return false; LocalVariableTag o = (LocalVariableTag)other; - return o.type.equals(type) && o.name.equals(name) && o.slot == slot; + return o.type.equals(type) && o.name.equals(name) && o.slot == slot && o.startPos == startPos; } private volatile int hashCode = 0; public int hashCode() { @@ -53,6 +57,7 @@ public final class LocalVariableTag extends Tag { ret = 37*ret + type.hashCode(); ret = 37*ret + name.hashCode(); ret = 37*ret + slot; + ret = 37*ret + startPos; hashCode = ret; } return hashCode; |