<classpathentry kind="lib" path="/lib/commons/commons.jar" sourcepath="/lib/commons/commons-src.zip"/>
<classpathentry kind="lib" path="/lib/bcel/bcel.jar" sourcepath="/lib/bcel/bcel-src.zip"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="lib" path="/lib/asm/asm-3.1.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
// Xset'table options
private boolean runMinimalMemory = false;
private boolean shouldPipelineCompilation = true;
+ private boolean shouldGenerateStackMaps = false;
protected boolean bcelRepositoryCaching = xsetBCEL_REPOSITORY_CACHING_DEFAULT.equalsIgnoreCase("true");
private boolean fastMethodPacking = false;
private boolean completeBinaryTypes = false;
public final static String xsetDEBUG_BRIDGING = "debugBridging"; // default false
public final static String xsetBCEL_REPOSITORY_CACHING = "bcelRepositoryCaching";
public final static String xsetPIPELINE_COMPILATION = "pipelineCompilation";
+ public final static String xsetGENERATE_STACKMAPS = "generateStackMaps";
public final static String xsetPIPELINE_COMPILATION_DEFAULT = "true";
public final static String xsetCOMPLETE_BINARY_TYPES = "completeBinaryTypes";
public final static String xsetCOMPLETE_BINARY_TYPES_DEFAULT = "false";
s = p.getProperty(xsetPIPELINE_COMPILATION, xsetPIPELINE_COMPILATION_DEFAULT);
shouldPipelineCompilation = s.equalsIgnoreCase("true");
+
+ s = p.getProperty(xsetGENERATE_STACKMAPS, "false");
+ shouldGenerateStackMaps = s.equalsIgnoreCase("true");
s = p.getProperty(xsetCOMPLETE_BINARY_TYPES, xsetCOMPLETE_BINARY_TYPES_DEFAULT);
completeBinaryTypes = s.equalsIgnoreCase("true");
ensureAdvancedConfigurationProcessed();
return shouldPipelineCompilation;
}
-
+
+ public boolean shouldGenerateStackMaps() {
+ ensureAdvancedConfigurationProcessed();
+ return shouldGenerateStackMaps;
+ }
+
public void setIncrementalCompileCouldFollow(boolean b) {
incrementalCompileCouldFollow = b;
}
import org.aspectj.weaver.World;
import org.aspectj.weaver.AjAttribute.WeaverVersionInfo;
import org.aspectj.weaver.UnresolvedType.TypeKind;
+import org.aspectj.weaver.bcel.asm.AsmDetector;
+import org.aspectj.weaver.bcel.asm.StackMapAdder;
/**
* Lazy lazy lazy. We don't unpack the underlying class unless necessary. Things like new methods and annotations accumulate in here
int highestLineNumber = 0; // ---- JSR 45 info
- private final SortedMap /* <String, InlinedSourceFileInfo> */inlinedFiles = new TreeMap();
+ private SortedMap /* <String, InlinedSourceFileInfo> */inlinedFiles = new TreeMap();
private boolean regenerateGenericSignatureAttribute = false;
private BcelObjectType myType; // XXX is not set for types we create
private ClassGen myGen;
- private final ConstantPool cp;
- private final World world;
- private final String packageName = null;
-
- private final List /* BcelField */fields = new ArrayList();
- private final List /* LazyMethodGen */methodGens = new ArrayList();
- private final List /* LazyClassGen */classGens = new ArrayList();
- private final List /* AnnotationGen */annotations = new ArrayList();
+ private ConstantPool cp;
+ private World world;
+ private String packageName = null;
+
+ private List /* BcelField */fields = new ArrayList();
+ private List /* LazyMethodGen */methodGens = new ArrayList();
+ private List /* LazyClassGen */classGens = new ArrayList();
+ private List /* AnnotationGen */annotations = new ArrayList();
private int childCounter = 0;
- private final InstructionFactory fact;
+ private InstructionFactory fact;
private boolean isSerializable = false;
private boolean hasSerialVersionUIDField = false;
writeBack(world);
byte[] wovenClassFileData = myGen.getJavaClass().getBytes();
// if is java 6 class file
- // if (myGen.getMajor()>=Constants.MAJOR_1_6 && AsmDetector.isAsmAround) {
- // wovenClassFileData = StackMapAdder.addStackMaps(wovenClassFileData);
- // }
-
+ if (myGen.getMajor()>=Constants.MAJOR_1_6 && world.shouldGenerateStackMaps() && AsmDetector.isAsmAround) {
+ wovenClassFileData = StackMapAdder.addStackMaps(world,wovenClassFileData);
+ }
+
WeaverStateInfo wsi = myType.getWeaverState();// getOrCreateWeaverStateInfo();
if (wsi != null && wsi.isReweavable()) { // && !reweavableDataInserted
// reweavableDataInserted = true;
--- /dev/null
+package org.aspectj.weaver.bcel.asm;
+
+import java.lang.reflect.Method;
+
+/**
+ * Determines if a version of asm is around that will enable us to add
+ * stack map attributes to classes that we produce.
+ *
+ * @author Andy Clement
+ */
+public class AsmDetector {
+
+ public static boolean isAsmAround;
+
+ static {
+ try {
+ Class reader = Class.forName("org.objectweb.asm.ClassReader");
+ Class visitor = Class.forName("org.objectweb.asm.ClassVisitor");
+ Method m = reader.getMethod("accept",new Class[]{visitor,Integer.TYPE});
+ isAsmAround = m!=null;
+ } catch (Exception e ) {
+ isAsmAround = false;
+ }
+ // System.out.println(isAsmAround?"ASM detected":"No ASM found");
+ }
+}
--- /dev/null
+package org.aspectj.weaver.bcel.asm;
+
+import org.aspectj.weaver.ResolvedType;
+import org.aspectj.weaver.UnresolvedType;
+import org.aspectj.weaver.World;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+
+/**
+ * Uses asm to add the stack map attribute to methods in a class. The class is passed in as pure byte data
+ * and then a reader/writer process it. The writer is wired into the world so that types can be resolved
+ * and getCommonSuperClass() can be implemented without class loading using the context class loader.
+ *
+ * @author Andy Clement
+ */
+public class StackMapAdder {
+
+ public static byte[] addStackMaps(World world, byte[] data) {
+ try {
+ ClassReader cr = new ClassReader(data);
+ ClassWriter cw = new AspectJConnectClassWriter(world);
+ cr.accept(cw,0);
+ return cw.toByteArray();
+ } catch (Throwable t) {
+ System.err.println("AspectJ Internal Error: unable to add stackmap attributes. "+t.getMessage());
+ AsmDetector.isAsmAround=false;
+ return data;
+ }
+ }
+
+ private static class AspectJConnectClassWriter extends ClassWriter {
+ private World world;
+
+ public AspectJConnectClassWriter(World w) {
+ super(ClassWriter.COMPUTE_FRAMES);
+ this.world = w;
+ }
+
+ // Implementation of getCommonSuperClass() that avoids Class.forName()
+ protected String getCommonSuperClass(final String type1, final String type2) {
+
+ ResolvedType resolvedType1 = world.resolve(UnresolvedType.forName(type1.replace('/','.')));
+ ResolvedType resolvedType2 = world.resolve(UnresolvedType.forName(type2.replace('/','.')));
+
+ if (resolvedType1.isAssignableFrom(resolvedType2)) {
+ return type1;
+ }
+
+ if (resolvedType2.isAssignableFrom(resolvedType1)) {
+ return type2;
+ }
+
+ if (resolvedType1.isInterface() || resolvedType2.isInterface()) {
+ return "java/lang/Object";
+ } else {
+ do {
+ resolvedType1 = resolvedType1.getSuperclass();
+ } while (!resolvedType1.isAssignableFrom(resolvedType2));
+ return resolvedType1.getName().replace('.','/');
+ }
+ }
+ }
+}