Program Slicing

advertisement
Plasterkowanie
Leszek Mierzejewski
Cel referatu
• kilka definicji
• struktury danych i algorytmy plasterkowania dla programów
imperatywnych
• analiza zależności w programach obiektowych
• reprezentacja metod, klas i obiektów
• plasterki spełniające różne kryteria
• zastosowania
Definicje
• Plasterkowanie polega na takim okrojeniu analizowanego programu,
żeby w zadanym miejscu programu oryginalnego i okrojonego, zadane
zmienne miały te same wartości.
• Zastosowania:
– debugowanie,
– testowanie,
– analiza, zrozumienie programu,
– porównywanie programów,
– bezpieczeństwo,
– zrównoleglanie.
• Plasterkowanie programu wprowadził Mark Weiser.
• Publikacja z 1979 roku
• Kryterium plasterkowania jest parą <p, V>, gdzie p jest punktem
programu, a V zbiorem zmiennych z p.
• Backward slice stanowi podzbiór programu, który wpływa na p.
• Forward slice stanowi podzbiór programu, na który wpływa p.
• Chop, pomiędzy punktami programu p i q, stanowi podzbiór programu
zależny od p, i który wpływa na q.
Backward slice
void main () {
int sum = 0;
int i = 1;
while (i < 11) {
sum = sum + i;
i = i + 1;
}
printf („%d\n”, sum);
printf („%d\n”, i);
}
Backward slice dla wyrażenia printf(„%d\n”, i)
Backward slice
void main () {
int sum = 0;
int i = 1;
while (i < 11) {
sum = sum + i;
i = i + 1;
}
printf („%d\n”, sum);
printf („%d\n”, i);
}
Backward slice dla wyrażenia printf(„%d\n”, i)
Forward slice
void main () {
int sum = 0;
int i = 1;
while (i < 11) {
sum = sum + i;
i = i + 1;
}
printf („%d\n”, sum);
printf („%d\n”, i);
}
Forward slice dla wyrażenia sum = 0
Forward slice
void main () {
int sum = 0;
int i = 1;
while (i < 11) {
sum = sum + i;
i = i + 1;
}
printf („%d\n”, sum);
printf („%d\n”, i);
}
Forward slice dla wyrażenia sum = 0
Chop
void main () {
int sum = 0;
int i = 1;
while (i < 11) {
sum = sum + i;
i = i + 1;
}
printf („%d\n”, sum);
printf („%d\n”, i);
}
Chop pomiędzy wyrażeniem sum = 0
i wyrażeniem printf(„%d\n”, i)
Chop
Brak przepływu
informacji
void main () {
int sum = 0;
int i = 1;
while (i < 11) {
sum = sum + i;
i = i + 1;
}
printf („%d\n”, sum);
printf („%d\n”, i);
}
Chop pomiędzy wyrażeniem sum = 0
i wyrażeniem printf(„%d\n”, i)
Program Dependence Graph
• graf skierowany, reprezentujący procedurę
• wierzchołki
– wierzchołki Control Flow Graph
• krawędzie
– zależności kontrolne
– zależności przepływu danych
• Backward slice dla punktu p jest podgrafem uzyskanym przez
przejście grafu PDG przeciwnie do kierunku, rozpoczynając z
wierzchołka p
• Forward slice dla punktu p jest podgrafem uzyskanym przez przejście
grafu PDG z wierzchołka p.
• Chop dla punktów p i q jest podgrafem PDG zawartym pomiędzy
wierzchołkami p i q.
System Dependence Graph
• System Dependence Graph
– PDG dla każdej procedury
– krawędzie pomiędzy procedurami łączą:
• wywołania procedur (calls) z wejściami procedur (entries)
• przekazywane parametry (actual parameters) z
otrzymywanymi parametrami (formal parameters)
• wyniki procedury (results) ze zmiennymi pobierającymi
rezultat (call-site return values)
• wyznaczenie plasterka jest problemem przejścia grafu
Backward slice
void main () {
int add (int x, int y) {
int sum = 0;
return x + y;
int i = 1;
}
while (i < 11) {
sum = add(sum,i);
i = add(i,1);
}
printf („%d\n”, sum);
printf („%d\n”, i);
}
Backward slice dla wyrażenia printf(„%d\n”, i)
Backward slice
void main () {
int add (int x, int y) {
int sum = 0;
return x + y;
int i = 1;
}
while (i < 11) {
sum = add(sum,i);
i = add(i,1);
}
printf („%d\n”, sum);
printf („%d\n”, i);
}
Backward slice dla wyrażenia printf(„%d\n”, i)
Plasterkowanie programów obiektowych
Class Dependency Graph (ClDG)
L.D. Larsen, M.J. Harrold, 1994.
• rozszerza SDG
• zawiera wejściowy wierzchołek dla każdej klasy, z którego wychodzą
krawędzie do wierzchołków wejściowych metod
• każdy wierzchołek wejściowy rozrasta się poprzez dodanie
wierzchołków reprezentujących parametry i atrybuty
Object-Oriented Program Dependency Graph
J.L. Chen, F.J. Wang, Y.L. Chen
• dwa rodzaje plasterków: state slice i behaviour slice.
• State slice dla obiektu jest zbiorem komunikatów i wyrażeń
kontrolnych, które mogą wpływać na stan obiektu.
• Behaviour slice jest zbiorem atrybutów i metod zdefiniowanych w
powiązanych klasach, które mogą wpływać na zachowanie obiektu.
PDG metody
•
•
•
•
•
•
•
•
Reprezentowana przez control flow graph (CFG)
CFG=<S, E, Sentry, Sexit>
E={<s1, s2> | s1,s2  S i po wykonaniu s1 można wykonać s2}.
Def(s) zmienne, których wartości są zdefiniowane (modyfikowane) w
punkcie s. (Parametry formalne in są związane z wierzchołkiem
wejścia.)
Ref(s) zmienne, do których wartości jest odwołanie w punkcie s.
Def(s,x) zmienne użyte do zdefiniowania zmiennej x.
Dep_D(s,x)={(x,s’,y) | yDef(s,x)  yDef(s’)   ścieżka z s’ do s,
na której y nie jest przedefiniowane.
Dep_R(s)={(x,s’,x) | jeśli s jest wyrażeniem kontrolnym (if, while), x
jest zmienną warunkową użytą w s i x  Def(s’)   istnieje ścieżka z
s’ od s, na której x nie jest przedefiniowany}.
public class Point {
int X;
int Y;
public Point (int x, int y) {
1: X=x;
2: Y=y;
}
public void Move (int z) {
3: X=X+z;
4: Y=Y+z;
public class Main {
public void main (String[] args) {
8: Point P1=new Point(10,20);
9: Point P2=new Point(0,0);
10: P1.Trans(10);
11: P2.Move(100);
12: P1.X=P1.X+P2.X++;
13: System.out.println (P1.X);
14: System.out.println (P2.X);
}
}
}
public void Trans (int z) {
5: if (z>0)
6:
Move(z);
else
7:
System.out.println (“error”);
}
}
Def(12)={P1.X, P2.X}
Ref(12)={P1.X, P2.X}
Def(12, P2.X)={P2.X}
Def(12, P1.X)={P1.X, P2.X}
Dep_D(14,P2.X)={P2.X,12,P2.X}
Dep_R(5)={wejście Trans}
Definicja 1 Program Dependence Graph dla metody M jest grafem
skierowanym ze znacznikami. PDG=<S’,E’,T>, gdzie S’=S (S jest
zbiorem wierzchołków grafu CFG), krawędzie E’=E1  E2, gdzie E1
zbiór krawędzi wyrażających zależności kontrolne, E2={<s1, s2> |
(x,s2,y)  Dep_D(s1,x)  (x,s2,x)  Dep_R(s1)} jest zbiorem krawędzi
wyrażających zależności danych. T jest zbiorem znaczników.
Znacznik na krawędzi <s1,s2>:
•(*,*), jeśli <s1,s2>  E1,
•(x,y), jeśli (x,s2,y)  Dep_D(s1),
•(x,x), jeśli (x,s2,x)  Dep_R(s1).
Entry
(X,X)
public void Move (int z) {
3: X=X+z;
4: Y=Y+z;
}
(X,z) (Y,z)
3
(Y,Y)
4
PDG Move
Analiza zależności
• Rodzaje parametrów: in, out, in out,
formalne, aktualne.
• Zależności pomiędzy parametrami
opisane są za pomocą zbiorów
zależności parametrów.
• Metody mogą współdziałać ze sobą
tylko za pomocą parametrów.
• Call Graph – graf skierowany,
opisuje powiązania pomiędzy
metodami
– wierzchołki – metody
– krawędzie – komunikaty, jeśli
metoda p wywołuje q, to <p,q>
należy do grafu.
Def(M) = In(Sexit) – {v|v jest zmienną lokalną
lub parametrem typu in};
if v  Def(M) then
if v jest parametrem formalnym then
Def(s)=Def(s)  {a};
a jest odpowiadającym parametrem
aktualnym.
else
Def(s)=Def(s)  {v}; // v jest zmienną
globalną
if y  Dep_PM(M,x) then
a i b są parametreami aktualnymi
odpowiadającymi zmiennym x i y
Def(s,a)=Def(s)  {b};
Analiza zależności (polimorfizm)
• W Javie polimorfizm jest wspierany przez abstrakcyjne metody.
• Obiekt, których typ może zmienić się podczas wykonania programu
jest nazywany obiektem polimorficznym
• Polimorficzny obiekt jest reprezentowany jako drzewo, w którym
korzeń reprezentuje polimorficzny obiekt, a liście reprezentują obiekty
możliwych typów.
• Java jest językiem typowanym statycznie.
• Polimorfizm jest reprezentowany przez zbiory zależności parametrów.
• Kiedy obiekt wywołuje metodę to rozważamy następujące przypadki:
Obiekt ma określony typ.
Obiekt nie ma określonego typu.
Metoda nie
polimorficzna.
Koniec.
Bierzemy wszystkie możliwe metody.
Metoda
polimorficzna.
Zamieniamy na odpowiadającą
metodę.
Dla wszystkich możliwych typów
obiektu zmieniamy polimorficzną
metodę na jej odpowiedniki.
PDG klasy
Klasa:
• pola danych
• PDG dla każdej metody
• podklasa dziedziczy PDG
rodzica
Reprezentacja obiektu:
• pola danych obiektu jako
parametry
• drzewo
– korzeń - obiekt
– dzieci - pola danych
PDG Move
PDG Trans
PDG Point
PDG klasy Point
Partial Slicing
• Dla podanego kryterium plasterkowania <s, v> partial slicing
plasterkuje tylko wybrane części programu (klasę, kilka metod,
obiekt).
• Użyteczny w dużych systemach, lub gdy mamy niekompletny kod.
• Plasterkujemy metodę, pomijając wywołania innych metod.
Analizujemy je w drugiej fazie.
• Plasterkowanie metody sprowadza się do plasterkowania kilku
pojedyńczych metod.
• Tylko parametry out i in out mają wpływ na stronę wywołującą.
• Zależności pomiędzy parametrami można wyznaczyć przez interfejsy.
Input: Program P, kryterium plasterkowania <s0, v>.
while PL !=  do
Output: Plasterek spełniający kryterium plasterkowania
Usuń element (P,x) z PL;
<s0, v>: Dep_S.
if P jest interesującą nas częścią then
Init: W={(s0, v)}; Dep_S = ; PL = ;
Dep_S = Dep_S  plasterek P dla x;
Algorithm:
if plasterek P dla x zawiera plasterek
repeat
Mi dla z then
Usuń element (s, x) z W;
PL = PL  {(Mi,z)};
for all krawędź <s, s’>, która nie była wybrana do
end;
Zaznacz jako wybraną krawędź <s, s’>; Niech T
będzie znacznikiem dla <s, s’>;
if T=(x, y) then // data dependence
W = W  {(s’, y)};
Dep_S = Dep_S  {s’};
if y jest nazwą metody then PL = PL  {(y, y)};
if y jest aktualnym parametrem metody M then
Niech y’ będzie odpowiadającym parametrem
formalnym.
PL = PL  {(M,y’)};
if T=(*,*) then // control dependence
Dep_S = Dep_S  {s’};
for all yi  Ref(s’) do W = W  {(s’,y)};
if y jest nazwą metody then PL  {(y,y)};
while W != ;
public class Point {
int X;
int Y;
public Point (int x, int y) {
1: X=x;
2: Y=y;
}
public void Move (int z) {
3: X=X+z;
4: Y=Y+z;
public class Main {
public void main (String[] args) {
8: Point P1=new Point(10,20);
9: Point P2=new Point(0,0);
10: P1.Trans(10);
11: P2.Move(100);
12: P1.X=P1.X+P2.X++;
13: System.out.println (P1.X);
14: System.out.println (P2.X);
}
}
}
public void Trans (int z) {
5: if (z>0)
6:
Move(z);
else
7:
System.out.println (“error”);
}
}
Kryterium plasterkowania
<13,P1.X> metody Move i Trans
Object Slicing
• Głównie użyteczny przy debugowaniu i analizie programu.
• Kryterium plasterkowania <s, v, Object>
• Wyznacza wyrażenia metod wybranego obiektu spełniające kryterium
<s, v>
• Korzystamy z algorytmu dla częściowego plasterkowania.
• Wyznaczamy plasterki metod obiektu Object (mogą być wywoływane
pośrednio lub bezpośrednio)
• Wynikiem jest suma wszystkich tych plasterków.
public class Point {
int X;
int Y;
public Point (int x, int y) {
1: X=x;
2: Y=y;
}
public void Move (int z) {
3: X=X+z;
4: Y=Y+z;
public class Main {
public void main (String[] args) {
8: Point P1=new Point(10,20);
9: Point P2=new Point(0,0);
10: P1.Trans(10);
11: P2.Move(100);
12: P1.X=P1.X+P2.X++;
13: System.out.println (P1.X);
14: System.out.println (P2.X);
}
}
}
public void Trans (int z) {
5: if (z>0)
6:
Move(z);
else
7:
System.out.println (“error”);
}
}
Kryterium plasterkowania
<14,P2.X,P2>
Class Slicing
• Kryterium plasterkowania <s, v, Class>
• Wyznacza pola danych i wyrażenia metod należących do klasy Class,
które spełniają kryterium plasterkowania <s, v>
• Algorytm:
– plasterkujemy każdą instancję, zaznaczając użyte pola danych
(kosztowne)
– plasterkujemy z punktu s, w trakcie zaznaczając wyrażenia i pola
danych klasy Class.
public class Point {
int X;
int Y;
public Point (int x, int y) {
1: X=x;
2: Y=y;
}
public void Move (int z) {
3: X=X+z;
4: Y=Y+z;
public class Main {
public void main (String[] args) {
8: Point P1=new Point(10,20);
9: Point P2=new Point(0,0);
10: P1.Trans(10);
11: P2.Move(100);
12: P1.X=P1.X+P2.X++;
13: System.out.println (P1.X);
14: System.out.println (P2.X);
}
}
}
public void Trans (int z) {
5: if (z>0)
6:
Move(z);
else
7:
System.out.println (“error”);
}
}
Kryterium plasterkowania
<14,P2.X,Point>
Zastosowania
• Zrozumienie programu
– Co wpływa na co?
• Zrównoleglanie (dekompozycja)
– Odzielenie osobnie wyliczanych zadań
• Specjalizacja
– plasterek = wyspecjalizowany program
• Porównywanie programów
– Wykrywanie rożnic semantycznych
• Testowanie
– Które fragmenty nie wymagają powtórnego testowania?
• Bezpieczeństwo
– Wykrywanie niebezpiecznych fragmentów programu.
Aplikacje i projekty
•
•
•
•
http://www.grammatech.com/products/codesufer/
http://www.infosun.fmi.uni-passau.de/st/staff/krinke/slicing
http://www.cs.wisc.edu/wpis.html
http://hissa.ncsl.gov/~jimmy/unravel.html
Bibliografia
• Z. Chen, B. Xu, “Slicing Object-Oriented Java Programs”
• Andrea De Lucia, “Program Slicing: Methods and Applications”
• www.grammatech.com
Dekompozycja
void char_count(FILE *f) {
int lines = 0;
int chars;
BOOL eof_flag = FALSE;
int n;
extern void scan_line(FILE *f, BOOL
*bp, int *ip);
scan_line(f, &eof_flag, &n);
chars = n;
while (eof_flag == FALSE) {
lines = lines + 1;
scan_line(f, &eof_flag, &n);
chars = chars + n;
}
printf(„lines = %d\n”, lines);
printf(„chars = %d\n”, chars);
}
void line_count(FILE *f) {
int lines = 0;
int chars;
BOOL eof_flag = FALSE;
int n;
extern void scan_line(FILE *f, BOOL
*bp, int *ip);
scan_line(f, &eof_flag, &n);
chars = n;
while (eof_flag == FALSE) {
lines = lines + 1;
scan_line(f, &eof_flag, &n);
chars = chars + n;
}
printf(„lines = %d\n”, lines);
printf(„chars = %d\n”, chars);
}
Download