diff --git a/src/main/java/cz/advel/stack/instrument/InstrumentMethod.java b/src/main/java/cz/advel/stack/instrument/InstrumentMethod.java
index 7bc2dfe..61559ac 100644
--- a/src/main/java/cz/advel/stack/instrument/InstrumentMethod.java
+++ b/src/main/java/cz/advel/stack/instrument/InstrumentMethod.java
@@ -4,11 +4,11 @@
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
+ *
+ * Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
- *
+ *
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
@@ -37,25 +37,25 @@
* @author jezek2
*/
class InstrumentMethod extends MethodNode {
-
+
private static String STACK_NAME = Type.getInternalName(Stack.class);
private static String STACK_ALLOC_CLASS_DESC = Type.getMethodDescriptor(Type.getType(Object.class), new Type[] { Type.getType(Class.class) } );
private static String STACK_ALLOC_OBJECT_DESC = Type.getMethodDescriptor(Type.getType(Object.class), new Type[] { Type.getType(Object.class) } );
private static String STATIC_ALLOC_DESC = Type.getDescriptor(StaticAlloc.class);
-
+
// Matthias Mann's Continuations library, see: http://www.matthiasmann.de/content/view/24/26/
private static String CONTINUATIONS_SUSPEND_EXECUTION_NAME = "de/matthiasmann/continuations/SuspendExecution";
-
+
private Instrumenter instr;
private InstrumentClass inscls;
private String className;
private ClassVisitor cv;
-
+
private List frames;
-
+
private boolean disableAllocation;
private boolean staticAllocation = false;
-
+
boolean emitMethod = true;
public InstrumentMethod(int access, String name, String desc, String signature, String[] exceptions, Instrumenter instr, InstrumentClass inscls, String className, ClassVisitor cv) {
@@ -64,7 +64,7 @@ public InstrumentMethod(int access, String name, String desc, String signature,
this.inscls = inscls;
this.className = className;
this.cv = cv;
-
+
disableAllocation = instr.isDisabled();
}
@@ -78,7 +78,7 @@ public void visitEnd() {
disableAllocation = true;
}
}
-
+
// check for StaticAlloc annotation, if present set staticAllocation to true and remove it:
if (invisibleAnnotations != null) {
for (int i=0; i(Arrays.asList(analyzer.getFrames()));
-
+
Set usedTypes = new HashSet();
boolean createStack = false;
-
+
AbstractInsnNode insn = instructions.getFirst();
-
+
while (insn != null) {
if (insn instanceof MethodInsnNode) {
MethodInsnNode min = (MethodInsnNode)insn;
-
+
// check for Stack.alloc(Class):
if (min.owner.equals(STACK_NAME) && min.name.equals("alloc") && min.desc.equals(STACK_ALLOC_CLASS_DESC)) {
AbstractInsnNode insnBefore = min.getPrevious();
Type type = null;
-
+
+ // GS: Java 8's compiler introduces LineNumberNode and LabelNode between LdcInsnNode and MethodInsnNode, skip them
+ if (insnBefore instanceof LineNumberNode)
+ insnBefore = insnBefore.getPrevious();
+ if (insnBefore instanceof LabelNode)
+ insnBefore = insnBefore.getPrevious();
+
if (insnBefore instanceof LdcInsnNode && ((LdcInsnNode)insnBefore).cst instanceof Type) {
type = (Type)((LdcInsnNode)insnBefore).cst;
removeInsn(insnBefore);
@@ -120,15 +126,15 @@ public void visitEnd() {
else {
logError("first parameter of Stack.alloc(Class) must be constant");
}
-
+
if (!staticAllocation) {
usedTypes.add(type.getInternalName());
instr.addStackType(type.getInternalName());
}
-
+
insn = replaceAllocClass(insn, type, stackVar).getNext();
removeInsn(min);
-
+
// remove redudant checkcast:
if (insn instanceof TypeInsnNode) {
TypeInsnNode tin = (TypeInsnNode)insn;
@@ -137,24 +143,24 @@ public void visitEnd() {
removeInsn(tin);
}
}
-
+
continue;
}
-
+
// check for Stack.alloc(Object):
if (min.owner.equals(STACK_NAME) && min.name.equals("alloc") && min.desc.equals(STACK_ALLOC_OBJECT_DESC)) {
Frame frame = frames.get(instructions.indexOf(insn));
BasicValue value = (BasicValue)frame.getStack(frame.getStackSize() - 1);
Type type = value.getType();
-
+
if (!staticAllocation) {
usedTypes.add(type.getInternalName());
instr.addStackType(type.getInternalName());
}
-
+
insn = replaceAllocObject(insn, type, stackVar).getNext();
removeInsn(min);
-
+
// remove redudant checkcast:
if (insn instanceof TypeInsnNode) {
TypeInsnNode tin = (TypeInsnNode)insn;
@@ -163,10 +169,10 @@ public void visitEnd() {
removeInsn(tin);
}
}
-
+
continue;
}
-
+
// check for Stack.libraryCleanCurrentThread():
if (min.owner.equals(STACK_NAME) && min.name.equals("libraryCleanCurrentThread") && min.desc.equals("()V")) {
if (instr.isDisabled() || instr.isSingleThread()) {
@@ -182,7 +188,7 @@ public void visitEnd() {
}
}
}
-
+
insn = insn.getNext();
}
@@ -198,7 +204,7 @@ public void visitEnd() {
if (usedTypes.size() > 0) {
String[] typesArray = usedTypes.toArray(new String[usedTypes.size()]);
insertPush(insn, typesArray, stackVar);
-
+
while (insn != null) {
if (insn instanceof InsnNode && isReturnOpcode(insn.getOpcode())) {
insertPop(insn, true, typesArray, stackVar);
@@ -215,7 +221,7 @@ public void visitEnd() {
tryCatchBlocks.add(new TryCatchBlockNode(startLabel, endLabel, endLabel, null));
}
}
-
+
if (emitMethod) {
accept(cv);
}
@@ -224,61 +230,61 @@ public void visitEnd() {
throw new IllegalStateException(e);
}
}
-
+
////////////////////////////////////////////////////////////////////////////
-
+
private void removeInsn(AbstractInsnNode insn) {
int idx = instructions.indexOf(insn);
instructions.remove(insn);
frames.remove(idx);
}
-
+
private AbstractInsnNode insertInsn(AbstractInsnNode insn, InsnList list) {
if (list.size() == 0) {
return insn;
}
-
+
int idx = instructions.indexOf(insn);
for (int i=0; i", "()V"));
-
+
list.add(new InsnNode(Opcodes.DUP_X1));
list.add(new InsnNode(Opcodes.SWAP));
-
+
Method m = StackGenerator.findGetMethodType(type.getInternalName());
list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, type.getInternalName(),
"set",
@@ -389,10 +395,10 @@ private AbstractInsnNode replaceAllocObject(AbstractInsnNode pos, Type type, int
else if (staticAllocation) {
int num = inscls.registerStaticAlloc(type.getInternalName());
list.add(new FieldInsnNode(Opcodes.GETSTATIC, className, "$stackTemp"+num, type.getDescriptor()));
-
+
list.add(new InsnNode(Opcodes.DUP_X1));
list.add(new InsnNode(Opcodes.SWAP));
-
+
Method m = StackGenerator.findGetMethodType(type.getInternalName());
list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, type.getInternalName(),
"set",
@@ -405,10 +411,10 @@ else if (staticAllocation) {
"get$"+Instrumenter.mangleInternalName(type.getInternalName()),
"("+type.getDescriptor()+")"+type.getDescriptor()));
}
-
+
return insertInsn(pos, list);
}
-
+
private void logError(String msg) {
throw new IllegalStateException(msg+" (in class "+className.replace('/', '.')+", method "+name+")");
}