nsse-2011-dpm-programslicing
DESCRIPTION
it is a copy of the presentations which is going on at silicon institute of technology(http://www.silicon.ac.in).TRANSCRIPT
Program Slicing
Dr. Durga Prasad Mohapatra
Associate Professor
CSE Department
National Institute of Technology
Rourkela
Outline of the Presentation
• Introduction
• Inter-procedural slicing
• Static Slicing of OOP
• Dynamic Slicing of OOP
• Dynamic Slicing of Concurrent OOPs
• Dynamic Slicing of Distributed OOPs
• Dynamic Slicing of AOPs
• Current Research Direction
• Conclusion
Program Slicing
• Slice of a program w.r.t. program point p and
variable x:
- All statements and predicates that might
affect the value of x at point p.
• <p, x> known as slicing criterion.
Example
1 main( )
2 {
3 int i, sum;
4 sum = 0;
5 i = 1;
6 while(i <= 10)
7 {
8 Sum = sum + 1;
9 ++ i;
10 }
11 printf(“%d”, sum);
12 printf(“%d”, i);
13 }
An Example Program & its slice w.r.t. <12, i>
Types of Slice
• Static Slice: Statements that may affect value of a variable at a program point for all possible executions.
• Dynamic Slice: Statements that actually affect value of a variable at a program point for that particular execution.
• Backward Slice: Statements that might haveaffected the variable at a program point.
• Forward Slice: Statements that might beaffected by the variable at a program point.
Applications of Slicing
• Debugging
• Program understanding
• Testing
• Software maintenance
• Complexity measurement
• Program integration
• Reverse engineering
• Software reuse
Approaches to Slicing
• CFG- based: Data flow equations are solved
• Dependence graph-based:
-PDG is used as intermediate representation
-Slice is computed as a reachability problem
• PDG of an OOP is a directed graph in which
-nodes represent statements and predicates
-edges represent data/control dependence
among the nodes
Inter-Procedural Slicing
Horwitz’s Approach
• PDG can not handle programs with multiple procedures.
• Here the intermediate representation is called as system dependence graph (SDG).
• SDG is based on procedure dependence graphs
• Same as PDG except that it includes vertices & edges for call statements, parameter passing& transitive dependence due to calls.
Inter-Procedural Slicing(cont.)
• On calling side, parameter passing is
represented by actual-in & out vertices.
• In called procedure, parameter passing is
represented by formal-in & out vertices.
Inter-Procedural slicing (cont.)
• A call edge is added from call site vertex to
corresponding procedure entry vertex.
• A parameter-in edge is added from each actual-
in vertex to corresponding formal-in vertex.
• A parameter-out edge is added from each
formal-out vertex to corresponding actual-out
vertex.
• To find the slice, Horwitz proposed a two-pass
algorithm.
Inter-Procedural Slicing (cont.)
• The traversal in pass one starts from desired
vertex & goes backwards along all edges except
parameter-out edges.
• The traversal in pass two starts from all vertices
reached in pass one and goes backwards along
all edges except call & parameter-in edges.
• The slice is the union of 2 sets of vertices.
Slicing of OOPs
• Present-day software systems are basically
object-oriented.
• O-O features such as classes, inheritance,
polymorphism need to be considered in slicing.
• Due to presence of polymorphism and dynamic
binding, process of tracing dependencies in
OOPs becomes complex.
Slicing OOPs
• Slicing OOPs is more complicated than slicing procedural programs.
- features such as classes, inheritance,
polymorphism need to be considered.
• Though, inheritance & polymorphism are strengths of OOPs
- they pose special challenges in slicing.
Slicing of OOPs (cont …)
• Due to presence of polymorphism and dynamic
binding,
- tracing dependencies in OOPs is complex.
Static Slicing of OOP• Larson and Harrold were the first to consider
these O-O features for slicing by extending the SDG for OOPs.
• They represented each class by a class dependence grpah (CLDG).
• The CLDG captures the control and data dependence relationships of a class.
• Each method in a class, is represented by a procedure dependence graph.
Static Slicing of OOP (cont.)
• Each method has a method entry vertex to
represent the entry into the method.
• CLDG contains a class entry vertex that is
connected to the method entry vertex for each
method, by class member edges.
• To represent parameter passing, CLDG creates
formal-in & formal-out vertices.
Inheritance
• Inheritance is considered as follows:
- each method defined by the derived class is
represented.
- reuse of the representations of all methods
inherited from base class.
polymorphism)
• Polymorphism lets the type of an object be decided at run-time.
• To represent polymorphic method calls
- a polymorphic vertex is used
- provides the dynamic choice among the
possible destinations
- polymorphic call edges are added between
the polymorphic vertex and method entry
vertices of the possible bound methods
Static Slicing of OOP (cont.)
• CLDG represents method calls by a call vertex.
• It adds actual-in & actual-out vertices at each
call vertex.
Example1 class Elevator {
public
2 Elevator(int1_top_floor)
3 {current_floor = 1;
4 current_direction = UP;
5 top_floor = 1_top_floor; }
6 virtual ~Elevator
7 void up( )
8 {current_direction = UP;}
9 void down( )
10 int which_floor( )
11 {current_direction = DOWN;}
12 {return current_floor; }
13 Direction direction( )
14 {return current_direction; }
15 virtual void go(int floor )
16 {if (current_direction = =UP)
17 {while(current_floor != floor) && (current_floor < = top_floor)
18 add(current_floor, 1); }
else
19 {while(current_floor != floor) && (current_floor > 0)
20 add(current_floor, -1); }
}
private:
21 add(int &a, const int &b)
22 { a = a + b; }
protected:
int current_floor;
Direction current_direction
int top_floor; };
23 class AlarmElevator : public Elevator {
public
24 AlarmElevator ( int top_floor)
25 Elevator (top_floor)
26 {alarm_on = 0;}
27 void set_alarm( )
28 {alarm_on = 1;}
29 void reset_alarm( )
30 {alarm_on = 0;}
31 void go (int floor)
32 { if (!alarm_on)
33 Elevator :: go (floor)
};
protected:
int alarm_on;
} ;
34 main( int argc, char **argv) {
Elevator *e_ptr;
35 If (argv[1])
36 e_ptr = new Elevator (10);
else
37 e_ptr = new AlarmElevator (10);
38 e_ptr - > go(5);
39 c_out << “\n currently on floor :” << e_ptr -> which_floor ( );
}
CLDG of the Example
Representing complete programs
• Construct the partial SDG for main()
• Connect the calls in the partial SDG to methods
in the CLDG for each class, by using
- call edges
- parameter-in edges
- parameter-out edges
SDG of the Example Program
Slicing the complete program
• Use the two-pass algorithm for computing the
static slice of the OOP.
• Shaded vertices in the SDG, are included in the
slice w.r.t. slicing criterion <39,current_floor>.
Limitations of Larson’s Approach
• It can not distinguish data members for different
objects instantiated from the same class.
• It fails to consider the fact that in different
method calls, data members used by the
methods might belong to different objects.
Limitations (cont.)
• Thus, it creates spurious data dependences.
• So the resulting slice may be imprecise.
• It can not represent an object that is used as a
parameter or data member of another object.
Limitations (cont.)
• It is not fit to represent larger programs, because
for a large program this SDG will be too large to
manage & understand.
• It can not handle dynamic slicing of OOPs.
Limitations(cont.)
int a,b; if(b>0) ba.m1();
virtual vm(){ vm(); ba.m2(1);
a=a+b; b=b+1; }
} } D(){
public: }; //end of base Base o;
Base(){ main1(){ C(o);
a=0; Base o; o.m2(1);
b=0; Base ba; }
} ba.m1();
m2 (int i){ ba.m2(1);
b=b+i; o.m2(1);
} }
A2-in
main1()
o.Base()
ba.base(
)
A2-
outA1-
out
A2-
out
A1-
out
ba.
m1()
A1-in A2-
outA1-
out
A3-in A2-in A2-
out
ba.
m2(1)
A3-in A2-
out
A2-in
o. m2(1)
Slice
A1-in: a-in=a
A2-in: b-in=b
A3-in: I-in=1
A1-out: a= a-out
A2-out: b=b-out
Class Base{ m1(){ C(Base &ba){
Control dependence edge
Data dependence edge
Summary edge.
Limitations (cont.)
• The data dependence edge between o.base() &
ba.m1() is a spurious data dependence edge.
• C(Base &ba) of the example can not be
represented using this approach.
Tonella’s improvement
• Tonella improved this by passing all data
members of an object as actual parameters,
when the object invokes a method.
• But, only few data members might be used in a
method.
• So this method is expensive.
Tonella’s improvement (cont.)
• For parameter object, he represented an object
as a single vertex.
• This may yield an imprecise slice.
• At the end of D(), ba.a does not affect o.b .
Example
Class Base{ func1( ) {
int a,b; Base o;
virtual vm() { Base ba,
a = a + b ; } ba.m1( );
public: ba.m2(1);
Base( ) { o.m2(1);
a = 0 ; }
b = 0 ; }
m2(int i) { C(Base &ba) {
b = b + i; } ba.m1( );
m1( ) { ba.m2(1); }
if (b > 0) D( ) {
vm( ); Base o;
b = b + 1; } C(o);
} // end of Base o.m2(1) }
Dynamic Slicing of OOPs
• Zhao presented the first algorithm, consisting of
two-phases, for dynamic slicing of OOPs.
• Used dynamic object-oriented dependence
graph (DODG) as intermediate representation.
• Defined Slicing Criterion - <s, v, t, i>.
s - statement number
v - variable of interest
t - execution trace
i - input
Dynamic Slicing of OOPs(cont.)
• Phase-1: Computing a dynamic slice over
the DODG using DFS/BFS.
• Phase-2: Mapping the slice over the DODG
to source code by defining a mapping
function.
DODG of The Example Program
Limitations of Zhao’s Approach
• The no.of nodes in a DODG is equal to the no.of
executed statements, which may be unbounded
for programs having many loops.
• Space Complexity is O(2n), but in Worst case it
is O(S), where S is the length of execution.
• In the worst case, the time complexity becomes
O(S2).
Motivation for Current Research
• Slicing is mainly used in interactive applications such as debugging & testing.
• So, the slicing techniques need to be efficient.
• This requires to develop
- efficient slicing algorithms &
- suitable intermediate representations
• Reports on slicing of OOPs are scarce & less efficient.
• So, there is a pressing necessity to develop efficient slicing algorithms for OOPs.
Motivation (cont …)
• Few techniques are available for dynamic slicing
of concurrent and distributed OOPs.
• So, there is a pressing necessity to develop
efficient dynamic slicing algorithms for
concurrent and distributed OOPs.
Objectives of Current Research
• Appropriate frame-work to compute slices
- static & dynamic
• Suitable intermediate representation
• Development of efficient dynamic slicing techniques for OOPs, Concurrent OOPs, Distributed OOPs, & AOPs.
Our Proposed Dynamic Slicing
Algorithms
• We proposed an algorithm known as edge-
marking dynamic slicing algorithm for OOPs.
• SDG is constructed statically only once.
• Based on marking & unmarking the edges as
and when the dependencies arise & cease
during run-time.
Dynamic Slicing Algorithm(cont.)
• We mark an edge when it’s associated
dependence exists.
• We unmark an edge when the associated
dependence ceases to exist.
44
Some Definitions
• Def(var). Let var be a variable in the program P.
A node x is said to be a Def(var) node if x
represents a definition stmt that defines var.
• Use(var). A node x is said to be a Use(var) node
if it uses the variable var.
• RecentDef(var). For each variable var,
RecentDef(var) represents the node (the label
no. of the stmt) corresponding to the most
recent definition of the variable var.
45
Some Definitions (cont …)
• After execution of each node u,
let (x1,u),…,(xk,u) be the marked incoming
edges of u for some variable var in the
ESDG.
• The dynamic slice w.r.t. some variable var in
node u is given by
dslice(u) = {x1,…,xk} dslice(x1) ... dslice(xK)
46
EMDS Algorithm
1. Construct the ESDG of the OOP statically.2. Do the following before execution of the program starts:
(a) unmark all the edges(b) set dslice(u)=Φ for every node u of ESDG(c) set RecentDef(var) = Φ for each variable
3. Run the Program & carry out the following after execution of each statement:(a) for each variable var used at u, do
(i) unmark the marked data dependence edgescorresponding to the previous execution of u.
(ii) mark the dep. edge (x,u) where x=RecentDef(var)(RecentDef(var)-node corr.to most recent defn of var)
47
EMDS Algorithm (cont …)
(b) update dslice(u) by using
dslice(u) = {x1,…,xk} dslice(x1) … dslice(xk)
(c) if u is a def(var) node, update RecentDef(var)=u.
(d) if u is a method entry node, then do the following:
(i) unmark all the marked edges including call
edges,parameter edges and summary edges for the
previous execution of the statement
(ii) mark the call edge for the present execution
(iii)mark the associated parameter edges
(iv) mark the associated summary edges
48
EMDS Algorithm (cont …)
(e) If u, is a creation node representing operator new,
then do the following:
(i) unmark the marked call edge, if any, between u
and the method entry node of it’s constructor
method for the previous execution
(ii) mark the call edge for the present execution
(iii) mark the associated parameter edges
(iv) mark the associated summary edges
49
EMDS Algorithm (cont …)
(f) If u is a node representing a polymorphic method call, then
do the following:
(i) unmark the data dependence edges for the
previous execution.
(ii) mark the data dependence edges for the present
execution
(iii) mark the polymorphic call edge for the
present execution
(iv) mark the associated parameter edges
(v) mark the associated summary edges
50
EMDS Algorithm (cont …)
4. (a) If a slicing command <s, V> is given, then do:
(i) look up dslice(u) for the content of the slice
(ii) display the resulting slice
(b) If the program has not terminated go to step 3.
51
Example1 class Elevator {
public
2 Elevator(int1_top_floor)
3 {current_floor = 1;
4 current_direction = UP;
5 top_floor = 1_top_floor; }
6 virtual ~Elevator
7 void up( )
8 {current_direction = UP;}
9 void down( )
10 int which_floor( )
11 {current_direction = DOWN;}
12 {return current_floor; }
13 Direction direction( )
14 {return current_direction; }
15 virtual void go(int floor )
16 {if (current_direction = =UP)
17 {while(current_floor != floor)
&& (current_floor < = top_floor)
18 add(current_floor, 1); }
else
19 {while(current_floor != floor) && (current_floor > 0)
20 add(current_floor, -1); }
}
private:
21 add(int &a, const int &b)
22 { a = a + b; }
protected:
int current_floor;
Direction current_direction
int top_floor; };
23 class AlarmElevator : public Elevator {
public
24 AlarmElevator ( int top_floor)
25 Elevator (top_floor)
26 {alarm_on = 0;}
27 void set_alarm( )
28 {alarm_on = 1;}
29 void reset_alarm( )
30 {alarm_on = 0;}
31 void go (int floor)
32 { if (!alarm_on)
33 Elevator :: go (floor)
};
protected:
int alarm_on;
} ;
34 main( int argc, char **argv) {
Elevator *e_ptr;
35 If (argv[1])
36 e_ptr = new Elevator (10);
else
37 e_ptr = new AlarmElevator (10);
38 e_ptr - > go(5);
39 c_out << “\n currently on floor :” << e_ptr -> which_floor ( );
}
52
CLDG for Elevator
53
ESDG of the Example Program
54
Working of the Algorithm
• Consider input data argv[1] = 3.
- the program will execute statements 34, 35,
36, 2, 3, 4, 5, 38, 15, 16,17, 18, 21, 22, 17,
18, 21, 22,17, 39, 11,12.
- the algorithm marks the corresponding edges
• Let us compute dynamic slice at statement 39.
dslice(39)={39 A4_in,12, 1} dslice(39 A4_in)
dslice(12) dslice(1)
• The dynamic slice is shown as shaded vertices in the figure.
55
Node-Marking Dynamic Slicing Algorithm
• We have also proposed an algorithm known as
node-marking dynamic slicing (NMDS)
algorithm for OOPs.
• Uses ESDG as the intermediate representation
• Based on marking & unmarking the executed
nodes appropriately during execution-time.
56
Algorithm
1. Construct the ESDG of the OOP statically.
2. Do the following before execution of the program P starts:
(a) unmark all the nodes
(b) set dslice(u)=Φ for every node u of ESDG
(c) set RecentDef(var) = Null for each variable
3. Run the Program& carry out the following:
(a) for each variable var used at u, do the following:
update dslice(u) by using
dslice(u)={x1,…,xk} dslice(x1) … dslice(xk)
57
Algorithm (cont…)
(b) if u is a def(var) node (definition node of var), then
(i) unmark the node RecentDef(var).
(ii) update RecentDef(var) = u.
(RecentDef(var)- node corr.to most recent defn of var)
(c) mark the node u.
(d) if u is a call vertex, then do the following:
(i) mark the vertex u.
(ii) mark the corresponding actual-in/out
vertices.
(iii) mark the method entry vertex of the
corresponding called method.
(iv) mark the corresponding formal-in/out
vertices.
4. Exit when the execution of program P terminates.
58ESDG of the Example
59
Complexity Analysis
• Space complexity of each algorithm is O(n2).
- n is the number of statements in the program
• Worst case time complexity of each algorithm is
O(n2S).
- S is the length of execution.
60
Comparison with Existing Algorithms
• The worst case space complexity of Zhao’s algorithm is O(S).
- S is the length of execution.
• But, the worst case space complexity of our algorithm is O(n2).
- n is the number of statements in the program
61
Comparison (cont …)
• In worst case, the time complexity of Zhao’s
algorithm becomes O(S2).
- worst case time complexity of our
algorithm is O(n2S).
- S is the length of execution
62
EMDS vs NMDS Algorithm
• EMDS Algorithm requires O(n2) time, in worst case, for marking & unmarking the edges.
• NMDS Algorithm requires constant time for marking & unmarking the nodes.
• So, NMDS is efficient than EMDS Algorithm.
63
Implementation
• We have implemented our algorithms and the
DODG based algorithm of Zhao.
• Our dynamic slicing tools were coded in C++
and uses compiler writing tools LEX and YACC.
• ESDG is constructed statically.
- adjacency list is used to store ESDG.
• Each element of the list contains a member field
for marking & unmarking the edges (nodes).
64
Implementation (cont …)
• We store the following information along with the
ESDG.
- the set defset(var) for each variable.
- label number of the statement.
- dslice(u) for every node u of ESDG.
65
Experimental Results
Table 1: Avg. Run-Time (in sec)
Sl. No. Prg.
Size
Zhao’s
Alg.
EMDS
Alg.
NMDS
Alg
1 20 0.58 0.32 0.32
2 39 1.12 0.54 0.52
3 62 1.98 0.95 0.92
4 81 2.78 1.32 1.28
5 102 3.82 1.64 1.61
66
Experimental Results (cont…)
Table 2: Slice Extraction ime (in ms)
Sl. No. Prg.
Size
Zhao’s
Alg.
EMDS
Alg.
NMDS
Alg.
1 20 4 1 1
2 39 19 1 1
3 62 32 1 1
4 81 48 1 1
5 102 74 2 2
67
Experimental Analysis
• The avg. run-time for Zhao’s algorithm is more
than our algorithms and increases rapidly as the
program size increases.
• This is due to the fact that, in Zhao’s algorithm
separate vertices are created at run-time for
different executions of the same statement.
• A DFS is performed on the graph.
68
Experimental Analysis (cont …)
• The slice extraction time for Zhao’s algorithm is
more than our algorithms and increases rapidly
as the program size increases.
• This is due to the fact that, in Zhao’s algorithm
the dynamic slice is computed only after the
whole program is executed.
• In our algorithms, the dynamic slice is computed
immediately after each statement is executed.
• So, our algorithms are efficient than Zhao’s alg.
69
Dynamic Slicing of Concurrent OOPs
• Many of the real life programs are concurrent which run on different nodes connected to a N/W
• Debugging of concurrent OOPs are much harder compared to sequential programs due to:
- non-deterministic nature
- lack of global states
- synchronization dependence
- multiple threads of control
- dynamically varying no.of processes
• No algorithm exists for dynamic slicing of concurrent OOPs
Dynamic Slicing of Concurrent OOPs
• Many of the real life programs are concurrent which run on different nodes connected to a N/W
• Debugging of concurrent OOPs are much harder compared to sequential programs due to:
- non-deterministic nature
- lack of global states
- synchronization dependence
- multiple threads of control
- dynamically varying no.of processes
• No algorithm exists for dynamic slicing of concurrent OOPs
Concurrent System Dependence
Graph (CSDG)
• A CSDG of a concurrent OOP is a directed
graph (NC, EC), where each node n NC
represents a statement. x, y NC, (y,x) EC,
iff one of the following holds:
- y is control dependent on x.
- y is data dependent on x.
- y is synchronization dependent on x.
- y is communication dependent on x.
Class Thread1 extends Thread {
private SyncObject O;
private CompObject C;
void Thread1(SyncObject O, CompObject a1,
CompObject a2, CompObject a3)
{
this.O=O;
this.a1=a1;
this.a2=a2;
this.a3=a3;
}
1. public void run() {
2. a2.mul(a1,a2); //a2=a1*a2
3. O.notify();
4. a1.mul(a1,a3); //a1=a1*a3
5. O.wait();
6. a3.mul(a2,a2); //a3=a2*a2
}
}
class Thread2 extends Thread {
private SyncObject O;
private CompObject C;
void Thread1(SyncObject O, CompObject a1,
CompObject a2, CompObject a3)
{
this.O=O;
this.a1=a1;
this.a2=a2;
this.a3=a3;
}
7 public void run() {
8 O.wait();
9 a2.mul(a1,a1);
10 O.notify();
11 if(a1=a2)
12 a3.mul(a2,a1);
else
13 a2.mul(a1,a1);
}
}
14 class example {
15 public static void main(mstring[] argm) {
CompObject a1,a2,a3;
SyncObject o1;
O1.reset();
16 a1=new CompObject(Integer.ParseInt(argm[0]);
17 a2=new CompObject(Integer.parseInt(argm[1]);
18 a3=new CompObject(Integer.ParseInt(argm[2]);
19 Thread t1=new Thread(o1,a1,a2,a3);
20 Thread t2=new Thread(o1,a1,a2,a3);
21 t1.start();
22 t2.start();
}
}
Example
Some Definitions
• Def(var). Let var be a variable in the program P.
A node x is said to be a Def(var) node if x
represents a definition stmt that defines var.
• Use(var). A node x is said to be a Use(var) node
if it uses the variable var.
• RecentDef(var). For each variable var,
RecentDef(var) represents the node (the label
no. of the stmt) corresponding to the most
recent definition of the variable var.
Example
Class Thread1 extends Thread {
private SyncObject O;
private CompObject C;
void Thread1(SyncObject O, CompObject a1, CompObject a2,
CompObject a3)
{
this.O=O;
this.a1=a1;
this.a2=a2;
this.a3=a3;
}
1. public void run() {
2. a2.mul(a1,a2); //a2=a1*a2
3. O.notify();
4. a1.mul(a1,a3); //a1=a1*a3
5. O.wait();
6. a3.mul(a2,a2); //a3=a2*a2
}
}
class Thread2 extends Thread {
private SyncObject O;
private CompObject C;
void Thread1(SyncObject O, CompObject a1, CompObject a2,
CompObject a3)
{
this.O=O;
this.a1=a1;
this.a2=a2;
this.a3=a3;
}
7 public void run() {
8 O.wait();
9 a2.mul(a1,a1);
10 O.notify();
11 if(a1=a2)
12 a3.mul(a2,a1);
else
13 a2.mul(a1,a1);
}
}
14 class example {
15 public static void main(mstring[] argm) {
CompObject a1,a2,a3;
SyncObject o1;
O1.reset();
16 a1=new CompObject(Integer.ParseInt(argm[0]);
17 a2=new CompObject(Integer.parseInt(argm[1]);
18 a3=new CompObject(Integer.ParseInt(argm[2]);
19 Thread t1=new Thread(o1,a1,a2,a3);
20 Thread t2=new Thread(o1,a1,a2,a3);
21 t1.start();
22 t2.start();
}
}
CPDG of the Example Program
14 15
16
17
18
20
19
21
22
1
2
7
12
13
111098
6543
Control dependence edge
Data Dependence edge
Sync. Dependence edge
Comm. Dependence edge
MBDS Algorithm
• Let (u, x1), … (u, xk) be the marked outgoing
dependence edges of u in the CPDG. Then,
the dynamic slice w.r.t.present execution of u ,
for variable var, is given by
Dynamic_Slice(u, var) = {x1 … xk} Dynamic_Slice(u, x1 )
… Dynamic_Slice(u, xk)
MBDS Algorithm (cont.)
• Let var1, …, vark be the variables defined or
used at statement u. Then, we define the
dynamic slice of the whole statement u, as
dyn_slice(u) = Dynamic_Slice(u, var1 ) … Dynamic_Slice(u, vark)
MBDS Algorithm (cont.)
• Our Algorithm operates in 3 main stages:
- Constructing the intermediate representation
- Managing the CPDG at run-time
- Computing the dynamic slice
Algorithm
Stage – 1. Constructing the Intermediate Representation1. CPDG Construction
(a) Adding control dependence edges
for each test(predicate) node u do
for each node x in the scope of u do
Add control dependence edge (x,u) and mark it.
(b) Adding data dependence edges
for each node x do
for each variable var used at x do
for each reaching definition u of var do
Add data dependence edge (x,u) and unmark it.
(c) Adding synchronization dependence edges
for each wait( ) node x do
for the corresponding notify( ) node u do
Add synchronization dependence edge (x,u) and unmark it.
(d) Adding communication dependence edges
for each Use(var) node x do the following
for each Def(var) node u do the following
Add communication dependence edge (x,u) and unmark it.
Stage-2. Managing the CPDG at run-time
1. Initialization: Do the following before execution of the program P
(a) Set Dynamic_slice(stmt, var) = for every variable var used or defined at every node u of the CPDG
(b) Set RecentDef(var) = NULL for every variable var of the program P.
2. Runtime Updations: Run the program and carry out the following after each statement u of the program P is executed.
(a) Unmark all outgoing marked dependence edges excluding the control dependence edges, if any, associated with the variable var,
corresponding to the previous execution of the node u.
(b) Updating data dependencies:For every variable var used at node u,
mark the data dependence edge corresponding to the most
recent definition RecentDef(var) of the variable var.
(c) Updating synchronization dependencies: If u is a wait( ) node,
then mark the outgoing synchronization dependence edge
corresponding to the associated notify( ) node.
(d) Updating communication dependencies: If u is a Use(var) node,
then mark the outgoing communication dependence edge, if any,
corresponding to the associated Def(var) node.
(e) Updating dynamic slice for different dependencies:
i. Handling data dependency:
Let {(u, d1), … (u, dj)} be the set of marked outgoing data
dependence edges from u.Then,
dyn_slice(u) = {d1, … ,dj} dyn_slice(d1) dyn_slice(dj).
ii. Handling control dependency:
Let (u,c) be the marked control dependence edge. Then, dyn_slice(u) = dyn_slice(u) {c} dyn_slice(c)
iii. Handling synchronization dependency:
Let u be a wait( ) node and (u,z) be the marked synchronization
dependence edge associated with the corresponding notify( )
node z. Then
dyn_slice(u) = dyn_slice(u) {z} dyn_slice(z)
iv. Handling communication dependency:
Let u be a Use(var) node and (u,s) be the marked communication dependence edge associated with the corresponding Def(var)
node s. Then,
dyn_slice(u) = dyn_slice(u) {s} dyn_slice(s)
Stage-3. Computing Dynamic Slice
1. For every variable var used at node u , do the following
Dynamic_Slice(u, var) = {d, z, t, c} dyn_slice(d) dyn_slice(z)
dyn_slice(t) dyn_slice(c).
where (u, d) represents a marked data dependence edge
(u, z) represents a marked sync. dependence edge
(u, t) represents a marked control dependence edge
(u, c) represents a marked communication dependence edge
Working of the Algorithm
• The updated CPDG is obtained after applying
stage 2 of our algorithm.
• Let the input data be argm[0] = 1, argm[1] = 1,
and argm[2] = 2.
• Let us compute the dynamic slice for slicing
criterion <6, a3>.
• All the control edges are marked.
• Sync. Dep. Edges (5,10) & (8,3) are marked.
• Comm. Dep. Edge (6,9) is also marked.
Updated CPDG of the Example Program
14 15
16
17
18
20
19
21
22
1
2
7
12
13
111098
6543
Control dependence edge
Data Dependence edge
Sync. Dependence edge
Comm. Dependence edge
Slice point
Working of the Algorithm (cont.)
• According to our algorithm, dynamic slice at
statement 6, is given by
Dynamic_Slice(6, a3) = {1, 5, 9} dyn_slice(1) dyn_slice(5)
dyn_slice(9).
• The vertices included in the dynamic slice are
shown as shaded vertices.
Implementation
• We have implemented our algorithm by using 4
modules:
- dependency updation module
- slice computation module
- slice updation module
- GUI module
Schematic representation of the
working of the slicer
Slicing of Distributed OOPs
• Many of the real life programs are concurrent which run on different nodes connected to a N/W
• Debugging of concurrent OOPs are much harder compared to sequential programs due to:
- non-deterministic nature
- lack of global states
- synchronization dependence
- multiple threads of control
- dynamically varying no.of processes
Our Dynamic Slicing Algorithm
• We propose an algorithm
- parallel dynamic slicing (PDS)
algorithm for distributed OOPs.
• We have used Distributed Program Dependence Graph (DPDG) as intermediate representation.
• Based on marking & unmarking the edges of the DPDG as and when the dependencies arise & cease during run-time.
Some Definitions
• Distributed Prg. A Distributed Prg P=(P1,…, Pn) is a collection of concurrent prgs Pi, s.t. each of the Pi’s communicate through reception and transmission of messages.
• Def(var). Let var be a variable in the program P. A node x is said to be a Def(var) node if x represents a definition stmt that defines var.
• Use(var). A node x is said to be a Use(var) node if it uses the variable var.
• RecentDef(var). For each variable var, RecentDef(var) represents the node (the label no. of the stmt) corresponding to the most recent definition of the variable var.
Definitions (cont.)
• In dist. programs, communication dependency
may exist between processes running on
different machines.
• A msgrcv() call executed on one m/c, might have
a pairing msgsnd() on some remote m/c.
• To incorporate this paradigm, we introduce a
logical(dummy) node in the DPDG.
• We call this logical node as a C-node.
C-node
• C-Node. Let x be a send node and y be the corr.
receive node. A C-node represents a logical
connection of the node y of a DPDG with the
node x of a remote DPDG.
• The node x is the pairing send for a receive call
at the node y.
• y is communication dependent on x.
• We represent C-node of x as C(x).
C-node (cont.)
• For every receive stmt in sub-program Pi, a
dummy node C(x) is made.
• A dummy communication edge (x, c(x)) is
added.
• The C-node contains the following information:
- process id of the sending node
- label no. of the sending node
- dynamic slice at the sending node
Distributed Program Dependence
Graph (DPDG)
• A DPDG of a distributed OOP is a directed
graph (NC, EC), where each node n NC
represents a statement & x, y NC, (y,x) EC,
iff one of the following holds:
- y is control dependent on x.
- y is data dependent on x.
- y is synchronization / fork dependent on x.
- y is communication dependent on x.
An Example Client Program
DPDG of Client Program
An Example Server Program
DPDG of Server Program
Consumer Program
Producer Programs
DPDG of First-Producer Program
DPDG of Second-Producer Program
PDS Algorithm
• Let (x1,u), … (xk,u) be the marked dependence
edges of u in the DPDG. Then, the dynamic
slice w.r.t.present execution of u, for variable var
in process p, is given by
Dynamic_Slice(p, u, var)={(p,x1), …(p,xk)} Dynamic_Slice(p, x1,var
)
… Dynamic_Slice(p, xk,var)
PDS Algorithm (cont.)
• Let var1, …, vark be the variables defined or
used at statement u. Then, we define the
dynamic slice of the whole statement u, as
dyn_slice(p, u) = Dynamic_Slice(p, u, var1 ) … Dynamic_Slice(p, u, vark)
PDS Algorithm (cont.)
• Our Algorithm operates in 3 main stages:
- Constructing the intermediate representation
- Managing the DPDG at run-time
- Computing the dynamic slice
Algorithm
Stage – 1. Constructing the Intermediate Representation1. DPDG Construction
(a) Adding control dependence edges
for each predicate node u do
for each node x in the scope of u do
Add control dependence edge (u,x) and mark it.
(b) Adding data dependence edges
for each node x do
for each variable var used at x do
for each reaching definition u of var do
Add data dependence edge (u,x) and unmark it.
(c) Adding synchronization / fork dependence edges
for each wait( ) node x do
for the corresponding notify( ) node u do
Add synchronization dependence edge (u,x) and unmark it.
(d) Adding communication dependence edges
for each receive(getInputStream()) node x do the following
Add one C-node C(x)
Add communication dependence edge (C(x),x) and unmark it.
Stage-2. Managing the DPDG at run-time
1. Initialization: Do the following before execution of each subprogram Pi
(a) Set Dynamic_slice(stmt, var) = for every variable var used or defined at every node u of the DPDG
(b) Set RecentDef(var) = NULL for every variable var of the program P.
2. Runtime Updations: Run the program and carry out the following after each statement (p,u) of the sub-program Pi is executed.
(a) Unmark all marked dependence edges excluding the control dependence edges, if any, associated with the variable var,
corresponding to the previous execution of the node u.
(b) Updating data dependencies:For every variable var used at node u,
mark the data dependence edge corresponding to the most
recent definition RecentDef(var) of the variable var.
(c) Updating synchronization dependencies: If u is a wait( ) node,
then mark the synchronization dependence edge
corresponding to the associated notify( ) node.
(d) Updating communication dependencies: If u is a receive node,
then mark the communication dependence edge, if any,
corresponding to the associated C-node.
(e) Updating dynamic slice for different dependencies:
i. Handling data dependency:
Let {(d1,u), … (dj,u)} be the set of marked data dependence edges
to node u.Then,
dyn_slice(p,u) = {d1,.. ,dj} dyn_slice(p,d1) dyn_slice(p,dj).
ii. Handling control dependency:
Let (c, u) be the marked control dependence edge. Then, dyn_slice(p,u) = dyn_slice(p,u) {(p,c)} dyn_slice(p,c)
iii. Handling synchronization dependency:
Let u be a wait( ) node and (z,u) be the marked synchronization
dependence edge associated with the corresponding notify( )
node z. Then
dyn_slice(p,u) = dyn_slice(p,u) {(p,z)} dyn_slice(p,z)
iv. Handling communication dependency:
Let u be a receive node and (C(u),u) be the marked
communication dependence edge associated with the
corresponding C-node C(u). Then,
dyn_slice(p,u) = dyn_slice(p,u) {(p,C(u))} dyn_slice(p,C(u))
Stage-3. Computing Dynamic Slice
1. For every variable var used at node u , do the following
Dynamic_Slice(p, u, var) = {d, z, t, c} dyn_slice(p,d)
dyn_slice(p,z) dyn_slice(p,t) dyn_slice(p,c).
where (d, u) represents a marked data dependence edge
(z, u) represents a marked sync. dependence edge
(t, u) represents a marked control dependence edge
(c, u) represents a marked communication dependence edge
Working of the Algorithm
• The updated DPDG is obtained after applying stage 2 of
our algorithm.
• Let the thread-IDs of the clthd be 1001, thread1 be 2001
and thread2 be 2002.
• Let us compute the dynamic slice at w.r.t var q at stmt 23
of clthd.
• This gives us the slicing criterion <1001, 23, q>
• During the initialization step, we unmark all the edges &
sets Dynamic_Slice<p, u, var>= .
• The algorithm marked the edges when the resp.
dependencies arose.
Working of the Algorithm (contd…)
• The marked edges are shown in the Fig.
• According to our algorithm the dynamic slice for
variable q at statement 23, is
Dynamic_slice(1001,23,q)={(1001,21),(1001,6)} U
dyn_slice(1001,21) U dyn_slice(1001,6)
• Evaluating the expression, we get the final
dynamic slice.
• The statements included in the slice are shown
as shaded vertices in the figure.
Working of the Algorithm (contd…)
• The updated DPDG is obtained after applying stage 2 of our algorithm.
• Let the PIDs be 9179 & 9184 resp. representing the if-part & else-part of consumer program.
• The PIDs for first-producer prg be 7639 & 7790 & for second-producer prg be 7890 & 7566.
• Let us compute the dynamic slice for slicing criterion <9184, 14, b> for a=1 & b=1.
• All the control edges are marked.
• The updated DPDG is shown in the figure.
• The vertices {1.6, 3.1, 3.3, 3.5, 2.4, 2.5, 2.6} are included in the slice.
Modification for Non-DSM Systems
• A distributed system having no support for shared memory reduces to a message passing system.
• We call it as a non-DSM system.
• In order to handle non-DSM systems, we have introduced a new type of node, R-node, in the DPDG.
• Because of addition of these logical (dummy) nodes in the DPDG, the above algorithm is updated by adding the functionality for handling of these R-nodes.
Modification for non-DSM Systems
(cont.)
• The existence of R-nodes in the DPDG depends on how we are maintaining the most recent information on shared variables.
• We have already discussed extensively how the C-nodes are incorporated in the DPDG.
• The R-nodes are handled in the similar manner for shared variables in non-DSM systems.
Modification for non-DSM Systems
(cont.)
• The modifications to be done in the above algorithm to incorporate the use of R-nodes involve the following steps:
• Stage-1: DPDG Construction
For each shared variable var used at u, do
Add a R-node R(u)
Add data dependence edge (u, R(u)) and unmark it.
• Stage-2: Managing the DPDG at Run-Time
Update shared data dependencies: For every shared variable
var used at node (p,u), mark the data dependence edge corr. to
the most recent definition recentDef(p,var) available at the R-node of var.
Updated consumer program
Updated first-producer DPDG
Updated second-producer DPDG
Implementation
• We have implemented our algorithm by using 4
modules:
- dependency updation module
- slice computation module
- slice updation module
- GUI module
Advantages
• Existing techniques use trace files to store the execution history, in computing dynamic slices.
• Our algorithm does not use any trace file.
• Our algorithm does not require any new nodes to be created and added to the intermediate graphs at run time.
• This saves the expensive node creation & file I/o steps.
Slicing of AOPs
• A-O features should be considered.
• Technique is like that of OO slicing.
124
Computing Dynamic Slices of Aspect-Oriented
Programs
• Gregor Kiczales and his team at Xerox PARC
originated the concept of Aspect Oriented Programming
(AOP).
• Aspect-oriented programming is a new programming
technique proposed for cleanly modularizing the cross-
cutting structure of concerns such as exception
handling, synchronization, security and resource
sharing.
• An "aspect" is an "area of concern" that cuts across the
structure of a program.
• The main idea behind aspect-oriented programming
125
Fundamental goal of AOP
•Allow for the separation of concerns as appropriate for
a host language.
•Provide a mechanism for the description of concerns
that crosscut other components.
126
AOP Vs. OOP
•Similarities- AOP utilizes advantages of OOP
AOP and OOP both use objects
Objects combine the behavior and data of a
concern into a single physical entity
•Differences- handling of cross-cutting concerns
OOP tries to push the scattered code for these
concerns up in the inheritance tree
This is often not possible and results in tangled
code
AOP collects scattered concerns into a single class
structure
127
Benefits of AOP
•It improves performance because the operations are
more succinct
•It allows programmer to spend less time rewriting the
same code
•Separation of Concerns
AOP makes it possible to encapsulate cross-cutting
concerns
128
Benefits of AOP (Cont.)
•Simpler System Evolution
Join points allow changes to programs to be
incorporated simply with aspects
•Reuse
Aspects can often be reused in other programs with
only slight modifications
129
An Example AspectJ Program
130
Algorithm: Trace file Based algorithm
1.Creation of execution trace file: To
create an execution trace file, do the
following:
a)For a given input, execute the program
and store each statement s in the order
of execution in a file after it has been
executed.
b)If the program contains loops, then
store each statement s inside the loop
in the trace file after each time it has
been executed.
131
Algorithm: Trace file Based algorithm (Cont.)
c)Add all control dependence edges, data
dependence edges and weaving edges
to these vertices.
3.Computation of dynamic slice: To
compute the dynamic slice over the
DADG, do the following:
a)Perform the breadth-first or depth-first
graph traversal over the DADG taking
any vertex corresponding to the
statement of interest as the starting
132
Working of the Algorithm
Input data: argv[0]=4.
Executed statements in order: 1, 2, 3, 13,
14, 15, 4, 5, 6, 7, 8, 9, 7, 8, 9, 7, 8, 9, 7, 8,
9, 7, 16, 17, 11.
Slicing criterion: < 11, p >.
Breadth-first search algorithm: 11, 17, 8,
16, 7, 8, 9, 7, 13, 5, 9, 7, 8, 9, 9, 3, 2, 4, 7,
8, 9, 1, 15, 7, 6, 14.
133
Execution Trace File
134
Dynamic Aspect-Oriented Dependence Graph (DADG)
135
Dynamic Slice
136
Average Runtime
Sl. No. Prg. Size
(# stmts)
Avg.
Runtime(in
sec.)
1 17 0.11
2 43 0.71
3 69 0.89
4 97 1.07
5 123 1.36
6 245 2.46
7 387 3.96
8 562 5.52
Current Research Directions
• Slicing of OOPs, Concurrent & Distributed
OOPs (dynamic, backward, forward).
• Slicing of AOPs, Concurrent & Distributed
AOPs.
• Slicing of Web Based Applications.
• Conditioned Slicing
• Slicing using Graph Coloring
• Applications such as Testing, Debugging,
Maintenance, Reverse Engg. Etc.
Software Testing using Slicing
• Define a metric for computing the impact /
influence of a
- statement
- method
- class
• Then, design the test cases accordingly.
Conclusion
• Discussed
- the intermediate representation for OOPs.
- static slicing of OOPs.
- dynamic slicing of OOPs.
- dynamic slicing of concurrent OOPs.
- dynamic slicing of distributed OOPs.
- dynamic slicing of AOPs.
• The edge marking algorithms do not use trace files to store the execution history.
• No extra file I/O operation is required.
References
[1] H. Agrawal, R. Demilo and E. Spafford, “Debugging with Dynamic Slicingand Backtracking,”Software- Practice and Experience, Vol.23, No.6, pp.589-616, 1993.
[2] S. Horwitz, T. Reps and D. Binkley, “Interprocedural Slicing UsingDependence Graphs,” ACM Transaction on Programming Language andSystem, Vol.12, No.1,pp.26-60, 1990 .
[3] L. D. Larson and M. J. Harrold, “Slicing Object-Oriented Software,”Proceedings of the18th International Conference on SoftwareEngineering, German, March, 1996.
[4] J. Zhao, J. Cheng and K. Ushijima, “Static Slicing of Concurrent Object-Oriented Programs,” Proceedings of the 20th IEEE Annual InternationalComputer Software and Applications Conference, pp. 312-320, August-1996 .
[5] J. Zhao, “Applying Program Dependence Analysis to Java Software,”Proceedings of the Workshop on Software Engineering and Data baseSystems, International Computer Symposium, pp.162-169, Tainan, Taiwan,December-1998.
[
References
[6] J. Zhao, “Dynamic Slicing of Object-Oriented Programs,” Technical Report,Software Engg.,pp.98-119,Information Processing Society of Japan, May–1998.
[7] K. B. Gallagher and J. R. Lyle, “Using Program Slicing in SoftwareMaintenance,” IEEE Transaction on Software Engineering, Vol.17, No. 8,pp.751-761, 1991.
[8] R. Chatterjee and B.Ryder, “Scalable Flow-sensitive Type Inference forStatically Typed Object-Oriented Languages,” Technical Report DCS-TR-326, Rutgers University, August-1994.
[9] W.Landi, B.Ryder, and S. Zhang, “Interprocedural Modification side effectanalysis with pointer aliasing,” Proceedings of SIGPLAN’93 Conference onProgramming Languages Design and Implementation, pp.56-57, June-1993.
[10] T. Reps, S. Horwitz, M. Sagiv, and D. Rosay, “Speeding up Slicing,”Proceedings of the 2nd ACM Conference on Software Engineering, pp. 11-20, December- 1994.
References
[11] P. Tonella, G.Antoniol, R.Fiutem, and E.Merlo, “Flow Insensitive C++ Pointers and Polymorphism Analysis and it’s Application to Slicing,” Proceedings of the 19th International Conference on Software Engineering, pp. 433-443,May-1997.
[12] J.T.Chan, and W.Yang, “A Program Slicing System for Object-Oriented Programs,” Proceedings of the 1996 International Computer Symposium, Taiwan, Dec-1996.
[13] J.T.Chen, F.J.Wang, and Y.L.Chen, “Slicing Object-Oriented Programs,”Proceedings of the APSEC’97, PP. 395-404, Hongkong, China, December-1997.
[14] A.Krishnaswamy, “Program Slicing: An Application of Object-Oriented Program Dependency Graphs,” Technical Report TR94-108, Department of Computer Science, Clemson University, August-1994.
[15] F. Tip, “A Survey on Program Slicing Techniques,” Journal of ProgrammingLanguages, Vol.3, No.3, pp.121-189, September-1995.
References
16]D. Goswami and R. Mall, “An Efficient Method for Computing Dynamic
Program Slices,” Information Processing Letters, Vol.81, pp.111-117, 2002.
[17]M. Weiser, “Programmers Use Slices When Debugging,” Communications
of the ACM, Vol.25, pp.446-452, 1982.
[18]R. Mall, Fundamentals of Software Engineering, Prentice-Hall, India, 1999.
[19]A. Aho, R.Sethi, J.Ullman, Compilers, Principles and Techniques, Addison-
Wesley,1986.
[20]G. B. Mund, R. Mall and S. Sarakar “An Efficient Technique for Dynamic
Slicing of Programs,” Information and Software Technology, March, 2002.
Thank You