Home | History | Annotate | Download | only in filter
      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  *    Evgeny Mandrikov - initial API and implementation
     10  *
     11  *******************************************************************************/
     12 package org.jacoco.core.internal.analysis.filter;
     13 
     14 import org.objectweb.asm.Opcodes;
     15 import org.objectweb.asm.tree.AbstractInsnNode;
     16 import org.objectweb.asm.tree.MethodNode;
     17 import org.objectweb.asm.tree.TryCatchBlockNode;
     18 
     19 /**
     20  * Filters code that is generated for synchronized statement.
     21  */
     22 public final class SynchronizedFilter implements IFilter {
     23 
     24 	public void filter(final String className, final String superClassName,
     25 			final MethodNode methodNode, final IFilterOutput output) {
     26 		for (TryCatchBlockNode tryCatch : methodNode.tryCatchBlocks) {
     27 			if (tryCatch.type != null) {
     28 				continue;
     29 			}
     30 			if (tryCatch.start == tryCatch.handler) {
     31 				continue;
     32 			}
     33 			final AbstractInsnNode to = new Matcher(tryCatch.handler).match();
     34 			if (to == null) {
     35 				continue;
     36 			}
     37 			output.ignore(tryCatch.handler, to);
     38 		}
     39 	}
     40 
     41 	private static class Matcher extends AbstractMatcher {
     42 		private final AbstractInsnNode start;
     43 
     44 		private Matcher(final AbstractInsnNode start) {
     45 			this.start = start;
     46 		}
     47 
     48 		private AbstractInsnNode match() {
     49 			if (nextIsEcj() || nextIsJavac()) {
     50 				return cursor;
     51 			}
     52 			return null;
     53 		}
     54 
     55 		private boolean nextIsJavac() {
     56 			cursor = start;
     57 			nextIsVar(Opcodes.ASTORE, "t");
     58 			nextIs(Opcodes.ALOAD);
     59 			nextIs(Opcodes.MONITOREXIT);
     60 			nextIsVar(Opcodes.ALOAD, "t");
     61 			nextIs(Opcodes.ATHROW);
     62 			return cursor != null;
     63 		}
     64 
     65 		private boolean nextIsEcj() {
     66 			cursor = start;
     67 			nextIs(Opcodes.ALOAD);
     68 			nextIs(Opcodes.MONITOREXIT);
     69 			nextIs(Opcodes.ATHROW);
     70 			return  cursor != null;
     71 		}
     72 	}
     73 
     74 }
     75