220 likes | 317 Views
Region Pointcut for AspectJ. Shumpei Akai Shigeru Chiba Muga Nishizawa. Background: Synchronization. Granularity of synchronization alters performance Fine-grained: Increase concurrency Coarse-grained: Less overhead Which granularity is better on a given machine?.
E N D
Region Pointcut for AspectJ Shumpei Akai Shigeru Chiba Muga Nishizawa
Background: Synchronization • Granularity of synchronization alters performance • Fine-grained: Increase concurrency • Coarse-grained: Less overhead • Which granularity is better on a given machine?
Motivating example: Javassist public class ProxyFactory { public Class createClass() { if (thisClass == null) { ClassLoader cl = getClassLoader(); synchronized (proxyCache) { if (useCache){createClass2(cl);} else {createClass3(cl);} }} return thisClass;} private voidcreateClass2(ClassLoader cl) { CacheKey key = new CacheKey(…); synchronized (proxyCache) { HashMap cacheForTheLoader =…; if (cacheForTheLoader == null) { cacheForTheLoader = new HashMap(); proxyCache.put(cl, cacheForTheLoader); cacheForTheLoader.put(key, key); }else {...}} synchronized (key) { Class c = isValidEntry(key); if (c == null) { createClass3(cl); key.proxyClass = new WeakReference(…); }else{thisClass = c;} }}} Coarse-grained candidate • A bug report of synchronization for Javassist [http://jira.jboss.org/jira/browse/JASSIST-28] • Adding synchronization to fix the bug. • coarse-grained is chosen in this case. • Separate synchronization code as an aspect • enable choosing appropriategranularity. Fine-grained
Separating synchronization with AOP • New pointcuts are needed • AspectJ provides execution, call, get, set pointcuts • They pick out Join “points”. • But synchronization is applied to a “range” of code. • Join points are not suitable • Need to pick out regions (or pieces of code)
Region pointcut • Regions are treated like join points • Use pattern matching • Static analysis and code transformation • Regions are determined by static analysis. • Extension toAspectJ
region[pc1;pc2;pc3;…] • A new pointcut for a region • Specify a sequence of join points • Find a matching path public void foo() { … obj.criticalSectionBegin();//from here if(…){ a(); } … obj.criticalSectionEnd();//to here …} void around(): region[ call(* *. criticalSectionBegin()); call(* *.a()); call(* *. criticalSectionEnd()); ] { synchronized(someObject){ proceed(); } }
Newpointcut: all() • all(pc1, pc2, pc3, …) • Matches a sequence including the join points all the pointcuts pc1, pc2, pc3, … match in some order. • The order of pointcuts does not matter. • because the order of join points may be changed by refactoring
Example of all() { a(); … b(); … c(); } region[ all( call(* *.a()), call(* *.b()), call(* *.c()) ) ] matches { c(); … b(); c(); … a(); } { b(); … c(); … a(); }
A region mayconflict with a control structure public void foo() { ... for(int i=0;i<100;i++){ bar(); beginCriticalSection(); // begin ... } endCriticalSection(); // end ... } • If aregion intersects a control structure • wecannot weave anaround advice void around(): region[ call(* *. criticalSectionBegin()); call(* *. criticalSectionEnd()) ]{ /* do something*/ }
Region adjustment public void foo() { ... for(int i=0;i<100;i++){ bar(); beginCriticalSection(); // begin ... } endCriticalSection(); // end ... } • Solves the conflict • Expand aselected region: • to fit a control structure • to include the first and the last selected join points • A minimum region satisfying the criteria above is selected
Context passing • Synchronization needs a lock object • Contexts must be available in an advice body • args(), target() are available in a pattern • Specified values must be accessible atthe beginningof the region
Example of context passing … List list = ... ; ... for(int index = 0; i < 100; i++){ beginCriticalSection(); ... Object o=list.get(index); ... endCriticalSection(); } ... pointcut pc(List l,int i) : region[ call(* *.beginCriticalSection()); call(* List+.get(int)) && target(l) && args(i) ; call(* *.endCriticalSection()); ];
Implementation • We implemented by extendingabc • abc:The AspectBench Compiler for AspectJ • Need information, where blocks, control structures and statements start/end • Add new instruction into Jimple
Around advice • In abc, some join points (e.g. execution) are split into static methods to weave anaround advice • Local variables are passed through arguments • We adopt this mechanism • This causes a fewproblems for theregion pointcut advice woven method original method original join point public void toBeAdvised(int x){ a(); b(x); c(); } public static void advice(int x){ beforeJoinPoint(); shadow(x); afterJoinPoint(); } public static shadow(int x){ a(); b(x); c(); } public void toBeAdvised(int x){ advice(x); }
Support an around advice : assignment (problem) public void toBeAdvised(int x){ String s="initial string"; a(); s="string was replaced"; b(); System.out.println(s); // what is the value of s? } • Assignment does not change the value of the local variable • Local variables are replicated. void around(): region[call(* *.a());call(* *.b())] { proceed(); }
Support an around advice : assignment(solution) • Share anobject between theregion and theoriginal method • Each field contains a value of alocal variable public void toBeAdvised(int x){ String s="initial string"; $localStorage = new LocalStorage(); $localStorage.s=s; s=$localStorage.s; a(); s="string was replaced"; b(); $localStorage.s=s; s=$localStorage.s; System.out.println(s); }
Support an around advice : jumps (problem) • Jumps (break or continue) to outside of region are unavailable public void includeJump(){ labelOfFor: for(;;){ a(); if(isFinished()){ break; //goto label0; } b(); } //label0: } void around(): region[call(* *.a());call(* *.b())] { proceed(); }
Support an aroundadvice : jumps (solution) • Transform the bytecode • Share the ID for each jump target • Jump to the tail of the region • After region, check the ID and jump public void includeJump(){ labelOfFor: for(;;){ a(); if(isFinished()){ $i=0; goto endLabel; } b(); endLabel: switch($i){ case 0: goto label0; } } label0: }
Applying to Javassist (coarse-grained) • Fixed Javassist’s synchronization problemusing region pointcut static WeakHashMap proxyCache; public Class createClass() { if (thisClass == null) { ClassLoader cl = …; if (useCache) createClass2(cl); else createClass3(cl); } return thisClass;} void around(): region[ get(static boolean *.useCache); call(* *.createClass2(..)); ] { synchronized(ProxyFactory.class) { proceed(); } }
Applying to javassist (fine-grained) static WeakHashMap proxyCache; private void createClass2(ClassLoader cl) { CacheKey key =…; HashMap cacheForTheLoader = (HashMap)proxyCache.get(cl); if (cacheForTheLoader == null) { proxyCache.put(...); }else{...} void around(): region[ call(* WeakHashMap.get(..)); call(* WeakHashMap.put(..)); ]{ synchronized( ProxyFactory.proxyCache){ proceed(); }}
Related work • Tracematch [Allan et al. ’05] • History-based pointcut • Dynamic pattern matching with execution history • LoopsAJ [Harbulot et al. ’06] • Picking out loops
Conclusion • Region pointcut: • Picks out regions as join points • We extended abc • Solved some design issues to weave an around advice • Work in progress • Formalize thepattern matching semantics using hedge automata • Case study