| Summary: | LocalVariableTable is incorrect for methods that are advised by 'before' advice | ||||||
|---|---|---|---|---|---|---|---|
| Product: | [Tools] AspectJ | Reporter: | yoav <yoav_> | ||||
| Component: | Compiler | Assignee: | aspectj inbox <aspectj-inbox> | ||||
| Status: | RESOLVED FIXED | QA Contact: | |||||
| Severity: | normal | ||||||
| Priority: | P3 | CC: | aclement, yoav_ | ||||
| Version: | 1.6.12 | ||||||
| Target Milestone: | 1.6.12 | ||||||
| Hardware: | PC | ||||||
| OS: | Windows 7 | ||||||
| Whiteboard: | |||||||
| Attachments: |
|
||||||
Created attachment 200942 [details]
patch for an AspectJ class
patch for weaver LazyMethodGen
changes are in, with testcase, also extended their range so parameter names range until the end of the method. (In reply to comment #2) > changes are in, with testcase, also extended their range so parameter names > range until the end of the method. could you post the final patch? not easily now I've committed it. Here is the complete method now:
private void addLocalVariables(MethodGen gen, Map<LocalVariableTag, LVPosition> localVariables) {
// now add local variables
gen.removeLocalVariables();
// this next iteration _might_ be overkill, but we had problems with
// bcel before with duplicate local variables. Now that we're patching
// bcel we should be able to do without it if we're paranoid enough
// through the rest of the compiler.
InstructionHandle methodStart = gen.getInstructionList().getStart();
InstructionHandle methodEnd = gen.getInstructionList().getEnd();
// Determine how many 'slots' are used by parameters to the method.
// Then below we can determine if a local variable is a parameter variable, if it is
// we force its range to from the method start (as it may have been shuffled down
// due to insertion of advice like cflow entry)
int paramSlots = gen.isStatic() ? 0 : 1;
Type[] argTypes = gen.getArgumentTypes();
if (argTypes!=null) {
for (int i = 0; i < argTypes.length; i++) {
if (argTypes[i].getSize() == 2) {
paramSlots += 2;
} else {
paramSlots += 1;
}
}
}
Map<InstructionHandle, Set<Integer>> duplicatedLocalMap = new HashMap<InstructionHandle, Set<Integer>>();
for (LocalVariableTag tag : localVariables.keySet()) {
// have we already added one with the same slot number and start
// location?
// if so, just continue.
LVPosition lvpos = localVariables.get(tag);
InstructionHandle start = (tag.getSlot() < paramSlots ? methodStart : lvpos.start);
InstructionHandle end = (tag.getSlot() < paramSlots ? methodEnd : lvpos.end);
Set<Integer> slots = duplicatedLocalMap.get(start);
if (slots == null) {
slots = new HashSet<Integer>();
duplicatedLocalMap.put(start, slots);
} else if (slots.contains(new Integer(tag.getSlot()))) {
// we already have a var starting at this tag with this slot
continue;
}
slots.add(Integer.valueOf(tag.getSlot()));
Type t = tag.getRealType();
if (t == null) {
t = BcelWorld.makeBcelType(UnresolvedType.forSignature(tag.getType()));
}
gen.addLocalVariable(tag.getName(), t, tag.getSlot(), start, end);
}
}
|
Build Identifier: 20110301-1815 The 'this' variable in the line number table is undefined in the first instructions of the advised method. This can confuse the Java debugging I/S. I suspect the problem is BcelAdvice.getAdviceInstructions. At the end of this method we go over this table and fix any variables that start at position 0: // Fix up the local variables: find any that have a startPC of 0 and ensure they target the new start of the method LocalVariableTable lvt = shadow.getEnclosingMethod().getMemberView().getMethod().getLocalVariableTable(); if (lvt != null) { LocalVariable[] lvTable = lvt.getLocalVariableTable(); for (int i = 0; i < lvTable.length; i++) { LocalVariable lv = lvTable[i]; if (lv.getStartPC() == 0) { start.addTargeter(new LocalVariableTag(lv.getSignature(), lv.getName(), lv.getIndex(), 0)); } } perhaps we can skip here the 'this' variable? Reproducible: Always Steps to Reproduce: 1. advise a method with a before advice 2. At some point when examining a stack frame inside an advice, I am trying to get a mirror to the ‘this’ object using StackFrame.thisObject(). I get an exception: Exception in thread "active event system driver" com.sun.jdi.InternalException: Unexpected JDWP Error: 35 at com.sun.tools.jdi.JDWPException.toJDIException(JDWPException.java:47) at com.sun.tools.jdi.StackFrameImpl.thisObject(StackFrameImpl.java:127)