@@ -0,0 +1,15 @@ | |||
import java.util.*; | |||
public class Code { | |||
public void m() { } | |||
public static void main(String []argv) { | |||
new Code().m(); | |||
} | |||
} | |||
aspect X { | |||
void around(): execution(* m(..)) { | |||
Arrays.asList(4, 5, 6).forEach((i) -> { System.out.println(i);}); | |||
} | |||
} | |||
@@ -0,0 +1,75 @@ | |||
//package org.acmsl.pocs.lambdafor; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.function.Function; | |||
import java.util.stream.Collectors; | |||
public class ControlFlow | |||
{ | |||
public <C extends Collection<I>, I, R> Collection<R> forloop( final C items, final Function<I, R> lambda) | |||
{ | |||
return functionalForLoop(items, lambda); | |||
} | |||
public <C extends Collection<I>, I, R> Collection<R> functionalForLoop( final C items, final Function<I, R> lambda) | |||
{ | |||
return items.stream().map(lambda::apply).collect(Collectors.toList()); | |||
} | |||
public Collection iterativeForloop( final Collection items, final Function lambda) | |||
{ | |||
final List<Object> result = new ArrayList<>(); | |||
for (final Object item: items) | |||
{ | |||
result.add(lambda.<Object>apply(item)); | |||
} | |||
return result; | |||
} | |||
public <C extends Collection<I>, I, R> Collection<R> externallyDrivenForloop( | |||
final ControlFlowDriver driver, final C items, final Function<I, R> lambda) | |||
{ | |||
final List<R> result = new ArrayList<>(items.size()); | |||
final List<I> list = new ArrayList<>(items); | |||
int position = -1; | |||
while (true) | |||
{ | |||
ControlFlowCommand command = driver.waitForCommand(); | |||
switch (command) | |||
{ | |||
case NEXT: | |||
position++; | |||
break; | |||
case PREVIOUS: | |||
position++; | |||
break; | |||
case RELOAD: | |||
break; | |||
default: | |||
break; | |||
} | |||
if (position < 0) | |||
{ | |||
position = 0; | |||
} | |||
else if (position > list.size() - 1) | |||
{ | |||
break; | |||
} | |||
result.set(position, lambda.apply(list.get(position))); | |||
} | |||
return result; | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
//package org.acmsl.pocs.lambdafor; | |||
public enum ControlFlowCommand { | |||
NEXT, | |||
PREVIOUS, | |||
RELOAD; | |||
} |
@@ -0,0 +1,75 @@ | |||
//package org.acmsl.pocs.lambdafor; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.function.Function; | |||
public class ControlFlowDriver { | |||
private static boolean m__bUsed = false; | |||
public ControlFlowDriver() { | |||
} | |||
protected static void immutableSetUsed(final boolean used) { | |||
m__bUsed = used; | |||
} | |||
protected static void setUsed(final boolean used) { | |||
immutableSetUsed(used); | |||
} | |||
public static boolean isUsed() { | |||
return m__bUsed; | |||
} | |||
public <C extends Collection<I>, I, R> Collection<R> forloop(final C items, | |||
final Function<I, R> lambda) { | |||
setUsed(true); | |||
final List<R> result = new ArrayList<R>(items.size()); | |||
final List<I> list = new ArrayList<I>(items); | |||
int position = -1; | |||
while (true) { | |||
ControlFlowCommand command = waitForCommand(); | |||
switch (command) { | |||
case NEXT: | |||
position++; | |||
break; | |||
case PREVIOUS: | |||
position++; | |||
break; | |||
case RELOAD: | |||
break; | |||
default: | |||
break; | |||
} | |||
if (position < 0) { | |||
position = 0; | |||
} else if (position > list.size() - 1) { | |||
break; | |||
} | |||
result.set(position, lambda.apply(list.get(position))); | |||
} | |||
return result; | |||
} | |||
protected ControlFlowCommand waitForCommand() { | |||
try { | |||
Thread.sleep(1000); | |||
} catch (final InterruptedException interruptedException) { | |||
// whatever | |||
} | |||
return ControlFlowCommand.NEXT; | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
//package org.acmsl.pocs.lambdafor; | |||
import java.util.Arrays; | |||
public aspect ForReplacer | |||
{ | |||
/** | |||
* Intercepting for loop constructs. | |||
*/ | |||
pointcut forLoopPointcut(): | |||
// execution(* Sample.sampleCode(..)); // -> error | |||
execution(* forloop(..)); | |||
// && args(Collect, ..); | |||
/** | |||
* Replacing the loop construct. | |||
*/ | |||
Object around() : forLoopPointcut() | |||
{ | |||
// return proceed(); | |||
// Collection<Integer> result = new ArrayList<>(); | |||
// result.addAll(new ControlFlow().externallyDrivenForloop(new ControlFlowDriver(), Arrays.asList(4, 5, 6), (i) -> { System.out.println(i); return i;})); | |||
// return result; | |||
return new ControlFlow().externallyDrivenForloop(new ControlFlowDriver(), Arrays.asList(4, 5, 6), (i) -> { System.out.println(i); return i;}); | |||
} | |||
/** | |||
* Intercepting for loop constructs. | |||
* | |||
pointcut forLoopPointcut(ControlFlow loop): | |||
call(* ControlFlow.forloop(..)) | |||
&& target(loop); | |||
// && args(items, ..); | |||
/** | |||
* Replacing the loop construct. | |||
* | |||
Collection around(ControlFlow loop) : forLoopPointcut(loop) | |||
{ | |||
return loop.externallyDrivenForloop(new ControlFlowDriver(), Arrays.asList(4, 5, 6), (i) -> { System.out.println(i); return i;}); | |||
// return new ControlFlow().externallyDrivenForloop(new ControlFlowDriver(), Arrays.asList(4, 5, 6), (i) -> { System.out.println(i); return i;}); | |||
} | |||
*/ | |||
} |
@@ -21,6 +21,14 @@ import org.aspectj.testing.XMLBasedAjcTestCase; | |||
*/ | |||
public class Ajc183Tests extends org.aspectj.testing.XMLBasedAjcTestCase { | |||
public void testConstantPool_445395_0() { | |||
runTest("constant pool 0"); | |||
} | |||
public void testConstantPool_445395() { | |||
runTest("constant pool"); | |||
} | |||
public void testAbstractAspectNPE_444398() { | |||
runTest("abstract aspect npe"); | |||
} |
@@ -2,6 +2,23 @@ | |||
<suite> | |||
<ajc-test dir="bugs183/445395" title="constant pool 0"> | |||
<compile options="-1.8" files="Code.java"> | |||
</compile> | |||
<run class="Code"> | |||
<stdout> | |||
<line text="4"/> | |||
<line text="5"/> | |||
<line text="6"/> | |||
</stdout> | |||
</run> | |||
</ajc-test> | |||
<ajc-test dir="bugs183/445395" title="constant pool"> | |||
<compile options="-1.8" files="ControlFlow.java ForReplacer.java ControlFlowCommand.java ControlFlowDriver.java"> | |||
</compile> | |||
</ajc-test> | |||
<ajc-test dir="bugs183/444398" title="abstract aspect npe"> | |||
<compile options="-1.8" files="Bottom.java Middle.java Top.java"> | |||
</compile> |
@@ -19,12 +19,14 @@ import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.Map; | |||
import org.aspectj.apache.bcel.Constants; | |||
import org.aspectj.apache.bcel.classfile.LocalVariable; | |||
import org.aspectj.apache.bcel.classfile.LocalVariableTable; | |||
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.InvokeDynamic; | |||
import org.aspectj.apache.bcel.generic.LineNumberTag; | |||
import org.aspectj.apache.bcel.generic.LocalVariableTag; | |||
import org.aspectj.bridge.ISourceLocation; | |||
@@ -69,7 +71,8 @@ class BcelAdvice extends Advice { | |||
*/ | |||
private Test runtimeTest; | |||
private ExposedState exposedState; | |||
private int containsInvokedynamic = 0;// 0 = dontknow, 1=no, 2=yes | |||
public BcelAdvice(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member adviceSignature, ResolvedType concreteAspect) { | |||
super(attribute, pointcut, simplify(attribute.getKind(), adviceSignature)); | |||
this.concreteAspect = concreteAspect; | |||
@@ -233,6 +236,24 @@ class BcelAdvice extends Advice { | |||
// Could be a symptom that the aspect failed to build last build... return the default answer of false | |||
return false; | |||
} | |||
// Need isJava8 check | |||
// Does the advice contain invokedynamic... | |||
if (boType.javaClass.getMajor() == Constants.MAJOR_1_8) { | |||
if (containsInvokedynamic == 0) { | |||
containsInvokedynamic = 1; | |||
LazyMethodGen lmg = boType.getLazyClassGen().getLazyMethodGen(this.signature); | |||
InstructionList ilist = lmg.getBody(); | |||
for (InstructionHandle src = ilist.getStart(); src != null; src = src.getNext()) { | |||
if (src.getInstruction().opcode == Constants.INVOKEDYNAMIC) { | |||
containsInvokedynamic = 2; | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
if (containsInvokedynamic == 2) { | |||
return false; | |||
} | |||
return boType.getLazyClassGen().isWoven(); | |||
} | |||
@@ -27,6 +27,11 @@ import java.util.Properties; | |||
import java.util.Set; | |||
import org.aspectj.apache.bcel.Constants; | |||
import org.aspectj.apache.bcel.classfile.Attribute; | |||
import org.aspectj.apache.bcel.classfile.BootstrapMethods; | |||
import org.aspectj.apache.bcel.classfile.ConstantInvokeDynamic; | |||
import org.aspectj.apache.bcel.classfile.ConstantMethodHandle; | |||
import org.aspectj.apache.bcel.classfile.ConstantMethodref; | |||
import org.aspectj.apache.bcel.classfile.ConstantPool; | |||
import org.aspectj.apache.bcel.classfile.Method; | |||
import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; | |||
@@ -42,6 +47,7 @@ import org.aspectj.apache.bcel.generic.InstructionLV; | |||
import org.aspectj.apache.bcel.generic.InstructionList; | |||
import org.aspectj.apache.bcel.generic.InstructionSelect; | |||
import org.aspectj.apache.bcel.generic.InstructionTargeter; | |||
import org.aspectj.apache.bcel.generic.InvokeDynamic; | |||
import org.aspectj.apache.bcel.generic.InvokeInstruction; | |||
import org.aspectj.apache.bcel.generic.LineNumberTag; | |||
import org.aspectj.apache.bcel.generic.LocalVariableTag; | |||
@@ -2204,7 +2210,7 @@ class BcelClassWeaver implements IClassWeaver { | |||
ConstantPool recipientCpg = recipient.getEnclosingClass().getConstantPool(); | |||
boolean isAcrossClass = donorCpg != recipientCpg; | |||
BootstrapMethods bootstrapMethods = null; | |||
// first pass: copy the instructions directly, populate the srcToDest | |||
// map, | |||
// fix frame instructions | |||
@@ -2214,13 +2220,60 @@ class BcelClassWeaver implements IClassWeaver { | |||
// OPTIMIZE optimize this stuff? | |||
if (fresh.isConstantPoolInstruction()) { | |||
// need to reset index to go to new constant pool. This is | |||
// totally | |||
// need to reset index to go to new constant pool. This is totally | |||
// a computation leak... we're testing this LOTS of times. Sigh. | |||
if (isAcrossClass) { | |||
InstructionCP cpi = (InstructionCP) fresh; | |||
cpi.setIndex(recipientCpg.addConstant(donorCpg.getConstant(cpi.getIndex()), donorCpg)); | |||
} | |||
// May need to copy bootstrapmethods across too. | |||
// if (fresh instanceof InvokeDynamic) { | |||
// InvokeDynamic id = (InvokeDynamic)fresh; | |||
// ConstantInvokeDynamic cid = (ConstantInvokeDynamic)donorCpg.getConstant(src.getInstruction().getIndex()); | |||
// int bmaIndex = cid.getBootstrapMethodAttrIndex(); | |||
// if (bootstrapMethods == null) { | |||
// Collection<Attribute> attributes = donor.getEnclosingClass().getAttributes(); | |||
// if (attributes != null) { | |||
// for (Attribute attribute: attributes) { | |||
// if (attribute instanceof BootstrapMethods) { | |||
// bootstrapMethods = (BootstrapMethods)attribute; | |||
// } | |||
// } | |||
// } | |||
// 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 = | |||
// new BootstrapMethods.BootstrapMethod(newMethodHandleIndex,newMethodArguments); | |||
// | |||
// Collection<Attribute> newAttributes = recipient.getEnclosingClass().getAttributes(); | |||
// BootstrapMethods newBootstrapMethods = null; | |||
// for (Attribute attr: newAttributes) { | |||
// if (attr instanceof BootstrapMethods) { | |||
// newBootstrapMethods = (BootstrapMethods)newBootstrapMethods; | |||
// } | |||
// } | |||
// if (newBootstrapMethods == null) { | |||
// newBootstrapMethods = | |||
// new BootstrapMethods(recipientCpg.addUtf8("BootstrapMethods"), | |||
// 2+newBootstrapMethod.getLength(), | |||
// new BootstrapMethods.BootstrapMethod[] {newBootstrapMethod}, | |||
// recipientCpg); | |||
// recipient.getEnclosingClass().addAttribute(newBootstrapMethods); | |||
// } | |||
// TODO need to copy over lambda$0 support methods too... | |||
// } | |||
// | |||
// } | |||
} | |||
if (src.getInstruction() == Range.RANGEINSTRUCTION) { | |||
dest = ret.append(Range.RANGEINSTRUCTION); |
@@ -20,6 +20,7 @@ import java.io.IOException; | |||
import java.io.PrintStream; | |||
import java.lang.reflect.Modifier; | |||
import java.util.ArrayList; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.Comparator; | |||
import java.util.HashMap; | |||
@@ -1582,6 +1583,14 @@ public final class LazyClassGen { | |||
public void addAttribute(AjAttribute attribute) { | |||
myGen.addAttribute(Utility.bcelAttribute(attribute, getConstantPool())); | |||
} | |||
public void addAttribute(Attribute attribute) { | |||
myGen.addAttribute(attribute); | |||
} | |||
public Collection<Attribute> getAttributes() { | |||
return myGen.getAttributes(); | |||
} | |||
// this test is like asking: | |||
// if |