aboutsummaryrefslogtreecommitdiff
path: root/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java
diff options
context:
space:
mode:
authorEvgeny Mandrikov <Godin@users.noreply.github.com>2017-03-28 19:20:48 +0200
committerGitHub <noreply@github.com>2017-03-28 19:20:48 +0200
commiteaef191fe12fc5abc81435016dbbd69cb55d1f68 (patch)
treef7ea74f56ff9a388e22cb44e5626dd3bcb83f50e /org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java
parent38a26f418483fd2053b19bf6b3adb7318c11be3f (diff)
downloadjacoco-eaef191fe12fc5abc81435016dbbd69cb55d1f68.tar.gz
Add internal API for filters and filter for synchronized statement (#501)
Diffstat (limited to 'org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java')
-rw-r--r--org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java90
1 files changed, 90 insertions, 0 deletions
diff --git a/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java
new file mode 100644
index 00000000..65e763d5
--- /dev/null
+++ b/org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/SynchronizedFilter.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Evgeny Mandrikov - initial API and implementation
+ *
+ *******************************************************************************/
+package org.jacoco.core.internal.analysis.filter;
+
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TryCatchBlockNode;
+
+/**
+ * Filters code that is generated for synchronized statement.
+ */
+public final class SynchronizedFilter implements IFilter {
+
+ public void filter(MethodNode methodNode, IFilterOutput output) {
+ for (TryCatchBlockNode tryCatch : methodNode.tryCatchBlocks) {
+ if (tryCatch.type != null) {
+ continue;
+ }
+ if (tryCatch.start == tryCatch.handler) {
+ continue;
+ }
+ final AbstractInsnNode to = new Matcher(tryCatch.handler).match();
+ if (to == null) {
+ continue;
+ }
+ output.ignore(tryCatch.handler, to);
+ }
+ }
+
+ private static class Matcher {
+ private final AbstractInsnNode start;
+ private AbstractInsnNode cursor;
+
+ private Matcher(final AbstractInsnNode start) {
+ this.start = start;
+ }
+
+ private AbstractInsnNode match() {
+ if (nextIsEcj() || nextIsJavac()) {
+ return cursor;
+ }
+ return null;
+ }
+
+ private boolean nextIsJavac() {
+ cursor = start;
+ return nextIs(Opcodes.ASTORE) && nextIs(Opcodes.ALOAD)
+ && nextIs(Opcodes.MONITOREXIT) && nextIs(Opcodes.ALOAD)
+ && nextIs(Opcodes.ATHROW);
+ }
+
+ private boolean nextIsEcj() {
+ cursor = start;
+ return nextIs(Opcodes.ALOAD) && nextIs(Opcodes.MONITOREXIT)
+ && nextIs(Opcodes.ATHROW);
+ }
+
+ /**
+ * Moves {@link #cursor} to next instruction and returns
+ * <code>true</code> if it has given opcode.
+ */
+ private boolean nextIs(int opcode) {
+ next();
+ return cursor != null && cursor.getOpcode() == opcode;
+ }
+
+ /**
+ * Moves {@link #cursor} to next instruction.
+ */
+ private void next() {
+ do {
+ cursor = cursor.getNext();
+ } while (cursor != null
+ && (cursor.getType() == AbstractInsnNode.FRAME
+ || cursor.getType() == AbstractInsnNode.LABEL
+ || cursor.getType() == AbstractInsnNode.LINE));
+ }
+ }
+
+}