December 5, 2004 Seminar on Aspect-Oriented Software Development (236800) Static Analysis of Aspects...

40
Seminar on Aspect- Oriented Software Development (236800) Static Analysis of Aspects December 5, 2004 Static Analysis of Aspects Evgeniy Gabrilovich http://www.cs.technion.ac.il/ ~gabr CS Department, Technion
  • date post

    20-Dec-2015
  • Category

    Documents

  • view

    213
  • download

    0

Transcript of December 5, 2004 Seminar on Aspect-Oriented Software Development (236800) Static Analysis of Aspects...

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Static Analysis of Aspects

Evgeniy Gabrilovich

http://www.cs.technion.ac.il/~gabr

CS Department, Technion

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Problems with AOP

1. Aspect applicability is usually decided dynamically

– Matching join points with pointcut designators incurs significant run-time overhead

2. Multiple pieces of advice may apply at the same program point Programs are difficult to maintain and debug

ComposeJ, JasCo/JAC

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

60 seconds about Dynamic Matching

• Aspect code monitors the execution of the base program

• Certain (sequences of) events trigger the aspect code (aka advice)– Monitored events are defined as patterns in

the call stack– An aspect can be applied recursively,

monitoring its own execution

• Dynamic matching is expensive !

Observer Pattern

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Outline

• New syntax for pointcut designators

• Running example

• Compiling aspects in AspectJ

• Static analysis

• Running example revisited

• Limitations of the approach

• Conclusions

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Reminder: Join points and pointcuts in AspectJ• Join point – a machine configuration

where advice might intervene

• Pointcut – a set of join points where a given advice should be executed– Examples: call(…), execution(…),

cflow(…), cflowbelow(…)– Complex pointcuts use boolean operators:

•!p, p1 || p2, p1 && p2

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

New syntax – regular expressions over control stack

• Intuition: join points as abstractions over control stack– modeling the sequence of procedure calls as

a graph

• A join point is a sequence of– Procedure calls (call)– Procedure executions (exec)– Advice executions (aexec)

Invocation of a procedure at the call site

Entry into the procedure’s body

Demeter used object

graphs

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Grammar for the language of possible join points

jp ::= jp_element*

jp_element ::= call(name, name,

actual_param*)

| exec name

| aexec name

Called procedure

Calling context

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Pointcut designators (PCDs)

• Regular expressions over an alphabet of element designators:ed ::= pcall pname

| pwithin name

| args var*

| ed or ed

| ed and ed

| not ed

| true

Matches join point elements of the form call(n,_,_)

Matches calls made from the context n: call(_,n,_)

args(x1,…,xn) matches call(_,_,[a1,…,an]), binding xi to ai

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Profiling Quicksort

• linesbuf is a global variable holding an array of strings

compare(i,j) returns true if linesbuf[i] < linesbuf[j]

swap(i,j) swaps lines i and j

readln(i) reads a line into linesbuf[i]

writeln(i) prints linesbuf[i]

partition(a,b) partitions linesbuf[a..b) with pivot linesbuf[a]

quicksort(a,b) sorts linesbuf[a..b)

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Gathering Quicksort statistics

1. Count the number of calls to partition2. Count the number of swap operations

• Note that– there may be other uses of swap apart from

the obvious ones within the partition routine– both swap and partition may also be used

outside quicksort

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Profiling aspect for Quicksort (1/4)

aspect Counts

var swaps, partitions: int;

advice PCount

before: {pcall(partition) /\ pwithin(quicksort)}; {true}*

begin

partitions := partitions + 1

end

Top of the call stack

A call to partition from the body of

quicksort

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Profiling aspect for Quicksort (2/4)

advice SCount

before: {pcall(swap);{true}*;{pcall(quicksort)};{true}*

begin

swaps := swaps + 1

endA call to swap within the context of a call

to quicksort

pcall(swap) /\ cflow(quicksort)

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Profiling aspect for Quicksort (3/4)

advice Init

before: {pcall(quicksort)}; {not pcall(quicksort)}*

begin

partitions := 0;

swaps := 0

end

Only matches non-recursive calls to

quicksort

pcall(quicksort) /\ not cflowbelow(quicksort)

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Profiling aspect for Quicksort (4/4)

advice Print

after: {pcall(quicksort)}; {not pcall(quicksort)}*

begin

println “Partitions: “ ++ partitions;

println “Swaps: “ ++ swaps;

end

end Counts

Only matches non-recursive calls to

quicksort

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Example

main()

quicksort()

f()

{pcall(quicksort)}; {not pcall(quicksort)}*

quicksort()

X

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

More examples

main()

quicksort()

f()

{pcall(swap);{true}*;{pcall(quicksort)};{true}*

partition()

swap()

main()readln()swap()X

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Interpreting aspects• Localizing the code that gathers quicksort

statistics is nice … provided the run-time cost is negligible

• Dynamic matching– Whenever a new join point is created,

it’s matched against all PCDs– If a match is found, the corresponding advice

is executed, with PCD variables bound in matching

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Interpreting aspects: example• Initialization trigger:

{pcall(quicksort)}; {not pcall(quicksort)}*• To check that a join point satisfies this

PCD, we must traverse the whole join point (= call stack)

• Upon each creation of a new join point, the interpreter may have to traverse the whole join point for each PCD

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

The AspectJ approach

• Each PCD corresponds to a DFA• The compiled program maintains a set of

such automata• Inspecting the automaton state determines

in O(1) whether the corresponding aspect code should be executed

Maintaining these automata is still a significant overhead, proportional to the number of PCDs (= pieces of advice)

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Static analysis of aspects• Our goal:

– Completely eliminate the matching process– Determine for each point in the program

exactly what PCDs will apply at run-time

• Then, a compiler can generate a tangled program that the programmer might have written before aspects were invented

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

The approach• Given the program call graph

– determine for each procedure call the set of all join points possible at that call

– statically determine all matching PCDs

• Perform source-to-source transformation by weaving all applicable advice at compile-time– No PCD matching is needed at run-time! – This is not always possible

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Analysis overview

• Each piece of advice (a) is associated with a PCD (pcd), which denotes a (usually infinite) set of join points: join_points(pcd)

• Advice a is executed if the current join point (= sequence of procedure calls in the call stack) belongs to join_points(pcd)

• For each procedure call p in the program, compute a set L(p) of all possible join points at evaluation of the call p.

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Static analysis by computing language containment

• L(p) is defined as a regular language over the call graph of the program

• join_points(pcd) is a regular language defined by the regular expression of pcd

Then:

• a always applies at p

• a never applies at p

• Otherwise, the analysis is inconclusive

s(pcd)join_point)( pL

s(pcd)join_point)( pL

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Examples {pcall(quicksort)}; {not pcall(quicksort)}*

main()quicksort()

Init

{pcall(swap);{true}*;{pcall(quicksort)};{true}*

main()swap()

quicksort()

partition()

SCount

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Constructing the call graph

• Nodes – procedure calls + aspects

• Edges – join point elements– elementary operations affecting the control

stack

• Join points – sequences of join point elements = paths in the call graph

• L(p) = a set of paths from the source

vertex v (main) to the vertex representing p

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Constructing the call graph (2)• Every path from v to p is a valid join point

at p – although it doesn’t have to occur in actual

program runs – overestimation !

• Every valid join point is represented by a path

• 3 kinds of edges (= join point elements):– procedure calls– procedure executions– advice executions

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Direct (unadvised)

path

Advised paths (possibly chaining multiple aspects)

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Pruning the call graph

• The construction yields a huge call graph with many infeasible edges

• Reducing the graph size by considering the topmost element of the call stack:– PCDs of the form {pcall(f) /\ …}; … can never

apply to a call to procedure g ≠ f

nodes for corresponding advice need not be included for such calls, and may be pruned

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Meet-over-all-paths analysis• Given the source program, construct its

call graph– The set of paths from v to p is a superset of

the set of possible call stacks at point p during program execution

• For each procedure call p– obtain a regular expression L(p)

• Tarjan’s algorithm – O(|E| · log (|V|)

– Test it for inclusion w.r.t. each PCD• O(|E| + |V|)

The set of join points at p

s(pcd)join_point)( pLs(pcd)join_point)( pL

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Analyzing the Quicksort example

• Legend (for a procedure call p and an advice a):– √ - a always applies at p– x – a can never apply at p– (blank) – the analysis is inconclusive

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Examples {pcall(quicksort)}; {not pcall(quicksort)}*

main()quicksort()

Init

{pcall(swap);{true}*;{pcall(quicksort)};{true}*

main()swap()

quicksort()

partition()

SCount

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Quicksort example (cont’d)

• PCount advice is in a sense static – it only depends on the textual location of the call– Only the topmost item of the stack is matched:

{pcall(partition) /\ pwithin(quicksort)}; {true}*

quicksort() {

partition();

}

partition() {

}

jp_element = call(partition,quicksort,_)

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Quicksort example (cont’d)

• The other two PCDs are truly dynamic and depend on the call stack:– {pcall(swap);{true}*;{pcall(quicksort)};{true}* - a call to

swap is within dynamic scope of quicksort– {pcall(quicksort)}; {not pcall(quicksort)}* - a call to

quicksort is not recursive

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Quicksort example (cont’d)

• The analysis was successful for each advice and each procedure call

Dynamic PCDs are in fact static in the context of the base program

Static matching is possible!

• Separation of concerns (sorting per se and profiling) does not sacrifice run-time efficiency

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Limitations of the approach• Static analysis is not always possible for

arbitrary PCDs– Consider a simple procedure f with a single

recursive call to itself– {pcall(f)}; {true}*; {pcall(f)}; {true}*; {pcall(f)}; {true}*;

• recursion depth ≥ 3

– This PCD applies to some – but not all – recursive calls from f to itself

• For example, it does not apply to the first such call

pcall(f) /\ cflowbelow ( pcall(f) /\ cflowbelow(pcall(f))

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Limitations (cont’d)• PCDs cannot make tests that depend on

dynamic values of variables (args)– Otherwise, the matching code cannot be

eliminated – we still must maintain a stack of variable bindings

• The construction of the call graph is complicated by virtual methods– At each virtual method call, we need to

determine what instances might be called– Open issue

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Conclusions

• Primitive language for describing patterns in the call stack using regular expressions

• Meet-over-all-paths analysis enables the compiler to determine aspect applicability statically– Run-time overhead of matching PCDs can be

reduced, and sometimes completely eliminated

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Conclusions (cont’d)

• In practice, static undecidability is limited to a few procedure calls in the program– Large portions of the call graph can still be

woven statically

• In large AO programs, it is important to warn programmers of potential interactions between aspects– Static analysis can detect when different

pieces of advice may both be executed at the same program point

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Bibliography1. D. Sereni and Oege de Moor. “Static Analysis of

Aspects”, AOSD 2003

2. H. Masuhara, G. Kiczales and C. Dutchyn. “Compilation Semantics of Aspect-Oriented Programs”, FOAL Workshop at AOSD 2002

3. M. Wand, G. Kiczales and C. Dutchyn. “A Semantics for Advice and Dynamic Join Points in AOP”, FOAL Workshop at AOSD 2002

4. E. Gamma, R. Helm, R. Johnson and J. Vlissides. “Design Patterns”, Addison-Wesley, 1995

5. R.E. Tarjan. “Fast Algorithms for Solving Path Problems”, JACM 28(3), 1981

Seminar on Aspect-Oriented Software Development (236800)

Static Analysis of Aspects December 5, 2004

Questions?