aboutsummaryrefslogtreecommitdiffstats
path: root/weaver
diff options
context:
space:
mode:
authorehilsdal <ehilsdal>2003-11-17 10:45:33 +0000
committerehilsdal <ehilsdal>2003-11-17 10:45:33 +0000
commita9928aafc2f0333ca7cc1ac0cbd46f916c58829b (patch)
tree1dacac06da0e0b393d50324e82bee757a84d55a9 /weaver
parentc796217f060ebf53e4561215307927e424e35358 (diff)
downloadaspectj-a9928aafc2f0333ca7cc1ac0cbd46f916c58829b.tar.gz
aspectj-a9928aafc2f0333ca7cc1ac0cbd46f916c58829b.zip
Added JSR45 attribute
Diffstat (limited to 'weaver')
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelShadow.java18
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java11
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java167
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java21
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/Utility.java13
5 files changed, 212 insertions, 18 deletions
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
index 6d45e96db..0ffdfc6be 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelShadow.java
@@ -1189,8 +1189,8 @@ public class BcelShadow extends Shadow {
return exitInstructions;
}
});
-
-
+
+
range.insert(entryInstructions, Range.InsideBefore);
}
@@ -1325,10 +1325,20 @@ public class BcelShadow extends Shadow {
parameterTypes,
new String[0],
getEnclosingClass());
+
+ String donorFileName = adviceMethod.getEnclosingClass().getInternalFileName();
+ String recipientFileName = getEnclosingClass().getInternalFileName();
+// System.err.println("donor " + donorFileName);
+// System.err.println("recip " + recipientFileName);
+ if (! donorFileName.equals(recipientFileName)) {
+ localAdviceMethod.fromFilename = donorFileName;
+ getEnclosingClass().addInlinedSourceFileInfo(
+ donorFileName,
+ adviceMethod.highestLineNumber);
+ }
getEnclosingClass().addMethodGen(localAdviceMethod);
-
// create a map that will move all slots in advice method forward by extraParamOffset
// in order to make room for the new proceed-required arguments that are added at
// the beginning of the parameter list
@@ -1341,6 +1351,8 @@ public class BcelShadow extends Shadow {
localAdviceMethod.getBody().insert(
BcelClassWeaver.genInlineInstructions(adviceMethod,
localAdviceMethod, varMap, fact, true));
+
+
localAdviceMethod.setMaxLocals(nVars);
diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
index 3a83bf2c4..97f26c916 100644
--- a/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
+++ b/weaver/src/org/aspectj/weaver/bcel/BcelWeaver.java
@@ -523,19 +523,18 @@ public class BcelWeaver implements IWeaver {
private void dump(UnwovenClassFile classFile, LazyClassGen clazz) throws IOException {
if (zipOutputStream != null) {
String mainClassName = classFile.getJavaClass().getClassName();
-
writeZipEntry(getEntryName(mainClassName),
- clazz.getJavaClass().getBytes());
- if (!clazz.getChildClasses().isEmpty()) {
- for (Iterator i = clazz.getChildClasses().iterator(); i.hasNext();) {
+ clazz.getJavaClass(world).getBytes());
+ if (!clazz.getChildClasses(world).isEmpty()) {
+ for (Iterator i = clazz.getChildClasses(world).iterator(); i.hasNext();) {
UnwovenClassFile.ChildClass c = (UnwovenClassFile.ChildClass) i.next();
writeZipEntry(getEntryName(mainClassName + "$" + c.name), c.bytes);
}
}
} else {
classFile.writeWovenBytes(
- clazz.getJavaClass().getBytes(),
- clazz.getChildClasses()
+ clazz.getJavaClass(world).getBytes(),
+ clazz.getChildClasses(world)
);
}
}
diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java
index b21460186..49d231e3e 100644
--- a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java
+++ b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java
@@ -25,11 +25,16 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.Attribute;
+import org.apache.bcel.classfile.ConstantUtf8;
import org.apache.bcel.classfile.Field;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
+import org.apache.bcel.classfile.Unknown;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.FieldGen;
@@ -41,6 +46,7 @@ import org.apache.bcel.generic.ObjectType;
import org.apache.bcel.generic.PUSH;
import org.apache.bcel.generic.RETURN;
import org.apache.bcel.generic.Type;
+import org.aspectj.bridge.IMessage;
import org.aspectj.util.CollectionUtil;
import org.aspectj.weaver.AjAttribute;
import org.aspectj.weaver.BCException;
@@ -51,7 +57,120 @@ import org.aspectj.weaver.TypeX;
import org.aspectj.weaver.WeaverStateInfo;
public final class LazyClassGen {
+
+ // ---- JSR 45 info
+ int highestLineNumber = 0;
+
+ private SortedMap /* <String, InlinedSourceFileInfo> */ inlinedFiles = new TreeMap();
+
+ static class InlinedSourceFileInfo {
+ int highestLineNumber;
+ int offset; // calculated
+
+ InlinedSourceFileInfo(int highestLineNumber) {
+ this.highestLineNumber = highestLineNumber;
+ }
+ }
+
+ void addInlinedSourceFileInfo(String fullpath, int highestLineNumber) {
+ Object o = inlinedFiles.get(fullpath);
+ if (o != null) {
+ InlinedSourceFileInfo info = (InlinedSourceFileInfo) o;
+ if (info.highestLineNumber < highestLineNumber) {
+ info.highestLineNumber = highestLineNumber;
+ }
+ } else {
+ inlinedFiles.put(fullpath, new InlinedSourceFileInfo(highestLineNumber));
+ }
+ }
+
+ void calculateSourceDebugExtensionOffsets() {
+ int i = roundUpToHundreds(highestLineNumber);
+ for (Iterator iter = inlinedFiles.values().iterator(); iter.hasNext();) {
+ InlinedSourceFileInfo element = (InlinedSourceFileInfo) iter.next();
+ element.offset = i;
+ i = roundUpToHundreds(i + element.highestLineNumber);
+ }
+ }
+ private static int roundUpToHundreds(int i) {
+ return ((i / 100) + 1) * 100;
+ }
+
+ int getSourceDebugExtensionOffset(String fullpath) {
+ return ((InlinedSourceFileInfo) inlinedFiles.get(fullpath)).offset;
+ }
+
+ private Unknown getSourceDebugExtensionAttribute() {
+ int nameIndex = constantPoolGen.addUtf8("SourceDebugExtension");
+ String data = getSourceDebugExtensionString();
+ System.err.println(data);
+ byte[] bytes = Utility.stringToUTF(data);
+ int length = bytes.length;
+
+ return new Unknown(nameIndex, length, bytes, constantPoolGen.getConstantPool());
+ }
+
+// private LazyClassGen() {}
+// public static void main(String[] args) {
+// LazyClassGen m = new LazyClassGen();
+// m.highestLineNumber = 37;
+// m.inlinedFiles.put("boo/baz/foo.java", new InlinedSourceFileInfo( 83));
+// m.inlinedFiles.put("boo/barz/foo.java", new InlinedSourceFileInfo(292));
+// m.inlinedFiles.put("boo/baz/moo.java", new InlinedSourceFileInfo(128));
+// m.calculateSourceDebugExtensionOffsets();
+// System.err.println(m.getSourceDebugExtensionString());
+// }
+
+ // For the entire pathname, we're using package names. This is probably wrong.
+ private String getSourceDebugExtensionString() {
+ StringBuffer out = new StringBuffer();
+ String myFileName = getFileName();
+ // header section
+ out.append("SMAP\n");
+ out.append(myFileName);
+ out.append("\nAspectJ\n");
+ // stratum section
+ out.append("*S AspectJ\n");
+ // file section
+ out.append("*F\n");
+ out.append("1 ");
+ out.append(myFileName);
+ out.append("\n");
+ int i = 2;
+ for (Iterator iter = inlinedFiles.keySet().iterator(); iter.hasNext();) {
+ String element = (String) iter.next();
+ int ii = element.lastIndexOf('/');
+ if (ii == -1) {
+ out.append(i++); out.append(' ');
+ out.append(element); out.append('\n');
+ } else {
+ out.append("+ "); out.append(i++); out.append(' ');
+ out.append(element.substring(ii+1)); out.append('\n');
+ out.append(element); out.append('\n');
+ }
+ }
+ // emit line section
+ out.append("*L\n");
+ out.append("1#1,");
+ out.append(highestLineNumber);
+ out.append(":1,1\n");
+ i = 2;
+ for (Iterator iter = inlinedFiles.values().iterator(); iter.hasNext();) {
+ InlinedSourceFileInfo element = (InlinedSourceFileInfo) iter.next();
+ out.append("1#");
+ out.append(i++); out.append(',');
+ out.append(element.highestLineNumber); out.append(":");
+ out.append(element.offset + 1); out.append(",1\n");
+ }
+ // end section
+ out.append("*E\n");
+ // and finish up...
+ return out.toString();
+ }
+
+ // ---- end JSR45-related stuff
+
/** Emit disassembled class and newline to out */
public static void disassemble(String path, String name, PrintStream out)
throws IOException {
@@ -123,6 +242,17 @@ public final class LazyClassGen {
}
+ public String getInternalFileName() {
+ String str = getInternalClassName();
+ int index = str.lastIndexOf('/');
+ if (index == -1) {
+ return getFileName();
+ } else {
+ return str.substring(0, index + 1) + getFileName();
+ }
+ }
+
+
public File getPackagePath(File root) {
String str = getInternalClassName();
int index = str.lastIndexOf('/');
@@ -143,6 +273,7 @@ public final class LazyClassGen {
public void addMethodGen(LazyMethodGen gen) {
//assert gen.getClassName() == super.getClassName();
methodGens.add(gen);
+ if (highestLineNumber < gen.highestLineNumber) highestLineNumber = gen.highestLineNumber;
}
public List getMethodGens() {
@@ -150,7 +281,7 @@ public final class LazyClassGen {
}
- private void writeBack() {
+ private void writeBack(BcelWorld world) {
if (myType != null && myType.getWeaverState() != null) {
myGen.addAttribute(BcelAttributes.bcelAttribute(
new AjAttribute.WeaverState(myType.getWeaverState()),
@@ -161,16 +292,42 @@ public final class LazyClassGen {
int len = methodGens.size();
myGen.setMethods(new Method[0]);
+
+ calculateSourceDebugExtensionOffsets();
for (int i = 0; i < len; i++) {
LazyMethodGen gen = (LazyMethodGen) methodGens.get(i);
// we skip empty clinits
if (isEmptyClinit(gen)) continue;
myGen.addMethod(gen.getMethod());
}
+ if (inlinedFiles.size() != 0) {
+ if (hasSourceDebugExtensionAttribute(myGen)) {
+ world.showMessage(
+ IMessage.WARNING,
+ "overwriting JSR45 information for "
+ + getFileName()
+ + " (compiler limitation)",
+ null,
+ null);
+ }
+ myGen.addAttribute(getSourceDebugExtensionAttribute());
+ }
}
- public JavaClass getJavaClass() {
- writeBack();
+ private static boolean hasSourceDebugExtensionAttribute(ClassGen gen) {
+ ConstantPoolGen pool = gen.getConstantPool();
+ Attribute[] attrs = gen.getAttributes();
+ for (int i = 0; i < attrs.length; i++) {
+ if ("SourceDebugExtension"
+ .equals(((ConstantUtf8) pool.getConstant(attrs[i].getNameIndex())).getBytes())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public JavaClass getJavaClass(BcelWorld world) {
+ writeBack(world);
return myGen.getJavaClass();
}
@@ -197,12 +354,12 @@ public final class LazyClassGen {
}
- public List getChildClasses() {
+ public List getChildClasses(BcelWorld world) {
if (classGens.isEmpty()) return Collections.EMPTY_LIST;
List ret = new ArrayList();
for (Iterator i = classGens.iterator(); i.hasNext();) {
LazyClassGen clazz = (LazyClassGen) i.next();
- byte[] bytes = clazz.getJavaClass().getBytes();
+ byte[] bytes = clazz.getJavaClass(world).getBytes();
String name = clazz.getName();
int index = name.lastIndexOf('$');
// XXX this could be bad, check use of dollar signs.
diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
index a6dcb0cc6..c0b125143 100644
--- a/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
+++ b/weaver/src/org/aspectj/weaver/bcel/LazyMethodGen.java
@@ -83,6 +83,14 @@ public final class LazyMethodGen {
private final Attribute[] attributes;
/* private */ final LazyClassGen enclosingClass;
private final BcelMethod memberView;
+ int highestLineNumber = 0;
+
+ /** This is nonnull if this method is the result of an "inlining". We currently
+ * copy methods into other classes for around advice. We add this field so
+ * we can get JSR45 information correct. If/when we do _actual_ inlining,
+ * we'll need to subtype LineNumberTag to have external line numbers.
+ */
+ String fromFilename = null;
private int maxLocals;
@@ -220,8 +228,7 @@ public final class LazyMethodGen {
return ih;
}
}
- }
-
+ }
private void unpackLineNumbers(MethodGen gen) {
LineNumberTag lr = null;
@@ -233,7 +240,9 @@ public final class LazyMethodGen {
if (targeter instanceof LineNumberGen) {
LineNumberGen lng = (LineNumberGen) targeter;
lng.updateTarget(ih, null);
- lr = new LineNumberTag(lng.getSourceLine());
+ int lineNumber = lng.getSourceLine();
+ if (highestLineNumber < lineNumber) highestLineNumber = lineNumber;
+ lr = new LineNumberTag(lineNumber);
}
}
}
@@ -830,13 +839,17 @@ public final class LazyMethodGen {
// now deal with line numbers
// and store up info for local variables
InstructionTargeter[] targeters = ih.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);
+ gen.addLineNumber(jh, line + lineNumberOffset);
currLine = line;
}
} else if (targeter instanceof LocalVariableTag) {
diff --git a/weaver/src/org/aspectj/weaver/bcel/Utility.java b/weaver/src/org/aspectj/weaver/bcel/Utility.java
index 16527dcc3..2ddfe8506 100644
--- a/weaver/src/org/aspectj/weaver/bcel/Utility.java
+++ b/weaver/src/org/aspectj/weaver/bcel/Utility.java
@@ -14,6 +14,8 @@
package org.aspectj.weaver.bcel;
import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
import java.io.IOException;
import java.lang.reflect.Modifier;
@@ -152,6 +154,17 @@ public class Utility {
Type.getArgumentTypes(newMethod.getSignature()),
kind);
}
+
+ public static byte[] stringToUTF(String s) {
+ try {
+ ByteArrayOutputStream out0 = new ByteArrayOutputStream();
+ DataOutputStream out1 = new DataOutputStream(out0);
+ out1.writeUTF(s);
+ return out0.toByteArray();
+ } catch (IOException e) {
+ throw new RuntimeException("sanity check");
+ }
+ }
public static Instruction createInstanceof(InstructionFactory fact, ReferenceType t) {
int cpoolEntry =