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); } */ }