/*
* Copyright (C) 2001 Mika Riekkinen, Joni Suominen
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package alt.jiapi.instrumentor;
import java.util.ArrayList;
import java.util.List;
import alt.jiapi.JiapiException;
import alt.jiapi.Rule;
import alt.jiapi.Runtime;
import alt.jiapi.reflect.InstructionList;
import alt.jiapi.reflect.Instruction;
import alt.jiapi.reflect.instruction.FieldAccess;
import alt.jiapi.reflect.instruction.OpcodeGroups;
import alt.jiapi.reflect.instruction.Opcodes;
/**
* This strategy finds field access instructions.
* Each known spot returned is only of length 1, pointing to
* field access Instruction.
*
* @author Mika Riekkinen
* @author Joni Suominen
* @version $Revision: 1.8 $ $Date: 2004/03/15 14:47:53 $
*/
public class FieldAccessStrategy extends AbstractStrategy {
public static final int READ_ACCESS = 1;
public static final int WRITE_ACCESS = 2;
private int accessPolicy;
/**
* Empty constructor. Access policy is set to READ_ACCESS + WRITE_ACCESS
* and all the field accesses are matched.
*/
public FieldAccessStrategy() {
this(new String[] {"*"}, false, READ_ACCESS + WRITE_ACCESS);
}
/**
* Constructor with specified access policy. Access policies may be
* summed together. For example, 'READ_ACCESS + WRITE_ACCESS'.
*
* @param accessPolicy a policy indicating which instructions are
* matched.
* @see #READ_ACCESS
* @see #WRITE_ACCESS
*/
public FieldAccessStrategy(String matcher, int accessPolicy) {
this(new String[] {matcher}, false, accessPolicy);
}
/**
* Constructor with specified access policy. Access policies may be
* summed together. For example, 'READ_ACCESS + WRITE_ACCESS'.
*
* @param accessPolicy a policy indicating which instructions are
* matched.
* @see #READ_ACCESS
* @see #WRITE_ACCESS
*/
public FieldAccessStrategy(String matcher, boolean reverseMatch, int accessPolicy) {
this(new String[] {matcher}, reverseMatch, accessPolicy);
}
/**
* Constructor with specified access policy. Access policies may be
* summed together. For example, 'READ_ACCESS + WRITE_ACCESS'.
*
* @param accessPolicy a policy indicating which instructions are
* matched.
* @see #READ_ACCESS
* @see #WRITE_ACCESS
*/
public FieldAccessStrategy(String [] matchers, boolean reverseMatch,
int accessPolicy) {
super(matchers, reverseMatch);
this.accessPolicy = accessPolicy;
}
/**
* Scans InstructionList for field access Instructions.
*
* @param il InstructionList to scan for field access instructions.
* @return A List of known spots, that points either to read access
* or write access instruction.
*/
public List findHotSpots(InstructionList il) {
Instrumentation instrumentation = getInstrumentation();
List hotSpots = new ArrayList();
int index = 0;
// Find getXXX or putXXX instructions
while ((index = il.indexOf(OpcodeGroups.FIELD_ACCESS_INSTRUCTIONS,
index)) != -1) {
FieldAccess fa = (FieldAccess)il.get(index);
int opcode = fa.getOpcode();
// Operand o = i.getOperand();
String targetName = fa.getFieldName();
// if (match(o.toString())) { // Resolution
if (match(targetName)) { // Resolution
if ((accessPolicy & READ_ACCESS) == READ_ACCESS) {
if ((opcode == Opcodes.GETFIELD) ||
(opcode == Opcodes.GETSTATIC)) {
HotSpot h = new HotSpot(index, index + 1);
//instrumentation.setTargetName(o.toString());
instrumentation.setTargetName(targetName);
hotSpots.add(h);
}
}
if ((accessPolicy & WRITE_ACCESS) == WRITE_ACCESS) {
if ((opcode == Opcodes.PUTFIELD) ||
(opcode == Opcodes.PUTSTATIC)) {
HotSpot h = new HotSpot(index, index + 1);
//instrumentation.setTargetName(o.toString());
instrumentation.setTargetName(targetName);
hotSpots.add(h);
}
}
}
index++;
}
return hotSpots;
}
}