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);}); | |||||
} | |||||
} | |||||
//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; | |||||
} | |||||
} |
//package org.acmsl.pocs.lambdafor; | |||||
public enum ControlFlowCommand { | |||||
NEXT, | |||||
PREVIOUS, | |||||
RELOAD; | |||||
} |
//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; | |||||
} | |||||
} |
//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;}); | |||||
} | |||||
*/ | |||||
} |
*/ | */ | ||||
public class Ajc183Tests extends 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() { | public void testAbstractAspectNPE_444398() { | ||||
runTest("abstract aspect npe"); | runTest("abstract aspect npe"); | ||||
} | } |
<suite> | <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"> | <ajc-test dir="bugs183/444398" title="abstract aspect npe"> | ||||
<compile options="-1.8" files="Bottom.java Middle.java Top.java"> | <compile options="-1.8" files="Bottom.java Middle.java Top.java"> | ||||
</compile> | </compile> |
import java.util.Collections; | import java.util.Collections; | ||||
import java.util.Map; | import java.util.Map; | ||||
import org.aspectj.apache.bcel.Constants; | |||||
import org.aspectj.apache.bcel.classfile.LocalVariable; | import org.aspectj.apache.bcel.classfile.LocalVariable; | ||||
import org.aspectj.apache.bcel.classfile.LocalVariableTable; | import org.aspectj.apache.bcel.classfile.LocalVariableTable; | ||||
import org.aspectj.apache.bcel.generic.InstructionConstants; | import org.aspectj.apache.bcel.generic.InstructionConstants; | ||||
import org.aspectj.apache.bcel.generic.InstructionFactory; | import org.aspectj.apache.bcel.generic.InstructionFactory; | ||||
import org.aspectj.apache.bcel.generic.InstructionHandle; | import org.aspectj.apache.bcel.generic.InstructionHandle; | ||||
import org.aspectj.apache.bcel.generic.InstructionList; | 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.LineNumberTag; | ||||
import org.aspectj.apache.bcel.generic.LocalVariableTag; | import org.aspectj.apache.bcel.generic.LocalVariableTag; | ||||
import org.aspectj.bridge.ISourceLocation; | import org.aspectj.bridge.ISourceLocation; | ||||
*/ | */ | ||||
private Test runtimeTest; | private Test runtimeTest; | ||||
private ExposedState exposedState; | private ExposedState exposedState; | ||||
private int containsInvokedynamic = 0;// 0 = dontknow, 1=no, 2=yes | |||||
public BcelAdvice(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member adviceSignature, ResolvedType concreteAspect) { | public BcelAdvice(AjAttribute.AdviceAttribute attribute, Pointcut pointcut, Member adviceSignature, ResolvedType concreteAspect) { | ||||
super(attribute, pointcut, simplify(attribute.getKind(), adviceSignature)); | super(attribute, pointcut, simplify(attribute.getKind(), adviceSignature)); | ||||
this.concreteAspect = concreteAspect; | this.concreteAspect = concreteAspect; | ||||
// Could be a symptom that the aspect failed to build last build... return the default answer of false | // Could be a symptom that the aspect failed to build last build... return the default answer of false | ||||
return 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(); | return boType.getLazyClassGen().isWoven(); | ||||
} | } | ||||
import java.util.Set; | import java.util.Set; | ||||
import org.aspectj.apache.bcel.Constants; | 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.ConstantPool; | ||||
import org.aspectj.apache.bcel.classfile.Method; | import org.aspectj.apache.bcel.classfile.Method; | ||||
import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; | import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; | ||||
import org.aspectj.apache.bcel.generic.InstructionList; | import org.aspectj.apache.bcel.generic.InstructionList; | ||||
import org.aspectj.apache.bcel.generic.InstructionSelect; | import org.aspectj.apache.bcel.generic.InstructionSelect; | ||||
import org.aspectj.apache.bcel.generic.InstructionTargeter; | 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.InvokeInstruction; | ||||
import org.aspectj.apache.bcel.generic.LineNumberTag; | import org.aspectj.apache.bcel.generic.LineNumberTag; | ||||
import org.aspectj.apache.bcel.generic.LocalVariableTag; | import org.aspectj.apache.bcel.generic.LocalVariableTag; | ||||
ConstantPool recipientCpg = recipient.getEnclosingClass().getConstantPool(); | ConstantPool recipientCpg = recipient.getEnclosingClass().getConstantPool(); | ||||
boolean isAcrossClass = donorCpg != recipientCpg; | boolean isAcrossClass = donorCpg != recipientCpg; | ||||
BootstrapMethods bootstrapMethods = null; | |||||
// first pass: copy the instructions directly, populate the srcToDest | // first pass: copy the instructions directly, populate the srcToDest | ||||
// map, | // map, | ||||
// fix frame instructions | // fix frame instructions | ||||
// OPTIMIZE optimize this stuff? | // OPTIMIZE optimize this stuff? | ||||
if (fresh.isConstantPoolInstruction()) { | 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. | // a computation leak... we're testing this LOTS of times. Sigh. | ||||
if (isAcrossClass) { | if (isAcrossClass) { | ||||
InstructionCP cpi = (InstructionCP) fresh; | InstructionCP cpi = (InstructionCP) fresh; | ||||
cpi.setIndex(recipientCpg.addConstant(donorCpg.getConstant(cpi.getIndex()), donorCpg)); | 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) { | if (src.getInstruction() == Range.RANGEINSTRUCTION) { | ||||
dest = ret.append(Range.RANGEINSTRUCTION); | dest = ret.append(Range.RANGEINSTRUCTION); |
import java.io.PrintStream; | import java.io.PrintStream; | ||||
import java.lang.reflect.Modifier; | import java.lang.reflect.Modifier; | ||||
import java.util.ArrayList; | import java.util.ArrayList; | ||||
import java.util.Collection; | |||||
import java.util.Collections; | import java.util.Collections; | ||||
import java.util.Comparator; | import java.util.Comparator; | ||||
import java.util.HashMap; | import java.util.HashMap; | ||||
public void addAttribute(AjAttribute attribute) { | public void addAttribute(AjAttribute attribute) { | ||||
myGen.addAttribute(Utility.bcelAttribute(attribute, getConstantPool())); | 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: | // this test is like asking: | ||||
// if | // if |