Home | History | Annotate | Download | only in instr
      1 /*******************************************************************************
      2  * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors
      3  * All rights reserved. This program and the accompanying materials
      4  * are made available under the terms of the Eclipse Public License v1.0
      5  * which accompanies this distribution, and is available at
      6  * http://www.eclipse.org/legal/epl-v10.html
      7  *
      8  * Contributors:
      9  *    Marc R. Hoffmann - initial API and implementation
     10  *
     11  *******************************************************************************/
     12 package org.jacoco.core.internal.instr;
     13 
     14 import org.objectweb.asm.Handle;
     15 import org.objectweb.asm.Label;
     16 import org.objectweb.asm.MethodVisitor;
     17 
     18 /**
     19  * Eliminates consecutive stackmap frame definitions which causes ASM to create
     20  * invalid class files. This situation occurs when the original class files
     21  * contains additional stackmap frames at unexpected offsets, which is case for
     22  * some class files compiled with ECJ.
     23  */
     24 class DuplicateFrameEliminator extends MethodVisitor {
     25 
     26 	private boolean instruction;
     27 
     28 	public DuplicateFrameEliminator(final MethodVisitor mv) {
     29 		super(InstrSupport.ASM_API_VERSION, mv);
     30 		instruction = true;
     31 	}
     32 
     33 	@Override
     34 	public void visitFrame(final int type, final int nLocal,
     35 			final Object[] local, final int nStack, final Object[] stack) {
     36 		if (instruction) {
     37 			instruction = false;
     38 			mv.visitFrame(type, nLocal, local, nStack, stack);
     39 		}
     40 	}
     41 
     42 	@Override
     43 	public void visitInsn(final int opcode) {
     44 		instruction = true;
     45 		mv.visitInsn(opcode);
     46 	}
     47 
     48 	@Override
     49 	public void visitIntInsn(final int opcode, final int operand) {
     50 		instruction = true;
     51 		mv.visitIntInsn(opcode, operand);
     52 	}
     53 
     54 	@Override
     55 	public void visitVarInsn(final int opcode, final int var) {
     56 		instruction = true;
     57 		mv.visitVarInsn(opcode, var);
     58 	}
     59 
     60 	@Override
     61 	public void visitTypeInsn(final int opcode, final String type) {
     62 		instruction = true;
     63 		mv.visitTypeInsn(opcode, type);
     64 	}
     65 
     66 	@Override
     67 	public void visitFieldInsn(final int opcode, final String owner,
     68 			final String name, final String desc) {
     69 		instruction = true;
     70 		mv.visitFieldInsn(opcode, owner, name, desc);
     71 	}
     72 
     73 	@Override
     74 	public void visitMethodInsn(final int opcode, final String owner,
     75 			final String name, final String desc, final boolean itf) {
     76 		instruction = true;
     77 		mv.visitMethodInsn(opcode, owner, name, desc, itf);
     78 	}
     79 
     80 	@Override
     81 	public void visitInvokeDynamicInsn(final String name, final String desc,
     82 			final Handle bsm, final Object... bsmArgs) {
     83 		instruction = true;
     84 		mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
     85 	}
     86 
     87 	@Override
     88 	public void visitJumpInsn(final int opcode, final Label label) {
     89 		instruction = true;
     90 		mv.visitJumpInsn(opcode, label);
     91 	}
     92 
     93 	@Override
     94 	public void visitLdcInsn(final Object cst) {
     95 		instruction = true;
     96 		mv.visitLdcInsn(cst);
     97 	}
     98 
     99 	@Override
    100 	public void visitIincInsn(final int var, final int increment) {
    101 		instruction = true;
    102 		mv.visitIincInsn(var, increment);
    103 	}
    104 
    105 	@Override
    106 	public void visitTableSwitchInsn(final int min, final int max,
    107 			final Label dflt, final Label... labels) {
    108 		instruction = true;
    109 		mv.visitTableSwitchInsn(min, max, dflt, labels);
    110 	}
    111 
    112 	@Override
    113 	public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
    114 			final Label[] labels) {
    115 		instruction = true;
    116 		mv.visitLookupSwitchInsn(dflt, keys, labels);
    117 	}
    118 
    119 	@Override
    120 	public void visitMultiANewArrayInsn(final String desc, final int dims) {
    121 		instruction = true;
    122 		mv.visitMultiANewArrayInsn(desc, dims);
    123 	}
    124 
    125 }
    126