/*
* Created on 15 fev. 2005
*
*/
package fr.lifl.stc.stan.samples.flow;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.generic.ATHROW;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.ReturnInstruction;
import org.apache.bcel.generic.BasicType;
//import org.apache.bcel.generic.ReferenceType;
import org.apache.bcel.generic.Type;
//import fr.lifl.rd2p.jits.tools.ea.execution.Interpreter;
//import fr.lifl.rd2p.jits.tools.ea.execution.stack.Value;
//import fr.lifl.rd2p.jits.tools.ea.analyser.GlobalAnalyser;
import fr.lifl.stc.stan.annotation.Annotation;
import fr.lifl.stc.stan.execution.Frame;
import fr.lifl.stc.stan.execution.MethodInfo;
import fr.lifl.stc.stan.execution.stack.JvmType;
import fr.lifl.stc.stan.execution.stack.MultiObject;
import fr.lifl.stc.stan.execution.stack.Reference;
import fr.lifl.stc.stan.link.Link;
import fr.lifl.stc.stan.link.TableLink;
import fr.lifl.stc.stan.policy.Policy;
import fr.lifl.stc.stan.signature.PartialSignature;
import fr.lifl.stc.stan.util.Printer;
import fr.lifl.stc.stan.link.defaultLink.DefaultLink;
/**
* @author dorina
*
*/
public class FlowAnnotation implements Annotation {
/* (non-Javadoc)
* @see fr.lifl.rd2p.jits.tools.ea.annotation.Annotation#update(fr.lifl.rd2p.jits.tools.ea.execution.Frame)
*/
/**
* contains: Excep StaticWorld Flux Arguments ...
* Arguments can be: Value or Reference
* if Reference && not array, it contains: SecretPart PublicPart
*/
private JvmType [] jvmTypes;
/**
* referes to []jvmTypes like this:
* deps[i][i] corresponds to jvmTypes[i-1]
* deps[0][0] corresponds to Return
*/
//private Link [][] deps;
private TableLink deps;
private boolean isStatic;
private int returnDeps;
Type returnType;
public FlowAnnotation (JvmType [] jvm, MethodInfo mi){
Method m = mi.getMethod();
returnType = m.getReturnType();
Type[] args = m.getArgumentTypes();
int n = args.length;
isStatic = m.isStatic();
int l = 3;
int startArg = 0;
if (!isStatic){
n++;
startArg =-1;
}
int dim = n + l;
jvmTypes = new JvmType[dim];
returnDeps = 1;
deps = new TableLink(dim+1, dim+1);
int j = l;
for(int i = startArg; i < args.length ; i++ ) {
JvmType t = findArgument(i, jvm);
if(t!=null) {
jvmTypes[j++] = t;
}
else
System.err.println("Argument "+j+" not found!!!");
}
for (int i = 0; i < jvm.length; i++){
if(jvm[i] instanceof Reference) {
Reference r = (Reference)jvm[i];
if (r.isThrown()){
jvmTypes[0] = r;
}
else if (r.isFlux()){
jvmTypes[2] = r;
}
else if (r.isArgument() && r.getId() == -2){
jvmTypes[1] = r;
}
}
}
}
/**
* Returns the argument with the index j (which can be
* Value or Reference)
* @param j the index of the desired argument
* @param r the list of references & values
* @return the argument j
*/
private JvmType findArgument(int j, JvmType [] r){
for(int i = 0; i < r.length; i++) {
if(r[i].isArgument() && r[i].getId() == j) {
if(r[i] instanceof Reference) {
if(((Reference)r[i]).getAll() != null) {
return ((Reference)r[i]).getAll();
}
}
return r[i];
}
}
return null;
}
/**
*
* @param r
* @return
*/
private int convert (JvmType r){
if(r instanceof Reference && ((Reference)r).getAll()!=null)
r = ((Reference)r).getAll();
for(int i = 0; i < jvmTypes.length; i++) {
if(jvmTypes[i] == r) return i;
}
return -1;
}
public TableLink link (Frame a){
TableLink t = new TableLink(jvmTypes.length, jvmTypes.length);
for (int i = 0; i < t.getSizeL(); i++){
if(jvmTypes[i] != null)
for(int j = 0; j < t.getSizeC(); j++)
if (jvmTypes[j]!=null) {
Link l = a.getLinkBetween(jvmTypes[i], jvmTypes[j]);
if(l!=null)
t.set(i, j, l.clone1());
}
}
return t;
}
/**
* @param t
* @return
*/
private boolean merge (TableLink t){
boolean updated = false;
for (int i = 0; i < t.getSizeL(); i++)
for (int j = 0; j < t.getSizeC(); j++) {
updated = deps.set(i+returnDeps, j+returnDeps,
Link.merge(deps.get(i+returnDeps, j+returnDeps), t.get(i,j)))
|| updated;
}
return updated;
}
public boolean update(Frame a,InstructionHandle ih) {
boolean updated = false;
MultiObject to;
// links between references
TableLink newtbl = link(a);
if (!(ih.getInstruction() instanceof ReturnInstruction ||
ih.getInstruction() instanceof ATHROW)){
return false;
}
updated = merge(newtbl);
if (ih.getInstruction() instanceof ReturnInstruction) {
// if(this._method.getName().equalsIgnoreCase("m1")) {
// Printer.println("before: "+a.getStack());
// printLinkValues();
// a.printLinkValues();
// }
// linked to the return value
ReturnInstruction ri = (ReturnInstruction) ih.getInstruction();
if (ri.getType() != Type.VOID) {
to = a.getStack().peek();
int linkType;
int returnPart;
returnPart = MethodInfo.partType(returnType);
if(returnType instanceof BasicType ){
linkType = Link.VALUE_LINK;
}
else{
linkType = Link.REFERENCE_LINK;
}
//make direct link
JvmType[] to1 = to.content();
for(int j = 0; j < to1.length; j++) {
int jj = convert(to1[j]);
if(jj!=-1)
updated = deps.set(0, jj+returnDeps,
Link.merge( deps.get(0, jj+returnDeps),a.createLink(returnPart, to1[j].getPartType(), linkType) ))
|| updated;
}
//make pointedBy
for(int j = 0; j < to1.length; j++) {
MultiObject res = a._pointedBy(to1[j]);
JvmType[] res1 = res.content();
int to2 = convert(to1[j]);
Link l1 = null;
if(to2 < 0)
l1 = a.createLink(returnPart, to1[j].getPartType(), linkType);
else
//l1 = deps[0][to2+returnDeps];
l1 = deps.get(0, to2+returnDeps);
for(int i = 0; i < res1.length; i++){
Link l = null;
int res2 = convert(res1[i]);
if(to2<0)
l = a.getLinkBetween(to1[j], res1[i]);
else
l = deps.get(to2+returnDeps, res2+returnDeps);
if(res2!= -1) {
updated = this.deps.set(0, res2+returnDeps,
Link.makePointedBy( deps.get(0, res2+returnDeps), l1, l ))
|| updated;
}
}
}
//make pointsTo
for(int j = 0; j < to1.length; j++) {
MultiObject res = a._pointsTo(to1[j]);
JvmType[] res1 = res.content();
int to2 = convert(to1[j]);
Link l1 = null;
if(to2 < 0)
l1 = a.createLink(returnPart, to1[j].getPartType(), linkType);
else
l1 = deps.get(0,to2+returnDeps);
for(int i = 0; i< res1.length; i++){
int res2 = convert(res1[i]);
Link l = null;
if(to2<0)
l = a.getLinkBetween(res1[i], to1[j]);
else
l = deps.get(res2+returnDeps, to2+returnDeps);
if(res2!=-1)
updated =
this.deps.set(res2+returnDeps, 0,
Link.makePointsToReturn( deps.get(res2+returnDeps, 0), l, l1, linkType))
|| updated;
}
}
}
//extends references from static world
for(int i = 0; i < deps.getSizeL(); i++)
Link.extendPublicReference( deps.get(2, i));//.extendPublicReference();
//Printer.println("after: "+a.getStack());
//printLinkValues();
}else { // ATHROW
to = a.getStack().peek();
JvmType[] to1 = to.content();
for(int j = 0; j < to1.length; j++) {
MultiObject res = a._pointedBy(to1[j]);
JvmType[] res1 = res.content();
int to2 = convert(to1[j]);
Link l1 = null;
if(to2 < 0)
l1 = a.createLink(JvmType.PUBLIC_PART, to1[j].getPartType(), Link.REFERENCE_LINK);
else
l1 = deps.get(1, to2+returnDeps);
for(int i = 0; i < res1.length; i++){
Link l = null;
int res2 = convert(res1[i]);
if(to2<0)
l = a.getLinkBetween(to1[j], res1[i]);
else
l = deps.get(to2+returnDeps, res2+returnDeps);
if(res2!= -1)
updated = this.deps.set(1, res2+returnDeps,
Link.makePointedBy( deps.get(1, res2+returnDeps), l1, l ));
}
}
}
return updated;
}
/* (non-Javadoc)
* @see fr.lifl.rd2p.jits.tools.ea.annotation.Annotation#toHTML()
*/
public String toHTML() {
String res= "
| " ; //int arg1; if(returnDeps == 1 ) res = res + " | R | "; res = res + "E | S | F | "; for (int i = 3; i < jvmTypes.length; i++){ res = res + ""+jvmTypes[i]+" | "; } res = res+"
| "+t[i]+" | "; for (int j = 0; j < deps.getSizeC(); j++){ res = res + ""+((deps.get(i,j)!=null) ? deps.get(i,j).toString():"")+" | "; //res = res + ""+deps.get(i,j)+" | "; } res = res + "|||
| "+ jvmTypes[i-returnDeps]+" | "; for (int k = 0; k < deps.getSizeC(); k++){ res = res + ""+((deps.get(i,k)!=null) ? deps.get(i,k).toString():"")+" | "; //res = res + ""+deps.get(i,k)+" | "; } res = res + "