You are on page 1of 144

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 have
affected the variable at a program point.
• Forward Slice: Statements that might be
affected 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.
1 class Elevator {
Example
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.)
Class Base{ m1(){ C(Base &ba){

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; } Slice
} ba.m1();
m2 (int i){ ba.m2(1); main1()
b=b+i; o.m2(1);
} } o. m2(1)
o.Base()
A1-in: a-in=a
A2-in: b-in=b A3-in A2-in A2-
A3-in: I-in=1 out
A1-out: a= a-out A2- A1-
out out
A2-out: b=b-out ba.base(
)

Control dependence edge A1- ba. ba.


A2-
out m1() m2(1)
out

Data dependence edge

Summary edge. A2-in A1-in A1- A2- A3-in A2-in A2-


out out out
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.
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.

44
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)

45
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 edges
corresponding 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)

46
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

47
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

48
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

49
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.

50
Example
1 class Elevator { 23 class AlarmElevator : public Elevator {
public public
2 Elevator(int1_top_floor) 24 AlarmElevator ( int top_floor)
3 {current_floor = 1; 25 Elevator (top_floor)
4 current_direction = UP; 26 {alarm_on = 0;}
5 top_floor = 1_top_floor; } 27 void set_alarm( )
6 virtual ~Elevator 28 {alarm_on = 1;}
7 void up( ) 29 void reset_alarm( )
8 {current_direction = UP;} 30 {alarm_on = 0;}
9 void down( ) 31 void go (int floor)
10 int which_floor( ) 32 { if (!alarm_on)
11 {current_direction = DOWN;} 33 Elevator :: go (floor)
12 {return current_floor; } };
13 Direction direction( ) protected:
14 {return current_direction; } int alarm_on;
15 virtual void go(int floor ) };
16 {if (current_direction = =UP) 34 main( int argc, char **argv) {
17 {while(current_floor != floor) Elevator *e_ptr;
&& (current_floor < = top_floor) 35 If (argv[1])
18 add(current_floor, 1); } 36 e_ptr = new Elevator (10);
else else
19 {while(current_floor != floor) && (current_floor > 0) 37 e_ptr = new AlarmElevator (10);
20 add(current_floor, -1); } 38 e_ptr - > go(5);
} 39 c_out << “\n currently on floor :” << e_ptr -> which_floor ( );
private: }
21 add(int &a, const int &b)
22 { a = a + b; }
protected:
int current_floor;
Direction current_direction
int top_floor; };
51
CLDG for Elevator

52
ESDG of the Example Program

53
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.

54
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.

55
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)

56
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.
57
ESDG of the Example
58
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.

59
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

60
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

61
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.

62
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).

63
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.

64
Experimental Results
Table 1: Avg. Run-Time (in sec)

Sl. No. Prg. Zhao’s EMDS NMDS


Size Alg. Alg. 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


65
Experimental Results (cont…)
Table 2: Slice Extraction ime (in ms)

Sl. No. Prg. Zhao’s EMDS NMDS


Size Alg. Alg. 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
66
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.

67
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.

68
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

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
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;
Example
void Thread1(SyncObject O, CompObject a1,
CompObject a2, CompObject a3)
{
this.O=O;
this.a1=a1;
this.a2=a2;
this.a3=a3;
} 14 class example {
1. public void run() { 15 public static void main(mstring[] argm) {
2. a2.mul(a1,a2); //a2=a1*a2 CompObject a1,a2,a3;
3. O.notify(); SyncObject o1;
4. a1.mul(a1,a3); //a1=a1*a3 O1.reset();
5. O.wait(); 16 a1=new CompObject(Integer.ParseInt(argm[0]);
6. a3.mul(a2,a2); //a3=a2*a2 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);
class Thread2 extends Thread {
20 Thread t2=new Thread(o1,a1,a2,a3);
private SyncObject O;
private CompObject C; 21 t1.start();
void Thread1(SyncObject O, CompObject a1, 22 t2.start();
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);
}
}
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

21 1

19 2 3 4 5 6

16
14 15
17
13
18

8 9 10 11
20

Control dependence edge


12
Data Dependence edge
22 7
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 Representation
1. 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

21 1
Slice point

19 2 3 4 5 6

16
14 15
17
13
18

8 9 10 11
20

Control dependence edge


12
Data Dependence edge
22 7
Sync. Dependence edge

Comm. Dependence edge


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 Representation
1. 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.
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.
124
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.

125
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 126
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
127
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

128
An Example AspectJ Program

129
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 has130
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 131
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,
132
Execution Trace File

133
Dynamic Aspect-Oriented Dependence Graph (DADG)

134
Dynamic Slice

135
Average Runtime

Sl. No. Prg. Size Avg.


(# stmts) 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
136
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 Slicing
and Backtracking,”Software- Practice and Experience, Vol.23, No.6, pp.589-
616, 1993.
[2] S. Horwitz, T. Reps and D. Binkley, “Interprocedural Slicing Using
Dependence Graphs,” ACM Transaction on Programming Language and
System, 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 Software
Engineering, German, March, 1996.
[4] J. Zhao, J. Cheng and K. Ushijima, “Static Slicing of Concurrent Object-
Oriented Programs,” Proceedings of the 20th IEEE Annual International
Computer 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 base
Systems, 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 Software
Maintenance,” IEEE Transaction on Software Engineering, Vol.17, No. 8,
pp.751-761, 1991.
[8] R. Chatterjee and B.Ryder, “Scalable Flow-sensitive Type Inference for
Statically Typed Object-Oriented Languages,” Technical Report DCS-TR-
326, Rutgers University, August-1994.
[9] W.Landi, B.Ryder, and S. Zhang, “Interprocedural Modification side effect
analysis with pointer aliasing,” Proceedings of SIGPLAN’93 Conference on
Programming 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 Programming
Languages, 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

You might also like