1 / 40

400 likes | 544 Vues

Static Analysis of Aspects. Evgeniy Gabrilovich http://www.cs.technion.ac.il/~gabr CS Department, Technion. Problems with AOP. Aspect applicability is usually decided dynamically Matching join points with pointcut designators incurs s ignificant run-time overhead

Télécharger la présentation
## Static Analysis of Aspects

**An Image/Link below is provided (as is) to download presentation**
Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.
Content is provided to you AS IS for your information and personal use only.
Download presentation by click this link.
While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.
During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

**Static Analysis of Aspects**Evgeniy Gabrilovich http://www.cs.technion.ac.il/~gabr CS Department, Technion Static Analysis of Aspects**Problems with AOP**• Aspect applicability is usually decided dynamically • Matching join points with pointcut designators incurs significant run-time overhead • Multiple pieces of advice may apply at the same program point Programs are difficult to maintain and debug ComposeJ, JasCo/JAC Static Analysis of Aspects**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 Static Analysis of Aspects**Outline**• New syntax for pointcut designators • Running example • Compiling aspects in AspectJ • Static analysis • Running example revisited • Limitations of the approach • Conclusions Static Analysis of Aspects**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 Static Analysis of Aspects**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) Demeter used object graphs Invocation of a procedure at the call site Entry into the procedure’s body Static Analysis of Aspects**Grammar for the language of possible join points**jp ::= jp_element* jp_element ::= call(name, name, actual_param*) | exec name | aexec name Calling context Called procedure Static Analysis of Aspects**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 Static Analysis of Aspects**Profiling Quicksort**• linesbuf is a global variable holding an array of strings Static Analysis of Aspects**Gathering Quicksort statistics**• Count the number of calls to partition • 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 Static Analysis of Aspects**Profiling aspect for Quicksort (1/4)**aspectCounts 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 Static Analysis of Aspects**Profiling aspect for Quicksort (2/4)**advice SCount before: {pcall(swap);{true}*;{pcall(quicksort)};{true}* begin swaps := swaps + 1 end A call to swap within the context of a call to quicksort pcall(swap) /\ cflow(quicksort) Static Analysis of Aspects**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) Static Analysis of Aspects**Profiling aspect for Quicksort (4/4)**advice Print after: {pcall(quicksort)}; {not pcall(quicksort)}* begin println “Partitions: “ ++ partitions; println “Swaps: “ ++ swaps; end endCounts Only matches non-recursive calls to quicksort Static Analysis of Aspects**Example**{pcall(quicksort)}; {not pcall(quicksort)}* main() f() quicksort() X quicksort() Static Analysis of Aspects**More examples**{pcall(swap);{true}*;{pcall(quicksort)};{true}* main() f() quicksort() partition() swap() X main() readln() swap() Static Analysis of Aspects**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 Static Analysis of Aspects**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 Static Analysis of Aspects**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) Static Analysis of Aspects**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 Static Analysis of Aspects**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 Static Analysis of Aspects**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. Static Analysis of Aspects**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 Static Analysis of Aspects**main()**partition() swap() quicksort() SCount Examples {pcall(quicksort)}; {not pcall(quicksort)}* main() quicksort() Init {pcall(swap);{true}*;{pcall(quicksort)};{true}* Static Analysis of Aspects**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 Static Analysis of Aspects**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 Static Analysis of Aspects**Direct (unadvised) path**Advised paths (possibly chaining multiple aspects) Static Analysis of Aspects**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 Static Analysis of Aspects**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 Static Analysis of Aspects**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 Static Analysis of Aspects**main()**partition() swap() quicksort() SCount Examples {pcall(quicksort)}; {not pcall(quicksort)}* main() quicksort() Init {pcall(swap);{true}*;{pcall(quicksort)};{true}* Static Analysis of Aspects**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}* jp_element = call(partition,quicksort,_) quicksort() { … partition(); … } partition() { … } Static Analysis of Aspects**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 Static Analysis of Aspects**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 Static Analysis of Aspects**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)) Static Analysis of Aspects**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 Static Analysis of Aspects**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 Static Analysis of Aspects**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 Static Analysis of Aspects**Bibliography**• D. Sereni and Oege de Moor. “Static Analysis of Aspects”, AOSD 2003 • H. Masuhara, G. Kiczales and C. Dutchyn. “Compilation Semantics of Aspect-Oriented Programs”, FOAL Workshop at AOSD 2002 • M. Wand, G. Kiczales and C. Dutchyn. “A Semantics for Advice and Dynamic Join Points in AOP”, FOAL Workshop at AOSD 2002 • E. Gamma, R. Helm, R. Johnson and J. Vlissides. “Design Patterns”, Addison-Wesley, 1995 • R.E. Tarjan. “Fast Algorithms for Solving Path Problems”, JACM 28(3), 1981 Static Analysis of Aspects**Questions?**Static Analysis of Aspects

More Related