com.sun.tdk.jcov.instrument.StaticInvokeMethodAdapter.java Source code

Java tutorial

Introduction

Here is the source code for com.sun.tdk.jcov.instrument.StaticInvokeMethodAdapter.java

Source

/*
 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.sun.tdk.jcov.instrument;

import com.sun.tdk.jcov.util.Utils;
import java.util.HashMap;
import java.util.Map;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import static org.objectweb.asm.Opcodes.*;

/*
 * This class serves abstract, native method and field access coverage
 * functionality for static instrumentation.
 * Works inside Instr2 process - at the beginning mapping of whole signatures
 * to collector's slots (not CollectDetect slots!) is filled from template - see
 * ClassMorph2 for details. Then, if this method adapter finds virtual invocations
 * of methods or fields from map, it hits respective slot.
 *
 * @author Dmitry Fazunenko
 * @author Alexey Fedorchenko
 **/
public class StaticInvokeMethodAdapter extends MethodVisitor {

    static int invokeCount = 0;
    private final String className;
    private final InstrumentationParams params;
    private String methName;

    public static int getInvokeID(String owner, String name, String descr) {
        String sig = owner + "." + name + descr;
        Integer id = map.get(sig);
        if (id != null) {
            return id;
        }
        return -1;
    }

    public static final Map<String, Integer> map = new HashMap<String, Integer>();

    public StaticInvokeMethodAdapter(MethodVisitor mv, String className, String methName, int access,
            final InstrumentationParams params) {
        super(Opcodes.ASM4, mv);
        this.className = className;
        this.params = params;
        this.methName = methName;
    }

    @Override
    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
        if (params.isInstrumentFields() && params.isIncluded(owner) && params.isCallerFilterAccept(className)) {
            if (getInvokeID(owner, name, desc) != -1) {
                int id = getInvokeID(owner, name, desc);
                InsnList il = new InsnList();
                il.add(new LdcInsnNode(id));
                il.add(new MethodInsnNode(INVOKESTATIC, "com/sun/tdk/jcov/runtime/Collect", "hit", "(I)V"));

                il.accept(this);
            }
        }
        super.visitFieldInsn(opcode, owner, name, desc);
    }

    @Override
    public void visitMethodInsn(int opcode, String owner, String name, String desc) {
        if ((opcode == INVOKEVIRTUAL || opcode == INVOKEINTERFACE) && params.isInstrumentAbstract()
                && params.isIncluded(owner)) {

            if (getInvokeID(owner, name, desc) != -1) {
                int id = getInvokeID(owner, name, desc);
                InsnList il = new InsnList();
                il.add(new LdcInsnNode(id));
                il.add(new MethodInsnNode(INVOKESTATIC, "com/sun/tdk/jcov/runtime/Collect", "hit", "(I)V"));
                il.accept(this);
            }
        }
        if (params.isCallerFilterOn() && params.isCallerFilterAccept(className)) {

            int id = (name + desc).hashCode();
            super.visitLdcInsn(id);
            super.visitMethodInsn(INVOKESTATIC, "com/sun/tdk/jcov/runtime/CollectDetect", "setExpected", "(I)V");

        }

        if (params.isInnerInvacationsOff() && Utils.isAdvanceStaticInstrAllowed(className, name)) {
            if (!owner.equals("java/lang/Object")) {

                int id = -1;
                super.visitLdcInsn(id);
                super.visitMethodInsn(INVOKESTATIC, "com/sun/tdk/jcov/runtime/CollectDetect", "setExpected",
                        "(I)V");

            }
        }

        super.visitMethodInsn(opcode, owner, name, desc);

    }

    @Override
    public void visitInsn(int opcode) {

        switch (opcode) {
        case Opcodes.IRETURN:
        case Opcodes.FRETURN:
        case Opcodes.ARETURN:
        case Opcodes.LRETURN:
        case Opcodes.DRETURN:
        case Opcodes.RETURN:
            if (params.isInnerInvacationsOff()
                    && Utils.isAdvanceStaticInstrAllowed(className, methName/*"<init>"*/)) {
                if (!methName.equals("<clinit>")) {
                    int id = 0;
                    super.visitLdcInsn(id);
                    super.visitMethodInsn(INVOKESTATIC, "com/sun/tdk/jcov/runtime/CollectDetect", "setExpected",
                            "(I)V");
                } else {
                    super.visitMethodInsn(INVOKESTATIC, "com/sun/tdk/jcov/runtime/CollectDetect", "leaveClinit",
                            "()V");
                }
            }
            break;
        default:
            break;
        }

        super.visitInsn(opcode);
    }

    public static void addID(String className, String name, String descr, int id) {
        String sig = className + "." + name + descr;
        map.put(sig, id);
    }
}