From: Andy Clement Date: Wed, 28 Feb 2018 19:53:14 +0000 (-0800) Subject: Bug#531694: generate more optional thisJoinPoint construction code X-Git-Tag: V1_9_0~9 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=7d47cba01043c93bab95b59e66b727580351e85f;p=aspectj.git Bug#531694: generate more optional thisJoinPoint construction code This commit introduces some new methods into the runtime Factory class and modifies code generation to use them (and to use the form of the LDC bytecode that loads class constants). --- diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionFactory.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionFactory.java index c5db1904a..4e1e6c8a8 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionFactory.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/InstructionFactory.java @@ -761,6 +761,7 @@ public class InstructionFactory implements InstructionConstants { iList.append(new InstructionCP(Instruction.LDC_W, classIndex)); } } else { + className = className.replace('/', '.'); iList.append(InstructionFactory.PUSH(cp, className)); iList.append(this.createInvoke("java.lang.Class", "forName", ObjectType.CLASS, Type.STRINGARRAY1, Constants.INVOKESTATIC)); diff --git a/bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java b/bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java index e1dc47348..9ce007b4f 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/generic/Type.java @@ -89,9 +89,9 @@ public abstract class Type { public static final BasicType CHAR = new BasicType(Constants.T_CHAR); public static final ObjectType OBJECT = new ObjectType("java.lang.Object"); public static final ObjectType STRING = new ObjectType("java.lang.String"); - public static final ObjectType OBJECT_ARRAY = new ObjectType("java.lang.Object[]"); - public static final ObjectType STRING_ARRAY = new ObjectType("java.lang.String[]"); - public static final ObjectType CLASS_ARRAY = new ObjectType("java.lang.Class[]"); + public static final ArrayType OBJECT_ARRAY = new ArrayType("java.lang.Object",1); + public static final ArrayType STRING_ARRAY = new ArrayType("java.lang.String",1); + public static final ArrayType CLASS_ARRAY = new ArrayType("java.lang.Class",1); public static final ObjectType STRINGBUFFER = new ObjectType("java.lang.StringBuffer"); public static final ObjectType STRINGBUILDER = new ObjectType("java.lang.StringBuilder"); public static final ObjectType THROWABLE = new ObjectType("java.lang.Throwable"); @@ -130,6 +130,7 @@ public abstract class Type { commonTypes.put(CLASS.getSignature(), CLASS); commonTypes.put(OBJECT.getSignature(), OBJECT); commonTypes.put(STRING_ARRAY.getSignature(), STRING_ARRAY); + commonTypes.put(CLASS_ARRAY.getSignature(), CLASS_ARRAY); commonTypes.put(OBJECT_ARRAY.getSignature(), OBJECT_ARRAY); commonTypes.put(INTEGER.getSignature(), INTEGER); commonTypes.put(EXCEPTION.getSignature(), EXCEPTION); diff --git a/build/products/tools/dist/lib/aspectjrt.jar b/build/products/tools/dist/lib/aspectjrt.jar index e69de29bb..935830ebc 100644 Binary files a/build/products/tools/dist/lib/aspectjrt.jar and b/build/products/tools/dist/lib/aspectjrt.jar differ diff --git a/build/updateAspectjrt.sh b/build/updateAspectjrt.sh new file mode 100755 index 000000000..03fcd7f2f --- /dev/null +++ b/build/updateAspectjrt.sh @@ -0,0 +1,3 @@ +cp ../aj-build/dist/tools/lib/aspectjrt.jar ../lib/test/aspectjrt.jar +cp ../aj-build/dist/tools/lib/aspectjrt.jar ../lib/aspectj/lib/aspectjrt.jar +cp ../aj-build/dist/tools/lib/aspectjrt.jar ../build/products/tools/dist/lib/aspectjrt.jar diff --git a/lib/aspectj/lib/aspectjrt.jar b/lib/aspectj/lib/aspectjrt.jar index ef06aa7fd..935830ebc 100644 Binary files a/lib/aspectj/lib/aspectjrt.jar and b/lib/aspectj/lib/aspectjrt.jar differ diff --git a/lib/bcel/bcel-src.zip b/lib/bcel/bcel-src.zip index 1cbe73979..b98e0889e 100644 Binary files a/lib/bcel/bcel-src.zip and b/lib/bcel/bcel-src.zip differ diff --git a/lib/bcel/bcel-verifier.jar b/lib/bcel/bcel-verifier.jar index b55ed6429..cee235ad9 100644 Binary files a/lib/bcel/bcel-verifier.jar and b/lib/bcel/bcel-verifier.jar differ diff --git a/lib/bcel/bcel.jar b/lib/bcel/bcel.jar index 2306787c5..793bf0d0d 100644 Binary files a/lib/bcel/bcel.jar and b/lib/bcel/bcel.jar differ diff --git a/lib/test/aspectjrt.jar b/lib/test/aspectjrt.jar index f0c7d5f7c..935830ebc 100644 Binary files a/lib/test/aspectjrt.jar and b/lib/test/aspectjrt.jar differ diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java index ada5639ef..032719165 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/BuildArgParser.java @@ -807,8 +807,10 @@ public class BuildArgParser extends Main { buildConfig.setTargetAspectjRuntimeLevel(Constants.RUNTIME_LEVEL_12); } else if (arg.endsWith(":1.5")) { buildConfig.setTargetAspectjRuntimeLevel(Constants.RUNTIME_LEVEL_15); + } else if (arg.endsWith(":1.9")) { + buildConfig.setTargetAspectjRuntimeLevel(Constants.RUNTIME_LEVEL_19); } else { - showError("-Xajruntimetarget: only supports a target level of 1.2 or 1.5"); + showError("-Xajruntimetarget: supports a target level of 1.2, 1.5, 1.9"); } } else if (arg.equals("-timers")) { buildConfig.setTiming(true); diff --git a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java index b92a4b439..4c7873df0 100644 --- a/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java +++ b/org.aspectj.ajdt.core/src/org/aspectj/ajdt/ajc/ConfigParser.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.StringTokenizer; public class ConfigParser { Location location; @@ -44,6 +45,13 @@ public class ConfigParser { for (int i = 0; i < argsArray.length; i++) { args.add(new Arg(argsArray[i], location)); } + String aspectjOptions = System.getProperty("ASPECTJ_OPTS"); + if (aspectjOptions != null) { + StringTokenizer st = new StringTokenizer(aspectjOptions); + while (st.hasMoreElements()) { + args.add(new Arg(st.nextToken(),location)); + } + } parseArgs(args); } @@ -138,12 +146,14 @@ public class ConfigParser { if (sourceFile.getName().charAt(0) == '*') { if (sourceFile.getName().equals("*.java")) { addFiles(sourceFile.getParentFile(), new FileFilter() { + @Override public boolean accept(File f) { return f != null && f.getName().endsWith(".java"); } }); } else if (sourceFile.getName().equals("*.aj")) { addFiles(sourceFile.getParentFile(), new FileFilter() { + @Override public boolean accept(File f) { return f != null && f.getName().endsWith(".aj"); } @@ -287,6 +297,7 @@ public class ConfigParser { private Location location; private String value; + @Override public String toString() { return "Arg[location="+location+" value="+value+"]"; } @@ -320,6 +331,7 @@ public class ConfigParser { public abstract int getLine(); + @Override public abstract String toString(); } @@ -332,36 +344,44 @@ public class ConfigParser { this.file = file; } + @Override public File getFile() { return file; } + @Override public File getDirectory() { return file.getParentFile(); } + @Override public int getLine() { return line; } + @Override public String toString() { return file.getPath() + ":" + line; } } static class CommandLineLocation extends Location { + @Override public File getFile() { return new File(System.getProperty("user.dir")); } + @Override public File getDirectory() { return new File(System.getProperty("user.dir")); } + @Override public int getLine() { return -1; } + @Override public String toString() { return "command-line"; } diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/Constants.java b/org.aspectj.matcher/src/org/aspectj/weaver/Constants.java index 4b99a32ab..bdbde3853 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/Constants.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/Constants.java @@ -22,6 +22,7 @@ public interface Constants { public final static String RUNTIME_LEVEL_12 = "1.2"; public final static String RUNTIME_LEVEL_15 = "1.5"; + public final static String RUNTIME_LEVEL_19 = "1.9"; // Default for 1.5.0 public final static String RUNTIME_LEVEL_DEFAULT = RUNTIME_LEVEL_15; diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/RuntimeVersion.java b/org.aspectj.matcher/src/org/aspectj/weaver/RuntimeVersion.java new file mode 100644 index 000000000..0cf90a9a2 --- /dev/null +++ b/org.aspectj.matcher/src/org/aspectj/weaver/RuntimeVersion.java @@ -0,0 +1,47 @@ +/* ******************************************************************* + * Copyright (c) 2018 Contributors + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * ******************************************************************/ +package org.aspectj.weaver; + +/** + * Captures important runtime versions. Typically new versions are added here if something + * changes in the runtime and the code generation may be able to do something different + * (more optimal) for a later runtime. + * + * @author Andy Clement + */ +public enum RuntimeVersion { + + V1_2("1.2"), V1_5("1.5"), V1_6_10("1.6.10"), V1_9("1.9"); + + private String[] aliases = null; + + RuntimeVersion(String... aliases) { + this.aliases = aliases; + } + + public static RuntimeVersion getVersionFor(String version) { + for (RuntimeVersion candidateVersion: values()) { + if (candidateVersion.name().equals(version)) { + return candidateVersion; + } + if (candidateVersion.aliases != null) { + for (String alias: candidateVersion.aliases) { + if (alias.equals(version)) { + return candidateVersion; + } + } + } + } + return null; + } + + public boolean isThisVersionOrLater(RuntimeVersion version) { + return this.compareTo(version) >= 0; + } +} diff --git a/org.aspectj.matcher/src/org/aspectj/weaver/World.java b/org.aspectj.matcher/src/org/aspectj/weaver/World.java index 19d61f5be..644f232ac 100644 --- a/org.aspectj.matcher/src/org/aspectj/weaver/World.java +++ b/org.aspectj.matcher/src/org/aspectj/weaver/World.java @@ -110,8 +110,9 @@ public abstract class World implements Dump.INode { private boolean incrementalCompileCouldFollow = false; /** The level of the aspectjrt.jar the code we generate needs to run on */ - private String targetAspectjRuntimeLevel = Constants.RUNTIME_LEVEL_DEFAULT; - + public static final RuntimeVersion RUNTIME_LEVEL_DEFAULT = RuntimeVersion.V1_5; + private RuntimeVersion targetAspectjRuntimeLevel = RUNTIME_LEVEL_DEFAULT; + /** Flags for the new joinpoints that are 'optional': -Xjoinpoints:arrayconstruction -Xjoinpoints:synchronization */ private boolean optionalJoinpoint_ArrayConstruction = false; private boolean optionalJoinpoint_Synchronization = false; @@ -202,6 +203,7 @@ public abstract class World implements Dump.INode { /** * Dump processing when a fatal error occurs */ + @Override public void accept(Dump.IVisitor visitor) { // visitor.visitObject("Extra configuration:"); // visitor.visitList(extraConfiguration.); @@ -982,7 +984,7 @@ public abstract class World implements Dump.INode { } public void setTargetAspectjRuntimeLevel(String s) { - targetAspectjRuntimeLevel = s; + targetAspectjRuntimeLevel = RuntimeVersion.getVersionFor(s); } public void setOptionalJoinpoints(String jps) { @@ -1005,20 +1007,18 @@ public abstract class World implements Dump.INode { return optionalJoinpoint_Synchronization; } - public String getTargetAspectjRuntimeLevel() { + public RuntimeVersion getTargetAspectjRuntimeLevel() { return targetAspectjRuntimeLevel; } - // OPTIMIZE are users falling foul of not supplying -1.5 and so targetting - // the old runtime? + // OPTIMIZE are users falling foul of not supplying -1.5 and so targetting the old runtime? public boolean isTargettingAspectJRuntime12() { boolean b = false; // pr116679 if (!isInJava5Mode()) { b = true; } else { - b = getTargetAspectjRuntimeLevel().equals(org.aspectj.weaver.Constants.RUNTIME_LEVEL_12); + b = (getTargetAspectjRuntimeLevel() == RuntimeVersion.V1_2); } - // System.err.println("Asked if targetting runtime 1.2 , returning: "+b); return b; } diff --git a/runtime/src/org/aspectj/runtime/reflect/Factory.java b/runtime/src/org/aspectj/runtime/reflect/Factory.java index 06e073873..759a1367b 100644 --- a/runtime/src/org/aspectj/runtime/reflect/Factory.java +++ b/runtime/src/org/aspectj/runtime/reflect/Factory.java @@ -1,6 +1,6 @@ /* ******************************************************************* * Copyright (c) 1999-2001 Xerox Corporation, - * 2002 Palo Alto Research Center, Incorporated (PARC). + * 2002-2018 Palo Alto Research Center, Incorporated (PARC), Contributors * All rights reserved. * This program and the accompanying materials are made available * under the terms of the Eclipse Public License v1.0 @@ -8,9 +8,10 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * Xerox/PARC initial implementation + * Xerox/PARC initial implementation * Alex Vasseur new factory methods for variants of JP - * Abraham Nevado new factory methods for collapsed SJPs + * Abraham Nevado new factory methods for collapsed SJPs + * Andy Clement new factory methods that rely on LDC * ******************************************************************/ package org.aspectj.runtime.reflect; @@ -38,6 +39,9 @@ public final class Factory { ClassLoader lookupClassLoader; String filename; int count; + + private static final Class[] NO_TYPES = new Class[0]; + private static final String[] NO_STRINGS = new String[0]; static Hashtable prims = new Hashtable(); static { @@ -55,7 +59,7 @@ public final class Factory { static Class makeClass(String s, ClassLoader loader) { if (s.equals("*")) return null; - Class ret = (Class) prims.get(s); + Class ret = (Class)prims.get(s); if (ret != null) return ret; try { @@ -113,6 +117,105 @@ public final class Factory { Signature sig = this.makeMethodSig(modifiers, methodName, declaringType, paramTypes, paramNames, "", returnType); return new JoinPointImpl.StaticPartImpl(count++, kind, sig, makeSourceLoc(l, -1)); } + + // These are direct routes to creating thisJoinPoint and thisEnclosingJoinPoint objects + // added in 1.9.1 + + public JoinPoint.StaticPart makeMethodSJP(String kind, int modifiers, String methodName, Class declaringType, Class[] paramTypes, String[] paramNames, Class[] exceptionTypes, Class returnType, int line) { + Signature sig = this.makeMethodSig(modifiers, methodName, declaringType, paramTypes==null?NO_TYPES:paramTypes, + paramNames==null?NO_STRINGS:paramNames, exceptionTypes==null?NO_TYPES:exceptionTypes, returnType == null?Void.TYPE:returnType); + return new JoinPointImpl.StaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.EnclosingStaticPart makeMethodESJP(String kind, int modifiers, String methodName, Class declaringType, Class[] paramTypes, String[] paramNames, Class[] exceptionTypes, Class returnType, int line) { + Signature sig = this.makeMethodSig(modifiers, methodName, declaringType, paramTypes==null?NO_TYPES:paramTypes, + paramNames==null?NO_STRINGS:paramNames, exceptionTypes==null?NO_TYPES:exceptionTypes, returnType == null?Void.TYPE:returnType); + return new JoinPointImpl.EnclosingStaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.StaticPart makeConstructorSJP(String kind, int modifiers, Class declaringType, Class[] parameterTypes, String[] parameterNames, Class[] exceptionTypes, int line) { + ConstructorSignatureImpl sig = new ConstructorSignatureImpl(modifiers, declaringType, parameterTypes==null?NO_TYPES:parameterTypes, parameterNames==null?NO_STRINGS:parameterNames, + exceptionTypes==null?NO_TYPES:exceptionTypes); + return new JoinPointImpl.StaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.EnclosingStaticPart makeConstructorESJP(String kind, int modifiers, Class declaringType, Class[] parameterTypes, String[] parameterNames, Class[] exceptionTypes, int line) { + ConstructorSignatureImpl sig = new ConstructorSignatureImpl(modifiers, declaringType, parameterTypes==null?NO_TYPES:parameterTypes, parameterNames==null?NO_STRINGS:parameterNames, + exceptionTypes==null?NO_TYPES:exceptionTypes); + return new JoinPointImpl.EnclosingStaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.StaticPart makeCatchClauseSJP(String kind, Class declaringType, Class parameterType, String parameterName, int line) { + CatchClauseSignatureImpl sig = new CatchClauseSignatureImpl(declaringType, parameterType, parameterName==null?"":parameterName); + return new JoinPointImpl.StaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.EnclosingStaticPart makeCatchClauseESJP(String kind, Class declaringType, Class parameterType, String parameterName, int line) { + CatchClauseSignatureImpl sig = new CatchClauseSignatureImpl(declaringType, parameterType, parameterName==null?"":parameterName); + return new JoinPointImpl.EnclosingStaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.StaticPart makeFieldSJP(String kind, int modifiers, String name, Class declaringType, Class fieldType, int line) { + FieldSignatureImpl sig = new FieldSignatureImpl(modifiers, name, declaringType, fieldType); + return new JoinPointImpl.StaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.EnclosingStaticPart makeFieldESJP(String kind, int modifiers, String name, Class declaringType, Class fieldType, int line) { + FieldSignatureImpl sig = new FieldSignatureImpl(modifiers, name, declaringType, fieldType); + return new JoinPointImpl.EnclosingStaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.StaticPart makeInitializerSJP(String kind, int modifiers, Class declaringType, int line) { + InitializerSignatureImpl sig = new InitializerSignatureImpl(modifiers, declaringType); + return new JoinPointImpl.StaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.EnclosingStaticPart makeInitializerESJP(String kind, int modifiers, Class declaringType, int line) { + InitializerSignatureImpl sig = new InitializerSignatureImpl(modifiers, declaringType); + return new JoinPointImpl.EnclosingStaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.StaticPart makeLockSJP(String kind, Class declaringType, int line) { + LockSignatureImpl sig = new LockSignatureImpl(declaringType); + return new JoinPointImpl.StaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.EnclosingStaticPart makeLockESJP(String kind, Class declaringType, int line) { + LockSignatureImpl sig = new LockSignatureImpl(declaringType); + return new JoinPointImpl.EnclosingStaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.StaticPart makeUnlockSJP(String kind, Class declaringType, int line) { + UnlockSignatureImpl sig = new UnlockSignatureImpl(declaringType); + return new JoinPointImpl.StaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.EnclosingStaticPart makeUnlockESJP(String kind, Class declaringType, int line) { + UnlockSignatureImpl sig = new UnlockSignatureImpl(declaringType); + return new JoinPointImpl.EnclosingStaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.StaticPart makeAdviceSJP(String kind, int modifiers, String name, Class declaringType, Class[] parameterTypes, + String[] parameterNames, Class[] exceptionTypes, Class returnType, int line) { + AdviceSignatureImpl sig = new AdviceSignatureImpl(modifiers, name, declaringType, + parameterTypes==null?NO_TYPES:parameterTypes, + parameterNames==null?NO_STRINGS:parameterNames, + exceptionTypes==null?NO_TYPES:exceptionTypes, + returnType==null?Void.TYPE:returnType); + return new JoinPointImpl.StaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + public JoinPoint.EnclosingStaticPart makeAdviceESJP(String kind, int modifiers, String name, Class declaringType, Class[] parameterTypes, + String[] parameterNames, Class[] exceptionTypes, Class returnType, int line) { + AdviceSignatureImpl sig = new AdviceSignatureImpl(modifiers, name, declaringType, + parameterTypes==null?NO_TYPES:parameterTypes, + parameterNames==null?NO_STRINGS:parameterNames, + exceptionTypes==null?NO_TYPES:exceptionTypes, + returnType==null?Void.TYPE:returnType); + return new JoinPointImpl.EnclosingStaticPartImpl(count++, kind, sig, makeSourceLoc(line, -1)); + } + + // --- public JoinPoint.StaticPart makeSJP(String kind, Signature sig, SourceLocation loc) { return new JoinPointImpl.StaticPartImpl(count++, kind, sig, loc); @@ -181,12 +284,16 @@ public final class Factory { ret.setLookupClassLoader(lookupClassLoader); return ret; } - + public MethodSignature makeMethodSig(String modifiers, String methodName, String declaringType, String paramTypes, String paramNames, String exceptionTypes, String returnType) { - int modifiersAsInt = Integer.parseInt(modifiers, 16); - Class declaringTypeClass = makeClass(declaringType, lookupClassLoader); + return makeMethodSig(modifiers, methodName, declaringTypeClass, paramTypes, paramNames, exceptionTypes, returnType); + } + + public MethodSignature makeMethodSig(String modifiers, String methodName, Class declaringTypeClass, String paramTypes, + String paramNames, String exceptionTypes, String returnType) { + int modifiersAsInt = Integer.parseInt(modifiers, 16); StringTokenizer st = new StringTokenizer(paramTypes, ":"); int numParams = st.countTokens(); @@ -216,8 +323,8 @@ public final class Factory { public MethodSignature makeMethodSig(int modifiers, String name, Class declaringType, Class[] parameterTypes, String[] parameterNames, Class[] exceptionTypes, Class returnType) { - MethodSignatureImpl ret = new MethodSignatureImpl(modifiers, name, declaringType, parameterTypes, parameterNames, - exceptionTypes, returnType); + MethodSignatureImpl ret = new MethodSignatureImpl(modifiers, name, declaringType, parameterTypes==null?NO_TYPES:parameterTypes, parameterNames, + exceptionTypes == null?NO_TYPES:exceptionTypes, returnType); ret.setLookupClassLoader(lookupClassLoader); return ret; } diff --git a/tests/features190/efficientTJP/Advice.java b/tests/features190/efficientTJP/Advice.java new file mode 100644 index 000000000..a85a445c2 --- /dev/null +++ b/tests/features190/efficientTJP/Advice.java @@ -0,0 +1,19 @@ +public class Advice { + public static void main(String []argv) { + } +} + +aspect X { + before(): execution(* main(..)) {} +} + +aspect Y { + before(): adviceexecution() && within(X) { + System.out.println("tjp:"+thisJoinPointStaticPart.getSignature()); + } + + before(): adviceexecution() && within(X) { + System.out.println("tejp:"+thisEnclosingJoinPointStaticPart.getSignature()); + } + +} diff --git a/tests/features190/efficientTJP/Clinit.java b/tests/features190/efficientTJP/Clinit.java new file mode 100644 index 000000000..e8acea835 --- /dev/null +++ b/tests/features190/efficientTJP/Clinit.java @@ -0,0 +1,16 @@ +public class Clinit { + public static void main(String []argv) { + new Inner(); + } + + static class Inner {} +} + +aspect X { + before(): staticinitialization(Clinit.Inner) { + System.out.println(thisJoinPointStaticPart.getSignature()); + } + before(): staticinitialization(Clinit) { + System.out.println(thisJoinPointStaticPart.getSignature()); + } +} diff --git a/tests/features190/efficientTJP/ClinitE.java b/tests/features190/efficientTJP/ClinitE.java new file mode 100644 index 000000000..a007a2014 --- /dev/null +++ b/tests/features190/efficientTJP/ClinitE.java @@ -0,0 +1,16 @@ +public class ClinitE { + public static void main(String []argv) { + new Inner(); + } + + static class Inner {} +} + +aspect X { + before(): staticinitialization(ClinitE.Inner) { + System.out.println(thisEnclosingJoinPointStaticPart.getSignature()); + } + before(): staticinitialization(ClinitE) { + System.out.println(thisEnclosingJoinPointStaticPart.getSignature()); + } +} diff --git a/tests/features190/efficientTJP/Fields.java b/tests/features190/efficientTJP/Fields.java new file mode 100644 index 000000000..ad1246568 --- /dev/null +++ b/tests/features190/efficientTJP/Fields.java @@ -0,0 +1,46 @@ +public class Fields { + int a = 1; + String s = "hello"; + double d = 1.0d; + boolean b = true; + + short ps = (short)1; + float fs = 1.0f; + long ls = 1L; + byte bs = (byte)3; + char cs = 'a'; + + + Inner obj = new Inner(); + static int as = 1; + static String ss = "hello"; + static double ds = 1.0d; + static Inner objs = new Inner(); + + public static void main(String []argv) { + Fields f = new Fields(); + int a2 = f.a; + String s2 = f.s; + double d2 = f.d; + Inner obj2 = f.obj; + + short ps2 = f.ps; + float fs2 = f.fs; + long ls2 = f.ls; + byte bs2 = f.bs; + char cs2 = f.cs; + + int a3 = as; + String s3 = ss; + double d3 = ds; + Inner obj3 = objs; + } + + static class Inner {} +} + +aspect X { + before(): within(Fields) && get(* *) { + System.out.println(thisJoinPointStaticPart.getSignature()); + } +} diff --git a/tests/features190/efficientTJP/Fields2.java b/tests/features190/efficientTJP/Fields2.java new file mode 100644 index 000000000..0a8aed75c --- /dev/null +++ b/tests/features190/efficientTJP/Fields2.java @@ -0,0 +1,40 @@ +public class Fields2 { + int a = 1; + String s = "hello"; + double d = 1.0d; + boolean b = true; + + short ps = (short)1; + float fs = 1.0f; + long ls = 1L; + byte bs = (byte)3; + char cs = 'a'; + + + Inner obj = new Inner(); + static int as = 1; + static String ss = "hello"; + static double ds = 1.0d; + static Inner objs = new Inner(); + + public static void main(String []argv) { + Fields2 f = new Fields2(); + f.a = 2; + f.ps = (short)3; + f.d = 2.0d; + f.obj = new Inner(); + f.s = "helo"; + f.fs = 4f; + f.ls = 3L; + f.bs = (byte)23; + f.cs = 'a'; + } + + static class Inner {} +} + +aspect X { + before(): within(Fields2) && set(* *) && withincode(* main(..)){ + System.out.println(thisJoinPointStaticPart.getSignature()); + } +} diff --git a/tests/features190/efficientTJP/FieldsE.java b/tests/features190/efficientTJP/FieldsE.java new file mode 100644 index 000000000..51bc923fa --- /dev/null +++ b/tests/features190/efficientTJP/FieldsE.java @@ -0,0 +1,46 @@ +public class FieldsE { + int a = 1; + String s = "hello"; + double d = 1.0d; + boolean b = true; + + short ps = (short)1; + float fs = 1.0f; + long ls = 1L; + byte bs = (byte)3; + char cs = 'a'; + + + Inner obj = new Inner(); + static int as = 1; + static String ss = "hello"; + static double ds = 1.0d; + static Inner objs = new Inner(); + + public static void main(String []argv) { + FieldsE f = new FieldsE(); + int a2 = f.a; + String s2 = f.s; + double d2 = f.d; + Inner obj2 = f.obj; + + short ps2 = f.ps; + float fs2 = f.fs; + long ls2 = f.ls; + byte bs2 = f.bs; + char cs2 = f.cs; + + int a3 = as; + String s3 = ss; + double d3 = ds; + Inner obj3 = objs; + } + + static class Inner {} +} + +aspect X { + before(): within(FieldsE) && get(* *) { + System.out.println(thisEnclosingJoinPointStaticPart.getSignature()); + } +} diff --git a/tests/features190/efficientTJP/Four.java b/tests/features190/efficientTJP/Four.java new file mode 100644 index 000000000..9857c8c62 --- /dev/null +++ b/tests/features190/efficientTJP/Four.java @@ -0,0 +1,21 @@ +public class Four { + public static void main(String []argv) { + new Four().run(); + } + + public void run() { + try { + System.out.println("run() running"); + throw new IllegalStateException(); + } catch (Throwable t) { + System.out.println("caught something"); + } + } + +} + +aspect X { + before(Throwable t): handler(Throwable) && args(t) { + System.out.println(thisJoinPointStaticPart.getSignature()); + } +} diff --git a/tests/features190/efficientTJP/FourA.java b/tests/features190/efficientTJP/FourA.java new file mode 100644 index 000000000..47694dcbf --- /dev/null +++ b/tests/features190/efficientTJP/FourA.java @@ -0,0 +1,21 @@ +public class FourA { + public static void main(String []argv) { + new FourA().run(); + } + + public void run() { + try { + System.out.println("run() running"); + throw new IllegalStateException(); + } catch (Throwable t) { + System.out.println("caught something"); + } + } + +} + +aspect X { + before(Throwable t): handler(Throwable) && args(t) { + System.out.println(thisEnclosingJoinPointStaticPart.getSignature()); + } +} diff --git a/tests/features190/efficientTJP/Init.java b/tests/features190/efficientTJP/Init.java new file mode 100644 index 000000000..200ce18ce --- /dev/null +++ b/tests/features190/efficientTJP/Init.java @@ -0,0 +1,24 @@ +public class Init { + public static void main(String []argv) { + new A(); + new B(); + } +} + +class A {} +class B {} + +aspect X { + before(): preinitialization(A.new(..)) && !within(X) { + System.out.println(thisJoinPointStaticPart.getSignature()); + } + before(): preinitialization(A.new(..)) && !within(X) { + System.out.println(thisEnclosingJoinPointStaticPart.getSignature()); + } + before(): initialization(B.new(..)) && !within(X) { + System.out.println(thisJoinPointStaticPart.getSignature()); + } + before(): initialization(B.new(..)) && !within(X) { + System.out.println(thisEnclosingJoinPointStaticPart.getSignature()); + } +} diff --git a/tests/features190/efficientTJP/One.java b/tests/features190/efficientTJP/One.java new file mode 100644 index 000000000..4fafcdaf7 --- /dev/null +++ b/tests/features190/efficientTJP/One.java @@ -0,0 +1,12 @@ +public class One { + public static void main(String []argv) { + System.out.println("One running"); + } +} + +aspect X { + void around(): execution(* main(..)) { + System.out.println(thisJoinPoint.getSignature()); + proceed(); + } +} diff --git a/tests/features190/efficientTJP/Three.java b/tests/features190/efficientTJP/Three.java new file mode 100644 index 000000000..479c7f7d1 --- /dev/null +++ b/tests/features190/efficientTJP/Three.java @@ -0,0 +1,19 @@ +public class Three { + public static void main(String []argv) { + System.out.println("Three running"); + new Three(); + new Three("abc"); + new Three(1,"abc"); + } + + Three() {} + Three(String s) {} + Three(int i, String s) {} +} + +aspect X { + void around(): execution(new(..)) && !within(X) { + System.out.println(thisJoinPointStaticPart.getSignature()); + proceed(); + } +} diff --git a/tests/features190/efficientTJP/ThreeA.java b/tests/features190/efficientTJP/ThreeA.java new file mode 100644 index 000000000..e3ffac941 --- /dev/null +++ b/tests/features190/efficientTJP/ThreeA.java @@ -0,0 +1,19 @@ +public class ThreeA { + public static void main(String []argv) { + System.out.println("ThreeA running"); + new ThreeA(); + new ThreeA("abc"); + new ThreeA(1,"abc"); + } + + ThreeA() {} + ThreeA(String s) {} + ThreeA(int i, String s) {} +} + +aspect X { + void around(): execution(new(..)) && !within(X) { + System.out.println(thisEnclosingJoinPointStaticPart.getSignature()); + proceed(); + } +} diff --git a/tests/features190/efficientTJP/Two.java b/tests/features190/efficientTJP/Two.java new file mode 100644 index 000000000..2d5d1da69 --- /dev/null +++ b/tests/features190/efficientTJP/Two.java @@ -0,0 +1,12 @@ +public class Two { + public static void main(String []argv) { + System.out.println("Two running"); + } +} + +aspect X { + void around(): execution(* main(..)) { + System.out.println(thisEnclosingJoinPointStaticPart.getSignature()); + proceed(); + } +} diff --git a/tests/src/org/aspectj/systemtest/ajc151/NewarrayJoinpointTests.java b/tests/src/org/aspectj/systemtest/ajc151/NewarrayJoinpointTests.java index 9c92f8488..9654c04dd 100644 --- a/tests/src/org/aspectj/systemtest/ajc151/NewarrayJoinpointTests.java +++ b/tests/src/org/aspectj/systemtest/ajc151/NewarrayJoinpointTests.java @@ -13,13 +13,13 @@ package org.aspectj.systemtest.ajc151; import java.io.File; import java.util.List; -import junit.framework.Test; - import org.aspectj.asm.AsmManager; import org.aspectj.asm.IProgramElement; import org.aspectj.asm.IRelationship; import org.aspectj.testing.XMLBasedAjcTestCase; +import junit.framework.Test; + /* * The design: * @@ -59,6 +59,15 @@ public class NewarrayJoinpointTests extends XMLBasedAjcTestCase { runTest("thisjoinpoint"); } + public void testThisJoinPoint19() { + try { + System.setProperty("ASPECTJ_OPTS", "-Xajruntimetarget:1.9"); + runTest("thisjoinpoint"); + } finally { + System.setProperty("ASPECTJ_OPTS", ""); + } + } + public void testDifferentAdviceKinds() { runTest("different advice kinds"); } @@ -105,9 +114,9 @@ public class NewarrayJoinpointTests extends XMLBasedAjcTestCase { assertTrue("Couldnt find 'Five' type in the model", ipe != null); List kids = ipe.getChildren(); assertTrue("Couldn't find 'main' method in the 'Five' type", kids != null && kids.size() == 1); - List codenodes = ((IProgramElement) kids.get(0)).getChildren(); + List codenodes = kids.get(0).getChildren(); assertTrue("Couldn't find nodes below 'main' method", codenodes != null && codenodes.size() == 1); - IProgramElement arrayCtorCallNode = (IProgramElement) codenodes.get(0); + IProgramElement arrayCtorCallNode = codenodes.get(0); String exp = "constructor-call(void java.lang.Integer[].(int))"; assertTrue("Expected '" + exp + "' but found " + arrayCtorCallNode.toString(), arrayCtorCallNode.toString().equals(exp)); List rels = AsmManager.lastActiveStructureModel.getRelationshipMap().get(arrayCtorCallNode); @@ -119,6 +128,7 @@ public class NewarrayJoinpointTests extends XMLBasedAjcTestCase { return XMLBasedAjcTestCase.loadSuite(NewarrayJoinpointTests.class); } + @Override protected File getSpecFile() { return getClassResource("newarray_joinpoint.xml"); } diff --git a/tests/src/org/aspectj/systemtest/ajc190/AllTestsAspectJ190.java b/tests/src/org/aspectj/systemtest/ajc190/AllTestsAspectJ190.java index 2ebc12e7c..d0f7734f3 100644 --- a/tests/src/org/aspectj/systemtest/ajc190/AllTestsAspectJ190.java +++ b/tests/src/org/aspectj/systemtest/ajc190/AllTestsAspectJ190.java @@ -20,7 +20,7 @@ public class AllTestsAspectJ190 { // $JUnit-BEGIN$ suite.addTest(Ajc190Tests.suite()); suite.addTest(SanityTests19.suite()); -// suite.addTest(EfficientTJPTests.suite()); + suite.addTest(EfficientTJPTests.suite()); suite.addTest(ModuleTests.suite()); suite.addTest(Annotations.suite()); // $JUnit-END$ diff --git a/tests/src/org/aspectj/systemtest/ajc190/EfficientTJPTests.java b/tests/src/org/aspectj/systemtest/ajc190/EfficientTJPTests.java new file mode 100644 index 000000000..3564f9469 --- /dev/null +++ b/tests/src/org/aspectj/systemtest/ajc190/EfficientTJPTests.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2018 Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.aspectj.systemtest.ajc190; + +import java.io.File; + +import org.aspectj.apache.bcel.classfile.JavaClass; +import org.aspectj.apache.bcel.classfile.Method; +import org.aspectj.testing.XMLBasedAjcTestCase; + +import junit.framework.Assert; +import junit.framework.Test; + +/** + * + * @author Andy Clement + */ +public class EfficientTJPTests extends XMLBasedAjcTestCase { + + public void testThisJoinPointMethodExecution() { + // Test setting it via sys props rather than passing the option directly + try { + System.setProperty("ASPECTJ_OPTS", "-Xajruntimetarget:1.9"); + runTest("tjp 1"); + checkPreClinitContains("One","Factory.makeMethodSJP"); + } finally { + System.setProperty("ASPECTJ_OPTS", ""); + } + } + + public void testThisEnclosingJoinPointMethodExecution() { + runTest("tjp 2"); + checkPreClinitContains("Two","Factory.makeMethodESJP"); + } + + public void testThisJoinPointConstructorExecution() { + runTest("tjp 3"); + checkPreClinitContains("Three","Factory.makeConstructorSJP"); + } + + public void testThisEnclosingJoinPointConstructorExecution() { + runTest("tjp 3a"); + checkPreClinitContains("ThreeA","Factory.makeConstructorESJP"); + } + + public void testThisJoinPointHandler() { + runTest("tjp 4"); + checkPreClinitContains("Four","Factory.makeCatchClauseSJP"); + } + + public void testThisEnclosingJoinPointHandler() { + runTest("tjp 4a"); + checkPreClinitContains("FourA","Factory.makeMethodESJP"); + } + + public void testThisJoinPointFieldGet() { + runTest("tjp get fields"); + checkPreClinitContains("Fields","Factory.makeFieldSJP"); + } + + public void testThisEnclosingJoinPointFieldGet() { + runTest("tjp get fieldsE"); + checkPreClinitContains("FieldsE","Factory.makeMethodESJP"); + } + + public void testThisJoinPointFieldSet() { + runTest("tjp set fields"); + checkPreClinitContains("Fields2","Factory.makeFieldSJP"); + } + + public void testThisJoinPointClinit() { + runTest("tjp clinit"); + checkPreClinitContains("Clinit","Factory.makeInitializerSJP"); + } + + public void testThisEnclosingJoinPointClinit() { + runTest("tejp clinit"); + checkPreClinitContains("ClinitE","Factory.makeInitializerESJP"); + } + + public void testThisJoinPointAdvice() { + // covers enclosing joinpoint too + runTest("tjp advice"); + checkPreClinitContains("X","Factory.makeAdviceESJP"); + } + + public void testThisJoinPointInitialization() { + runTest("tjp init"); + checkPreClinitContains("A","Factory.makeConstructorESJP"); + checkPreClinitContains("B","Factory.makeConstructorESJP"); + } + + // /////////////////////////////////////// + public static Test suite() { + return XMLBasedAjcTestCase.loadSuite(EfficientTJPTests.class); + } + + @Override + protected File getSpecFile() { + return getClassResource("features190.xml"); + } + + public void checkPreClinitContains(String classname, String text) { + try { + JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), classname); + Method[] meths = jc.getMethods(); + for (int i = 0; i < meths.length; i++) { + Method method = meths[i]; + if (method.getName().equals("ajc$preClinit")) { + String code = method.getCode().getCodeString(); + assertTrue("Expected to contain '"+text+"':\n"+code,code.contains(text)); + return; + } + } + Assert.fail("Unable to find ajc$preClinit in class "+classname); + } catch (Exception e) { + Assert.fail(e.toString()); + } + } + +} diff --git a/tests/src/org/aspectj/systemtest/ajc190/features190.xml b/tests/src/org/aspectj/systemtest/ajc190/features190.xml new file mode 100644 index 000000000..1fb931e97 --- /dev/null +++ b/tests/src/org/aspectj/systemtest/ajc190/features190.xml @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java b/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java index 395e07e10..4ade1e125 100644 --- a/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java +++ b/weaver/src/org/aspectj/weaver/bcel/BcelWorld.java @@ -723,26 +723,32 @@ public class BcelWorld extends World implements Repository { // / The repository interface methods + @Override public JavaClass findClass(String className) { return lookupJavaClass(classPath, className); } + @Override public JavaClass loadClass(String className) throws ClassNotFoundException { return lookupJavaClass(classPath, className); } + @Override public void storeClass(JavaClass clazz) { // doesn't need to do anything } + @Override public void removeClass(JavaClass clazz) { throw new RuntimeException("Not implemented"); } + @Override public JavaClass loadClass(Class clazz) throws ClassNotFoundException { throw new RuntimeException("Not implemented"); } + @Override public void clear() { delegate.clear(); // throw new RuntimeException("Not implemented"); @@ -1291,10 +1297,12 @@ public class BcelWorld extends World implements Repository { } + @Override public TypeMap getTypeMap() { return typeMap; } + @Override public boolean isLoadtimeWeaving() { return false; } @@ -1306,6 +1314,7 @@ public class BcelWorld extends World implements Repository { typeDelegateResolvers.add(typeDelegateResolver); } + @Override public void classWriteEvent(char[][] compoundName) { typeMap.classWriteEvent(new String(CharOperation.concatWith(compoundName, '.'))); } diff --git a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java index 24240d7ca..95ef524b5 100644 --- a/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java +++ b/weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java @@ -53,15 +53,16 @@ import org.aspectj.apache.bcel.generic.Type; import org.aspectj.bridge.IMessage; import org.aspectj.bridge.ISourceLocation; import org.aspectj.bridge.SourceLocation; -import org.aspectj.util.LangUtil; import org.aspectj.weaver.AjAttribute; import org.aspectj.weaver.AjAttribute.WeaverState; import org.aspectj.weaver.AjAttribute.WeaverVersionInfo; import org.aspectj.weaver.BCException; import org.aspectj.weaver.Member; +import org.aspectj.weaver.MemberKind; import org.aspectj.weaver.NameMangler; import org.aspectj.weaver.ResolvedMember; import org.aspectj.weaver.ResolvedType; +import org.aspectj.weaver.RuntimeVersion; import org.aspectj.weaver.Shadow; import org.aspectj.weaver.SignatureUtils; import org.aspectj.weaver.TypeVariable; @@ -80,6 +81,45 @@ import org.aspectj.weaver.bcel.asm.StackMapAdder; */ public final class LazyClassGen { + private static final Type[] ARRAY_7STRING_INT = new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING, + Type.STRING, Type.STRING, Type.INT }; + + private static final Type[] ARRAY_8STRING_INT = new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING, + Type.STRING, Type.STRING, Type.STRING, Type.INT }; + + private static final Type[] PARAMSIGNATURE_MAKESJP_METHOD = new Type[] { + Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY, Type.CLASS_ARRAY, Type.CLASS, Type.INT + }; + + private static final Type[] PARAMSIGNATURE_MAKESJP_CONSTRUCTOR = new Type[] { + Type.STRING, Type.INT, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY, Type.CLASS_ARRAY, Type.INT + }; + + private static final Type[] PARAMSIGNATURE_MAKESJP_CATCHCLAUSE = new Type[] { + Type.STRING, Type.CLASS, Type.CLASS, Type.STRING, Type.INT + }; + + private static final Type[] PARAMSIGNATURE_MAKESJP_FIELD = new Type[] { + Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS, Type.INT + }; + + private static final Type[] PARAMSIGNATURE_MAKESJP_INITIALIZER = new Type[] { + Type.STRING, Type.INT, Type.CLASS, Type.INT + }; + + private static final Type[] PARAMSIGNATURE_MAKESJP_MONITOR = new Type[] { + Type.STRING, Type.CLASS, Type.INT + }; + + private static final Type[] PARAMSIGNATURE_MAKESJP_ADVICE = new Type[] { + Type.STRING, Type.INT, Type.STRING, Type.CLASS, Type.CLASS_ARRAY, Type.STRING_ARRAY, + Type.CLASS_ARRAY, Type.CLASS, Type.INT + }; + + + + + private static final int ACC_SYNTHETIC = 0x1000; private static final String[] NO_STRINGS = new String[0]; @@ -1232,6 +1272,7 @@ public final class LazyClassGen { List> entries = new ArrayList>(tjpFields.entrySet()); Collections.sort(entries, new Comparator>() { + @Override public int compare(Map.Entry a, Map.Entry b) { return (a.getValue()).getName().compareTo((b.getValue()).getName()); } @@ -1253,6 +1294,10 @@ public final class LazyClassGen { } private void initializeTjp(InstructionFactory fact, InstructionList list, Field field, BcelShadow shadow) { + if (world.getTargetAspectjRuntimeLevel() == RuntimeVersion.V1_9) { + initializeTjpOptimal(fact, list, field, shadow); + return; + } boolean fastSJP = false; // avoid fast SJP if it is for an enclosing joinpoint boolean isFastSJPAvailable = shadow.getWorld().isTargettingRuntime1_6_10() @@ -1274,9 +1319,7 @@ public final class LazyClassGen { String signatureMakerName = SignatureUtils.getSignatureMakerName(sig); ObjectType signatureType = new ObjectType(SignatureUtils.getSignatureType(sig)); UnresolvedType[] exceptionTypes = null; - if (world.isTargettingAspectJRuntime12()) { // TAG:SUPPORTING12: We - // didn't have optimized - // factory methods in 1.2 + if (world.isTargettingAspectJRuntime12()) { // TAG:SUPPORTING12: We didn't have optimized factory methods in 1.2 list.append(InstructionFactory.PUSH(cp, SignatureUtils.getSignatureString(sig, shadow.getWorld()))); list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1, Constants.INVOKEVIRTUAL)); @@ -1370,6 +1413,7 @@ public final class LazyClassGen { list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY2, Constants.INVOKEVIRTUAL)); } else { + // TODO looks like this block is unused code list.append(InstructionFactory.PUSH(cp, SignatureUtils.getSignatureString(sig, shadow.getWorld()))); list.append(fact.createInvoke(factoryType.getClassName(), signatureMakerName, signatureType, Type.STRINGARRAY1, Constants.INVOKEVIRTUAL)); @@ -1415,10 +1459,208 @@ public final class LazyClassGen { } } - private static final Type[] ARRAY_7STRING_INT = new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING, - Type.STRING, Type.STRING, Type.INT }; - private static final Type[] ARRAY_8STRING_INT = new Type[] { Type.STRING, Type.STRING, Type.STRING, Type.STRING, Type.STRING, - Type.STRING, Type.STRING, Type.STRING, Type.INT }; + public String getFactoryMethod(Field field, BcelShadow shadow) { + StringBuilder b = new StringBuilder(); + b.append("make"); + MemberKind kind = shadow.getSignature().getKind(); + if (kind.equals(Member.METHOD)) { + b.append("Method"); + } else if (kind.equals(Member.CONSTRUCTOR)) { + b.append("Constructor"); + } else if (kind.equals(Member.HANDLER)) { + b.append("CatchClause"); + } else if (kind.equals(Member.FIELD)) { + b.append("Field"); + } else if (kind.equals(Member.STATIC_INITIALIZATION)) { + b.append("Initializer"); + } else if (kind.equals(Member.MONITORENTER)) { + b.append("Lock"); + } else if (kind.equals(Member.MONITOREXIT)) { + b.append("Unlock"); + } else if (kind.equals(Member.ADVICE)) { + b.append("Advice"); + } else { + throw new IllegalStateException(kind.toString()); + } + if (staticTjpType.equals(field.getType())) { + b.append("SJP"); + } else if (enclosingStaticTjpType.equals(field.getType())) { + b.append("ESJP"); + } + return b.toString(); + } + + /** + * Generate optimal joinpoint initialization code. + * + * As of version 1.9.1 the runtime includes new factory methods for joinpoints that take classes, not strings + * and using them requires different code generation. Using these instead of the old ones means we can avoid + * deferred classloading for these types. By using the LDC instruction that loads classes, it also means + * anything modifying woven code and changing type names will also pick up on these references. + */ + private void initializeTjpOptimal(InstructionFactory fact, InstructionList list, Field field, BcelShadow shadow) { + list.append(InstructionFactory.createLoad(factoryType, 0)); + pushString(list, shadow.getKind().getName()); + String factoryMethod = getFactoryMethod(field, shadow); + Member sig = shadow.getSignature(); + BcelWorld w = shadow.getWorld(); + + if (sig.getKind().equals(Member.METHOD)) { + pushInt(list, sig.getModifiers(w)); + pushString(list, sig.getName()); + pushClass(list, sig.getDeclaringType()); + pushClasses(list, sig.getParameterTypes()); + pushStrings(list, sig.getParameterNames(w)); + pushClasses(list, sig.getExceptions(w)); + pushClass(list, sig.getReturnType()); + pushInt(list, shadow.getSourceLine()); + list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), + PARAMSIGNATURE_MAKESJP_METHOD, Constants.INVOKEVIRTUAL)); + } else if (sig.getKind().equals(Member.CONSTRUCTOR)) { + if (w.isJoinpointArrayConstructionEnabled() && sig.getDeclaringType().isArray()) { + pushInt(list, Modifier.PUBLIC); + pushClass(list, sig.getDeclaringType()); + pushClasses(list, sig.getParameterTypes()); + pushStrings(list, null); + pushClasses(list, null); + } else { + pushInt(list, sig.getModifiers(w)); + pushClass(list, sig.getDeclaringType()); + pushClasses(list, sig.getParameterTypes()); + pushStrings(list, sig.getParameterNames(w)); + pushClasses(list, sig.getExceptions(w)); + } + pushInt(list, shadow.getSourceLine()); + list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), + PARAMSIGNATURE_MAKESJP_CONSTRUCTOR, Constants.INVOKEVIRTUAL)); + } else if (sig.getKind().equals(Member.HANDLER)) { + pushClass(list, sig.getDeclaringType()); + pushClass(list, sig.getParameterTypes()[0]); + String pname = null; + String[] pnames = sig.getParameterNames(w); + if (pnames != null && pnames.length>0) { + pname = pnames[0]; + } + pushString(list, pname); + pushInt(list, shadow.getSourceLine()); + list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), + PARAMSIGNATURE_MAKESJP_CATCHCLAUSE, Constants.INVOKEVIRTUAL)); + } else if (sig.getKind().equals(Member.FIELD)) { + pushInt(list, sig.getModifiers(w)); + pushString(list, sig.getName()); + // see pr227401 + UnresolvedType dType = sig.getDeclaringType(); + if (dType.getTypekind() == TypeKind.PARAMETERIZED || dType.getTypekind() == TypeKind.GENERIC) { + dType = sig.getDeclaringType().resolve(world).getGenericType(); + } + pushClass(list, dType); + pushClass(list, sig.getReturnType()); + pushInt(list,shadow.getSourceLine()); + list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), + PARAMSIGNATURE_MAKESJP_FIELD, Constants.INVOKEVIRTUAL)); + } else if (sig.getKind().equals(Member.STATIC_INITIALIZATION)) { + pushInt(list, sig.getModifiers(w)); + pushClass(list, sig.getDeclaringType()); + pushInt(list, shadow.getSourceLine()); + list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), + PARAMSIGNATURE_MAKESJP_INITIALIZER, Constants.INVOKEVIRTUAL)); + } else if (sig.getKind().equals(Member.MONITORENTER)) { + pushClass(list, sig.getDeclaringType()); + pushInt(list, shadow.getSourceLine()); + list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), + PARAMSIGNATURE_MAKESJP_MONITOR, Constants.INVOKEVIRTUAL)); + } else if (sig.getKind().equals(Member.MONITOREXIT)) { + pushClass(list, sig.getDeclaringType()); + pushInt(list, shadow.getSourceLine()); + list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), + PARAMSIGNATURE_MAKESJP_MONITOR, Constants.INVOKEVIRTUAL)); + } else if (sig.getKind().equals(Member.ADVICE)) { + pushInt(list, sig.getModifiers(w)); + pushString(list, sig.getName()); + pushClass(list, sig.getDeclaringType()); + pushClasses(list, sig.getParameterTypes()); + pushStrings(list, sig.getParameterNames(w)); + pushClasses(list, sig.getExceptions(w)); + pushClass(list, sig.getReturnType()); + pushInt(list, shadow.getSourceLine()); + list.append(fact.createInvoke(factoryType.getClassName(), factoryMethod, field.getType(), + PARAMSIGNATURE_MAKESJP_ADVICE, Constants.INVOKEVIRTUAL)); + } else { + throw new IllegalStateException("not sure what to do: "+shadow); + } + list.append(fact.createFieldAccess(getClassName(), field.getName(), field.getType(), Constants.PUTSTATIC)); + } + + private void pushStrings(InstructionList list, String[] strings) { + // Build an array loaded with the strings + if (strings == null || strings.length == 0) { + list.append(InstructionFactory.ACONST_NULL); + } else { + list.append(InstructionFactory.PUSH(cp, strings.length)); + list.append(fact.createNewArray(Type.STRING, (short)1)); + for (int s=0;s