From: aclement Date: Wed, 17 Sep 2008 19:49:01 +0000 (+0000) Subject: can add stackmap attributes with: -1.6 -Xset:generateStackMaps=true X-Git-Tag: V1_6_2~56 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=3a9d4a2bc3092d0e8bd92eec472ddd8203f8ece8;p=aspectj.git can add stackmap attributes with: -1.6 -Xset:generateStackMaps=true --- diff --git a/weaver/.classpath b/weaver/.classpath index 0ac3d80ff..adee2df97 100644 --- a/weaver/.classpath +++ b/weaver/.classpath @@ -12,5 +12,6 @@ + diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java index 265ccbc08..ea1253a0a 100644 --- a/weaver/src/org/aspectj/weaver/World.java +++ b/weaver/src/org/aspectj/weaver/World.java @@ -111,6 +111,7 @@ public abstract class World implements Dump.INode { // 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; @@ -758,6 +759,7 @@ public abstract class World implements Dump.INode { 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"; @@ -1144,6 +1146,9 @@ public abstract class World implements Dump.INode { 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"); @@ -1183,7 +1188,12 @@ public abstract class World implements Dump.INode { ensureAdvancedConfigurationProcessed(); return shouldPipelineCompilation; } - + + public boolean shouldGenerateStackMaps() { + ensureAdvancedConfigurationProcessed(); + return shouldGenerateStackMaps; + } + public void setIncrementalCompileCouldFollow(boolean b) { incrementalCompileCouldFollow = b; } diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java index 253e50e15..b70f7db94 100644 --- a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java +++ b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java @@ -65,6 +65,8 @@ import org.aspectj.weaver.WeaverStateInfo; 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 @@ -79,23 +81,23 @@ public final class LazyClassGen { int highestLineNumber = 0; // ---- JSR 45 info - private final SortedMap /* */inlinedFiles = new TreeMap(); + private SortedMap /* */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; @@ -613,10 +615,10 @@ public final class LazyClassGen { 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; diff --git a/weaver/src/org/aspectj/weaver/bcel/asm/AsmDetector.java b/weaver/src/org/aspectj/weaver/bcel/asm/AsmDetector.java new file mode 100644 index 000000000..415e38efc --- /dev/null +++ b/weaver/src/org/aspectj/weaver/bcel/asm/AsmDetector.java @@ -0,0 +1,26 @@ +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"); + } +} diff --git a/weaver/src/org/aspectj/weaver/bcel/asm/StackMapAdder.java b/weaver/src/org/aspectj/weaver/bcel/asm/StackMapAdder.java new file mode 100644 index 000000000..96d6a8822 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/bcel/asm/StackMapAdder.java @@ -0,0 +1,63 @@ +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('.','/'); + } + } + } +}