package alt.jiapi.util;
import alt.jiapi.reflect.Instruction;
import alt.jiapi.reflect.InstructionList;
import alt.jiapi.reflect.Signature;
import alt.jiapi.reflect.instruction.FieldAccess;
import alt.jiapi.reflect.instruction.Invocation;
/**
* HotSpot.<p>
*
* HotSpot is defined as being an interesting Instruction,
* and all the Instructions before it, that has a total
* stack usage of 0.<p>
*
* If the interesting Instruction has a positive or zero stack usage,
* HotSpot is defined as being that single Instruction.<p>
*
* NOTE: We might change this definition to be exactly zero stack usage<p>
*
* For invocation, this would be
* <ol>
* <li>Object reference of target (if <i>invokevirtual</i>)
* <li>All the Instructions, that push arguments into stack
* <li>Actual method invoke
* </ol>
*
*
* @author Mika Riekkinen
*/
public class HotSpot {
private Instruction startIns;
private Instruction endIns;
private InstructionList il;
/**
* Create new hotspot for a single Instruction.
*
* @param il InstructionList that contains hotspot
* @param ins An Instruction, that makes up this hotspot
*/
public HotSpot(InstructionList il, Instruction ins) {
this(il, ins, ins);
}
/**
* Create new hotspot.
*
* @param il InstructionList that contains hotspot.
* @param start First instruction of the hotspot
* @param end Last instruction of the hotspot
*/
public HotSpot(InstructionList il, Instruction start, Instruction end) {
this.il = il;
this.startIns = start;
this.endIns = end;
}
/**
* Get the InstructionList that represents this hotspot.
*
* InstructionList returned is a view to underlying list. All the
* modifications made to view, is reflected back to
* underlying list.
*
* @return a view of the hotspot
*/
public InstructionList getInstructionList() {
int i1 = il.indexOf(startIns);
int i2 = il.indexOf(endIns);
return il.createView(i1, i2 + 1);
}
/**
* Get the InstructionList that represents arguments of this hotspot.
* Arguments of the HotSpot is defined as being all the instructions
* returned by getInstructionList(), except the one
* returned by getHotSpotInstruction().<p>
*
* InstructionList returned is a view to underlying list. All the
* modifications made to view, is reflected back to
* underlying list.
*
* @return a view of the hotspot
*/
public InstructionList getArgumentList() {
int i1 = il.indexOf(startIns);
int i2 = il.indexOf(endIns);
return il.createView(i1, i2);
}
/**
* Get the Instruction, that was used to trigger creation of this
* HotSpot. By definition, hotspot-instruction is allways the
* last instruction of the hotspot. So this method is a
* shortcut to <code>getInstructionList().get(il.size() - 1);</code>
*
* @return Instruction
*/
public Instruction getHotSpotInstruction() {
return endIns;
}
/**
* Gets the name of this HotSpot.
* For invocations, name of the hotspot is constructed like this:<br>
* <i>ret-type class-name.method-name(param1,param2,...)</i><p>
*
* For example, for <br>
* <code><b>invokevirtual</b> java.io.PrintStream.println(Ljava/lang/String;)V</code><br>
* <code>void java.io.PrintStream.println(java.lang.String)</code> is
* returned
*
* <p>
*
* For field accesses, name of the hotspot is <br>
* <i>class-name.field-name</i><p>
*
* For the rest of the hotspots, an empty String is returned.
*
* @return Name of the hotspot
*/
public String getName() {
if (endIns instanceof Invocation) {
Invocation inv = (Invocation)endIns;
StringBuffer sb = new StringBuffer();
if (!"<init>".equals(inv.getMethodName())) {
sb.append(inv.getReturnType());
sb.append(' ');
}
sb.append(inv.getClassName());
sb.append('.');
sb.append(inv.getMethodName());
sb.append('(');
String[] params = inv.getParameterTypes();
for (int i = 0; i < params.length; i++) {
sb.append(params[i]);
if (i < params.length - 1) {
sb.append(',');
}
}
sb.append(')');
return sb.toString();
}
else if (endIns instanceof FieldAccess) {
FieldAccess fa = (FieldAccess)endIns;
return fa.getClassName() + "." + fa.getFieldName();
}
return ""; // Should we return null instead?
}
}