|
|
@@ -1,15 +1,14 @@ |
|
|
|
/* ******************************************************************* |
|
|
|
* 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; |
|
|
@@ -22,9 +21,9 @@ import java.util.Iterator; |
|
|
|
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; |
|
|
@@ -94,6 +93,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
|
|
|
|
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, |
|
|
@@ -399,7 +399,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
|
|
|
|
/** |
|
|
|
* Weave a class and indicate through the return value whether the class was modified. |
|
|
|
* |
|
|
|
* |
|
|
|
* @return true if the class was modified |
|
|
|
*/ |
|
|
|
public boolean weave() { |
|
|
@@ -569,7 +569,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
// 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) { |
|
|
@@ -670,7 +670,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
/** |
|
|
|
* 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) { |
|
|
@@ -697,7 +697,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
|
|
|
|
/** |
|
|
|
* 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, |
|
|
@@ -709,7 +709,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
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); |
|
|
@@ -720,12 +720,12 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
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) { |
|
|
@@ -761,7 +761,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
|
|
|
|
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]; |
|
|
@@ -773,19 +773,19 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
* 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(); |
|
|
@@ -903,7 +903,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
if (decaMs.isEmpty()) { |
|
|
|
return false; // nothing to do |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Set<DeclareAnnotation> unusedDecams = new HashSet<DeclareAnnotation>(); |
|
|
|
unusedDecams.addAll(decaMs); |
|
|
|
|
|
|
@@ -913,7 +913,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
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())); |
|
|
@@ -944,7 +944,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
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); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -979,8 +979,8 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// deal with all the other methods... |
|
|
|
List<LazyMethodGen> members = clazz.getMethodGens(); |
|
|
|
if (!members.isEmpty()) { |
|
|
@@ -1193,7 +1193,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
/** |
|
|
|
* 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) { |
|
|
@@ -1373,7 +1373,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
// 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 |
|
|
@@ -1677,7 +1677,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
|
|
|
|
/** |
|
|
|
* 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. |
|
|
@@ -1687,11 +1687,11 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
|
|
|
|
/* |
|
|
|
* 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, |
|
|
|
*/ |
|
|
@@ -1721,10 +1721,10 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
|
|
|
|
/** |
|
|
|
* 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. |
|
|
|
*/ |
|
|
@@ -2190,7 +2190,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
|
|
|
|
/** |
|
|
|
* 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. |
|
|
@@ -2240,21 +2240,21 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
// } |
|
|
|
// } |
|
|
|
// } |
|
|
|
// 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) { |
|
|
@@ -2263,7 +2263,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
// } |
|
|
|
// } |
|
|
|
// if (newBootstrapMethods == null) { |
|
|
|
// newBootstrapMethods = |
|
|
|
// newBootstrapMethods = |
|
|
|
// new BootstrapMethods(recipientCpg.addUtf8("BootstrapMethods"), |
|
|
|
// 2+newBootstrapMethod.getLength(), |
|
|
|
// new BootstrapMethods.BootstrapMethod[] {newBootstrapMethod}, |
|
|
@@ -2272,7 +2272,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
// } |
|
|
|
// TODO need to copy over lambda$0 support methods too... |
|
|
|
// } |
|
|
|
// |
|
|
|
// |
|
|
|
// } |
|
|
|
} |
|
|
|
if (src.getInstruction() == Range.RANGEINSTRUCTION) { |
|
|
@@ -2540,7 +2540,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
|
|
|
|
/** |
|
|
|
* 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. |
|
|
@@ -2572,7 +2572,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
|
|
|
|
/** |
|
|
|
* 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) { |
|
|
@@ -3052,7 +3052,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
|
|
|
|
/** |
|
|
|
* 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 |
|
|
@@ -3098,7 +3098,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
* 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' |
|
|
|
*/ |
|
|
@@ -3133,7 +3133,7 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
* 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' |
|
|
|
*/ |
|
|
@@ -3269,7 +3269,6 @@ class BcelClassWeaver implements IClassWeaver { |
|
|
|
} |
|
|
|
|
|
|
|
if (methodName.startsWith(SWITCH_TABLE_SYNTHETIC_METHOD_PREFIX)) { |
|
|
|
// we shouldn't process calls to synthetic methods (since they're not 'declared') |
|
|
|
proceed = false; |
|
|
|
} |
|
|
|
|