aboutsummaryrefslogtreecommitdiffstats
path: root/weaver
diff options
context:
space:
mode:
authorAndy Clement <aclement@pivotal.io>2018-02-28 11:53:14 -0800
committerAndy Clement <aclement@pivotal.io>2018-03-09 17:18:45 -0800
commit7d47cba01043c93bab95b59e66b727580351e85f (patch)
tree07a7fed0235f2d0e3b9221ebf097e5c24d16aaf0 /weaver
parent6b620ba3aa4b0c9d29560dfa42f8c67dcafb1229 (diff)
downloadaspectj-7d47cba01043c93bab95b59e66b727580351e85f.tar.gz
aspectj-7d47cba01043c93bab95b59e66b727580351e85f.zip
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).
Diffstat (limited to 'weaver')
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/BcelWorld.java9
-rw-r--r--weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java276
2 files changed, 277 insertions, 8 deletions
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<Map.Entry<BcelShadow, Field>> entries = new ArrayList<Map.Entry<BcelShadow, Field>>(tjpFields.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<BcelShadow, Field>>() {
+ @Override
public int compare(Map.Entry<BcelShadow, Field> a, Map.Entry<BcelShadow, Field> 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<strings.length;s++) {
+ list.append(InstructionFactory.DUP);
+ list.append(InstructionFactory.PUSH(cp, s));
+ list.append(InstructionFactory.PUSH(cp, strings[s]));
+ list.append(InstructionFactory.AASTORE);
+ }
+ }
+ }
+
+ private void pushClass(InstructionList list, UnresolvedType type) {
+ if (type.isPrimitiveType()) {
+ if (type.getSignature().equals("I")) {
+ list.append(fact.createGetStatic("java/lang/Integer","TYPE", Type.CLASS));
+ } else if (type.getSignature().equals("D")) {
+ list.append(fact.createGetStatic("java/lang/Double","TYPE", Type.CLASS));
+ } else if (type.getSignature().equals("S")) {
+ list.append(fact.createGetStatic("java/lang/Short","TYPE", Type.CLASS));
+ } else if (type.getSignature().equals("J")) {
+ list.append(fact.createGetStatic("java/lang/Long","TYPE", Type.CLASS));
+ } else if (type.getSignature().equals("F")) {
+ list.append(fact.createGetStatic("java/lang/Float","TYPE", Type.CLASS));
+ } else if (type.getSignature().equals("C")) {
+ list.append(fact.createGetStatic("java/lang/Character","TYPE", Type.CLASS));
+ } else if (type.getSignature().equals("B")) {
+ list.append(fact.createGetStatic("java/lang/Byte","TYPE", Type.CLASS));
+ } else if (type.getSignature().equals("Z")) {
+ list.append(fact.createGetStatic("java/lang/Boolean","TYPE", Type.CLASS));
+ } else if (type.getSignature().equals("V")) {
+ list.append(InstructionFactory.ACONST_NULL);
+ }
+ return;
+ }
+ String classString = makeLdcClassString(type);
+ if (classString == null) {
+ list.append(InstructionFactory.ACONST_NULL);
+ } else {
+ list.append(fact.PUSHCLASS(cp, classString));
+ }
+ }
+
+ private void pushClasses(InstructionList list, UnresolvedType[] types) {
+ // Build an array loaded with the class objects
+ if (types == null || types.length == 0) {
+ list.append(InstructionFactory.ACONST_NULL);
+ } else {
+ list.append(InstructionFactory.PUSH(cp, types.length));
+ list.append(fact.createNewArray(Type.CLASS, (short)1));
+ for (int t=0;t<types.length;t++) {
+ list.append(InstructionFactory.DUP);
+ list.append(InstructionFactory.PUSH(cp, t));
+ pushClass(list, types[t]);
+ list.append(InstructionFactory.AASTORE);
+ }
+ }
+ }
+
+ private final void pushString(InstructionList list, String string) {
+ list.append(InstructionFactory.PUSH(cp, string));
+ }
+
+ private final void pushInt(InstructionList list, int value) {
+ list.append(InstructionFactory.PUSH(cp, value));
+ }
protected String makeString(int i) {
return Integer.toString(i, 16); // ??? expensive
@@ -1438,6 +1680,24 @@ public final class LazyClassGen {
}
}
}
+
+ protected String makeLdcClassString(UnresolvedType type) {
+ if (type.isVoid() || type.isPrimitiveType()) {
+ return null;
+ }
+ if (type.isArray()) {
+ return type.getSignature();
+ } else {
+ if (type.isParameterizedType()) {
+ type = type.getRawType();
+ }
+ String signature = type.getSignature();
+ if (signature.length() ==1 ) {
+ return signature;
+ }
+ return signature.substring(1,signature.length()-1);
+ }
+ }
protected String makeString(UnresolvedType[] types) {
if (types == null) {