Преглед изворни кода

296484:296501: annotationbinding

tags/V1_6_7
aclement пре 14 година
родитељ
комит
6abc8f8488

+ 25
- 6
weaver/src/org/aspectj/weaver/bcel/AnnotationAccessFieldVar.java Прегледај датотеку

@@ -15,8 +15,9 @@ import java.util.Iterator;
import java.util.List;

import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
import org.aspectj.apache.bcel.classfile.annotation.EnumElementValue;
import org.aspectj.apache.bcel.classfile.annotation.NameValuePair;
import org.aspectj.apache.bcel.classfile.annotation.SimpleElementValue;
import org.aspectj.apache.bcel.generic.InstructionFactory;
import org.aspectj.apache.bcel.generic.InstructionList;
import org.aspectj.apache.bcel.generic.Type;
@@ -44,6 +45,7 @@ class AnnotationAccessFieldVar extends BcelVar {
this.annoFieldOfInterest = annoFieldOfInterest;
}

@Override
public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) {
// Only possible to do annotation field value extraction at
// MethodExecution
@@ -62,12 +64,27 @@ class AnnotationAccessFieldVar extends BcelVar {
boolean doneAndDusted = false;
for (Iterator iterator = vals.iterator(); iterator.hasNext();) {
NameValuePair object = (NameValuePair) iterator.next();
EnumElementValue v = (EnumElementValue) object.getValue();
String s = v.getEnumTypeString();
ResolvedType rt = toType.getWorld().resolve(UnresolvedType.forSignature(s));
if (rt.equals(toType)) {
il.append(fact.createGetStatic(rt.getName(), v.getEnumValueString(), Type.getType(rt.getSignature())));
Object o = object.getValue();
if (o instanceof EnumElementValue) {
EnumElementValue v = (EnumElementValue) object.getValue();
String s = v.getEnumTypeString();
ResolvedType rt = toType.getWorld().resolve(UnresolvedType.forSignature(s));
if (rt.equals(toType)) {
il.append(fact.createGetStatic(rt.getName(), v.getEnumValueString(), Type.getType(rt.getSignature())));
doneAndDusted = true;
}
} else if (o instanceof SimpleElementValue) {
// FIXASC types other than String will go bang bang at runtime
SimpleElementValue v = (SimpleElementValue) object.getValue();
il.append(fact.createConstant(v.getValueString()));
doneAndDusted = true;
// String s = v.getEnumTypeString();
// ResolvedType rt = toType.getWorld().resolve(UnresolvedType.forSignature(s));
// if (rt.equals(toType)) {
// il.append(fact.createGetStatic(rt.getName(), v.getEnumValueString(), Type.getType(rt.getSignature())));
// doneAndDusted = true;
// }
int stop = 1;
}
}
if (!doneAndDusted) {
@@ -91,6 +108,7 @@ class AnnotationAccessFieldVar extends BcelVar {
}
}

@Override
public void insertLoad(InstructionList il, InstructionFactory fact) {
// Only possible to do annotation field value extraction at
// MethodExecution
@@ -100,6 +118,7 @@ class AnnotationAccessFieldVar extends BcelVar {
appendLoadAndConvert(il, fact, annoFieldOfInterest);
}

@Override
public String toString() {
return super.toString();
}

+ 37
- 4
weaver/src/org/aspectj/weaver/bcel/AnnotationAccessVar.java Прегледај датотеку

@@ -13,9 +13,12 @@
package org.aspectj.weaver.bcel;

import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.Field;
import org.aspectj.apache.bcel.generic.Instruction;
import org.aspectj.apache.bcel.generic.InstructionBranch;
import org.aspectj.apache.bcel.generic.InstructionConstants;
import org.aspectj.apache.bcel.generic.InstructionFactory;
import org.aspectj.apache.bcel.generic.InstructionHandle;
import org.aspectj.apache.bcel.generic.InstructionList;
import org.aspectj.apache.bcel.generic.ObjectType;
import org.aspectj.apache.bcel.generic.Type;
@@ -32,12 +35,15 @@ import org.aspectj.weaver.ast.Var;
*/
public class AnnotationAccessVar extends BcelVar {

private BcelShadow shadow;
private Kind kind; // What kind of shadow are we at?
private UnresolvedType containingType; // The type upon which we want to ask for 'member'
private Member member; // Holds the member that has the annotations (for method/field join points)

public AnnotationAccessVar(Kind kind, ResolvedType annotationType, UnresolvedType theTargetIsStoredHere, Member sig) {
public AnnotationAccessVar(BcelShadow shadow, Kind kind, ResolvedType annotationType, UnresolvedType theTargetIsStoredHere,
Member sig) {
super(annotationType, 0);
this.shadow = shadow;
this.kind = kind;
this.containingType = theTargetIsStoredHere;
this.member = sig;
@@ -47,30 +53,37 @@ public class AnnotationAccessVar extends BcelVar {
return kind;
}

@Override
public String toString() {
return "AnnotationAccessVar(" + getType() + ")";
}

@Override
public Instruction createLoad(InstructionFactory fact) {
throw new IllegalStateException("unimplemented");
}

@Override
public Instruction createStore(InstructionFactory fact) {
throw new IllegalStateException("unimplemented");
}

@Override
public InstructionList createCopyFrom(InstructionFactory fact, int oldSlot) {
throw new IllegalStateException("unimplemented");
}

@Override
public void appendLoad(InstructionList il, InstructionFactory fact) {
il.append(createLoadInstructions(getType(), fact));
}

@Override
public void appendLoadAndConvert(InstructionList il, InstructionFactory fact, ResolvedType toType) {
il.append(createLoadInstructions(toType, fact));
}

@Override
public void insertLoad(InstructionList il, InstructionFactory fact) {
il.insert(createLoadInstructions(getType(), fact));
}
@@ -93,9 +106,10 @@ public class AnnotationAccessVar extends BcelVar {
((kind == Shadow.FieldGet || kind == Shadow.FieldSet) && member.getKind() == Member.METHOD)) {

Type jlrMethod = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava/lang/reflect/Method;"));
Type jlAnnotation = BcelWorld.makeBcelType(UnresolvedType.forSignature("Ljava/lang/annotation/Annotation;"));
Type[] paramTypes = BcelWorld.makeBcelTypes(member.getParameterTypes());

il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));
// il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));

if (kind == Shadow.MethodCall
|| kind == Shadow.MethodExecution
@@ -105,16 +119,34 @@ public class AnnotationAccessVar extends BcelVar {
((kind == Shadow.FieldGet || kind == Shadow.FieldSet) && member.getKind() == Member.METHOD)
|| ((kind == Shadow.ConstructorCall || kind == Shadow.ConstructorExecution) && member.getKind() == Member.METHOD)) {

// Need to look at the cached annotation before going to fetch it again
Field annotationCachingField = shadow.getEnclosingClass().getAnnotationCachingField(shadow, toType);

// Basic idea here is to check if the cached field is null, if it is then initialize it, otherwise use it
il.append(fact
.createGetStatic(shadow.getEnclosingClass().getName(), annotationCachingField.getName(), jlAnnotation));
il.append(InstructionConstants.DUP);
InstructionBranch ifNonNull = InstructionFactory.createBranchInstruction(Constants.IFNONNULL, null);
il.append(ifNonNull);
il.append(InstructionConstants.POP);
il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));

il.append(fact.createConstant(member.getName()));
buildArray(il, fact, jlClass, paramTypes, 1);
// OPTIMIZE cache result of getDeclaredMethod and getAnnotation? Might be able to use it again if someone else needs
// the same annotations?
// OPTIMIZE cache result of getDeclaredMethod?
il.append(fact.createInvoke("java/lang/Class", "getDeclaredMethod", jlrMethod,
new Type[] { jlString, jlClassArray }, Constants.INVOKEVIRTUAL));
il.append(pushConstant);// fact.createConstant(new ObjectType(toType.getName())));
il.append(fact.createInvoke("java/lang/reflect/Method", "getAnnotation", jlaAnnotation, new Type[] { jlClass },
Constants.INVOKEVIRTUAL));
il.append(InstructionConstants.DUP);
il.append(fact
.createPutStatic(shadow.getEnclosingClass().getName(), annotationCachingField.getName(), jlAnnotation));
InstructionHandle ifNullElse = il.append(InstructionConstants.NOP);
ifNonNull.setTarget(ifNullElse);

} else { // init/preinit/ctor-call/ctor-exec
il.append(fact.createConstant(BcelWorld.makeBcelType(containingType)));
buildArray(il, fact, jlClass, paramTypes, 1);
Type jlrCtor = BcelWorld.makeBcelType(UnresolvedType.JAVA_LANG_REFLECT_CONSTRUCTOR);
// OPTIMIZE cache result of getDeclaredConstructor and getAnnotation? Might be able to use it again if someone else
@@ -201,6 +233,7 @@ public class AnnotationAccessVar extends BcelVar {
* @param valueType The type from the annotation that is of interest
* @return a variable that represents access to that annotation value
*/
@Override
public Var getAccessorForValue(ResolvedType valueType) {
return new AnnotationAccessFieldVar(this, valueType);
}

+ 4
- 3
weaver/src/org/aspectj/weaver/bcel/BcelShadow.java Прегледај датотеку

@@ -1592,7 +1592,7 @@ public class BcelShadow extends Shadow {
}

for (ResolvedType annotationType : annotations) {
AnnotationAccessVar accessVar = new AnnotationAccessVar(getKind(), annotationType.resolve(world), relevantType,
AnnotationAccessVar accessVar = new AnnotationAccessVar(this, getKind(), annotationType.resolve(world), relevantType,
annotationHolder);
kindedAnnotationVars.put(annotationType, accessVar);
}
@@ -1640,7 +1640,7 @@ public class BcelShadow extends Shadow {
for (int i = 0; i < annotations.length; i++) {
ResolvedType ann = annotations[i];
Kind k = Shadow.StaticInitialization;
withinAnnotationVars.put(ann, new AnnotationAccessVar(k, ann, getEnclosingType(), null));
withinAnnotationVars.put(ann, new AnnotationAccessVar(this, k, ann, getEnclosingType(), null));
}
}

@@ -1656,7 +1656,8 @@ public class BcelShadow extends Shadow {
ResolvedType ann = annotations[i];
Kind k = (getEnclosingMethod().getMemberView().getKind() == Member.CONSTRUCTOR ? Shadow.ConstructorExecution
: Shadow.MethodExecution);
withincodeAnnotationVars.put(ann, new AnnotationAccessVar(k, ann, getEnclosingType(), getEnclosingCodeSignature()));
withincodeAnnotationVars.put(ann,
new AnnotationAccessVar(this, k, ann, getEnclosingType(), getEnclosingCodeSignature()));
}
}


+ 54
- 2
weaver/src/org/aspectj/weaver/bcel/LazyClassGen.java Прегледај датотеку

@@ -320,7 +320,8 @@ public final class LazyClassGen {
ResolvedMember[] fields = type.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
ResolvedMember field = fields[i];
if (field.getName().equals("serialVersionUID") && Modifier.isStatic(field.getModifiers()) && field.getType().equals(ResolvedType.LONG)) {
if (field.getName().equals("serialVersionUID") && Modifier.isStatic(field.getModifiers())
&& field.getType().equals(ResolvedType.LONG)) {
return true;
}
}
@@ -926,10 +927,13 @@ public final class LazyClassGen {

// reflective thisJoinPoint support
private Map<BcelShadow, Field> tjpFields = new HashMap<BcelShadow, Field>();
Map<CacheKey, Field> annotationCachingFieldCache = new HashMap<CacheKey, Field>();
private int tjpFieldsCounter = -1; // -1 means not yet initialized
private int annoFieldsCounter = 0;
public static final ObjectType proceedingTjpType = new ObjectType("org.aspectj.lang.ProceedingJoinPoint");
public static final ObjectType tjpType = new ObjectType("org.aspectj.lang.JoinPoint");
public static final ObjectType staticTjpType = new ObjectType("org.aspectj.lang.JoinPoint$StaticPart");
public static final ObjectType typeForAnnotation = new ObjectType("java.lang.annotation.Annotation");
public static final ObjectType enclosingStaticTjpType = new ObjectType("org.aspectj.lang.JoinPoint$EnclosingStaticPart");
private static final ObjectType sigType = new ObjectType("org.aspectj.lang.Signature");
// private static final ObjectType slType =
@@ -991,7 +995,7 @@ public final class LazyClassGen {
tjpFieldsCounter = 0;
} else {
tjpFieldsCounter = Integer.parseInt(lastField.getName().substring(8)) + 1;
//System.out.println("tjp counter starting at " + tjpFieldsCounter);
// System.out.println("tjp counter starting at " + tjpFieldsCounter);
}
}
}
@@ -1003,6 +1007,54 @@ public final class LazyClassGen {
return tjpField;
}

/**
* Create a field in the type containing the shadow where the annotation retrieved during binding can be stored - for later fast
* access.
*
* @param shadow the shadow at which the @annotation result is being cached
* @return a field
*/
public Field getAnnotationCachingField(BcelShadow shadow, ResolvedType toType) {
// Multiple annotation types at a shadow. A different field would be required for each
CacheKey cacheKey = new CacheKey(shadow, toType);
Field field = annotationCachingFieldCache.get(cacheKey);
if (field == null) {
// private static Annotation ajc$anno$<nnn>
StringBuilder sb = new StringBuilder();
sb.append(NameMangler.ANNOTATION_CACHE_FIELD_NAME);
sb.append(annoFieldsCounter++);
FieldGen annotationCacheField = new FieldGen(Modifier.PRIVATE | Modifier.STATIC, typeForAnnotation, sb.toString(), cp);
addField(annotationCacheField);
field = annotationCacheField.getField();
annotationCachingFieldCache.put(cacheKey, field);
}
return field;
}

static class CacheKey {
private BcelShadow shadow;
private ResolvedType annotationType;

CacheKey(BcelShadow shadow, ResolvedType annotationType) {
this.shadow = shadow;
this.annotationType = annotationType;
}

@Override
public int hashCode() {
return shadow.hashCode() * 37 + annotationType.hashCode();
}

@Override
public boolean equals(Object other) {
if (!(other instanceof CacheKey)) {
return false;
}
CacheKey oCacheKey = (CacheKey) other;
return shadow.equals(oCacheKey.shadow) && annotationType.equals(oCacheKey.annotationType);
}
}

// FIXME ATAJ needed only for slow Aspects.aspectOf - keep or remove
// private void addAjClassField() {
// // Andy: Why build it again??

Loading…
Откажи
Сачувај