</stdout>
</run>
</ajc-test>
+
+ <ajc-test dir="bugs195/switch" vm="1.8" title="avoid weaving switch infrastructure">
+ <compile files="HelloWorldEnumSwitch.java Azpect.java" options="-showWeaveInfo -1.8 -XnoInline">
+ <message kind="weave" text="Join point 'constructor-execution(void HelloWorldEnumSwitch.<init>())' in Type 'HelloWorldEnumSwitch' (HelloWorldEnumSwitch.java:1) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'field-get(HelloWorldEnumSwitch$TestEnum HelloWorldEnumSwitch$TestEnum.A)' in Type 'HelloWorldEnumSwitch' (HelloWorldEnumSwitch.java:4) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'method-call(int HelloWorldEnumSwitch$TestEnum.ordinal())' in Type 'HelloWorldEnumSwitch' (HelloWorldEnumSwitch.java:4) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'field-get(java.io.PrintStream java.lang.System.out)' in Type 'HelloWorldEnumSwitch' (HelloWorldEnumSwitch.java:6) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'method-call(void java.io.PrintStream.println(java.lang.String))' in Type 'HelloWorldEnumSwitch' (HelloWorldEnumSwitch.java:6) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'field-get(java.io.PrintStream java.lang.System.out)' in Type 'HelloWorldEnumSwitch' (HelloWorldEnumSwitch.java:9) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'method-call(void java.io.PrintStream.println(java.lang.String))' in Type 'HelloWorldEnumSwitch' (HelloWorldEnumSwitch.java:9) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'method-execution(void HelloWorldEnumSwitch.main(java.lang.String[]))' in Type 'HelloWorldEnumSwitch' (HelloWorldEnumSwitch.java:3) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'staticinitialization(void HelloWorldEnumSwitch.<clinit>())' in Type 'HelloWorldEnumSwitch' (HelloWorldEnumSwitch.java:1) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'initialization(void HelloWorldEnumSwitch.<init>())' in Type 'HelloWorldEnumSwitch' (HelloWorldEnumSwitch.java:1) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'preinitialization(void HelloWorldEnumSwitch.<init>())' in Type 'HelloWorldEnumSwitch' (HelloWorldEnumSwitch.java:1) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'constructor-call(void HelloWorldEnumSwitch$TestEnum.<init>(java.lang.String, int))' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:15) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'field-set(HelloWorldEnumSwitch$TestEnum HelloWorldEnumSwitch$TestEnum.A)' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:15) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'constructor-call(void HelloWorldEnumSwitch$TestEnum.<init>(java.lang.String, int))' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:16) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'field-set(HelloWorldEnumSwitch$TestEnum HelloWorldEnumSwitch$TestEnum.B)' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:16) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'field-get(HelloWorldEnumSwitch$TestEnum HelloWorldEnumSwitch$TestEnum.A)' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:14) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'field-get(HelloWorldEnumSwitch$TestEnum HelloWorldEnumSwitch$TestEnum.B)' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:14) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'staticinitialization(void HelloWorldEnumSwitch$TestEnum.<clinit>())' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:14) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'constructor-execution(void HelloWorldEnumSwitch$TestEnum.<init>(java.lang.String, int))' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:18) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'method-call(void java.lang.System.arraycopy(java.lang.Object, int, java.lang.Object, int, int))' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:1) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'method-execution(HelloWorldEnumSwitch$TestEnum[] HelloWorldEnumSwitch$TestEnum.values())' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:1) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'method-call(java.lang.Enum java.lang.Enum.valueOf(java.lang.Class, java.lang.String))' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:1) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'method-execution(HelloWorldEnumSwitch$TestEnum HelloWorldEnumSwitch$TestEnum.valueOf(java.lang.String))' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:1) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'initialization(void HelloWorldEnumSwitch$TestEnum.<init>(java.lang.String, int))' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:18) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ <message kind="weave" text="Join point 'preinitialization(void HelloWorldEnumSwitch$TestEnum.<init>(java.lang.String, int))' in Type 'HelloWorldEnumSwitch$TestEnum' (HelloWorldEnumSwitch.java:18) advised by before advice from 'Azpect' (Azpect.java:2)"/>
+ </compile>
+
+ <run class="HelloWorldEnumSwitch">
+ <stdout>
+ <line text=">0"/>
+ <line text=">3"/>
+ <line text=">15"/>
+ <line text=">15"/>
+ <line text=">18"/>
+ <line text=">18"/>
+ <line text=">18"/>
+ <line text=">15"/>
+ <line text=">16"/>
+ <line text=">18"/>
+ <line text=">18"/>
+ <line text=">18"/>
+ <line text=">16"/>
+ <line text=">14"/>
+ <line text=">14"/>
+ <line text=">1"/>
+ <line text=">1"/>
+ <line text=">4"/>
+ <line text=">4"/>
+ <line text=">6"/>
+ <line text=">6"/>
+ <line text="A"/>
+ </stdout>
+ </run>
+ </ajc-test>
</suite>
/* *******************************************************************
* Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
- * 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
- *
- * Contributors:
- * PARC initial implementation
+ * 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
+ *
+ * Contributors:
+ * PARC initial implementation
* ******************************************************************/
-
package org.aspectj.weaver.bcel;
import java.lang.reflect.Modifier;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Properties;
import java.util.Set;
-import java.util.Objects;
import org.aspectj.apache.bcel.Constants;
import org.aspectj.apache.bcel.classfile.BootstrapMethods;
private static Trace trace = TraceFactory.getTraceFactory().getTrace(BcelClassWeaver.class);
+ // Name of helper method generated by JDT compiler. Javac uses a separate inner class.
private static final String SWITCH_TABLE_SYNTHETIC_METHOD_PREFIX = "$SWITCH_TABLE$";
public static boolean weave(BcelWorld world, LazyClassGen clazz, List<ShadowMunger> shadowMungers,
/**
* Weave a class and indicate through the return value whether the class was modified.
- *
+ *
* @return true if the class was modified
*/
public boolean weave() {
// FIXASC refactor into ResolvedType or even ResolvedMember?
/**
* Check if a particular method is overriding another - refactored into this helper so it can be used from multiple places.
- * @return method that is overriding if it
+ * @return method that is overriding if it
*/
private static ResolvedMember isOverriding(ResolvedType typeToCheck, ResolvedMember methodThatMightBeGettingOverridden,
String mname, String mrettype, int mmods, boolean inSamePackage, UnresolvedType[] methodParamsArray) {
/**
* Looks at the visibility modifiers between two methods, and knows whether they are from classes in the same package, and
* decides whether one overrides the other.
- *
+ *
* @return true if there is an overrides rather than a 'hides' relationship
*/
static boolean isVisibilityOverride(int methodMods, ResolvedMember inheritedMethod, boolean inSamePackage) {
/**
* This method recurses up a specified type looking for a method that overrides the one passed in.
- *
+ *
* @return the method being overridden or null if none is found
*/
public static void checkForOverride(ResolvedType typeToCheck, String mname, String mparams, String mrettype,
if (typeToCheck instanceof MissingResolvedTypeWithKnownSignature) {
return; // we just can't tell !
}
-
+
if (typeToCheck.getWorld().forDEBUG_bridgingCode) {
System.err.println(" Bridging:checking for override of " + mname + " in " + typeToCheck);
packageName = "";
}
// used when looking at visibility rules
- boolean inSamePackage = packageName.equals(mpkg);
+ boolean inSamePackage = packageName.equals(mpkg);
ResolvedMember[] methods = typeToCheck.getDeclaredMethods();
for (int ii = 0; ii < methods.length; ii++) {
// the method we are going to check
- ResolvedMember methodThatMightBeGettingOverridden = methods[ii];
+ ResolvedMember methodThatMightBeGettingOverridden = methods[ii];
ResolvedMember isOverriding = isOverriding(typeToCheck, methodThatMightBeGettingOverridden, mname, mrettype, mmods,
inSamePackage, methodParamsArray);
if (isOverriding != null) {
ResolvedType superclass = typeToCheck.getSuperclass();
checkForOverride(superclass, mname, mparams, mrettype, mmods, mpkg, methodParamsArray,overriddenMethodsCollector);
-
+
ResolvedType[] interfaces = typeToCheck.getDeclaredInterfaces();
for (int i = 0; i < interfaces.length; i++) {
ResolvedType anInterface = interfaces[i];
* We need to determine if any methods in this type require bridge methods - this method should only be called if necessary to
* do this calculation, i.e. we are on a 1.5 VM (where covariance/generics exist) and the type hierarchy for the specified class
* has changed (via decp/itd).
- *
+ *
* See pr108101
*/
public static boolean calculateAnyRequiredBridgeMethods(BcelWorld world, LazyClassGen clazz) {
world.ensureAdvancedConfigurationProcessed();
-
+
if (!world.isInJava5Mode()) {
return false; // just double check... the caller should have already
}
if (clazz.isInterface()) {
return false; // dont bother if we are an interface
}
-
+
boolean didSomething = false; // set if we build any bridge methods
// So what methods do we have right now in this class?
List<LazyMethodGen> methods = clazz.getMethodGens();
if (decaMs.isEmpty()) {
return false; // nothing to do
}
-
+
Set<DeclareAnnotation> unusedDecams = new HashSet<DeclareAnnotation>();
unusedDecams.addAll(decaMs);
if (addedLazyMethodGens!=null) {
for (LazyMethodGen method: addedLazyMethodGens) {
// They have no resolvedmember of their own, conjure one up for matching purposes
- ResolvedMember resolvedmember =
+ ResolvedMember resolvedmember =
new ResolvedMemberImpl(ResolvedMember.METHOD,method.getEnclosingClass().getType(),method.getAccessFlags(),
BcelWorld.fromBcel(method.getReturnType()),method.getName(),
BcelWorld.fromBcel(method.getArgumentTypes()),UnresolvedType.forNames(method.getDeclaredExceptions()));
unusedDecams.remove(decam);
} else if (!decam.isStarredAnnotationPattern()) {
// an annotation is specified that might be put on by a subsequent decaf
- worthRetrying.add(decam);
+ worthRetrying.add(decam);
}
}
}
}
}
-
-
+
+
// deal with all the other methods...
List<LazyMethodGen> members = clazz.getMethodGens();
if (!members.isEmpty()) {
/**
* Applies some set of declare @field constructs (List<DeclareAnnotation>) to some bunch of ITDfields (List<BcelTypeMunger>. It
* will iterate over the fields repeatedly until everything has been applied.
- *
+ *
*/
private boolean weaveAtFieldRepeatedly(List<DeclareAnnotation> decaFs, List<ConcreteTypeMunger> itdFields,
List<Integer> reportedErrors) {
// skip it for now
/**
* Weave any declare @field statements into the fields of the supplied class. This will attempt to apply them to the ITDs too.
- *
+ *
* Interesting case relating to public ITDd fields. The annotations are really stored against the interfieldinit method in the
* aspect, but the public field is placed in the target type and then is processed in the 2nd pass over fields that occurs. I
* think it would be more expensive to avoid putting the annotation on that inserted public field than just to have it put there
/**
* inline a particular call in bytecode.
- *
+ *
* @param donor the method we want to inline
* @param recipient the method containing the call we want to inline
* @param call the instructionHandle in recipient's body holding the call we want to inline.
/*
* Implementation notes:
- *
+ *
* We allocate two slots for every tempvar so we don't screw up longs and doubles which may share space. This could be
* conservatively avoided (no reference to a long/double instruction, don't do it) or packed later. Right now we don't
* bother to pack.
- *
+ *
* Allocate a new var for each formal param of the inlined. Fill with stack contents. Then copy the inlined instructions in
* with the appropriate remap table. Any framelocs used by locals in inlined are reallocated to top of frame,
*/
/**
* Input method is a synchronized method, we remove the bit flag for synchronized and then insert a try..finally block
- *
+ *
* Some jumping through firey hoops required - depending on the input code level (1.5 or not) we may or may not be able to use
* the LDC instruction that takes a class literal (doesnt on <1.5).
- *
+ *
* FIXME asc Before promoting -Xjoinpoints:synchronization to be a standard option, this needs a bunch of tidying up - there is
* some duplication that can be removed.
*/
/**
* generate the instructions to be inlined.
- *
+ *
* @param donor the method from which we will copy (and adjust frame and jumps) instructions.
* @param recipient the method the instructions will go into. Used to get the frame size so we can allocate new frame locations
* for locals in donor.
// }
// }
// }
-// BootstrapMethods.BootstrapMethod bootstrapMethod =
+// BootstrapMethods.BootstrapMethod bootstrapMethod =
// bootstrapMethods.getBootstrapMethods()[bmaIndex];
// ConstantMethodHandle methodhandle = (ConstantMethodHandle)donorCpg.getConstant(bootstrapMethod.getBootstrapMethodRef());
// int bootstrapMethodArguments[] = bootstrapMethod.getBootstrapArguments();
-//
+//
// // Finally have all we need to build the new one...
-//
+//
// int newMethodHandleIndex = recipientCpg.addConstant(methodhandle, donorCpg);
// int[] newMethodArguments = new int[bootstrapMethodArguments.length];
// for (int a=0; a<bootstrapMethodArguments.length; a++) {
// newMethodArguments[a] = recipientCpg.addConstant(donorCpg.getConstant(bootstrapMethodArguments[a]),donorCpg);
// }
-// BootstrapMethods.BootstrapMethod newBootstrapMethod =
+// BootstrapMethods.BootstrapMethod newBootstrapMethod =
// new BootstrapMethods.BootstrapMethod(newMethodHandleIndex,newMethodArguments);
-//
+//
// Collection<Attribute> newAttributes = recipient.getEnclosingClass().getAttributes();
// BootstrapMethods newBootstrapMethods = null;
// for (Attribute attr: newAttributes) {
// }
// }
// if (newBootstrapMethods == null) {
-// newBootstrapMethods =
+// newBootstrapMethods =
// new BootstrapMethods(recipientCpg.addUtf8("BootstrapMethods"),
// 2+newBootstrapMethod.getLength(),
// new BootstrapMethods.BootstrapMethod[] {newBootstrapMethod},
// }
// TODO need to copy over lambda$0 support methods too...
// }
-//
+//
// }
}
if (src.getInstruction() == Range.RANGEINSTRUCTION) {
/**
* generate the argument stores in preparation for inlining.
- *
+ *
* @param donor the method we will inline from. Used to get the signature.
* @param recipient the method we will inline into. Used to get the frame size so we can allocate fresh locations.
* @param frameEnv an empty environment we populate with a map from donor frame to recipient frame.
/**
* get a called method: Assumes the called method is in this class, and the reference to it is exact (a la INVOKESPECIAL).
- *
+ *
* @param ih The InvokeInstruction instructionHandle pointing to the called method.
*/
private LazyMethodGen getCalledMethod(InstructionHandle ih) {
/**
* Find the specified member in the specified type.
- *
+ *
* @param type the type to search for the member
* @param methodName the name of the method to find
* @param params the method parameters that the discovered method should have
* For a given resolvedmember, this will discover the real annotations for it. <b>Should only be used when the resolvedmember is
* the contents of an effective signature attribute, as thats the only time when the annotations aren't stored directly in the
* resolvedMember</b>
- *
+ *
* @param rm the sig we want it to pretend to be 'int A.m()' or somesuch ITD like thing
* @param declaredSig the real sig 'blah.ajc$xxx'
*/
* For a given resolvedmember, this will discover the real annotations for it. <b>Should only be used when the resolvedmember is
* the contents of an effective signature attribute, as thats the only time when the annotations aren't stored directly in the
* resolvedMember</b>
- *
+ *
* @param rm the sig we want it to pretend to be 'int A.m()' or somesuch ITD like thing
* @param declaredSig the real sig 'blah.ajc$xxx'
*/
}
if (methodName.startsWith(SWITCH_TABLE_SYNTHETIC_METHOD_PREFIX)) {
- // we shouldn't process calls to synthetic methods (since they're not 'declared')
proceed = false;
}