package fr.lifl.stc.stan.samples.escape; import org.apache.bcel.classfile.Method; import org.apache.bcel.generic.ATHROW; import org.apache.bcel.generic.InstructionHandle; import org.apache.bcel.generic.InstructionList; import org.apache.bcel.generic.ReferenceType; import org.apache.bcel.generic.ReturnInstruction; 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.Reference; import fr.lifl.stc.stan.link.Link; import fr.lifl.stc.stan.signature.PartialSignature; import fr.lifl.stc.stan.analyser.StatsEscape; public class EscapeAnnotation implements Annotation { private Reference [] refs; private boolean [] escaped; private Reference excep; // TODO bof private Method m; public EscapeAnnotation (Reference [] r, MethodInfo mi){ this.m = mi.getMethod(); int n = 0,j=0; for (int i = 0; i < r.length; i++){ if (r[i].isNew()) n++; else if (r[i].isThrown()) excep = r[i]; } refs = new Reference [n]; escaped = new boolean [n]; for (int i = 0; i < r.length; i++) if (r[i].isNew()){ refs[j] = r[i]; j++; } } private int convert (Reference r){ for (int i = 0; i < refs.length; i++){ if (refs[i] == r) return i; } return -1; } public boolean update(Frame a, InstructionHandle ih) { boolean updated = false; JvmType[] s; if (!(ih.getInstruction() instanceof ReturnInstruction || ih.getInstruction() instanceof ATHROW)) { return false; } if (ih.getInstruction() instanceof ReturnInstruction) { // verif de la valeur de retour ReturnInstruction ri = (ReturnInstruction) ih.getInstruction(); if (ri.getType() instanceof ReferenceType) { s = a.pointedBy(a.getStack().peek(),Link.REFERENCE_LINK,JvmType.WHOLE_PART,JvmType.WHOLE_PART).content(); for (int i = 0, k = 0; i < s.length; i++) { k = convert((Reference) s[i]); if (k != -1 && !escaped[k]) { escaped[k] = true; updated = true; } } } } else { s = a.pointedBy(a.getStack().peek(),Link.REFERENCE_LINK,JvmType.WHOLE_PART,JvmType.WHOLE_PART).content(); for (int i = 0, k = 0; i < s.length; i++) { k = convert((Reference) s[i]); if (k != -1 && !escaped[k]) { escaped[k] = true; updated = true; } } } // verif des statics s = a.pointedBy(a.getStaticWorld(),Link.REFERENCE_LINK,JvmType.WHOLE_PART,JvmType.WHOLE_PART).content(); // TODO moche for (int i = 0, k = 0; i < s.length; i++) { k = convert((Reference) s[i]); if (k != -1 && !escaped[k]) { escaped[k] = true; updated = true; } } // verif des link for (int i = 0; i < refs.length; i++) { s = a.pointsTo(refs[i],Link.REFERENCE_LINK,JvmType.WHOLE_PART,JvmType.WHOLE_PART).content(); for (int j = 0; j < s.length; j++) { if (((Reference) s[j]).isArgument() && !escaped[i]) { escaped[i] = true; updated = true; } } } // verif des exceptions s = a.pointedBy(excep,Link.REFERENCE_LINK,JvmType.WHOLE_PART,JvmType.WHOLE_PART).content(); for (int i = 0, k = 0; i < s.length; i++) { k = convert((Reference) s[i]); if (k != -1 && !escaped[k]) { escaped[k] = true; updated = true; } } return updated; } public PartialSignature getPartialSignature() { return new EscapePartialSignature(this.getClass().getName(),getOffsets()); } public String toHTML() { short[] offsets = getOffsets(); int nb = offsets.length; String res = "

Escape Annotation

"; for (int i = 0; i < nb; i++){ res = res + ""; } res = res +"
"+ offsets[i] + "
"+ "number of new = "+ refs.length + "
number of captured objects = " + nb ; if (refs.length != 0){ res = res + "
rate = " + (int)((double) nb/refs.length * 100) + "%"; } StatsEscape.add(refs.length, nb); return res ; } public void addResults (){ /*GlobalAnalyser.newNb = GlobalAnalyser.newNb+refs.length; GlobalAnalyser.newS = GlobalAnalyser.newS+getOffsets().length;*/ } public short[] getOffsets() { InstructionList il = new InstructionList(m.getCode().getCode()); InstructionHandle[] ihs = il.getInstructionHandles(); int nb = 0; for (int i = 0; i < refs.length; i++){ if (!escaped[i]) { nb++; } } short[] res = new short[nb]; int j = 0; for (int i = 0; i < refs.length; i++){ if (!escaped[i]) { res[j] = (short)ihs[refs[i].getId()].getPosition(); j++; } } return res; } }