package fr.lifl.stc.stan.execution;
import org.apache.bcel.generic.Type;
import org.apache.bcel.SignatureConstants;
import fr.lifl.stc.stan.analyser.GlobalAnalyser;
import fr.lifl.stc.stan.execution.stack.ExecutionStack;
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.samples.flow.FlowAnnotation;
import fr.lifl.stc.stan.samples.flow.FlowPartialSignature;
import fr.lifl.stc.stan.samples.flow.FlowPartialSignatureData;
import fr.lifl.stc.stan.signature.Signature;
import fr.lifl.stc.stan.util.Printer;
import fr.lifl.stc.stan.util.Utils;
import fr.lifl.stc.stan.analyser.MethodAnalyzer;
import fr.lifl.stc.stan.dsl.Flow;
import fr.lifl.stc.stan.dsl.FlowChecker;
import fr.lifl.stc.stan.dsl.FlowCheckerException;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;
import fr.lifl.stc.stan.link.defaultLink.DefaultLink;
import org.apache.bcel.generic.InstructionHandle;
/*
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
*/
/**
* @author yann
* @author dorina
*/
public class Frame {
// pseudo-variable for exceptions
private MultiObject exception;
// static implicit variable
private MultiObject staticWorld;
// pseudo-variable for flux
private MultiObject flux;
// variables states for each instruction of the method
private MultiObject[] variablesArray;
// stack state for each instruction of the method
private ExecutionStack executionStack;
//private boolean[][] links;
//private Link[][] linksValues;
private TableLink linksFlow;
private Interpreter interpreter;
////////////////////////////////////////////////////////////////
//// Constructor
////////////////////////////////////////////////////////////////
/**
* Creates a new Frame
instance.
*
* @param m
*/
public Frame(Interpreter interpreter) {
this.interpreter = interpreter;
// initialization of the variableStates field
int loc = interpreter.getMethodInfo().getMethod().getCode().getMaxLocals();
variablesArray = new MultiObject[loc];
for (int i = 0; i < loc; i++) {
variablesArray[i] = new MultiObject();
}
// initialization of the static world implicit variable
staticWorld = new MultiObject();
// initialization of the exception pseudo variable
exception = new MultiObject();
// initialization of the flux pseudo variable
flux = new MultiObject();
// initialization of the stackStates field
executionStack = new ExecutionStack();
int m = interpreter.getRefValues().length;// + interpreter.getRefs().length;
linksFlow = new TableLink(m,m);
}
////////////////////////////////////////////////////////////////
//// Methods for variable array
////////////////////////////////////////////////////////////////
public MultiObject[] getVariablesArray() {
return variablesArray;
}
public boolean saveVariablesArray(MultiObject[] va) {
if (variablesArray.length != va.length) {
System.err
.println("Warning: Frame.saveVariableArray attempts to compare different size arrays");
return false;
}
boolean res = false;
for (int i = 0; i < va.length; i++) {
res = variablesArray[i].merge(va[i]) || res;
}
return res;
}
////////////////////////////////////////////////////////////////
//// Methods for stack
////////////////////////////////////////////////////////////////
public ExecutionStack getStack() {
return executionStack;
}
public boolean saveStack(ExecutionStack stack) {
return this.executionStack.merge(stack);
}
////////////////////////////////////////////////////////////////
//// Methods for static world
////////////////////////////////////////////////////////////////
public MultiObject getStaticWorld() {
return staticWorld;
}
public boolean saveStaticWorld(MultiObject sw) {
return staticWorld.merge(sw);
}
////////////////////////////////////////////////////////////////
//// Methods for exceptions
////////////////////////////////////////////////////////////////
public MultiObject getException() {
return exception;
}
public boolean saveException(MultiObject ex) {
return exception.merge(ex);
}
////////////////////////////////////////////////////////////////
//// Methods for flux
////////////////////////////////////////////////////////////////
public MultiObject getFlux() {
return flux;
}
public boolean saveFlux(MultiObject ex) {
return flux.merge(ex);
}
////////////////////////////////////////////////////////////////
////
////////////////////////////////////////////////////////////////
public boolean equals(Object o){
Frame f = (Frame)o;
boolean isEqual = true;
isEqual = isEqual && this.getStack().equals(f.getStack());
isEqual = isEqual && this.getException().equals(f.getException());
isEqual = isEqual && this.getFlux().equals(f.getFlux());
isEqual = isEqual && this.getStaticWorld().equals(f.getStaticWorld());
MultiObject[] var = f.getVariablesArray();
for(int i = 0; i < this.getVariablesArray().length; i++)
isEqual = isEqual && this.variablesArray[i].equals(var[i]);
isEqual = isEqual && this.getLinks().equals(f.getLinks());
/*
TableLink l = f.getLinks();
for(int i = 0; i < this.linksFlow.getSizeL(); i++ )
for(int j = 0; j < this.linksFlow.getSizeC(); j++)
isEqual = isEqual && Link.equals(linksFlow.get(i,j), l.get(i,j));
*/
return isEqual;
}
public boolean merge(Frame with) {
boolean res1 = saveStack(with.getStack());
boolean res2 = saveStaticWorld(with.getStaticWorld());
boolean res3 = saveVariablesArray(with.getVariablesArray());
boolean res4 = saveException(with.getException());
boolean res5 = saveFlux(with.getFlux());
boolean res6 = saveLinks(with.getLinks());
return res1 || res2 || res3 || res4 || res5 || res6;
}
public boolean saveLinks(TableLink l){
boolean updated = false;
for(int i = 0; i < this.linksFlow.getSizeL(); i++)
for(int j = 0; j < this.linksFlow.getSizeC(); j++)
updated = this.linksFlow.set(i, j, Link.merge(linksFlow.get(i,j), l.get(i, j))) || updated;
return updated;
}
public TableLink getLinks(){
return this.linksFlow;
}
public Object clone() {
Frame f = new Frame(interpreter);
f.saveStaticWorld(getStaticWorld());
f.saveVariablesArray(getVariablesArray());
f.saveException(getException());
f.saveFlux(getFlux());
f.executionStack = (ExecutionStack) executionStack.clone();
f.linksFlow = (TableLink)this.linksFlow.clone();
return f;
}
public String toString() {
String str = new String("***\nstatic : ");
MultiObject sw = getStaticWorld();
ExecutionStack st = getStack();
MultiObject[] localvars = getVariablesArray();
str += sw + "\nstack : ";
str += st + "locals : ";
for (int z = 0; z < localvars.length; z++)
str += localvars[z];
str += "\nlinks# : ";
//str += linkstoString();
int count=0;
for (int i = 0; i < linksFlow.getSizeL(); i++) {
for (int j = 0; j < linksFlow.getSizeC(); j++) {
Link l = linksFlow.get(i, j);
if(l!=null && !l.isEmpty())
count++;
}
}
str += count + "\n";
str += "***\n";
return str;
}
private String linksValuesToString() {
String str = " ";
JvmType[] refs = interpreter.getRefValues();
for (int i = 0; i < refs.length; i++) {
str += refs[i] + " ";
}
str += "\n";
for (int i = 0; i < linksFlow.getSizeL(); i++) {
str += refs[i] + " ";
for (int j = 0; j < linksFlow.getSizeC(); j++) {
Link l = linksFlow.get(i, j);
if(l!=null && !l.isEmpty())
str += "0 ";
else
str += l + " ";
}
str += "\n";
}
return str;
}
public void printLinkValues(){
JvmType[] j = interpreter.getRefValues();
Printer.debugPrint("\t");
for(int i = 0;i < j.length; i++) {
Printer.debugPrint(""+j[i]);
}
Printer.debugPrintln("");
for(int i = 0;i < j.length; i++) {
Printer.debugPrint(j[i]+"\t");
for(int k = 0;k _method.getArgumentTypes().length
// || (oto.getId()+5) > _method.getArgumentTypes().length )
// {
// System.out.println("bug" + executionStack.size());
// return l;
// }
// Flow f = new Flow(_class, _method, oto.getId()+5, ofrom.getId()+5, ((DefaultLink)l).getLink());
// try {
// fc.check(f);
// } catch(FlowCheckerException e) {
// int srcLine = _method.getLineNumberTable().getSourceLine(interpreter.getCurrentInstruction().getPosition());
// //int srcLine = 2;
// System.out.println("[E]{" + _class.getClassName() + "}{" + _method.getName() + ":" + srcLine +"} " + e.getMessage());
// }
return l;
}
/**
* Creates a link between from
and to
of type linkType
.
* @param from
* @param to
* @param linkType
* @return the new link
*/
public Link createLink(int from, int to, int linkType){
// InstructionHandle inst = interpreter.getCurrentInstruction();
// System.out.println("create link=" + inst);
// System.out.println("src=" + interpreter.getMethodAnalyzer().getMethod().getLineNumberTable().getSourceLine(inst.getPosition()));
// //System.out.println("stack = " + this);
// InstructionHandle tmp = inst;
// short op = inst.getInstruction().getOpcode();
// InstructionHandle prev = tmp.getPrev();
// FlowAnnotation fa = (FlowAnnotation)interpreter.getMethodAnalyzer().getAnnotations()[0];
// MethodAnalyzer ma = interpreter.getMethodAnalyzer();
// FlowChecker fc = ma.getFlowChecker();
// JavaClass _class = ma.getJavaClass();
// Method _method = ma.getMethod();
// Flow f = new Flow(_class, _method, oto.getId()+5, ofrom.getId()+5, ((DefaultLink)l).getLink());
// try {
// fc.check(f);
// } catch(FlowCheckerException e) {
// int srcLine = _method.getLineNumberTable().getSourceLine(interpreter.getCurrentInstruction().getPosition());
// //int srcLine = 2;
// System.out.println("[E]{" + _class.getClassName() + "}{" + _method.getName() + ":" + srcLine +"} " + e.getMessage());
// }
// System.out.println("from" + from + "-to" + to);
// if ( tmp.getInstruction().getName() == "putfield" )
// op = prev.getInstruction().getOpcode();
// tmp = prev.getPrev();
// while ( tmp != null )
// {
// if ( tmp.getInstruction().getOpcode() == op )
// {
// System.out.println("yiiieahhh : " + tmp);
// tmp = null;
// }
// else
// tmp = tmp.getPrev();
// }
// for(MultiObject m : variablesArray)
// {
// System.out.println(m);
// }
Link l = GlobalAnalyser.linkFactory.createLink(from, to, linkType);
return l;
}
/**
*
* @param t
* @param partType
* @return
*/
public static JvmType getPart(JvmType t, int partType){
if(t instanceof Reference){
Reference r = (Reference)t;
if(r.getAll()!=null)
r = r.getAll();
switch(partType){
case JvmType.SECRET_PART:
if(r.hasSecret())
return r.getSecret();
break;
case JvmType.PUBLIC_PART:
if(r.hasPublic())
return r.getPublic();
break;
}
return r;
}
return t;
}
/**
* translates the r
into its associated index in the table of values and references
* @param r The JVmType to be translated
* @return the index of r
in the table containing the values and references
*/
private int _translate(JvmType r) {
if(r instanceof Reference && ((Reference)r).getAll()!=null)
r = ((Reference)r).getAll();
return r.getIndex();
/*
for (int i = 0; i < interpreter.getRefValues().length; i++) {
if (r.equals(interpreter.getRefValues()[i])) {
return i;
}
}
return -1;
*/
}
/**
* Returns an object of type Link
representing the link between t1
and t2
.
* @param t1 The element that points to t1
* @param t2 The element that is pointed by t2
* @return null, if error
* the link between
*/
public Link getLinkBetween(JvmType t1, JvmType t2){
int i1 = _translate(t1);
int i2 = _translate(t2);
if(i1>=0 && i2>=0)
return linksFlow.get(i1, i2);
return null;
}
/**
* Creates the link between from
and to
and computes also the transitive
* closure
*
* Suppose we want to create a link between from
and to
*
* we have:
* a = from
* to = b
* from = to
*
* These are the required steps to compute the transitive closure:
* -create link between from and to (simple make point)
* -create link between a and to (makePointTO)
* -create link between from and b (makePointedBy)
* -create link between a and b (makePointTo(from, b))
*
* @param from
* @param to
* @param type
*/
public void makePoint(MultiObject from, MultiObject to, Type type) {
//save elements pointed by from for later use
MultiObject pointedBy = _pointedBy(from);
//create the link between from
and to
simpleMakePoint(from, to, type);
makePointTo(from, to);
makePointedBy(from, to);
makePointTo(from, _pointedBy(to));
/*
* if t -> t1
* t -> t2
* => t1 -> t2
*/
makePointArray(from, pointedBy, to);
//computes the transive closure after creating link between _pointedBy(from) and to
//@see #makePointArray to understand why we need a link between _pointedBy(from) and to
makePointTo(pointedBy, to);
makePointedBy(pointedBy, to);
MultiObject mto = _pointedBy(to);
makePointTo(pointedBy, mto);
}
/**
* To handle reference links
*
* Suppose we have some objects a, b, c, d
* a.b = x
* a.b.c = y
*
* => x->y
*
* More general:
* if t -> t1
* t -> t2
* => t1 -> t2
*
* Here: t = arrayref
* t1 = pointedByArrayRef
* t2 = to
* => pointedByArrayRef -> to
*
* @param arrayref the array
* @param pointedByArrayRef the objects that are already pointed by arrayref
* @param to the new objects that are pointed by arrayref
*
* note: this rule comes from arrays: when assigning an object to an array, links between all objects
* in this array must be created
*/
public void makePointArray(MultiObject arrayref, MultiObject pointedByArrayRef, MultiObject to){
JvmType[] arr = arrayref.content();
JvmType[] to1 = to.content();
JvmType[] res1 = pointedByArrayRef.content();
for(int i = 0; i < arr.length; i++){
//MultiObject res = _pointedBy(arr[i]);
int i2 = _translate(arr[i]);
for(int j = 0 ; j < res1.length; j++){
int res2 = _translate(res1[j]);
for(int k = 0; k < to1.length; k++){
int to2 = _translate(to1[k]);
if(!res1[j].equals(to1[k]))
linksFlow.set(res2, to2, Link.makePointArray( linksFlow.get(res2,to2) , linksFlow.get(i2, res2), linksFlow.get(i2,to2)));
//this.linksValues[res2][to2].makePointArray(this.linksValues[i2][res2], this.linksValues[i2][to2]);
}
}
}
}
/**
* Creates links between objects in from
and objects in to
. The type
* of link (value
or reference
) is specified by type
.
* This method creates only direct links, and not the trasitive closure! To compute the trasitive closure,
* see makePoint
*
* @param from
* @param to
* @param type
* @deprecated
*/
public void simpleMakePoint(MultiObject from, MultiObject to, Type type){
int linkType = MethodInfo.linkType(type);
JvmType[] from1 = from.content();
JvmType[] to1 = to.content();
for(int i = 0; i < from1.length; i++){
for(int j = 0; j < to1.length; j++) {
int ii = _translate(from1[i]);
int jj = _translate(to1[j]);
linksFlow.set(ii, jj, Link.merge(linksFlow.get(ii,jj), createLink(from1[i].getPartType(), to1[j].getPartType(), linkType)));
//linksValues[ii][jj].merge( Frame.createLink(from1[i].getPartType(), to1[j].getPartType(), linkType));
}
}
}
/**
*
* @param from
* @param to
* @see #makePointTo(JvmType, MultiObject)
* @deprecated
*/
public void makePointTo(MultiObject from, MultiObject to){
JvmType[] from1 = from.content();
for(int j = 0; j < from1.length; j++)
makePointTo(from1[j], to);
}
/**
* When a link between two entities is created (e.g. from-\>to
, a trasitive closure must be also calculated, in order
* to take into account the reflexivity.
*
* This method creates links between elements that point to from
and elements in to
.
* Let x
be an element in to
.
*
* Suppose we have a -> from
*
* This function will create a link between a
and from
: a-\> x
*
* @param from
* @param to
*/
public void makePointTo(JvmType from, MultiObject to){
MultiObject res =_pointsTo(from);
JvmType[] res1 = res.content();
JvmType[] to1 = to.content();
int from2 = _translate(from);
for(int i = 0; i < res1.length; i++){
int res2 = _translate(res1[i]);
Link l = linksFlow.get(res2, from2);
for(int k = 0; k < to1.length; k++){
int to2 = _translate(to1[k]);
linksFlow.set(res2, to2, Link.makePointTo(linksFlow.get(res2, to2), l, linksFlow.get(from2, to2)));
}
}
}
/**
* Returns all the objects that point to the r
(that have a non-null link to r
.
* Example: a=b => _pointsTo(b)=a
* @param r
* @return an Multiobject
containing all the objects that point to r
* @deprecated
*/
public MultiObject _pointsTo(JvmType r){
MultiObject res = new MultiObject();
int ir = _translate(r);
for (int i = 0; i < linksFlow.getSizeL(); i++) {
Link l = linksFlow.get(i,ir);
if (l!=null && !l.isEmpty()) {
res.add(interpreter.getRefValues()[i]);
}
}
return res;
}
/**
*
* @param from
* @param to
* @see #makePointedBy(MultiObject, JvmType)
* @deprecated
*/
public void makePointedBy(MultiObject from, MultiObject to){
JvmType[] to1 = to.content();
for(int j = 0; j < to1.length; j++)
makePointedBy(from, to1[j]);
}
/**
* When a link between two entities is created (e.g. from-\>to
, a trasitive closure must be also calculated, in order
* to take into account the reflexivity.
*
* This method creates links between elements in from
and elements that are pointed by
* to
.
*
* Let x
be an element in from
.
*
* Suppose we have to -> b
*
* This function will create a link between x
and b
: b-\> x
*
* @param from
* @param to
* @deprecated
*/
public void makePointedBy(MultiObject from, JvmType to){
MultiObject res =_pointedBy(to);
JvmType[] res1 = res.content();
JvmType[] from1 = from.content();
int to2 = _translate(to);
for(int i = 0; i < res1.length; i++){
int res2 = _translate(res1[i]);
Link l = linksFlow.get(to2, res2);
for(int k = 0; k < from1.length; k++){
int from2 = _translate(from1[k]);
linksFlow.set(from2, res2, Link.makePointedBy(linksFlow.get(from2, res2), linksFlow.get(from2, to2), l));
}
}
}
/**
* Returns all the objects that point to the r
(that have a non-null reference link to r
.
* Example: a=b => _pointsTo(b)=a
* @param r
* @return an Multiobject
containing all the objects that point to r
*/
/*public MultiObject _refPointsTo(JvmType r){
MultiObject res = new MultiObject();
int ir = _translate(r);
for (int i = 0; i < linksFlow.getSizeL(); i++) {
Link l = linksFlow.get(i,ir);
if (l!=null && l.isLinkOfType(Link.REFERENCE_LINK)) {
res.add(interpreter.getRefValues()[i]);
}
}
return res;
}*/
/**
* Returns all the objects that point to the r
(that have a non-null reference link to r
).
* Example: a=b => _pointsTo(b)=a
* @param r
* @param linkType Link type : Value, reference or any
* @param fromPart part of the object that points to r
* @param toPart part of r that is pointed
* @return an Multiobject
containing all the objects that point to r
*/
public MultiObject pointsTo(JvmType r, int linkType, int fromPart, int toPart){
MultiObject res = new MultiObject();
int ir = _translate(r);
for (int i = 0; i < linksFlow.getSizeL(); i++) {
Link l = linksFlow.get(i,ir);
if (l!=null && l.isLinkOfType(linkType)&&l.isLinkFromPart(fromPart) && l.isLinkToPart(toPart)) {
res.add(interpreter.getRefValues()[i]);
}
}
return res;
}
/**
* Returns the references that are pointed by all the objects in o
* @param o
* @param linkType Link type : Value, reference or any
* @param fromPart part of o
* @param toPart part of the object pointed by o
* @return an Multiobject
containing all the objects that are pointed by o
* @return
* @see #_pointedBy(JvmType)
*/
public MultiObject pointedBy(MultiObject o, int linkType, int fromPart, int toPart){
JvmType[] content = o.content();
MultiObject res = new MultiObject();
for (int i = 0; i < content.length; i++) {
res.merge(pointedBy(content[i],linkType, fromPart, toPart));
}
//FIXME do we need this?
//res.merge(o1); // TODO: is this sound? (same below)
return res;
}
/**
* Returns the objects that are pointed by r
.
* @see #_pointedBy(JvmType)
* @param linkType Link type : Value, reference or any
* @param fromPart part of r
* @param toPart part of the object pointed by r
*/
public MultiObject pointedBy(JvmType r, int linkType, int fromPart, int toPart){
MultiObject res = new MultiObject();
int ir = _translate(r);
//int linkType = MethodInfo.linkType(t);
for (int i = 0; i < linksFlow.getSizeC(); i++) {
Link l = linksFlow.get(ir, i);
if (l!=null && l.isLinkOfType(linkType)&&l.isLinkFromPart(fromPart) && l.isLinkToPart(toPart)) {
res.add(interpreter.getRefValues()[i]);
}
}
return res;
}
/**
* Returns the references that are pointed by all the objects in o
* @param o
* @return
* @see #_pointedBy(JvmType)
*/
/*public MultiObject _refPointedBy(MultiObject o){
JvmType[] content = o.content();
MultiObject res = new MultiObject();
for (int i = 0; i < content.length; i++) {
res.merge(_pointedBy(content[i],Type.OBJECT));
}
//FIXME do we need this?
//res.merge(o1); // TODO: is this sound? (same below)
return res;
}*/
/**
* Returns the objects that are pointed by all the objects in o
* @param o
* @return
* @see #_pointedBy(JvmType)
*/
public MultiObject _pointedBy(MultiObject o){
JvmType[] content = o.content();
MultiObject res = new MultiObject();
for (int i = 0; i < content.length; i++) {
res.merge(_pointedBy(content[i]));
}
//FIXME do we need this?
//res.merge(o1); // TODO: is this sound? (same below)
return res;
}
/**
* Returns the objects that are pointed by r
(that can be accessed through r
)
* Example: a=b => _pointedBy(a)=b
* @param r
* @return A Multiobject
containing all the objects pointed by r
*/
public MultiObject _pointedBy(JvmType r) {
MultiObject res = new MultiObject();
int ir = _translate(r);
//Link[] l = linksValues[ir];
for (int i = 0; i < linksFlow.getSizeC(); i++) {
Link l = linksFlow.get(ir, i);
if(l!=null && !l.isEmpty()){
//if (!l[i].isEmpty()) {
res.add(interpreter.getRefValues()[i]);
}
}
return res;
}
/**
* Returns the objects that are pointed by r
. The link between these objects and
* r
must be of the type specified by t
(reference or value)
* @param r
* @param t
* @return
* @see #_pointedBy(JvmType)
*/
public MultiObject _pointedBy(JvmType r, Type t){
MultiObject res = new MultiObject();
int ir = _translate(r);
int linkType = MethodInfo.linkType(t);
for (int i = 0; i < linksFlow.getSizeC(); i++) {
Link l = linksFlow.get(ir, i);
if(l!=null){// && !l.isEmpty()){
JvmType o = l.getPointedPart(r, interpreter.getRefValues()[i], linkType);
if (o != null) {
res.add(o);
}
}
}
return res;
}
/**
*
* @param signature
* @param returnValue
* @param argv
* @deprecated
*/
/*
public void applySignature(Signature signature, MultiObject returnValue,
MultiObject argv[]) {
FlowPartialSignature sign = (FlowPartialSignature) signature
.getPartialSignature(FlowAnnotation.class.getName());
//((FlowPartialSignatureData)sign.getComponent()).display(System.out);
TableLink s = ((FlowPartialSignatureData)sign.getComponent()).getData();
applyAux(s, 0, returnValue, returnValue, argv);
applyAux(s, 1, exception, returnValue, argv);
applyAux(s, 2, staticWorld, returnValue, argv);
applyAux(s, 3, flux, returnValue, argv);
int j = 4;
for (int i = 0; i < argv.length; i++, j++) {
applyAux(s, j, argv[i], returnValue, argv);
}
}
*/
/**
*
* @param deps
* @param line
* @param from
* @param returnValue
* @param argv
* @deprecated
*/
/*
private void applyAux(TableLink deps, int line, MultiObject from, MultiObject returnValue, MultiObject[]argv){
Link l = deps.get(line, 0);
if(l!=null && !l.isEmpty())
makePointApplySignature(from, returnValue, l);
l = deps.get(line, 1);
if(l!=null && !l.isEmpty())
makePointApplySignature(from, exception, l);
l = deps.get(line, 2);
if(l!=null && !l.isEmpty())
makePointApplySignature(from, staticWorld, l);
l = deps.get(line, 3);
if(l!=null && !l.isEmpty())
makePointApplySignature(from, flux, l);
int j = 4;
for(int i = 0; i < argv.length; i++, j++){
l = deps.get(line, j);
if(l!=null && !l.isEmpty())
makePointApplySignature(from, argv[i], l);
}
}
*/
/**
*
* @param from
* @param to
* @param l
* @deprecated
*/
/*
private void makePointApplySignature(MultiObject from, MultiObject to, Link l){
JvmType[]from1 = from.content();
JvmType[]to1 = to.content();
for(int i = 0; i < from1.length; i++){
int from2 = _translate(from1[i]);
for(int j = 0; j < to1.length; j++){
int to2 = _translate(to1[j]);
linksFlow.set(from2, to2, Link.applySignature( linksFlow.get(from2, to2), from1[i].getPartType(), to1[j].getPartType(), l ));
}
}
//FIXME should we do that after we mark all the signatures?
//Printer.println("pontebBy(to)= "+_pointedBy(to).size());
makePointTo(from, to);
makePointedBy(from, to);
makePointTo(from, _pointedBy(to));
}
*/
////////////////////////////////////////////////////////
//
// proof annotation
//
////////////////////////////////////////////////////////
/**
* format:
* length(number of bytes to follow) bytes_link_table_to_follow link_table bytes_of_stack_too_follow stack bytes_of_localvar_tofollow local_variables
*/
public byte[] toBytes(byte codification, Frame previous){
byte[] output = null;
int length = 0;
TableLink previousTable = null;
if(previous != null)
previousTable = previous.getLinks();
byte[] stack = this.executionStack.toBytes(codification, this.interpreter);
byte[] localvar = this.variableArrayToBytes(codification);
byte[] linkTable = this.linksFlow.toBytes(previousTable);
length = stack.length + localvar.length + linkTable.length;
//set length
output = new byte[length+4*SignatureConstants.TOTAL_LENGTH_SIZE ];
//fill output
int index = 0;
byte [] arrSize = SignatureConstants.toByteArray(length+3*SignatureConstants.TOTAL_LENGTH_SIZE ,
SignatureConstants.TOTAL_LENGTH_SIZE);
System.arraycopy(arrSize, 0, output, index, arrSize.length);
index += arrSize.length;
//set link table length
arrSize = SignatureConstants.toByteArray(linkTable.length,
SignatureConstants.TOTAL_LENGTH_SIZE);
System.arraycopy(arrSize, 0, output, index, arrSize.length);
index += arrSize.length;
//set link table
System.arraycopy(linkTable, 0, output, index, linkTable.length);
index += linkTable.length;
//set stack length
arrSize = SignatureConstants.toByteArray(stack.length,
SignatureConstants.TOTAL_LENGTH_SIZE);
System.arraycopy(arrSize, 0, output, index, arrSize.length);
index += arrSize.length;
//set stack
System.arraycopy(stack, 0, output, index, stack.length);
index += stack.length;
//set localvar length
arrSize = SignatureConstants.toByteArray(localvar.length,
SignatureConstants.TOTAL_LENGTH_SIZE);
System.arraycopy(arrSize, 0, output, index, arrSize.length);
index += arrSize.length;
//set localvar
System.arraycopy(localvar, 0, output, index, localvar.length);
index += localvar.length;
return output;
}
/**
*
* @param codification
* @return
*/
byte[] variableArrayToBytes(byte codification) {
int length = this.variablesArray.length;
int i;
for(i= this.variablesArray.length-1; i>=0 ; i--) {
if(this.variablesArray[i] != null && this.variablesArray[i].size()>0) {
break;
}
}
// if(i >= 0)
// length = i+1;
return MultiObject.toBytes(this.variablesArray, length, codification, this.interpreter);
}
/////////////////////////////////////////////////////////////////
//
// NEW VERSION : using index in refVal table instead of objects
//
/////////////////////////////////////////////////////////////////
/**
* Creates the link between from
and to
and computes also the transitive
* closure
*
* Suppose we want to create a link between from
and to
*
* we have:
* a = from
* to = b
* from = to
*
* These are the required steps to compute the transitive closure:
* -create link between from and to (simple make point)
* -create link between a and to (makePointTO)
* -create link between from and b (makePointedBy)
* -create link between a and b (makePointTo(from, b))
*
* @param from
* @param to
* @param type
*/
public void new_makePoint(MultiObject o_from, MultiObject o_to, Type type) {
int[] from = new_translate(o_from);
int[] to = new_translate(o_to);
//save elements pointed by from for later use
int[] pointedBy = _new_pointedBy(from);
//create the link between from
and to
new_simpleMakePoint(o_from, o_to, type);
new_makePointTo(from, to);
new_makePointedBy(from, to);
new_makePointTo(from, _new_pointedBy(to));
/*
* if t -> t1
* t -> t2
* => t1 -> t2
*/
new_makePointArray(from, pointedBy, to);
//computes the transive closure after creating link between _pointedBy(from) and to
//@see #makePointArray to understand why we need a link between _pointedBy(from) and to
new_makePointTo(pointedBy, to);
new_makePointedBy(pointedBy, to);
int[] mto = _new_pointedBy(to);
new_makePointTo(pointedBy, mto);
}
/**
* To handle reference links
*
* Suppose we have some objects a, b, c, d
* a.b = x
* a.b.c = y
*
* => x->y
*
* More general:
* if t -> t1
* t -> t2
* => t1 -> t2
*
* Here: t = arrayref
* t1 = pointedByArrayRef
* t2 = to
* => pointedByArrayRef -> to
*
* @param arrayref the array
* @param pointedByArrayRef the objects that are already pointed by arrayref
* @param to the new objects that are pointed by arrayref
*
* note: this rule comes from arrays: when assigning an object to an array, links between all objects
* in this array must be created
*/
public void new_makePointArray(MultiObject arrayref, MultiObject pointedByArrayRef, MultiObject to){
int []i1 = new_translate(arrayref);
int []i2 = new_translate(pointedByArrayRef);
int []i3 = new_translate(to);
new_makePointArray(i1, i2, i3);
}
/**
*
* @param arrayref
* @param pointedByArrayRef
* @param to
* @see #new_makePointArray(MultiObject, MultiObject, MultiObject)
*/
public void new_makePointArray(int[] arrayref, int[] pointedByArrayRef, int[] to){
for(int i = 0; i < arrayref.length && arrayref[i]!=-1; i++){
for(int j = 0 ; j < pointedByArrayRef.length && pointedByArrayRef[j]!=-1; j++){
int res2 = pointedByArrayRef[j];
for(int k = 0; k < to.length && to[k]!=-1; k++){
int to2 = to[k];
linksFlow.set(res2, to2, Link.makePointArray( linksFlow.get(res2,to2) , linksFlow.get(arrayref[i], res2), linksFlow.get(arrayref[i],to2)));
//this.linksValues[res2][to2].makePointArray(this.linksValues[i2][res2], this.linksValues[i2][to2]);
}
}
}
}
/**
* translates the r
into its associated index in the table of values and references
* @param r The JVmType to be translated
* @return the index of r
in the table containing the values and references
*/
private int _new_translate(JvmType r) {
if(r instanceof Reference && ((Reference)r).getAll()!=null)
r = ((Reference)r).getAll();
for (int i = 0; i < interpreter.getRefValues().length; i++) {
if (r.equals(interpreter.getRefValues()[i])) {
return i;
}
}
return -1;
}
/**
* translates the r
into its associated index in the table of values and references
* @param r The JVmType to be translated
* @return the index of r
in the table containing the values and references
*/
private int[] new_translate(MultiObject r) {
int res[] = new int[this.interpreter.getRefValuesLength()];
int j = 0;
JvmType[] content = r.content();
for(int i = 0 ; i < content.length; i++)
j = Utils.add(res , j, _new_translate(content[i]));
if(j < res.length)
res[j] = -1;
return res;
}
/**
* Creates links between objects in from
and objects in to
. The type
* of link (value
or reference
) is specified by type
.
* This method creates only direct links, and not the trasitive closure! To compute the trasitive closure,
* see makePoint
*
* @param from
* @param to
* @param type
*/
public void new_simpleMakePoint(MultiObject from, MultiObject to, Type type) {
/*
* int[] from1 = new_translate(from); int[] to1 = new_translate(to);
* new_simpleMakePoint(from, to , from1, to1, type);
*/
int linkType = MethodInfo.linkType(type);
JvmType[] from1 = from.content();
JvmType[] to1 = to.content();
for (int i = 0; i < from1.length; i++) {
for (int j = 0; j < to1.length; j++) {
int ii = _translate(from1[i]);
int jj = _translate(to1[j]);
//System.out.println("new_simpleMakePoint : from = "+from1[i] + ", to = " + to1[j]);
linksFlow.set(ii, jj, Link.merge(linksFlow.get(ii, jj), createLink(from1[i].getPartType(), to1[j].getPartType(), linkType)));
// linksValues[ii][jj].merge(
// Frame.createLink(from1[i].getPartType(),
// to1[j].getPartType(), linkType));
}
}
}
/**
* Returns all the objects that point to the entity at index r
* (that have a non-null link to r
. Suppose that element at
* position index
is b
. Example: a=b =>
* _pointsTo(b)=a
*
* @param r
* @return an array of int containing the index of all the objects that
* point to b
*
*/
public int[] _new_pointsTo(int index) {
int[] as = new int[this.interpreter.getRefValuesLength()];
int j = 0;
for (int i = 0; i < linksFlow.getSizeL(); i++) {
Link l = linksFlow.get(i,index);
if (l!=null && !l.isEmpty()) {
as[j++] = i;
//res.add(interpreter.getRefValues()[i]);
}
}
if(jir (that can be accessed through it).
* If a is the element at position ir
* Example: a=b => _pointedBy(a)=b
* @param ir
* @return An array of int
containing the index of all the objects pointed by element at ir
*/
public int[] _new_pointedBy(int ir) {
int[] res = new int[this.interpreter.getRefValuesLength()];
int j = 0;
for (int i = 0; i < linksFlow.getSizeC(); i++) {
Link l = linksFlow.get(ir, i);
if(l!=null && !l.isEmpty()){
res[j++] = i;
}
}
if(jo
* @param o
* @return
* @see #_new_pointedBy(int)
*/
public int[] _new_pointedBy(int[] o){
int[] res = new int[this.interpreter.getRefValuesLength()];
int j = 0;
for (int i = 0; i < o.length && o[i]!=-1; i++) {
j = Utils.merge(res, j, _new_pointedBy(o[i]));
}
if(jfrom-\>to, a trasitive closure must be also calculated, in order
* to take into account the reflexivity.
*
* This method creates links between elements in from
and elements that are pointed by
* to
.
*
* Let x
be an element in from
.
*
* Suppose we have to -> b
*
* This function will create a link between x
and b
: b-\> x
*
* @param from
* @param to
*/
public void new_makePointedBy(int[] from, int to){
int[] res =_new_pointedBy(to);
int res1 = 0;
int from1;
int res2, from2;
while(res1from-\>to, a trasitive closure must be also calculated, in order
* to take into account the reflexivity.
*
* This method creates links between elements that point to from
and elements in to
.
* Let x
be an element in to
.
*
* Suppose we have a -> from
*
* This function will create a link between a
and from
: a-\> x
*
* @param from
* @param to
*/
public void new_makePointTo(int from, int[] to){
int[] res =_new_pointsTo(from);
for(int i = 0; i < res.length && res[i]!=-1; i++){
Link l = linksFlow.get(res[i], from);
for(int k = 0; k < to.length && to[k]!=-1; k++){
linksFlow.set(res[i], to[k], Link.makePointTo(linksFlow.get(res[i], to[k]), l, linksFlow.get(from, to[k])));
}
}
}
/**
*
* @param signature
* @param returnValue
* @param argv
*
*/
public void new_applySignature(Signature signature, MultiObject returnValue,
MultiObject argv[] ) {
new_applySignature_ref(signature, returnValue, argv, Link.REFERENCE_LINK );
new_applySignature_ref(signature, returnValue, argv, Link.VALUE_LINK );
}
public void new_applySignature_ref(Signature signature, MultiObject returnValue,
MultiObject argv[], int linkType ) {
FlowPartialSignature sign = (FlowPartialSignature) signature
.getPartialSignature(FlowAnnotation.class.getName());
//((FlowPartialSignatureData)sign.getComponent()).display(System.out);
TableLink s = ((FlowPartialSignatureData)sign.getComponent()).getData();
new_applyAux(s, 0, returnValue, returnValue, argv, linkType );
new_applyAux(s, 1, exception, returnValue, argv, linkType );
new_applyAux(s, 2, staticWorld, returnValue, argv, linkType );
new_applyAux(s, 3, flux, returnValue, argv, linkType );
int j = 4;
for (int i = 0; i < argv.length; i++, j++) {
new_applyAux(s, j, argv[i], returnValue, argv, linkType );
}
}
/**
*
* @param deps
* @param line
* @param from
* @param returnValue
* @param argv
*
*/
private void new_applyAux(TableLink deps, int line, MultiObject from, MultiObject returnValue, MultiObject[]argv,
int linkType){
Link l = deps.get(line, 0);
int []from1 = new_translate(from);
if(l!=null && !l.isEmpty() && l.isLinkOfType(linkType))
new_makePointApplySignature(from, from1, returnValue, l);
l = deps.get(line, 1);
if(l!=null && !l.isEmpty() && l.isLinkOfType(linkType))
new_makePointApplySignature(from, from1, exception, l);
l = deps.get(line, 2);
if(l!=null && !l.isEmpty() && l.isLinkOfType(linkType))
new_makePointApplySignature(from, from1, staticWorld, l);
l = deps.get(line, 3);
if(l!=null && !l.isEmpty() && l.isLinkOfType(linkType))
new_makePointApplySignature(from, from1, flux, l);
MultiObject aaa[] = new MultiObject[argv.length];
int j = 4;
for(int i = 0; i < argv.length; i++, j++){
l = deps.get(line, j);
if(l!=null && !l.isEmpty() && l.isLinkOfType(linkType))
aaa[i] = _pointedBy(from);
}
j = 4;
for(int i = 0; i < argv.length; i++, j++){
l = deps.get(line, j);
if(l!=null && !l.isEmpty() && l.isLinkOfType(linkType))
new_makePointApplySignature_2(from, from1, aaa[i], argv[i], l);
}
}
/**
*
* @param from
* @param to
* @param l
*
*/
private void new_makePointApplySignature(MultiObject from, int[]fromArray, MultiObject to, Link l){
MultiObject pointedBy = _pointedBy(from);
new_makePointApplySignature_2(from, fromArray, pointedBy, to, l);
}
private void new_makePointApplySignature_2(MultiObject from, int[]fromArray, MultiObject pbf, MultiObject to, Link l){
MultiObject pointedBy = pbf;
JvmType[]from1 = from.content();
JvmType[]to1 = to.content();
for(int i = 0; i < from1.length; i++){
int from2 = _translate(from1[i]);
for(int j = 0; j < to1.length; j++){
int to2 = _translate(to1[j]);
linksFlow.set(from2, to2, Link.applySignature( linksFlow.get(from2, to2), from1[i].getPartType(), to1[j].getPartType(), l ));
}
}
//FIXME should we do that after we mark all the signatures?
//Printer.println("pontebBy(to)= "+_pointedBy(to).size());
//int toTrans[] = new_translate(to);
//new_makePointTo( fromArray, toTrans);
//new_makePointedBy(fromArray, toTrans);
//new_makePointTo(fromArray, _new_pointedBy(toTrans));
makePointTo(from, to);
makePointedBy(from, to);
makePointTo(from, _pointedBy(to));
/*
* if t -> t1
* t -> t2
* => t1 -> t2
*/
if(!pointedBy.equals(to)) {
makePointArray(from, pointedBy, to);
//computes the transive closure after creating link between _pointedBy(from) and to
//@see #makePointArray to understand why we need a link between _pointedBy(from) and to
makePointTo(pointedBy, to);
makePointedBy(pointedBy, to);
MultiObject mto = _pointedBy(to);
makePointTo(pointedBy, mto);
}
}
/////////////////////////////////////////////////////////
/// deprecated methods
/////////////////////////////////////////////////////////
/**
* Creates links between objects in from
and objects in to
. The type
* of link (value
or reference
) is specified by type
.
* This method creates only direct links, and not the trasitive closure! To compute the trasitive closure,
* see makePoint
*
* @param from
* @param to
* @param type
*/
/*
public void new_simpleMakePoint(int[] from, int[] to, Type type){
int linkType;
if(type instanceof BasicType ){
linkType = Link.VALUE_LINK;
}
else{
linkType = Link.REFERENCE_LINK;
}
int from1 = 0;
int to1 = 0;
int ii,jj;
while(from1 < from.length && from[from1]!=-1) {
ii = from[from1];
to1 = 0;
while(to1 < to.length && to[to1]!=-1) {
jj = to[to1];
linksFlow.set(ii, jj, Link.merge(linksFlow.get(ii,jj), Frame.createLink(interpreter.getRefValues()[ii].getPartType(), interpreter.getRefValues()[jj].getPartType(), linkType)));
to1++;
//linksValues[ii][jj].merge( Frame.createLink(from1[i].getPartType(), to1[j].getPartType(), linkType));
}
from1++;
}
}
*/
/**
* Returns the objects that are pointed by r
. The link between these objects and
* r
must be of the type specified by t
(reference or value)
* @param r
* @param t
* @return
* @see #_new_pointedBy(JvmType)
*/
/*
public int[] _new_pointedBy(JvmType r, Type t){
int ir = _translate(r);
return _new_pointedBy(ir, t);
}
*/
/**
* Returns all the objects that point to the r
(that have a non-null link to r
.
* Example: a=b => _pointsTo(b)=a
* @param r
* @return an Multiobject
containing all the objects that point to r
*
*/
/*
public int[] _new_pointsTo(JvmType r){
int ir = _translate(r);
return _new_pointsTo(ir);
}*/
/**
*
* @param r
* @return
* @see #_new_pointedBy(int, Type)
*/
/*
public int[] _new_pointedBy(JvmType r){
int ir = _translate(r);
return _new_pointedBy(ir);
}
*/
}