Diego Garbervetsky, Mike Barnett, Manuel Fähndrich, Francesco Logozzo ANNOTATIONS FOR (MORE) PRECISE POINTS-TO ANALYSIS Objetivos Incrementar la precisión en el análisis de efectos de métodos no analizables de Salcianu –Rinard . Definir un lenguaje de anotaciones que establezca características de métodos con respecto a su pureza y efectos. Definiciones Método no analizable Un método es no analizable si su código no está disponible. Método débilmente puro Un método es débilmente puro si no “muta” ninguna locación existente en el estado correcto anterior a la invocación del método. El problema List<int> copy(Iterable<int> src) { List<int> l = new LinkedList<int>(); Iterator<int> iter = src.iterator(); while (iter.hasNext()){ int x = iter.next(); l.add(x); } return l; } ¿Que haría Salcianu? Salcianu “resuelve” este problema estableciendo que todos los parámetros que se le pasan al método no analizable escapan globalmente. MUY CONSERVADOR!!! No puede analizar llamadas a métodos de interfaces de las cuales no conocemos ninguna implementación. Métodos no analizables Supongamos que tenemos un método no analizable. De este método sabemos que podría escribir sobre todo objeto alcanzable desde un parámetro: m2(p1) p1.f1 = 0; p1.f1.f2 = 0; p1.f1.f2….fn = 0; Tenemos además otro método del que tenemos información solamente sobre a1.f1, y este método llama a m2: m1() … m2(a1); Métodos no analizables Tenemos información insuficiente sobre el contexto de m1. Sería un error considerar los efectos de m2 solo sobre a1.f1. Necesitamos un mecanismo para hacer que los efectos del método llamado persistan en el contexto del método llamador, y así actualizar a1 cuando dispongamos de más información. Extensiones para métodos no analizables (nodos) Omega nodes (ω) Modelan el conjunto de nodos alcanzables desde ese nodo. Omega Confined nodes (ωC) Subcojunto de ω. Son nodos ω que representan solo aquellos nodos alcanzables por los campos de los que el objeto es dueño. El objeto O de tipo T es dueño del objeto apuntado por su campo f si la clase T es dueña del campo f (i.e. el campo f está marcado como own en la clase T). Extensiones para métodos no analizables (ejes) Ejes “?” Representan cualquier campo existente. Ejes “$” Campos no owneados. Permite distinguir entre referencias a objetos que pueden ser escritos por el método y los que únicamente pueden ser leídos. Matcheo interprocedural Matcheo con ω: calculamos el conjunto de nodos (del llamador) alcanzables desde este, y finalmente todos los load nodes se convierten en ω. Matcheo con ωC: consideramos solo caminos que pasan por los ejes “?” y los ejes owned. Rechazamos los que contienen ejes “$”. Ejemplo: binding omega nodes caller(){ T1 a1 = new T1(); a1.f1 = new T3(); T2 a2 = new T2(); a2.f2 = this.c; callee(a1, a2); } callee(Object p1, Object p2); Ejemplo: binding omega nodes (callee) p1 p2 ω1 ω2 ? Ejemplo: binding omega nodes (caller) caller(){ T1 a1 = new T1(); a1.f1 = new T3(); T2 a2 = new T2(); a2.f2 = this.c; a1 a2 IN1 IN2 f1 f2 callee(a1, a2); } IN3 L4 Ejemplo: omega nodes (caller bindeando con callee) a1 IN1 a2 ? IN2 ? f1 IN3 ? ? f2 L4 Ejemplo: omega nodes (caller bindeando con callee) a1 IN1 a2 ? IN2 ? f1 IN3 ? ? f2 ωL4 Ejemplo: omega nodes (bindeado) a1 IN1 a2 ? IN2 ? f1 IN3 ? ? f2 ωL4 Anotaciones Proveemos un sistema de anotaciones para clasificar métodos puros. Es útil porque: Proveen informacion sobre los efectos y los Points-to Graphs. Nos permite mitigar los problemas de los métodos no analizables. Ejemplo: iteradores int result = o; it = p1.iterator(); while(it.hasNext()) result+=it.next().data; return result; p1 IN next LN Ejemplo: iteradores [Pure] iterator() Ejemplo: iteradores [Pure][Fresh] iterator() Ejemplo: iteradores [Escapes(true)] [Pure][Fresh] iterator() Ejemplo: iteradores [GlobalAccess(false)] [Escapes(true)] [Pure][Fresh] iterator() this ωLN ? IN ret Ejemplo: iteradores int result = o; it = p1.iterator(); while(it.hasNext()) result+=it.next().data; return result; p1 it IN ? IN next ωLN ? Ejemplo: iteradores [GlobalAccess(false)] next() ωLN this ? Ejemplo: iteradores int result = o; it = p1.iterator(); while(it.hasNext()) result+=it.next().data; return result; p1 it IN ? IN next ωLN ? ? ? $ Ejemplo: iteradores [GlobalAccess(false)] [Escapes(true)] [Pure][Fresh] iterator() this ωLN ? IN ret Ejemplo: iteradores [Capture(false)] [GlobalAccess(false)] [Escapes(true)] [Pure][Fresh] iterator() $ this ωLN IN ret Ejemplo: iteradores int result = o; it = p1.iterator(); while(it.hasNext()) result+=it.next().data; return result; p1 it IN $ IN next ωLN $ Ejemplo: iteradores [GlobalAccess(false)] next() ωLN this ? Ejemplo: iteradores [WriteConfined] next() ωCLN this ? $ ω Ejemplo: iteradores int result = o; it = p1.iterator(); while(it.hasNext()) result+=it.next().data; return result; p1 it IN $ IN next ωLN $ ? Anotaciones (resumen) Conclusiones Se logró extender el analisis de Salcianu para tratar los métodos no analizables de manera más precisa, mediante los nodos omega y el lenguaje de anotaciones. Verificaciones con la especificación es suficientemente simple utilizando el lenguaje de anotaciones.