/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library 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 Lesser General Public License for more
* details.
*/
package com.liferay.whip.instrument;
import com.liferay.whip.coveragedata.ClassData;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.MethodNode;
/**
* @author Shuyang Zhou
*/
public class OutlineMethodVisitor extends MethodVisitor {
public OutlineMethodVisitor(
ClassData classData, MethodVisitor methodVisitor, int access,
String name, String desc, String signature, String[] exceptions) {
super(
Opcodes.ASM5,
new BackwardCompatibleMethodNode(
access, name, desc, signature, exceptions));
_classData = classData;
_methodVisitor = methodVisitor;
_methodNode = (MethodNode)mv;
}
@Override
public void visitEnd() {
super.visitEnd();
MethodVisitor methodVisitor = _methodVisitor;
if (!_lineLabels.isEmpty()) {
methodVisitor = new TouchMethodVisitor(
_classData.getName(), _methodNode, _methodVisitor, _jumpLabels,
_lineLabels, _switchLabels);
}
_methodNode.accept(methodVisitor);
}
@Override
public void visitJumpInsn(int opcode, Label label) {
if ((_currentLine != 0) && (opcode != Opcodes.GOTO) &&
(opcode != Opcodes.JSR)) {
_classData.addLineJump(_currentLine, _currentJump++);
_jumpLabels.add(label);
}
super.visitJumpInsn(opcode, label);
}
@Override
public void visitLineNumber(int line, Label start) {
_currentLine = line;
_currentJump = 0;
_currentSwitch = 0;
_classData.addLine(_currentLine);
_lineLabels.put(start, line);
}
@Override
public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
super.visitLookupSwitchInsn(dflt, keys, labels);
if (_currentLine != 0) {
_switchLabels.put(
dflt, new SwitchHolder(_currentLine, _currentSwitch, -1));
for (int i = 0; i < labels.length; i++) {
_switchLabels.put(
labels[i],
new SwitchHolder(_currentLine, _currentSwitch, i));
}
_classData.addLineSwitch(_currentLine, _currentSwitch++, keys);
}
}
@Override
public void visitTableSwitchInsn(
int min, int max, Label dflt, Label... labels) {
super.visitTableSwitchInsn(min, max, dflt, labels);
if (_currentLine != 0) {
_switchLabels.put(
dflt, new SwitchHolder(_currentLine, _currentSwitch, -1));
for (int i = 0; i < labels.length; i++) {
_switchLabels.put(
labels[i],
new SwitchHolder(_currentLine, _currentSwitch, i));
}
_classData.addLineSwitch(_currentLine, _currentSwitch++, min, max);
}
}
private final ClassData _classData;
private int _currentJump;
private int _currentLine;
private int _currentSwitch;
private final Set<Label> _jumpLabels = new HashSet<>();
private final Map<Label, Integer> _lineLabels = new HashMap<>();
private final MethodNode _methodNode;
private final MethodVisitor _methodVisitor;
private final Map<Label, SwitchHolder> _switchLabels = new HashMap<>();
}