verifyVarInfoss = new VerifyVarInfo[numCodeBlocks-1][];
}
mv.visitCode();
Label lMethodStart = new Label();
Label lMethodEnd = new Label();
Label lCatchSEE = new Label();
Label lCatchAll = new Label();
Label[] lMethodCalls = new Label[numCodeBlocks-1];
for(int i=1 ; i<numCodeBlocks ; i++) {
lMethodCalls[i-1] = new Label();
}
mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchSEE, CheckInstrumentationVisitor.EXCEPTION_NAME);
for(TryCatchBlockNode tcb : mn.tryCatchBlocks) {
if (hasReflectInvoke && REFLECT_EXCEPTION_SET.contains(tcb.type)) {
if (reflectExceptionHandlers == null){
reflectExceptionHandlers = new HashSet<LabelNode>();
}
reflectExceptionHandlers.add(tcb.handler);
}
if(CheckInstrumentationVisitor.EXCEPTION_NAME.equals(tcb.type)) {
throw new UnableToInstrumentException("catch for " +
SuspendExecution.class.getSimpleName(), className, mn.name, mn.desc);
}
tcb.accept(mv);
}
if(mn.visibleParameterAnnotations != null) {
dumpParameterAnnotations(mv, mn.visibleParameterAnnotations, true);
}
if(mn.invisibleParameterAnnotations != null) {
dumpParameterAnnotations(mv, mn.invisibleParameterAnnotations, false);
}
if(mn.visibleAnnotations != null) {
for(Object o : mn.visibleAnnotations) {
AnnotationNode an = (AnnotationNode)o;
an.accept(mv.visitAnnotation(an.desc, true));
}
}
mv.visitTryCatchBlock(lMethodStart, lMethodEnd, lCatchAll, null);
mv.visitMethodInsn(Opcodes.INVOKESTATIC, STACK_NAME, "getStack", "()L"+STACK_NAME+";");
mv.visitInsn(Opcodes.DUP);
mv.visitVarInsn(Opcodes.ASTORE, lvarStack);
if (db.isAllowOutofCoroutine()) {
mv.visitJumpInsn(Opcodes.IFNULL, lMethodStart);
mv.visitVarInsn(Opcodes.ALOAD, lvarStack);
}
if (verifyVarInfoss != null) {
mv.visitLdcInsn(classAndMethod);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "nextMethodEntryV", "(Ljava/lang/String;)I");
}else {
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STACK_NAME, "nextMethodEntry", "()I");
}
mv.visitInsn(Opcodes.DUP);
Label tableSwitchLabel = new Label();
mv.visitJumpInsn(Opcodes.IFGE, tableSwitchLabel);
mv.visitInsn(Opcodes.POP);
mv.visitInsn(Opcodes.ACONST_NULL);
mv.visitVarInsn(Opcodes.ASTORE, lvarStack);
mv.visitJumpInsn(Opcodes.GOTO, lMethodStart);
mv.visitLabel(tableSwitchLabel);
mv.visitTableSwitchInsn(1, numCodeBlocks-1, lMethodStart, lMethodCalls);
mv.visitLabel(lMethodStart);
dumpCodeBlock(mv, 0, 0);
for(int i=1 ; i<numCodeBlocks ; i++) {
FrameInfo fi = codeBlocks[i];
MethodInsnNode min = (MethodInsnNode)(mn.instructions.get(fi.endInstruction));
if(InstrumentClass.COROUTINE_NAME.equals(min.owner) && "yield".equals(min.name)) {
// special case - call to yield() - resume AFTER the call
if(min.getOpcode() != Opcodes.INVOKESTATIC) {
throw new UnableToInstrumentException("invalid call to yield()", className, mn.name, mn.desc);
}
if (verifyVarInfoss != null) {
mv.visitMethodInsn(Opcodes.INVOKESTATIC, "nginx/clojure/wave/SuspendMethodVerifier", "onYield", "()V");
}
emitStoreState(mv, i, fi);
mv.visitFieldInsn(Opcodes.GETSTATIC, STACK_NAME,
"exception_instance_not_for_user_code",
CheckInstrumentationVisitor.EXCEPTION_DESC);
mv.visitInsn(Opcodes.ATHROW);
min.accept(mv); // only the call
mv.visitLabel(lMethodCalls[i-1]);
emitRestoreState(mv, i, fi);
dumpCodeBlock(mv, i, 1); // skip the call
} else {
final Label ocl = new Label();
if (db.isAllowOutofCoroutine()) {
mv.visitVarInsn(Opcodes.ALOAD, lvarStack);
mv.visitJumpInsn(Opcodes.IFNULL, ocl);
}