You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Common Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/cpl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * Alexandre Vasseur support for @AJ aspects
  12. * ******************************************************************/
  13. package org.aspectj.weaver.bcel;
  14. import java.lang.reflect.Modifier;
  15. import java.util.ArrayList;
  16. import java.util.HashMap;
  17. import java.util.Iterator;
  18. import java.util.List;
  19. import java.util.Map;
  20. import org.aspectj.apache.bcel.Constants;
  21. import org.aspectj.apache.bcel.classfile.Field;
  22. import org.aspectj.apache.bcel.generic.ACONST_NULL;
  23. import org.aspectj.apache.bcel.generic.ALOAD;
  24. import org.aspectj.apache.bcel.generic.ANEWARRAY;
  25. import org.aspectj.apache.bcel.generic.ArrayType;
  26. import org.aspectj.apache.bcel.generic.BranchInstruction;
  27. import org.aspectj.apache.bcel.generic.ConstantPoolGen;
  28. import org.aspectj.apache.bcel.generic.DUP;
  29. import org.aspectj.apache.bcel.generic.DUP_X1;
  30. import org.aspectj.apache.bcel.generic.FieldInstruction;
  31. import org.aspectj.apache.bcel.generic.INVOKEINTERFACE;
  32. import org.aspectj.apache.bcel.generic.INVOKESPECIAL;
  33. import org.aspectj.apache.bcel.generic.INVOKESTATIC;
  34. import org.aspectj.apache.bcel.generic.Instruction;
  35. import org.aspectj.apache.bcel.generic.InstructionConstants;
  36. import org.aspectj.apache.bcel.generic.InstructionFactory;
  37. import org.aspectj.apache.bcel.generic.InstructionHandle;
  38. import org.aspectj.apache.bcel.generic.InstructionList;
  39. import org.aspectj.apache.bcel.generic.InstructionTargeter;
  40. import org.aspectj.apache.bcel.generic.InvokeInstruction;
  41. import org.aspectj.apache.bcel.generic.LoadInstruction;
  42. import org.aspectj.apache.bcel.generic.MULTIANEWARRAY;
  43. import org.aspectj.apache.bcel.generic.NEW;
  44. import org.aspectj.apache.bcel.generic.ObjectType;
  45. import org.aspectj.apache.bcel.generic.PUSH;
  46. import org.aspectj.apache.bcel.generic.ReturnInstruction;
  47. import org.aspectj.apache.bcel.generic.SWAP;
  48. import org.aspectj.apache.bcel.generic.StoreInstruction;
  49. import org.aspectj.apache.bcel.generic.TargetLostException;
  50. import org.aspectj.apache.bcel.generic.Type;
  51. import org.aspectj.bridge.IMessage;
  52. import org.aspectj.bridge.ISourceLocation;
  53. import org.aspectj.bridge.Message;
  54. import org.aspectj.weaver.Advice;
  55. import org.aspectj.weaver.AdviceKind;
  56. import org.aspectj.weaver.AjcMemberMaker;
  57. import org.aspectj.weaver.BCException;
  58. import org.aspectj.weaver.IntMap;
  59. import org.aspectj.weaver.Member;
  60. import org.aspectj.weaver.MemberImpl;
  61. import org.aspectj.weaver.NameMangler;
  62. import org.aspectj.weaver.NewConstructorTypeMunger;
  63. import org.aspectj.weaver.NewFieldTypeMunger;
  64. import org.aspectj.weaver.NewMethodTypeMunger;
  65. import org.aspectj.weaver.ResolvedMember;
  66. import org.aspectj.weaver.ResolvedMemberImpl;
  67. import org.aspectj.weaver.ResolvedType;
  68. import org.aspectj.weaver.Shadow;
  69. import org.aspectj.weaver.ShadowMunger;
  70. import org.aspectj.weaver.UnresolvedType;
  71. import org.aspectj.weaver.WeaverMessages;
  72. import org.aspectj.weaver.World;
  73. import org.aspectj.weaver.ast.Var;
  74. /*
  75. * Some fun implementation stuff:
  76. *
  77. * * expressionKind advice is non-execution advice
  78. * * may have a target.
  79. * * if the body is extracted, it will be extracted into
  80. * a static method. The first argument to the static
  81. * method is the target
  82. * * advice may expose a this object, but that's the advice's
  83. * consideration, not ours. This object will NOT be cached in another
  84. * local, but will always come from frame zero.
  85. *
  86. * * non-expressionKind advice is execution advice
  87. * * may have a this.
  88. * * target is same as this, and is exposed that way to advice
  89. * (i.e., target will not be cached, will always come from frame zero)
  90. * * if the body is extracted, it will be extracted into a method
  91. * with same static/dynamic modifier as enclosing method. If non-static,
  92. * target of callback call will be this.
  93. *
  94. * * because of these two facts, the setup of the actual arguments (including
  95. * possible target) callback method is the same for both kinds of advice:
  96. * push the targetVar, if it exists (it will not exist for advice on static
  97. * things), then push all the argVars.
  98. *
  99. * Protected things:
  100. *
  101. * * the above is sufficient for non-expressionKind advice for protected things,
  102. * since the target will always be this.
  103. *
  104. * * For expressionKind things, we have to modify the signature of the callback
  105. * method slightly. For non-static expressionKind things, we modify
  106. * the first argument of the callback method NOT to be the type specified
  107. * by the method/field signature (the owner), but rather we type it to
  108. * the currentlyEnclosing type. We are guaranteed this will be fine,
  109. * since the verifier verifies that the target is a subtype of the currently
  110. * enclosingType.
  111. *
  112. * Worries:
  113. *
  114. * * ConstructorCalls will be weirder than all of these, since they
  115. * supposedly don't have a target (according to AspectJ), but they clearly
  116. * do have a target of sorts, just one that needs to be pushed on the stack,
  117. * dupped, and not touched otherwise until the constructor runs.
  118. *
  119. * @author Jim Hugunin
  120. * @author Erik Hilsdale
  121. *
  122. */
  123. public class BcelShadow extends Shadow {
  124. private ShadowRange range;
  125. private final BcelWorld world;
  126. private final LazyMethodGen enclosingMethod;
  127. private boolean fallsThrough; //XXX not used anymore
  128. // Some instructions have a target type that will vary
  129. // from the signature (pr109728) (1.4 declaring type issue)
  130. private String actualInstructionTargetType;
  131. // ---- initialization
  132. /**
  133. * This generates an unassociated shadow, rooted in a particular method but not rooted
  134. * to any particular point in the code. It should be given to a rooted ShadowRange
  135. * in the {@link ShadowRange#associateWithShadow(BcelShadow)} method.
  136. */
  137. public BcelShadow(
  138. BcelWorld world,
  139. Kind kind,
  140. Member signature,
  141. LazyMethodGen enclosingMethod,
  142. BcelShadow enclosingShadow)
  143. {
  144. super(kind, signature, enclosingShadow);
  145. this.world = world;
  146. this.enclosingMethod = enclosingMethod;
  147. fallsThrough = kind.argsOnStack();
  148. }
  149. // ---- copies all state, including Shadow's mungers...
  150. public BcelShadow copyInto(LazyMethodGen recipient, BcelShadow enclosing) {
  151. BcelShadow s = new BcelShadow(world, getKind(), getSignature(), recipient, enclosing);
  152. List src = mungers;
  153. List dest = s.mungers;
  154. for (Iterator i = src.iterator(); i.hasNext(); ) {
  155. dest.add(i.next());
  156. }
  157. return s;
  158. }
  159. // ---- overridden behaviour
  160. public World getIWorld() {
  161. return world;
  162. }
  163. private void deleteNewAndDup() {
  164. final ConstantPoolGen cpg = getEnclosingClass().getConstantPoolGen();
  165. int depth = 1;
  166. InstructionHandle ih = range.getStart();
  167. while (true) {
  168. Instruction inst = ih.getInstruction();
  169. if (inst instanceof INVOKESPECIAL
  170. && ((INVOKESPECIAL) inst).getName(cpg).equals("<init>")) {
  171. depth++;
  172. } else if (inst instanceof NEW) {
  173. depth--;
  174. if (depth == 0) break;
  175. }
  176. ih = ih.getPrev();
  177. }
  178. // now IH points to the NEW. We're followed by the DUP, and that is followed
  179. // by the actual instruciton we care about.
  180. InstructionHandle newHandle = ih;
  181. InstructionHandle endHandle = newHandle.getNext();
  182. InstructionHandle nextHandle;
  183. if (endHandle.getInstruction() instanceof DUP) {
  184. nextHandle = endHandle.getNext();
  185. retargetFrom(newHandle, nextHandle);
  186. retargetFrom(endHandle, nextHandle);
  187. } else if (endHandle.getInstruction() instanceof DUP_X1) {
  188. InstructionHandle dupHandle = endHandle;
  189. endHandle = endHandle.getNext();
  190. nextHandle = endHandle.getNext();
  191. if (endHandle.getInstruction() instanceof SWAP) {}
  192. else {
  193. // XXX see next XXX comment
  194. throw new RuntimeException("Unhandled kind of new " + endHandle);
  195. }
  196. retargetFrom(newHandle, nextHandle);
  197. retargetFrom(dupHandle, nextHandle);
  198. retargetFrom(endHandle, nextHandle);
  199. } else {
  200. endHandle = newHandle;
  201. nextHandle = endHandle.getNext();
  202. retargetFrom(newHandle, nextHandle);
  203. // add a POP here... we found a NEW w/o a dup or anything else, so
  204. // we must be in statement context.
  205. getRange().insert(InstructionConstants.POP, Range.OutsideAfter);
  206. }
  207. // assert (dupHandle.getInstruction() instanceof DUP);
  208. try {
  209. range.getBody().delete(newHandle, endHandle);
  210. } catch (TargetLostException e) {
  211. throw new BCException("shouldn't happen");
  212. }
  213. }
  214. private void retargetFrom(InstructionHandle old, InstructionHandle fresh) {
  215. InstructionTargeter[] sources = old.getTargeters();
  216. if (sources != null) {
  217. for (int i = sources.length - 1; i >= 0; i--) {
  218. sources[i].updateTarget(old, fresh);
  219. }
  220. }
  221. }
  222. protected void prepareForMungers() {
  223. // if we're a constructor call, we need to remove the new:dup or the new:dup_x1:swap,
  224. // and store all our
  225. // arguments on the frame.
  226. // ??? This is a bit of a hack (for the Java langauge). We do this because
  227. // we sometime add code "outsideBefore" when dealing with weaving join points. We only
  228. // do this for exposing state that is on the stack. It turns out to just work for
  229. // everything except for constructor calls and exception handlers. If we were to clean
  230. // this up, every ShadowRange would have three instructionHandle points, the start of
  231. // the arg-setup code, the start of the running code, and the end of the running code.
  232. if (getKind() == ConstructorCall) {
  233. deleteNewAndDup();
  234. initializeArgVars();
  235. } else if (getKind() == PreInitialization) { // pr74952
  236. ShadowRange range = getRange();
  237. range.insert(InstructionConstants.NOP,Range.InsideAfter);
  238. } else if (getKind() == ExceptionHandler) {
  239. ShadowRange range = getRange();
  240. InstructionList body = range.getBody();
  241. InstructionHandle start = range.getStart();
  242. // Create a store instruction to put the value from the top of the
  243. // stack into a local variable slot. This is a trimmed version of
  244. // what is in initializeArgVars() (since there is only one argument
  245. // at a handler jp and only before advice is supported) (pr46298)
  246. argVars = new BcelVar[1];
  247. int positionOffset = (hasTarget() ? 1 : 0) + ((hasThis() && !getKind().isTargetSameAsThis()) ? 1 : 0);
  248. UnresolvedType tx = getArgType(0);
  249. argVars[0] = genTempVar(tx, "ajc$arg0");
  250. InstructionHandle insertedInstruction =
  251. range.insert(argVars[0].createStore(getFactory()), Range.OutsideBefore);
  252. // Now the exception range starts just after our new instruction.
  253. // The next bit of code changes the exception range to point at
  254. // the store instruction
  255. InstructionTargeter[] targeters = start.getTargeters();
  256. for (int i = 0; i < targeters.length; i++) {
  257. InstructionTargeter t = targeters[i];
  258. if (t instanceof ExceptionRange) {
  259. ExceptionRange er = (ExceptionRange) t;
  260. er.updateTarget(start, insertedInstruction, body);
  261. }
  262. }
  263. }
  264. // now we ask each munger to request our state
  265. isThisJoinPointLazy = world.isXlazyTjp();
  266. for (Iterator iter = mungers.iterator(); iter.hasNext();) {
  267. ShadowMunger munger = (ShadowMunger) iter.next();
  268. munger.specializeOn(this);
  269. }
  270. initializeThisJoinPoint();
  271. // If we are an expression kind, we require our target/arguments on the stack
  272. // before we do our actual thing. However, they may have been removed
  273. // from the stack as the shadowMungers have requested state.
  274. // if any of our shadowMungers requested either the arguments or target,
  275. // the munger will have added code
  276. // to pop the target/arguments into temporary variables, represented by
  277. // targetVar and argVars. In such a case, we must make sure to re-push the
  278. // values.
  279. // If we are nonExpressionKind, we don't expect arguments on the stack
  280. // so this is moot. If our argVars happen to be null, then we know that
  281. // no ShadowMunger has squirrelled away our arguments, so they're still
  282. // on the stack.
  283. InstructionFactory fact = getFactory();
  284. if (getKind().argsOnStack() && argVars != null) {
  285. // Special case first (pr46298). If we are an exception handler and the instruction
  286. // just after the shadow is a POP then we should remove the pop. The code
  287. // above which generated the store instruction has already cleared the stack.
  288. // We also don't generate any code for the arguments in this case as it would be
  289. // an incorrect aload.
  290. if (getKind() == ExceptionHandler
  291. && range.getEnd().getNext().getInstruction().equals(InstructionConstants.POP)) {
  292. // easier than deleting it ...
  293. range.getEnd().getNext().setInstruction(InstructionConstants.NOP);
  294. } else {
  295. range.insert(
  296. BcelRenderer.renderExprs(fact, world, argVars),
  297. Range.InsideBefore);
  298. if (targetVar != null) {
  299. range.insert(
  300. BcelRenderer.renderExpr(fact, world, targetVar),
  301. Range.InsideBefore);
  302. }
  303. if (getKind() == ConstructorCall) {
  304. range.insert((Instruction) InstructionFactory.createDup(1), Range.InsideBefore);
  305. range.insert(
  306. fact.createNew(
  307. (ObjectType) BcelWorld.makeBcelType(
  308. getSignature().getDeclaringType())),
  309. Range.InsideBefore);
  310. }
  311. }
  312. }
  313. }
  314. // ---- getters
  315. public ShadowRange getRange() {
  316. return range;
  317. }
  318. public void setRange(ShadowRange range) {
  319. this.range = range;
  320. }
  321. public int getSourceLine() {
  322. // if the kind of join point for which we are a shadow represents
  323. // a method or constructor execution, then the best source line is
  324. // the one from the enclosingMethod declarationLineNumber if available.
  325. Kind kind = getKind();
  326. if ( (kind == MethodExecution) ||
  327. (kind == ConstructorExecution) ||
  328. (kind == AdviceExecution) ||
  329. (kind == StaticInitialization) ||
  330. (kind == PreInitialization) ||
  331. (kind == Initialization)) {
  332. if (getEnclosingMethod().hasDeclaredLineNumberInfo()) {
  333. return getEnclosingMethod().getDeclarationLineNumber();
  334. }
  335. }
  336. if (range == null) {
  337. if (getEnclosingMethod().hasBody()) {
  338. return Utility.getSourceLine(getEnclosingMethod().getBody().getStart());
  339. } else {
  340. return 0;
  341. }
  342. }
  343. int ret = Utility.getSourceLine(range.getStart());
  344. if (ret < 0) return 0;
  345. return ret;
  346. }
  347. // overrides
  348. public UnresolvedType getEnclosingType() {
  349. return getEnclosingClass().getType();
  350. }
  351. public LazyClassGen getEnclosingClass() {
  352. return enclosingMethod.getEnclosingClass();
  353. }
  354. public BcelWorld getWorld() {
  355. return world;
  356. }
  357. // ---- factory methods
  358. public static BcelShadow makeConstructorExecution(
  359. BcelWorld world,
  360. LazyMethodGen enclosingMethod,
  361. InstructionHandle justBeforeStart)
  362. {
  363. final InstructionList body = enclosingMethod.getBody();
  364. BcelShadow s =
  365. new BcelShadow(
  366. world,
  367. ConstructorExecution,
  368. world.makeJoinPointSignature(enclosingMethod),
  369. enclosingMethod,
  370. null);
  371. ShadowRange r = new ShadowRange(body);
  372. r.associateWithShadow(s);
  373. r.associateWithTargets(
  374. Range.genStart(body, justBeforeStart.getNext()),
  375. Range.genEnd(body));
  376. return s;
  377. }
  378. public static BcelShadow makeStaticInitialization(
  379. BcelWorld world,
  380. LazyMethodGen enclosingMethod)
  381. {
  382. InstructionList body = enclosingMethod.getBody();
  383. // move the start past ajc$preClinit
  384. InstructionHandle clinitStart = body.getStart();
  385. if (clinitStart.getInstruction() instanceof InvokeInstruction) {
  386. InvokeInstruction ii = (InvokeInstruction)clinitStart.getInstruction();
  387. if (ii
  388. .getName(enclosingMethod.getEnclosingClass().getConstantPoolGen())
  389. .equals(NameMangler.AJC_PRE_CLINIT_NAME)) {
  390. clinitStart = clinitStart.getNext();
  391. }
  392. }
  393. InstructionHandle clinitEnd = body.getEnd();
  394. //XXX should move the end before the postClinit, but the return is then tricky...
  395. // if (clinitEnd.getInstruction() instanceof InvokeInstruction) {
  396. // InvokeInstruction ii = (InvokeInstruction)clinitEnd.getInstruction();
  397. // if (ii.getName(enclosingMethod.getEnclosingClass().getConstantPoolGen()).equals(NameMangler.AJC_POST_CLINIT_NAME)) {
  398. // clinitEnd = clinitEnd.getPrev();
  399. // }
  400. // }
  401. BcelShadow s =
  402. new BcelShadow(
  403. world,
  404. StaticInitialization,
  405. world.makeJoinPointSignature(enclosingMethod),
  406. enclosingMethod,
  407. null);
  408. ShadowRange r = new ShadowRange(body);
  409. r.associateWithShadow(s);
  410. r.associateWithTargets(
  411. Range.genStart(body, clinitStart),
  412. Range.genEnd(body, clinitEnd));
  413. return s;
  414. }
  415. /** Make the shadow for an exception handler. Currently makes an empty shadow that
  416. * only allows before advice to be woven into it.
  417. */
  418. public static BcelShadow makeExceptionHandler(
  419. BcelWorld world,
  420. ExceptionRange exceptionRange,
  421. LazyMethodGen enclosingMethod,
  422. InstructionHandle startOfHandler,
  423. BcelShadow enclosingShadow)
  424. {
  425. InstructionList body = enclosingMethod.getBody();
  426. UnresolvedType catchType = exceptionRange.getCatchType();
  427. UnresolvedType inType = enclosingMethod.getEnclosingClass().getType();
  428. ResolvedMemberImpl sig = MemberImpl.makeExceptionHandlerSignature(inType, catchType);
  429. sig.parameterNames = new String[] {findHandlerParamName(startOfHandler)};
  430. BcelShadow s =
  431. new BcelShadow(
  432. world,
  433. ExceptionHandler,
  434. sig,
  435. enclosingMethod,
  436. enclosingShadow);
  437. ShadowRange r = new ShadowRange(body);
  438. r.associateWithShadow(s);
  439. InstructionHandle start = Range.genStart(body, startOfHandler);
  440. InstructionHandle end = Range.genEnd(body, start);
  441. r.associateWithTargets(start, end);
  442. exceptionRange.updateTarget(startOfHandler, start, body);
  443. return s;
  444. }
  445. private static String findHandlerParamName(InstructionHandle startOfHandler) {
  446. if (startOfHandler.getInstruction() instanceof StoreInstruction &&
  447. startOfHandler.getNext() != null)
  448. {
  449. int slot = ((StoreInstruction)startOfHandler.getInstruction()).getIndex();
  450. //System.out.println("got store: " + startOfHandler.getInstruction() + ", " + index);
  451. InstructionTargeter[] targeters = startOfHandler.getNext().getTargeters();
  452. if (targeters!=null) {
  453. for (int i=targeters.length-1; i >= 0; i--) {
  454. if (targeters[i] instanceof LocalVariableTag) {
  455. LocalVariableTag t = (LocalVariableTag)targeters[i];
  456. if (t.getSlot() == slot) {
  457. return t.getName();
  458. }
  459. //System.out.println("tag: " + targeters[i]);
  460. }
  461. }
  462. }
  463. }
  464. return "<missing>";
  465. }
  466. /** create an init join point associated w/ an interface in the body of a constructor */
  467. public static BcelShadow makeIfaceInitialization(
  468. BcelWorld world,
  469. LazyMethodGen constructor,
  470. Member interfaceConstructorSignature)
  471. {
  472. InstructionList body = constructor.getBody();
  473. // UnresolvedType inType = constructor.getEnclosingClass().getType();
  474. BcelShadow s =
  475. new BcelShadow(
  476. world,
  477. Initialization,
  478. interfaceConstructorSignature,
  479. constructor,
  480. null);
  481. s.fallsThrough = true;
  482. // ShadowRange r = new ShadowRange(body);
  483. // r.associateWithShadow(s);
  484. // InstructionHandle start = Range.genStart(body, handle);
  485. // InstructionHandle end = Range.genEnd(body, handle);
  486. //
  487. // r.associateWithTargets(start, end);
  488. return s;
  489. }
  490. public void initIfaceInitializer(InstructionHandle end) {
  491. final InstructionList body = enclosingMethod.getBody();
  492. ShadowRange r = new ShadowRange(body);
  493. r.associateWithShadow(this);
  494. InstructionHandle nop = body.insert(end, InstructionConstants.NOP);
  495. r.associateWithTargets(
  496. Range.genStart(body, nop),
  497. Range.genEnd(body, nop));
  498. }
  499. // public static BcelShadow makeIfaceConstructorExecution(
  500. // BcelWorld world,
  501. // LazyMethodGen constructor,
  502. // InstructionHandle next,
  503. // Member interfaceConstructorSignature)
  504. // {
  505. // // final InstructionFactory fact = constructor.getEnclosingClass().getFactory();
  506. // InstructionList body = constructor.getBody();
  507. // // UnresolvedType inType = constructor.getEnclosingClass().getType();
  508. // BcelShadow s =
  509. // new BcelShadow(
  510. // world,
  511. // ConstructorExecution,
  512. // interfaceConstructorSignature,
  513. // constructor,
  514. // null);
  515. // s.fallsThrough = true;
  516. // ShadowRange r = new ShadowRange(body);
  517. // r.associateWithShadow(s);
  518. // // ??? this may or may not work
  519. // InstructionHandle start = Range.genStart(body, next);
  520. // //InstructionHandle end = Range.genEnd(body, body.append(start, fact.NOP));
  521. // InstructionHandle end = Range.genStart(body, next);
  522. // //body.append(start, fact.NOP);
  523. //
  524. // r.associateWithTargets(start, end);
  525. // return s;
  526. // }
  527. /** Create an initialization join point associated with a constructor, but not
  528. * with any body of code yet. If this is actually matched, it's range will be set
  529. * when we inline self constructors.
  530. *
  531. * @param constructor The constructor starting this initialization.
  532. */
  533. public static BcelShadow makeUnfinishedInitialization(
  534. BcelWorld world,
  535. LazyMethodGen constructor)
  536. {
  537. BcelShadow ret = new BcelShadow(
  538. world,
  539. Initialization,
  540. world.makeJoinPointSignature(constructor),
  541. constructor,
  542. null);
  543. if (constructor.getEffectiveSignature() != null) {
  544. ret.setMatchingSignature(constructor.getEffectiveSignature().getEffectiveSignature());
  545. }
  546. return ret;
  547. }
  548. public static BcelShadow makeUnfinishedPreinitialization(
  549. BcelWorld world,
  550. LazyMethodGen constructor)
  551. {
  552. BcelShadow ret = new BcelShadow(
  553. world,
  554. PreInitialization,
  555. world.makeJoinPointSignature(constructor),
  556. constructor,
  557. null);
  558. ret.fallsThrough = true;
  559. if (constructor.getEffectiveSignature() != null) {
  560. ret.setMatchingSignature(constructor.getEffectiveSignature().getEffectiveSignature());
  561. }
  562. return ret;
  563. }
  564. public static BcelShadow makeMethodExecution(
  565. BcelWorld world,
  566. LazyMethodGen enclosingMethod,
  567. boolean lazyInit)
  568. {
  569. if (!lazyInit) return makeMethodExecution(world, enclosingMethod);
  570. BcelShadow s =
  571. new BcelShadow(
  572. world,
  573. MethodExecution,
  574. enclosingMethod.getMemberView(),
  575. enclosingMethod,
  576. null);
  577. return s;
  578. }
  579. public void init() {
  580. if (range != null) return;
  581. final InstructionList body = enclosingMethod.getBody();
  582. ShadowRange r = new ShadowRange(body);
  583. r.associateWithShadow(this);
  584. r.associateWithTargets(
  585. Range.genStart(body),
  586. Range.genEnd(body));
  587. }
  588. public static BcelShadow makeMethodExecution(
  589. BcelWorld world,
  590. LazyMethodGen enclosingMethod)
  591. {
  592. return makeShadowForMethod(world, enclosingMethod, MethodExecution,
  593. enclosingMethod.getMemberView()); //world.makeMethodSignature(enclosingMethod));
  594. }
  595. public static BcelShadow makeShadowForMethod(BcelWorld world,
  596. LazyMethodGen enclosingMethod, Shadow.Kind kind, Member sig)
  597. {
  598. final InstructionList body = enclosingMethod.getBody();
  599. BcelShadow s =
  600. new BcelShadow(
  601. world,
  602. kind,
  603. sig,
  604. enclosingMethod,
  605. null);
  606. ShadowRange r = new ShadowRange(body);
  607. r.associateWithShadow(s);
  608. r.associateWithTargets(
  609. Range.genStart(body),
  610. Range.genEnd(body));
  611. return s;
  612. }
  613. public static BcelShadow makeAdviceExecution(
  614. BcelWorld world,
  615. LazyMethodGen enclosingMethod)
  616. {
  617. final InstructionList body = enclosingMethod.getBody();
  618. BcelShadow s =
  619. new BcelShadow(
  620. world,
  621. AdviceExecution,
  622. world.makeJoinPointSignatureFromMethod(enclosingMethod, Member.ADVICE),
  623. enclosingMethod,
  624. null);
  625. ShadowRange r = new ShadowRange(body);
  626. r.associateWithShadow(s);
  627. r.associateWithTargets(Range.genStart(body), Range.genEnd(body));
  628. return s;
  629. }
  630. // constructor call shadows are <em>initially</em> just around the
  631. // call to the constructor. If ANY advice gets put on it, we move
  632. // the NEW instruction inside the join point, which involves putting
  633. // all the arguments in temps.
  634. public static BcelShadow makeConstructorCall(
  635. BcelWorld world,
  636. LazyMethodGen enclosingMethod,
  637. InstructionHandle callHandle,
  638. BcelShadow enclosingShadow)
  639. {
  640. final InstructionList body = enclosingMethod.getBody();
  641. Member sig = world.makeJoinPointSignatureForMethodInvocation(
  642. enclosingMethod.getEnclosingClass(),
  643. (InvokeInstruction) callHandle.getInstruction());
  644. BcelShadow s =
  645. new BcelShadow(
  646. world,
  647. ConstructorCall,
  648. sig,
  649. enclosingMethod,
  650. enclosingShadow);
  651. ShadowRange r = new ShadowRange(body);
  652. r.associateWithShadow(s);
  653. r.associateWithTargets(
  654. Range.genStart(body, callHandle),
  655. Range.genEnd(body, callHandle));
  656. retargetAllBranches(callHandle, r.getStart());
  657. return s;
  658. }
  659. public static BcelShadow makeMethodCall(
  660. BcelWorld world,
  661. LazyMethodGen enclosingMethod,
  662. InstructionHandle callHandle,
  663. BcelShadow enclosingShadow)
  664. {
  665. final InstructionList body = enclosingMethod.getBody();
  666. BcelShadow s =
  667. new BcelShadow(
  668. world,
  669. MethodCall,
  670. world.makeJoinPointSignatureForMethodInvocation(
  671. enclosingMethod.getEnclosingClass(),
  672. (InvokeInstruction) callHandle.getInstruction()),
  673. enclosingMethod,
  674. enclosingShadow);
  675. ShadowRange r = new ShadowRange(body);
  676. r.associateWithShadow(s);
  677. r.associateWithTargets(
  678. Range.genStart(body, callHandle),
  679. Range.genEnd(body, callHandle));
  680. retargetAllBranches(callHandle, r.getStart());
  681. return s;
  682. }
  683. public static BcelShadow makeShadowForMethodCall(
  684. BcelWorld world,
  685. LazyMethodGen enclosingMethod,
  686. InstructionHandle callHandle,
  687. BcelShadow enclosingShadow,
  688. Kind kind,
  689. ResolvedMember sig)
  690. {
  691. final InstructionList body = enclosingMethod.getBody();
  692. BcelShadow s =
  693. new BcelShadow(
  694. world,
  695. kind,
  696. sig,
  697. enclosingMethod,
  698. enclosingShadow);
  699. ShadowRange r = new ShadowRange(body);
  700. r.associateWithShadow(s);
  701. r.associateWithTargets(
  702. Range.genStart(body, callHandle),
  703. Range.genEnd(body, callHandle));
  704. retargetAllBranches(callHandle, r.getStart());
  705. return s;
  706. }
  707. public static BcelShadow makeFieldGet(
  708. BcelWorld world,
  709. ResolvedMember field,
  710. LazyMethodGen enclosingMethod,
  711. InstructionHandle getHandle,
  712. BcelShadow enclosingShadow)
  713. {
  714. final InstructionList body = enclosingMethod.getBody();
  715. BcelShadow s =
  716. new BcelShadow(
  717. world,
  718. FieldGet,
  719. field,
  720. // BcelWorld.makeFieldSignature(
  721. // enclosingMethod.getEnclosingClass(),
  722. // (FieldInstruction) getHandle.getInstruction()),
  723. enclosingMethod,
  724. enclosingShadow);
  725. ShadowRange r = new ShadowRange(body);
  726. r.associateWithShadow(s);
  727. r.associateWithTargets(
  728. Range.genStart(body, getHandle),
  729. Range.genEnd(body, getHandle));
  730. retargetAllBranches(getHandle, r.getStart());
  731. return s;
  732. }
  733. public static BcelShadow makeFieldSet(
  734. BcelWorld world,
  735. LazyMethodGen enclosingMethod,
  736. InstructionHandle setHandle,
  737. BcelShadow enclosingShadow)
  738. {
  739. final InstructionList body = enclosingMethod.getBody();
  740. BcelShadow s =
  741. new BcelShadow(
  742. world,
  743. FieldSet,
  744. BcelWorld.makeFieldJoinPointSignature(
  745. enclosingMethod.getEnclosingClass(),
  746. (FieldInstruction) setHandle.getInstruction()),
  747. enclosingMethod,
  748. enclosingShadow);
  749. ShadowRange r = new ShadowRange(body);
  750. r.associateWithShadow(s);
  751. r.associateWithTargets(
  752. Range.genStart(body, setHandle),
  753. Range.genEnd(body, setHandle));
  754. retargetAllBranches(setHandle, r.getStart());
  755. return s;
  756. }
  757. public static void retargetAllBranches(InstructionHandle from, InstructionHandle to) {
  758. InstructionTargeter[] sources = from.getTargeters();
  759. if (sources != null) {
  760. for (int i = sources.length - 1; i >= 0; i--) {
  761. InstructionTargeter source = sources[i];
  762. if (source instanceof BranchInstruction) {
  763. source.updateTarget(from, to);
  764. }
  765. }
  766. }
  767. }
  768. // // ---- type access methods
  769. // private ObjectType getTargetBcelType() {
  770. // return (ObjectType) BcelWorld.makeBcelType(getTargetType());
  771. // }
  772. // private Type getArgBcelType(int arg) {
  773. // return BcelWorld.makeBcelType(getArgType(arg));
  774. // }
  775. // ---- kinding
  776. /**
  777. * If the end of my range has no real instructions following then
  778. * my context needs a return at the end.
  779. */
  780. public boolean terminatesWithReturn() {
  781. return getRange().getRealNext() == null;
  782. }
  783. /**
  784. * Is arg0 occupied with the value of this
  785. */
  786. public boolean arg0HoldsThis() {
  787. if (getKind().isEnclosingKind()) {
  788. return !getSignature().isStatic();
  789. } else if (enclosingShadow == null) {
  790. //XXX this is mostly right
  791. // this doesn't do the right thing for calls in the pre part of introduced constructors.
  792. return !enclosingMethod.isStatic();
  793. } else {
  794. return ((BcelShadow)enclosingShadow).arg0HoldsThis();
  795. }
  796. }
  797. // ---- argument getting methods
  798. private BcelVar thisVar = null;
  799. private BcelVar targetVar = null;
  800. private BcelVar[] argVars = null;
  801. private Map/*<UnresolvedType,BcelVar>*/ kindedAnnotationVars = null;
  802. private Map/*<UnresolvedType,BcelVar>*/ thisAnnotationVars = null;
  803. private Map/*<UnresolvedType,BcelVar>*/ targetAnnotationVars = null;
  804. private Map/*<UnresolvedType,BcelVar>*/[] argAnnotationVars = null;
  805. private Map/*<UnresolvedType,BcelVar>*/ withinAnnotationVars = null;
  806. private Map/*<UnresolvedType,BcelVar>*/ withincodeAnnotationVars = null;
  807. public Var getThisVar() {
  808. if (!hasThis()) {
  809. throw new IllegalStateException("no this");
  810. }
  811. initializeThisVar();
  812. return thisVar;
  813. }
  814. public Var getThisAnnotationVar(UnresolvedType forAnnotationType) {
  815. if (!hasThis()) {
  816. throw new IllegalStateException("no this");
  817. }
  818. initializeThisAnnotationVars(); // FIXME asc Why bother with this if we always return one?
  819. // Even if we can't find one, we have to return one as we might have this annotation at runtime
  820. Var v = (Var) thisAnnotationVars.get(forAnnotationType);
  821. if (v==null)
  822. v = new TypeAnnotationAccessVar(forAnnotationType.resolve(world),(BcelVar)getThisVar());
  823. return v;
  824. }
  825. public Var getTargetVar() {
  826. if (!hasTarget()) {
  827. throw new IllegalStateException("no target");
  828. }
  829. initializeTargetVar();
  830. return targetVar;
  831. }
  832. public Var getTargetAnnotationVar(UnresolvedType forAnnotationType) {
  833. if (!hasTarget()) {
  834. throw new IllegalStateException("no target");
  835. }
  836. initializeTargetAnnotationVars(); // FIXME asc why bother with this if we always return one?
  837. Var v =(Var) targetAnnotationVars.get(forAnnotationType);
  838. // Even if we can't find one, we have to return one as we might have this annotation at runtime
  839. if (v==null)
  840. v = new TypeAnnotationAccessVar(forAnnotationType.resolve(world),(BcelVar)getTargetVar());
  841. return v;
  842. }
  843. public Var getArgVar(int i) {
  844. initializeArgVars();
  845. return argVars[i];
  846. }
  847. public Var getArgAnnotationVar(int i,UnresolvedType forAnnotationType) {
  848. initializeArgAnnotationVars();
  849. Var v= (Var) argAnnotationVars[i].get(forAnnotationType);
  850. if (v==null)
  851. v = new TypeAnnotationAccessVar(forAnnotationType.resolve(world),(BcelVar)getArgVar(i));
  852. return v;
  853. }
  854. public Var getKindedAnnotationVar(UnresolvedType forAnnotationType) {
  855. initializeKindedAnnotationVars();
  856. return (Var) kindedAnnotationVars.get(forAnnotationType);
  857. }
  858. public Var getWithinAnnotationVar(UnresolvedType forAnnotationType) {
  859. initializeWithinAnnotationVars();
  860. return (Var) withinAnnotationVars.get(forAnnotationType);
  861. }
  862. public Var getWithinCodeAnnotationVar(UnresolvedType forAnnotationType) {
  863. initializeWithinCodeAnnotationVars();
  864. return (Var) withincodeAnnotationVars.get(forAnnotationType);
  865. }
  866. // reflective thisJoinPoint support
  867. private BcelVar thisJoinPointVar = null;
  868. private boolean isThisJoinPointLazy;
  869. private int lazyTjpConsumers = 0;
  870. private BcelVar thisJoinPointStaticPartVar = null;
  871. // private BcelVar thisEnclosingJoinPointStaticPartVar = null;
  872. public final Var getThisJoinPointStaticPartVar() {
  873. return getThisJoinPointStaticPartBcelVar();
  874. }
  875. public final Var getThisEnclosingJoinPointStaticPartVar() {
  876. return getThisEnclosingJoinPointStaticPartBcelVar();
  877. }
  878. public void requireThisJoinPoint(boolean hasGuardTest) {
  879. if (!hasGuardTest) {
  880. isThisJoinPointLazy = false;
  881. } else {
  882. lazyTjpConsumers++;
  883. }
  884. if (thisJoinPointVar == null) {
  885. thisJoinPointVar = genTempVar(UnresolvedType.forName("org.aspectj.lang.JoinPoint"));
  886. }
  887. }
  888. public Var getThisJoinPointVar() {
  889. requireThisJoinPoint(false);
  890. return thisJoinPointVar;
  891. }
  892. void initializeThisJoinPoint() {
  893. if (thisJoinPointVar == null) return;
  894. if (isThisJoinPointLazy) {
  895. isThisJoinPointLazy = checkLazyTjp();
  896. }
  897. if (isThisJoinPointLazy) {
  898. createThisJoinPoint(); // make sure any state needed is initialized, but throw the instructions out
  899. if (lazyTjpConsumers == 1) return; // special case only one lazyTjpUser
  900. InstructionFactory fact = getFactory();
  901. InstructionList il = new InstructionList();
  902. il.append(InstructionConstants.ACONST_NULL);
  903. il.append(thisJoinPointVar.createStore(fact));
  904. range.insert(il, Range.OutsideBefore);
  905. } else {
  906. InstructionFactory fact = getFactory();
  907. InstructionList il = createThisJoinPoint();
  908. il.append(thisJoinPointVar.createStore(fact));
  909. range.insert(il, Range.OutsideBefore);
  910. }
  911. }
  912. private boolean checkLazyTjp() {
  913. // check for around advice
  914. for (Iterator i = mungers.iterator(); i.hasNext();) {
  915. ShadowMunger munger = (ShadowMunger) i.next();
  916. if (munger instanceof Advice) {
  917. if ( ((Advice)munger).getKind() == AdviceKind.Around) {
  918. world.getLint().canNotImplementLazyTjp.signal(
  919. new String[] {toString()},
  920. getSourceLocation(),
  921. new ISourceLocation[] { munger.getSourceLocation() }
  922. );
  923. return false;
  924. }
  925. }
  926. }
  927. return true;
  928. }
  929. InstructionList loadThisJoinPoint() {
  930. InstructionFactory fact = getFactory();
  931. InstructionList il = new InstructionList();
  932. if (isThisJoinPointLazy) {
  933. il.append(createThisJoinPoint());
  934. if (lazyTjpConsumers > 1) {
  935. il.append(thisJoinPointVar.createStore(fact));
  936. InstructionHandle end = il.append(thisJoinPointVar.createLoad(fact));
  937. il.insert(InstructionFactory.createBranchInstruction(Constants.IFNONNULL, end));
  938. il.insert(thisJoinPointVar.createLoad(fact));
  939. }
  940. } else {
  941. thisJoinPointVar.appendLoad(il, fact);
  942. }
  943. return il;
  944. }
  945. InstructionList createThisJoinPoint() {
  946. InstructionFactory fact = getFactory();
  947. InstructionList il = new InstructionList();
  948. BcelVar staticPart = getThisJoinPointStaticPartBcelVar();
  949. staticPart.appendLoad(il, fact);
  950. if (hasThis()) {
  951. ((BcelVar)getThisVar()).appendLoad(il, fact);
  952. } else {
  953. il.append(new ACONST_NULL());
  954. }
  955. if (hasTarget()) {
  956. ((BcelVar)getTargetVar()).appendLoad(il, fact);
  957. } else {
  958. il.append(new ACONST_NULL());
  959. }
  960. switch(getArgCount()) {
  961. case 0:
  962. il.append(fact.createInvoke("org.aspectj.runtime.reflect.Factory",
  963. "makeJP", LazyClassGen.tjpType,
  964. new Type[] { LazyClassGen.staticTjpType,
  965. Type.OBJECT, Type.OBJECT},
  966. Constants.INVOKESTATIC));
  967. break;
  968. case 1:
  969. ((BcelVar)getArgVar(0)).appendLoadAndConvert(il, fact, world.getCoreType(ResolvedType.OBJECT));
  970. il.append(fact.createInvoke("org.aspectj.runtime.reflect.Factory",
  971. "makeJP", LazyClassGen.tjpType,
  972. new Type[] { LazyClassGen.staticTjpType,
  973. Type.OBJECT, Type.OBJECT, Type.OBJECT},
  974. Constants.INVOKESTATIC));
  975. break;
  976. case 2:
  977. ((BcelVar)getArgVar(0)).appendLoadAndConvert(il, fact, world.getCoreType(ResolvedType.OBJECT));
  978. ((BcelVar)getArgVar(1)).appendLoadAndConvert(il, fact, world.getCoreType(ResolvedType.OBJECT));
  979. il.append(fact.createInvoke("org.aspectj.runtime.reflect.Factory",
  980. "makeJP", LazyClassGen.tjpType,
  981. new Type[] { LazyClassGen.staticTjpType,
  982. Type.OBJECT, Type.OBJECT, Type.OBJECT, Type.OBJECT},
  983. Constants.INVOKESTATIC));
  984. break;
  985. default:
  986. il.append(makeArgsObjectArray());
  987. il.append(fact.createInvoke("org.aspectj.runtime.reflect.Factory",
  988. "makeJP", LazyClassGen.tjpType,
  989. new Type[] { LazyClassGen.staticTjpType,
  990. Type.OBJECT, Type.OBJECT, new ArrayType(Type.OBJECT, 1)},
  991. Constants.INVOKESTATIC));
  992. break;
  993. }
  994. return il;
  995. }
  996. /**
  997. * Get the Var for the jpStaticPart
  998. * @return
  999. */
  1000. public BcelVar getThisJoinPointStaticPartBcelVar() {
  1001. return getThisJoinPointStaticPartBcelVar(false);
  1002. }
  1003. /**
  1004. * Get the Var for the xxxxJpStaticPart, xxx = this or enclosing
  1005. * @param isEnclosingJp true to have the enclosingJpStaticPart
  1006. * @return
  1007. */
  1008. public BcelVar getThisJoinPointStaticPartBcelVar(final boolean isEnclosingJp) {
  1009. if (thisJoinPointStaticPartVar == null) {
  1010. Field field = getEnclosingClass().getTjpField(this, isEnclosingJp);
  1011. thisJoinPointStaticPartVar =
  1012. new BcelFieldRef(
  1013. isEnclosingJp?
  1014. world.getCoreType(UnresolvedType.forName("org.aspectj.lang.JoinPoint$EnclosingStaticPart")):
  1015. world.getCoreType(UnresolvedType.forName("org.aspectj.lang.JoinPoint$StaticPart")),
  1016. getEnclosingClass().getClassName(),
  1017. field.getName());
  1018. // getEnclosingClass().warnOnAddedStaticInitializer(this,munger.getSourceLocation());
  1019. }
  1020. return thisJoinPointStaticPartVar;
  1021. }
  1022. /**
  1023. * Get the Var for the enclosingJpStaticPart
  1024. * @return
  1025. */
  1026. public BcelVar getThisEnclosingJoinPointStaticPartBcelVar() {
  1027. if (enclosingShadow == null) {
  1028. // the enclosing of an execution is itself
  1029. return getThisJoinPointStaticPartBcelVar(true);
  1030. } else {
  1031. return ((BcelShadow)enclosingShadow).getThisJoinPointStaticPartBcelVar(true);
  1032. }
  1033. }
  1034. //??? need to better understand all the enclosing variants
  1035. public Member getEnclosingCodeSignature() {
  1036. if (getKind().isEnclosingKind()) {
  1037. return getSignature();
  1038. } else if (getKind() == Shadow.PreInitialization) {
  1039. // PreInit doesn't enclose code but its signature
  1040. // is correctly the signature of the ctor.
  1041. return getSignature();
  1042. } else if (enclosingShadow == null) {
  1043. return getEnclosingMethod().getMemberView();
  1044. } else {
  1045. return enclosingShadow.getSignature();
  1046. }
  1047. }
  1048. private InstructionList makeArgsObjectArray() {
  1049. InstructionFactory fact = getFactory();
  1050. BcelVar arrayVar = genTempVar(UnresolvedType.OBJECTARRAY);
  1051. final InstructionList il = new InstructionList();
  1052. int alen = getArgCount() ;
  1053. il.append(Utility.createConstant(fact, alen));
  1054. il.append((Instruction)fact.createNewArray(Type.OBJECT, (short)1));
  1055. arrayVar.appendStore(il, fact);
  1056. int stateIndex = 0;
  1057. for (int i = 0, len = getArgCount(); i<len; i++) {
  1058. arrayVar.appendConvertableArrayStore(il, fact, stateIndex, (BcelVar)getArgVar(i));
  1059. stateIndex++;
  1060. }
  1061. arrayVar.appendLoad(il, fact);
  1062. return il;
  1063. }
  1064. // ---- initializing var tables
  1065. /* initializing this is doesn't do anything, because this
  1066. * is protected from side-effects, so we don't need to copy its location
  1067. */
  1068. private void initializeThisVar() {
  1069. if (thisVar != null) return;
  1070. thisVar = new BcelVar(getThisType().resolve(world), 0);
  1071. thisVar.setPositionInAroundState(0);
  1072. }
  1073. public void initializeTargetVar() {
  1074. InstructionFactory fact = getFactory();
  1075. if (targetVar != null) return;
  1076. if (getKind().isTargetSameAsThis()) {
  1077. if (hasThis()) initializeThisVar();
  1078. targetVar = thisVar;
  1079. } else {
  1080. initializeArgVars(); // gotta pop off the args before we find the target
  1081. UnresolvedType type = getTargetType();
  1082. type = ensureTargetTypeIsCorrect(type);
  1083. targetVar = genTempVar(type, "ajc$target");
  1084. range.insert(targetVar.createStore(fact), Range.OutsideBefore);
  1085. targetVar.setPositionInAroundState(hasThis() ? 1 : 0);
  1086. }
  1087. }
  1088. /* PR 72528
  1089. * This method double checks the target type under certain conditions. The Java 1.4
  1090. * compilers seem to take calls to clone methods on array types and create bytecode that
  1091. * looks like clone is being called on Object. If we advise a clone call with around
  1092. * advice we extract the call into a helper method which we can then refer to. Because the
  1093. * type in the bytecode for the call to clone is Object we create a helper method with
  1094. * an Object parameter - this is not correct as we have lost the fact that the actual
  1095. * type is an array type. If we don't do the check below we will create code that fails
  1096. * java verification. This method checks for the peculiar set of conditions and if they
  1097. * are true, it has a sneak peek at the code before the call to see what is on the stack.
  1098. */
  1099. public UnresolvedType ensureTargetTypeIsCorrect(UnresolvedType tx) {
  1100. if (tx.equals(ResolvedType.OBJECT) && getKind() == MethodCall &&
  1101. getSignature().getReturnType().equals(ResolvedType.OBJECT) &&
  1102. getSignature().getArity()==0 &&
  1103. getSignature().getName().charAt(0) == 'c' &&
  1104. getSignature().getName().equals("clone")) {
  1105. // Lets go back through the code from the start of the shadow
  1106. InstructionHandle searchPtr = range.getStart().getPrev();
  1107. while (Range.isRangeHandle(searchPtr) ||
  1108. searchPtr.getInstruction() instanceof StoreInstruction) { // ignore this instruction - it doesnt give us the info we want
  1109. searchPtr = searchPtr.getPrev();
  1110. }
  1111. // A load instruction may tell us the real type of what the clone() call is on
  1112. if (searchPtr.getInstruction() instanceof LoadInstruction) {
  1113. LoadInstruction li = (LoadInstruction)searchPtr.getInstruction();
  1114. li.getIndex();
  1115. LocalVariableTag lvt = LazyMethodGen.getLocalVariableTag(searchPtr,li.getIndex());
  1116. return lvt.getType();
  1117. }
  1118. // A field access instruction may tell us the real type of what the clone() call is on
  1119. if (searchPtr.getInstruction() instanceof FieldInstruction) {
  1120. FieldInstruction si = (FieldInstruction)searchPtr.getInstruction();
  1121. Type t = si.getFieldType(getEnclosingClass().getConstantPoolGen());
  1122. return BcelWorld.fromBcel(t);
  1123. }
  1124. // A new array instruction obviously tells us it is an array type !
  1125. if (searchPtr.getInstruction() instanceof ANEWARRAY) {
  1126. //ANEWARRAY ana = (ANEWARRAY)searchPoint.getInstruction();
  1127. //Type t = ana.getType(getEnclosingClass().getConstantPoolGen());
  1128. // Just use a standard java.lang.object array - that will work fine
  1129. return BcelWorld.fromBcel(new ArrayType(Type.OBJECT,1));
  1130. }
  1131. // A multi new array instruction obviously tells us it is an array type !
  1132. if (searchPtr.getInstruction() instanceof MULTIANEWARRAY) {
  1133. MULTIANEWARRAY ana = (MULTIANEWARRAY)searchPtr.getInstruction();
  1134. // Type t = ana.getType(getEnclosingClass().getConstantPoolGen());
  1135. // t = new ArrayType(t,ana.getDimensions());
  1136. // Just use a standard java.lang.object array - that will work fine
  1137. return BcelWorld.fromBcel(new ArrayType(Type.OBJECT,ana.getDimensions()));
  1138. }
  1139. throw new BCException("Can't determine real target of clone() when processing instruction "+
  1140. searchPtr.getInstruction());
  1141. }
  1142. return tx;
  1143. }
  1144. public void initializeArgVars() {
  1145. if (argVars != null) return;
  1146. InstructionFactory fact = getFactory();
  1147. int len = getArgCount();
  1148. argVars = new BcelVar[len];
  1149. int positionOffset = (hasTarget() ? 1 : 0) +
  1150. ((hasThis() && !getKind().isTargetSameAsThis()) ? 1 : 0);
  1151. if (getKind().argsOnStack()) {
  1152. // we move backwards because we're popping off the stack
  1153. for (int i = len - 1; i >= 0; i--) {
  1154. UnresolvedType type = getArgType(i);
  1155. BcelVar tmp = genTempVar(type, "ajc$arg" + i);
  1156. range.insert(tmp.createStore(getFactory()), Range.OutsideBefore);
  1157. int position = i;
  1158. position += positionOffset;
  1159. tmp.setPositionInAroundState(position);
  1160. argVars[i] = tmp;
  1161. }
  1162. } else {
  1163. int index = 0;
  1164. if (arg0HoldsThis()) index++;
  1165. for (int i = 0; i < len; i++) {
  1166. UnresolvedType type = getArgType(i);
  1167. BcelVar tmp = genTempVar(type, "ajc$arg" + i);
  1168. range.insert(tmp.createCopyFrom(fact, index), Range.OutsideBefore);
  1169. argVars[i] = tmp;
  1170. int position = i;
  1171. position += positionOffset;
  1172. // System.out.println("set position: " + tmp + ", " + position + " in " + this);
  1173. // System.out.println(" hasThis: " + hasThis() + ", hasTarget: " + hasTarget());
  1174. tmp.setPositionInAroundState(position);
  1175. index += type.getSize();
  1176. }
  1177. }
  1178. }
  1179. public void initializeForAroundClosure() {
  1180. initializeArgVars();
  1181. if (hasTarget()) initializeTargetVar();
  1182. if (hasThis()) initializeThisVar();
  1183. // System.out.println("initialized: " + this + " thisVar = " + thisVar);
  1184. }
  1185. public void initializeThisAnnotationVars() {
  1186. if (thisAnnotationVars != null) return;
  1187. thisAnnotationVars = new HashMap();
  1188. // populate..
  1189. }
  1190. public void initializeTargetAnnotationVars() {
  1191. if (targetAnnotationVars != null) return;
  1192. if (getKind().isTargetSameAsThis()) {
  1193. if (hasThis()) initializeThisAnnotationVars();
  1194. targetAnnotationVars = thisAnnotationVars;
  1195. } else {
  1196. targetAnnotationVars = new HashMap();
  1197. ResolvedType[] rtx = this.getTargetType().resolve(world).getAnnotationTypes(); // what about annotations we havent gotten yet but we will get in subclasses?
  1198. for (int i = 0; i < rtx.length; i++) {
  1199. ResolvedType typeX = rtx[i];
  1200. targetAnnotationVars.put(typeX,new TypeAnnotationAccessVar(typeX,(BcelVar)getTargetVar()));
  1201. }
  1202. // populate.
  1203. }
  1204. }
  1205. public void initializeArgAnnotationVars() {
  1206. if (argAnnotationVars != null) return;
  1207. int numArgs = getArgCount();
  1208. argAnnotationVars = new Map[numArgs];
  1209. for (int i = 0; i < argAnnotationVars.length; i++) {
  1210. argAnnotationVars[i] = new HashMap();
  1211. //FIXME asc just delete this logic - we always build the Var on demand, as we don't know at weave time
  1212. // what the full set of annotations could be (due to static/dynamic type differences...)
  1213. }
  1214. }
  1215. protected Member getRelevantMember(Member foundMember, Member relevantMember, ResolvedType relevantType){
  1216. if (foundMember != null){
  1217. return foundMember;
  1218. }
  1219. foundMember = getSignature().resolve(world);
  1220. if (foundMember == null && relevantMember != null) {
  1221. foundMember = relevantType.lookupMemberWithSupersAndITDs(relevantMember);
  1222. }
  1223. // check the ITD'd dooberries
  1224. List mungers = relevantType.resolve(world).getInterTypeMungers();
  1225. for (Iterator iter = mungers.iterator(); iter.hasNext();) {
  1226. BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next();
  1227. if (typeMunger.getMunger() instanceof NewMethodTypeMunger ||
  1228. typeMunger.getMunger() instanceof NewConstructorTypeMunger) {
  1229. ResolvedMember fakerm = typeMunger.getSignature();
  1230. if (fakerm.getName().equals(getSignature().getName()) &&
  1231. fakerm.getParameterSignature().equals(getSignature().getParameterSignature())){
  1232. if (foundMember.getKind()==ResolvedMember.CONSTRUCTOR){
  1233. foundMember = AjcMemberMaker.interConstructor(
  1234. relevantType,
  1235. (ResolvedMember)foundMember,
  1236. typeMunger.getAspectType());
  1237. } else {
  1238. foundMember = AjcMemberMaker.interMethod((ResolvedMember)foundMember,
  1239. typeMunger.getAspectType(), false);
  1240. }
  1241. // in the above.. what about if it's on an Interface? Can that happen?
  1242. // then the last arg of the above should be true
  1243. return foundMember;
  1244. }
  1245. }
  1246. }
  1247. return foundMember;
  1248. }
  1249. protected ResolvedType [] getAnnotations(Member foundMember, Member relevantMember, ResolvedType relevantType){
  1250. if (foundMember == null){
  1251. // check the ITD'd dooberries
  1252. List mungers = relevantType.resolve(world).getInterTypeMungers();
  1253. for (Iterator iter = mungers.iterator(); iter.hasNext();) {
  1254. BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next();
  1255. if (typeMunger.getMunger() instanceof NewMethodTypeMunger ||
  1256. typeMunger.getMunger() instanceof NewConstructorTypeMunger) {
  1257. ResolvedMember fakerm = typeMunger.getSignature();
  1258. //if (fakerm.hasAnnotations())
  1259. ResolvedMember ajcMethod = (getSignature().getKind()==ResolvedMember.CONSTRUCTOR?
  1260. AjcMemberMaker.postIntroducedConstructor(typeMunger.getAspectType(),fakerm.getDeclaringType(),fakerm.getParameterTypes()):
  1261. AjcMemberMaker.interMethodDispatcher(fakerm,typeMunger.getAspectType()));
  1262. //AjcMemberMaker.interMethodBody(fakerm,typeMunger.getAspectType()));
  1263. ResolvedMember rmm = findMethod(typeMunger.getAspectType(),ajcMethod);
  1264. if (fakerm.getName().equals(getSignature().getName()) &&
  1265. fakerm.getParameterSignature().equals(getSignature().getParameterSignature())) {
  1266. relevantType = typeMunger.getAspectType();
  1267. foundMember = rmm;
  1268. return foundMember.getAnnotationTypes();
  1269. }
  1270. }
  1271. }
  1272. // didn't find in ITDs, look in supers
  1273. foundMember = relevantType.lookupMemberWithSupersAndITDs(relevantMember);
  1274. if (foundMember == null) {
  1275. throw new IllegalStateException("Couldn't find member " + relevantMember + " for type " + relevantType);
  1276. }
  1277. }
  1278. return foundMember.getAnnotationTypes();
  1279. }
  1280. public void initializeKindedAnnotationVars() {
  1281. if (kindedAnnotationVars != null) return;
  1282. kindedAnnotationVars = new HashMap();
  1283. // by determining what "kind" of shadow we are, we can find out the
  1284. // annotations on the appropriate element (method, field, constructor, type).
  1285. // Then create one BcelVar entry in the map for each annotation, keyed by
  1286. // annotation type (UnresolvedType).
  1287. // FIXME asc Refactor this code, there is duplication
  1288. ResolvedType[] annotations = null;
  1289. Member relevantMember = getSignature();
  1290. ResolvedType relevantType = relevantMember.getDeclaringType().resolve(world);
  1291. if (getKind() == Shadow.StaticInitialization) {
  1292. annotations = relevantType.resolve(world).getAnnotationTypes();
  1293. } else if (getKind() == Shadow.MethodCall || getKind() == Shadow.ConstructorCall) {
  1294. Member foundMember = findMethod2(relevantType.resolve(world).getDeclaredMethods(),getSignature());
  1295. annotations = getAnnotations(foundMember, relevantMember, relevantType);
  1296. relevantMember = getRelevantMember(foundMember,relevantMember,relevantType);
  1297. relevantType = relevantMember.getDeclaringType().resolve(world);
  1298. } else if (getKind() == Shadow.FieldSet || getKind() == Shadow.FieldGet) {
  1299. relevantMember = findField(relevantType.getDeclaredFields(),getSignature());
  1300. if (relevantMember==null) {
  1301. // check the ITD'd dooberries
  1302. List mungers = relevantType.resolve(world).getInterTypeMungers();
  1303. for (Iterator iter = mungers.iterator(); iter.hasNext();) {
  1304. BcelTypeMunger typeMunger = (BcelTypeMunger) iter.next();
  1305. if (typeMunger.getMunger() instanceof NewFieldTypeMunger) {
  1306. ResolvedMember fakerm = typeMunger.getSignature();
  1307. //if (fakerm.hasAnnotations())
  1308. ResolvedMember ajcMethod = AjcMemberMaker.interFieldInitializer(fakerm,typeMunger.getAspectType());
  1309. ResolvedMember rmm = findMethod(typeMunger.getAspectType(),ajcMethod);
  1310. if (fakerm.equals(getSignature())) {
  1311. relevantType = typeMunger.getAspectType();
  1312. relevantMember = rmm;
  1313. }
  1314. }
  1315. }
  1316. }
  1317. annotations = relevantMember.getAnnotationTypes();
  1318. } else if (getKind() == Shadow.MethodExecution || getKind() == Shadow.ConstructorExecution ||
  1319. getKind() == Shadow.AdviceExecution) {
  1320. ResolvedMember rm[] = relevantType.getDeclaredMethods();
  1321. Member foundMember = findMethod2(relevantType.getDeclaredMethods(),getSignature());
  1322. annotations = getAnnotations(foundMember, relevantMember,relevantType);
  1323. relevantMember = foundMember;
  1324. relevantMember = getRelevantMember(foundMember, relevantMember,relevantType);
  1325. } else if (getKind() == Shadow.ExceptionHandler) {
  1326. relevantType = getSignature().getParameterTypes()[0].resolve(world);
  1327. annotations = relevantType.getAnnotationTypes();
  1328. } else if (getKind() == Shadow.PreInitialization || getKind() == Shadow.Initialization) {
  1329. ResolvedMember found = findMethod2(relevantType.getDeclaredMethods(),getSignature());
  1330. annotations = found.getAnnotationTypes();
  1331. }
  1332. if (annotations == null) {
  1333. // We can't have recognized the shadow - should blow up now to be on the safe side
  1334. throw new BCException("Couldn't discover annotations for shadow: "+getKind());
  1335. }
  1336. for (int i = 0; i < annotations.length; i++) {
  1337. ResolvedType aTX = annotations[i];
  1338. KindedAnnotationAccessVar kaav = new KindedAnnotationAccessVar(getKind(),aTX.resolve(world),relevantType,relevantMember);
  1339. kindedAnnotationVars.put(aTX,kaav);
  1340. }
  1341. }
  1342. //FIXME asc whats the real diff between this one and the version in findMethod()?
  1343. ResolvedMember findMethod2(ResolvedMember rm[], Member sig) {
  1344. ResolvedMember found = null;
  1345. // String searchString = getSignature().getName()+getSignature().getParameterSignature();
  1346. for (int i = 0; i < rm.length && found==null; i++) {
  1347. ResolvedMember member = rm[i];
  1348. if (member.getName().equals(sig.getName()) && member.getParameterSignature().equals(sig.getParameterSignature()))
  1349. found = member;
  1350. }
  1351. return found;
  1352. }
  1353. private ResolvedMember findMethod(ResolvedType aspectType, ResolvedMember ajcMethod) {
  1354. ResolvedMember decMethods[] = aspectType.getDeclaredMethods();
  1355. for (int i = 0; i < decMethods.length; i++) {
  1356. ResolvedMember member = decMethods[i];
  1357. if (member.equals(ajcMethod)) return member;
  1358. }
  1359. return null;
  1360. }
  1361. private ResolvedMember findField(ResolvedMember[] members,Member lookingFor) {
  1362. for (int i = 0; i < members.length; i++) {
  1363. ResolvedMember member = members[i];
  1364. if ( member.getName().equals(getSignature().getName()) &&
  1365. member.getType().equals(getSignature().getType())) {
  1366. return member;
  1367. }
  1368. }
  1369. return null;
  1370. }
  1371. public void initializeWithinAnnotationVars() {
  1372. if (withinAnnotationVars != null) return;
  1373. withinAnnotationVars = new HashMap();
  1374. ResolvedType[] annotations = getEnclosingType().resolve(world).getAnnotationTypes();
  1375. for (int i = 0; i < annotations.length; i++) {
  1376. ResolvedType ann = annotations[i];
  1377. Kind k = Shadow.StaticInitialization;
  1378. withinAnnotationVars.put(ann,new KindedAnnotationAccessVar(k,ann,getEnclosingType(),null));
  1379. }
  1380. }
  1381. public void initializeWithinCodeAnnotationVars() {
  1382. if (withincodeAnnotationVars != null) return;
  1383. withincodeAnnotationVars = new HashMap();
  1384. // For some shadow we are interested in annotations on the method containing that shadow.
  1385. ResolvedType[] annotations = getEnclosingMethod().getMemberView().getAnnotationTypes();
  1386. for (int i = 0; i < annotations.length; i++) {
  1387. ResolvedType ann = annotations[i];
  1388. Kind k = (getEnclosingMethod().getMemberView().getKind()==Member.CONSTRUCTOR?
  1389. Shadow.ConstructorExecution:Shadow.MethodExecution);
  1390. withincodeAnnotationVars.put(ann,
  1391. new KindedAnnotationAccessVar(k,ann,getEnclosingType(),getEnclosingCodeSignature()));
  1392. }
  1393. }
  1394. // ---- weave methods
  1395. void weaveBefore(BcelAdvice munger) {
  1396. range.insert(
  1397. munger.getAdviceInstructions(this, null, range.getRealStart()),
  1398. Range.InsideBefore);
  1399. }
  1400. public void weaveAfter(BcelAdvice munger) {
  1401. weaveAfterThrowing(munger, UnresolvedType.THROWABLE);
  1402. weaveAfterReturning(munger);
  1403. }
  1404. /**
  1405. * We guarantee that the return value is on the top of the stack when
  1406. * munger.getAdviceInstructions() will be run
  1407. * (Unless we have a void return type in which case there's nothing)
  1408. */
  1409. public void weaveAfterReturning(BcelAdvice munger) {
  1410. // InstructionFactory fact = getFactory();
  1411. List returns = new ArrayList();
  1412. Instruction ret = null;
  1413. for (InstructionHandle ih = range.getStart(); ih != range.getEnd(); ih = ih.getNext()) {
  1414. if (ih.getInstruction() instanceof ReturnInstruction) {
  1415. returns.add(ih);
  1416. ret = Utility.copyInstruction(ih.getInstruction());
  1417. }
  1418. }
  1419. InstructionList retList;
  1420. InstructionHandle afterAdvice;
  1421. if (ret != null) {
  1422. retList = new InstructionList(ret);
  1423. afterAdvice = retList.getStart();
  1424. } else /* if (munger.hasDynamicTests()) */ {
  1425. /*
  1426. *
  1427. 27: getstatic #72; //Field ajc$cflowCounter$0:Lorg/aspectj/runtime/internal/CFlowCounter;
  1428. 30: invokevirtual #87; //Method org/aspectj/runtime/internal/CFlowCounter.dec:()V
  1429. 33: aload 6
  1430. 35: athrow
  1431. 36: nop
  1432. 37: getstatic #72; //Field ajc$cflowCounter$0:Lorg/aspectj/runtime/internal/CFlowCounter;
  1433. 40: invokevirtual #87; //Method org/aspectj/runtime/internal/CFlowCounter.dec:()V
  1434. 43: d2i
  1435. 44: invokespecial #23; //Method java/lang/Object."<init>":()V
  1436. */
  1437. retList = new InstructionList(InstructionConstants.NOP);
  1438. afterAdvice = retList.getStart();
  1439. // } else {
  1440. // retList = new InstructionList();
  1441. // afterAdvice = null;
  1442. }
  1443. InstructionList advice = new InstructionList();
  1444. BcelVar tempVar = null;
  1445. if (munger.hasExtraParameter()) {
  1446. UnresolvedType tempVarType = getReturnType();
  1447. if (tempVarType.equals(ResolvedType.VOID)) {
  1448. tempVar = genTempVar(UnresolvedType.OBJECT);
  1449. advice.append(InstructionConstants.ACONST_NULL);
  1450. tempVar.appendStore(advice, getFactory());
  1451. } else {
  1452. tempVar = genTempVar(tempVarType);
  1453. advice.append(InstructionFactory.createDup(tempVarType.getSize()));
  1454. tempVar.appendStore(advice, getFactory());
  1455. }
  1456. }
  1457. advice.append(munger.getAdviceInstructions(this, tempVar, afterAdvice));
  1458. if (ret != null) {
  1459. InstructionHandle gotoTarget = advice.getStart();
  1460. for (Iterator i = returns.iterator(); i.hasNext();) {
  1461. InstructionHandle ih = (InstructionHandle) i.next();
  1462. Utility.replaceInstruction(
  1463. ih,
  1464. InstructionFactory.createBranchInstruction(
  1465. Constants.GOTO,
  1466. gotoTarget),
  1467. enclosingMethod);
  1468. }
  1469. range.append(advice);
  1470. range.append(retList);
  1471. } else {
  1472. range.append(advice);
  1473. range.append(retList);
  1474. }
  1475. }
  1476. public void weaveAfterThrowing(BcelAdvice munger, UnresolvedType catchType) {
  1477. // a good optimization would be not to generate anything here
  1478. // if the shadow is GUARANTEED empty (i.e., there's NOTHING, not even
  1479. // a shadow, inside me).
  1480. if (getRange().getStart().getNext() == getRange().getEnd()) return;
  1481. InstructionFactory fact = getFactory();
  1482. InstructionList handler = new InstructionList();
  1483. BcelVar exceptionVar = genTempVar(catchType);
  1484. exceptionVar.appendStore(handler, fact);
  1485. // pr62642
  1486. // I will now jump through some firey BCEL hoops to generate a trivial bit of code:
  1487. // if (exc instanceof ExceptionInInitializerError)
  1488. // throw (ExceptionInInitializerError)exc;
  1489. if (this.getEnclosingMethod().getName().equals("<clinit>")) {
  1490. ResolvedType eiieType = world.resolve("java.lang.ExceptionInInitializerError");
  1491. ObjectType eiieBcelType = (ObjectType)BcelWorld.makeBcelType(eiieType);
  1492. InstructionList ih = new InstructionList(InstructionConstants.NOP);
  1493. handler.append(exceptionVar.createLoad(fact));
  1494. handler.append(fact.createInstanceOf(eiieBcelType));
  1495. BranchInstruction bi =
  1496. InstructionFactory.createBranchInstruction(Constants.IFEQ,ih.getStart());
  1497. handler.append(bi);
  1498. handler.append(exceptionVar.createLoad(fact));
  1499. handler.append(fact.createCheckCast(eiieBcelType));
  1500. handler.append(InstructionConstants.ATHROW);
  1501. handler.append(ih);
  1502. }
  1503. InstructionList endHandler = new InstructionList(
  1504. exceptionVar.createLoad(fact));
  1505. handler.append(munger.getAdviceInstructions(this, exceptionVar, endHandler.getStart()));
  1506. handler.append(endHandler);
  1507. handler.append(InstructionConstants.ATHROW);
  1508. InstructionHandle handlerStart = handler.getStart();
  1509. if (isFallsThrough()) {
  1510. InstructionHandle jumpTarget = handler.append(InstructionConstants.NOP);
  1511. handler.insert(InstructionFactory.createBranchInstruction(Constants.GOTO, jumpTarget));
  1512. }
  1513. InstructionHandle protectedEnd = handler.getStart();
  1514. range.insert(handler, Range.InsideAfter);
  1515. enclosingMethod.addExceptionHandler(range.getStart().getNext(), protectedEnd.getPrev(),
  1516. handlerStart, (ObjectType)BcelWorld.makeBcelType(catchType), //???Type.THROWABLE,
  1517. // high priority if our args are on the stack
  1518. getKind().hasHighPriorityExceptions());
  1519. }
  1520. //??? this shares a lot of code with the above weaveAfterThrowing
  1521. //??? would be nice to abstract that to say things only once
  1522. public void weaveSoftener(BcelAdvice munger, UnresolvedType catchType) {
  1523. // a good optimization would be not to generate anything here
  1524. // if the shadow is GUARANTEED empty (i.e., there's NOTHING, not even
  1525. // a shadow, inside me).
  1526. if (getRange().getStart().getNext() == getRange().getEnd()) return;
  1527. InstructionFactory fact = getFactory();
  1528. InstructionList handler = new InstructionList();
  1529. InstructionList rtExHandler = new InstructionList();
  1530. BcelVar exceptionVar = genTempVar(catchType);
  1531. handler.append(fact.createNew(NameMangler.SOFT_EXCEPTION_TYPE));
  1532. handler.append(InstructionFactory.createDup(1));
  1533. handler.append(exceptionVar.createLoad(fact));
  1534. handler.append(fact.createInvoke(NameMangler.SOFT_EXCEPTION_TYPE, "<init>",
  1535. Type.VOID, new Type[] { Type.THROWABLE }, Constants.INVOKESPECIAL)); //??? special
  1536. handler.append(InstructionConstants.ATHROW);
  1537. // ENH 42737
  1538. exceptionVar.appendStore(rtExHandler, fact);
  1539. // aload_1
  1540. rtExHandler.append(exceptionVar.createLoad(fact));
  1541. // instanceof class java/lang/RuntimeException
  1542. rtExHandler.append(fact.createInstanceOf(new ObjectType("java.lang.RuntimeException")));
  1543. // ifeq go to new SOFT_EXCEPTION_TYPE instruction
  1544. rtExHandler.append(InstructionFactory.createBranchInstruction(Constants.IFEQ,handler.getStart()));
  1545. // aload_1
  1546. rtExHandler.append(exceptionVar.createLoad(fact));
  1547. // athrow
  1548. rtExHandler.append(InstructionFactory.ATHROW);
  1549. InstructionHandle handlerStart = rtExHandler.getStart();
  1550. if (isFallsThrough()) {
  1551. InstructionHandle jumpTarget = range.getEnd();//handler.append(fact.NOP);
  1552. rtExHandler.insert(InstructionFactory.createBranchInstruction(Constants.GOTO, jumpTarget));
  1553. }
  1554. rtExHandler.append(handler);
  1555. InstructionHandle protectedEnd = rtExHandler.getStart();
  1556. range.insert(rtExHandler, Range.InsideAfter);
  1557. enclosingMethod.addExceptionHandler(range.getStart().getNext(), protectedEnd.getPrev(),
  1558. handlerStart, (ObjectType)BcelWorld.makeBcelType(catchType),
  1559. // high priority if our args are on the stack
  1560. getKind().hasHighPriorityExceptions());
  1561. }
  1562. public void weavePerObjectEntry(final BcelAdvice munger, final BcelVar onVar) {
  1563. final InstructionFactory fact = getFactory();
  1564. InstructionList entryInstructions = new InstructionList();
  1565. InstructionList entrySuccessInstructions = new InstructionList();
  1566. onVar.appendLoad(entrySuccessInstructions, fact);
  1567. entrySuccessInstructions.append(
  1568. Utility.createInvoke(fact, world,
  1569. AjcMemberMaker.perObjectBind(munger.getConcreteAspect())));
  1570. InstructionList testInstructions =
  1571. munger.getTestInstructions(this, entrySuccessInstructions.getStart(),
  1572. range.getRealStart(),
  1573. entrySuccessInstructions.getStart());
  1574. entryInstructions.append(testInstructions);
  1575. entryInstructions.append(entrySuccessInstructions);
  1576. range.insert(entryInstructions, Range.InsideBefore);
  1577. }
  1578. // PTWIMPL Create static initializer to call the aspect factory
  1579. /**
  1580. * Causes the aspect instance to be *set* for later retrievable through localAspectof()/aspectOf()
  1581. */
  1582. public void weavePerTypeWithinAspectInitialization(final BcelAdvice munger,UnresolvedType t) {
  1583. if (t.resolve(world).isInterface()) return; // Don't initialize statics in
  1584. final InstructionFactory fact = getFactory();
  1585. InstructionList entryInstructions = new InstructionList();
  1586. InstructionList entrySuccessInstructions = new InstructionList();
  1587. BcelObjectType aspectType = BcelWorld.getBcelObjectType(munger.getConcreteAspect());
  1588. String aspectname = munger.getConcreteAspect().getName();
  1589. String ptwField = NameMangler.perTypeWithinFieldForTarget(munger.getConcreteAspect());
  1590. entrySuccessInstructions.append(new PUSH(fact.getConstantPool(),t.getName()));
  1591. entrySuccessInstructions.append(fact.createInvoke(aspectname,"ajc$createAspectInstance",new ObjectType(aspectname),
  1592. new Type[]{new ObjectType("java.lang.String")},Constants.INVOKESTATIC));
  1593. entrySuccessInstructions.append(fact.createPutStatic(t.getName(),ptwField,
  1594. new ObjectType(aspectname)));
  1595. entryInstructions.append(entrySuccessInstructions);
  1596. range.insert(entryInstructions, Range.InsideBefore);
  1597. }
  1598. public void weaveCflowEntry(final BcelAdvice munger, final Member cflowField) {
  1599. final boolean isPer = munger.getKind() == AdviceKind.PerCflowBelowEntry ||
  1600. munger.getKind() == AdviceKind.PerCflowEntry;
  1601. final Type objectArrayType = new ArrayType(Type.OBJECT, 1);
  1602. final InstructionFactory fact = getFactory();
  1603. final BcelVar testResult = genTempVar(ResolvedType.BOOLEAN);
  1604. InstructionList entryInstructions = new InstructionList();
  1605. {
  1606. InstructionList entrySuccessInstructions = new InstructionList();
  1607. if (munger.hasDynamicTests()) {
  1608. entryInstructions.append(Utility.createConstant(fact, 0));
  1609. testResult.appendStore(entryInstructions, fact);
  1610. entrySuccessInstructions.append(Utility.createConstant(fact, 1));
  1611. testResult.appendStore(entrySuccessInstructions, fact);
  1612. }
  1613. if (isPer) {
  1614. entrySuccessInstructions.append(
  1615. fact.createInvoke(munger.getConcreteAspect().getName(),
  1616. NameMangler.PERCFLOW_PUSH_METHOD,
  1617. Type.VOID,
  1618. new Type[] { },
  1619. Constants.INVOKESTATIC));
  1620. } else {
  1621. BcelVar[] cflowStateVars = munger.getExposedStateAsBcelVars();
  1622. if (cflowStateVars.length == 0) {
  1623. // This should be getting managed by a counter - lets make sure.
  1624. if (!cflowField.getType().getName().endsWith("CFlowCounter"))
  1625. throw new RuntimeException("Incorrectly attempting counter operation on stacked cflow");
  1626. entrySuccessInstructions.append(
  1627. Utility.createGet(fact, cflowField));
  1628. //arrayVar.appendLoad(entrySuccessInstructions, fact);
  1629. entrySuccessInstructions.append(fact.createInvoke(NameMangler.CFLOW_COUNTER_TYPE,"inc",Type.VOID,new Type[] { },Constants.INVOKEVIRTUAL));
  1630. } else {
  1631. BcelVar arrayVar = genTempVar(UnresolvedType.OBJECTARRAY);
  1632. int alen = cflowStateVars.length;
  1633. entrySuccessInstructions.append(Utility.createConstant(fact, alen));
  1634. entrySuccessInstructions.append(
  1635. (Instruction) fact.createNewArray(Type.OBJECT, (short) 1));
  1636. arrayVar.appendStore(entrySuccessInstructions, fact);
  1637. for (int i = 0; i < alen; i++) {
  1638. arrayVar.appendConvertableArrayStore(
  1639. entrySuccessInstructions,
  1640. fact,
  1641. i,
  1642. cflowStateVars[i]);
  1643. }
  1644. entrySuccessInstructions.append(
  1645. Utility.createGet(fact, cflowField));
  1646. arrayVar.appendLoad(entrySuccessInstructions, fact);
  1647. entrySuccessInstructions.append(
  1648. fact.createInvoke(NameMangler.CFLOW_STACK_TYPE, "push", Type.VOID,
  1649. new Type[] { objectArrayType },
  1650. Constants.INVOKEVIRTUAL));
  1651. }
  1652. }
  1653. InstructionList testInstructions =
  1654. munger.getTestInstructions(this, entrySuccessInstructions.getStart(),
  1655. range.getRealStart(),
  1656. entrySuccessInstructions.getStart());
  1657. entryInstructions.append(testInstructions);
  1658. entryInstructions.append(entrySuccessInstructions);
  1659. }
  1660. // this is the same for both per and non-per
  1661. weaveAfter(new BcelAdvice(null, null, null, 0, 0, 0, null, null) {
  1662. public InstructionList getAdviceInstructions(
  1663. BcelShadow s,
  1664. BcelVar extraArgVar,
  1665. InstructionHandle ifNoAdvice) {
  1666. InstructionList exitInstructions = new InstructionList();
  1667. if (munger.hasDynamicTests()) {
  1668. testResult.appendLoad(exitInstructions, fact);
  1669. exitInstructions.append(
  1670. InstructionFactory.createBranchInstruction(
  1671. Constants.IFEQ,
  1672. ifNoAdvice));
  1673. }
  1674. exitInstructions.append(Utility.createGet(fact, cflowField));
  1675. if (munger.getKind() != AdviceKind.PerCflowEntry &&
  1676. munger.getKind() != AdviceKind.PerCflowBelowEntry &&
  1677. munger.getExposedStateAsBcelVars().length==0) {
  1678. exitInstructions
  1679. .append(
  1680. fact
  1681. .createInvoke(
  1682. NameMangler.CFLOW_COUNTER_TYPE,
  1683. "dec",
  1684. Type.VOID,
  1685. new Type[] {
  1686. }, Constants.INVOKEVIRTUAL));
  1687. } else {
  1688. exitInstructions
  1689. .append(
  1690. fact
  1691. .createInvoke(
  1692. NameMangler.CFLOW_STACK_TYPE,
  1693. "pop",
  1694. Type.VOID,
  1695. new Type[] {
  1696. }, Constants.INVOKEVIRTUAL));
  1697. }
  1698. return exitInstructions;
  1699. }
  1700. });
  1701. range.insert(entryInstructions, Range.InsideBefore);
  1702. }
  1703. public void weaveAroundInline(
  1704. BcelAdvice munger,
  1705. boolean hasDynamicTest)
  1706. {
  1707. /* Implementation notes:
  1708. *
  1709. * AroundInline still extracts the instructions of the original shadow into
  1710. * an extracted method. This allows inlining of even that advice that doesn't
  1711. * call proceed or calls proceed more than once.
  1712. *
  1713. * It extracts the instructions of the original shadow into a method.
  1714. *
  1715. * Then it extracts the instructions of the advice into a new method defined on
  1716. * this enclosing class. This new method can then be specialized as below.
  1717. *
  1718. * Then it searches in the instructions of the advice for any call to the
  1719. * proceed method.
  1720. *
  1721. * At such a call, there is stuff on the stack representing the arguments to
  1722. * proceed. Pop these into the frame.
  1723. *
  1724. * Now build the stack for the call to the extracted method, taking values
  1725. * either from the join point state or from the new frame locs from proceed.
  1726. * Now call the extracted method. The right return value should be on the
  1727. * stack, so no cast is necessary.
  1728. *
  1729. * If only one call to proceed is made, we can re-inline the original shadow.
  1730. * We are not doing that presently.
  1731. *
  1732. * If the body of the advice can be determined to not alter the stack, or if
  1733. * this shadow doesn't care about the stack, i.e. method-execution, then the
  1734. * new method for the advice can also be re-lined. We are not doing that
  1735. * presently.
  1736. */
  1737. // !!! THIS BLOCK OF CODE SHOULD BE IN A METHOD CALLED weaveAround(...);
  1738. Member mungerSig = munger.getSignature();
  1739. ResolvedType declaringType = world.resolve(mungerSig.getDeclaringType(),true);
  1740. if (declaringType == ResolvedType.MISSING) {
  1741. IMessage msg = new Message(
  1742. WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_DURING_AROUND_WEAVE,declaringType.getClassName()),
  1743. "",IMessage.ERROR,getSourceLocation(),null,
  1744. new ISourceLocation[]{ munger.getSourceLocation()});
  1745. world.getMessageHandler().handleMessage(msg);
  1746. }
  1747. //??? might want some checks here to give better errors
  1748. BcelObjectType ot = BcelWorld.getBcelObjectType(declaringType);
  1749. LazyMethodGen adviceMethod = ot.getLazyClassGen().getLazyMethodGen(mungerSig);
  1750. if (!adviceMethod.getCanInline()) {
  1751. weaveAroundClosure(munger, hasDynamicTest);
  1752. return;
  1753. }
  1754. // specific test for @AJ proceedInInners
  1755. if (munger.getConcreteAspect().isAnnotationStyleAspect()) {
  1756. // if we can't find one proceed()
  1757. // we suspect that the call is happening in an inner class
  1758. // so we don't inline it.
  1759. // Note: for code style, this is done at Aspect compilation time.
  1760. boolean canSeeProceedPassedToOther = false;
  1761. InstructionHandle curr = adviceMethod.getBody().getStart();
  1762. InstructionHandle end = adviceMethod.getBody().getEnd();
  1763. ConstantPoolGen cpg = adviceMethod.getEnclosingClass().getConstantPoolGen();
  1764. while (curr != end) {
  1765. InstructionHandle next = curr.getNext();
  1766. Instruction inst = curr.getInstruction();
  1767. if ((inst instanceof InvokeInstruction)
  1768. && ((InvokeInstruction)inst).getSignature(cpg).indexOf("Lorg/aspectj/lang/ProceedingJoinPoint;") > 0) {
  1769. // we may want to refine to exclude stuff returning jp ?
  1770. // does code style skip inline if i write dump(thisJoinPoint) ?
  1771. canSeeProceedPassedToOther = true;// we see one pjp passed around - dangerous
  1772. break;
  1773. }
  1774. curr = next;
  1775. }
  1776. if (canSeeProceedPassedToOther) {
  1777. // remember this decision to avoid re-analysis
  1778. adviceMethod.setCanInline(false);
  1779. weaveAroundClosure(munger, hasDynamicTest);
  1780. return;
  1781. }
  1782. }
  1783. // We can't inline around methods if they have around advice on them, this
  1784. // is because the weaving will extract the body and hence the proceed call.
  1785. //??? should consider optimizations to recognize simple cases that don't require body extraction
  1786. enclosingMethod.setCanInline(false);
  1787. // start by exposing various useful things into the frame
  1788. final InstructionFactory fact = getFactory();
  1789. // now generate the aroundBody method
  1790. LazyMethodGen extractedMethod =
  1791. extractMethod(
  1792. NameMangler.aroundCallbackMethodName(
  1793. getSignature(),
  1794. getEnclosingClass()),
  1795. Modifier.PRIVATE,
  1796. munger
  1797. );
  1798. // now extract the advice into its own method
  1799. String adviceMethodName =
  1800. NameMangler.aroundCallbackMethodName(
  1801. getSignature(),
  1802. getEnclosingClass()) + "$advice";
  1803. List argVarList = new ArrayList();
  1804. List proceedVarList = new ArrayList();
  1805. int extraParamOffset = 0;
  1806. // Create the extra parameters that are needed for passing to proceed
  1807. // This code is very similar to that found in makeCallToCallback and should
  1808. // be rationalized in the future
  1809. if (thisVar != null) {
  1810. argVarList.add(thisVar);
  1811. proceedVarList.add(new BcelVar(thisVar.getType(), extraParamOffset));
  1812. extraParamOffset += thisVar.getType().getSize();
  1813. }
  1814. if (targetVar != null && targetVar != thisVar) {
  1815. argVarList.add(targetVar);
  1816. proceedVarList.add(new BcelVar(targetVar.getType(), extraParamOffset));
  1817. extraParamOffset += targetVar.getType().getSize();
  1818. }
  1819. for (int i = 0, len = getArgCount(); i < len; i++) {
  1820. argVarList.add(argVars[i]);
  1821. proceedVarList.add(new BcelVar(argVars[i].getType(), extraParamOffset));
  1822. extraParamOffset += argVars[i].getType().getSize();
  1823. }
  1824. if (thisJoinPointVar != null) {
  1825. argVarList.add(thisJoinPointVar);
  1826. proceedVarList.add(new BcelVar(thisJoinPointVar.getType(), extraParamOffset));
  1827. extraParamOffset += thisJoinPointVar.getType().getSize();
  1828. }
  1829. Type[] adviceParameterTypes = adviceMethod.getArgumentTypes();
  1830. Type[] extractedMethodParameterTypes = extractedMethod.getArgumentTypes();
  1831. Type[] parameterTypes =
  1832. new Type[extractedMethodParameterTypes.length
  1833. + adviceParameterTypes.length
  1834. + 1];
  1835. int parameterIndex = 0;
  1836. System.arraycopy(
  1837. extractedMethodParameterTypes,
  1838. 0,
  1839. parameterTypes,
  1840. parameterIndex,
  1841. extractedMethodParameterTypes.length);
  1842. parameterIndex += extractedMethodParameterTypes.length;
  1843. parameterTypes[parameterIndex++] =
  1844. BcelWorld.makeBcelType(adviceMethod.getEnclosingClass().getType());
  1845. System.arraycopy(
  1846. adviceParameterTypes,
  1847. 0,
  1848. parameterTypes,
  1849. parameterIndex,
  1850. adviceParameterTypes.length);
  1851. LazyMethodGen localAdviceMethod =
  1852. new LazyMethodGen(
  1853. Modifier.PRIVATE | Modifier.FINAL | Modifier.STATIC,
  1854. adviceMethod.getReturnType(),
  1855. adviceMethodName,
  1856. parameterTypes,
  1857. new String[0],
  1858. getEnclosingClass());
  1859. String donorFileName = adviceMethod.getEnclosingClass().getInternalFileName();
  1860. String recipientFileName = getEnclosingClass().getInternalFileName();
  1861. // System.err.println("donor " + donorFileName);
  1862. // System.err.println("recip " + recipientFileName);
  1863. if (! donorFileName.equals(recipientFileName)) {
  1864. localAdviceMethod.fromFilename = donorFileName;
  1865. getEnclosingClass().addInlinedSourceFileInfo(
  1866. donorFileName,
  1867. adviceMethod.highestLineNumber);
  1868. }
  1869. getEnclosingClass().addMethodGen(localAdviceMethod);
  1870. // create a map that will move all slots in advice method forward by extraParamOffset
  1871. // in order to make room for the new proceed-required arguments that are added at
  1872. // the beginning of the parameter list
  1873. int nVars = adviceMethod.getMaxLocals() + extraParamOffset;
  1874. IntMap varMap = IntMap.idMap(nVars);
  1875. for (int i=extraParamOffset; i < nVars; i++) {
  1876. varMap.put(i-extraParamOffset, i);
  1877. }
  1878. localAdviceMethod.getBody().insert(
  1879. BcelClassWeaver.genInlineInstructions(adviceMethod,
  1880. localAdviceMethod, varMap, fact, true));
  1881. localAdviceMethod.setMaxLocals(nVars);
  1882. //System.err.println(localAdviceMethod);
  1883. // the shadow is now empty. First, create a correct call
  1884. // to the around advice. This includes both the call (which may involve
  1885. // value conversion of the advice arguments) and the return
  1886. // (which may involve value conversion of the return value). Right now
  1887. // we push a null for the unused closure. It's sad, but there it is.
  1888. InstructionList advice = new InstructionList();
  1889. // InstructionHandle adviceMethodInvocation;
  1890. {
  1891. for (Iterator i = argVarList.iterator(); i.hasNext(); ) {
  1892. BcelVar var = (BcelVar)i.next();
  1893. var.appendLoad(advice, fact);
  1894. }
  1895. // ??? we don't actually need to push NULL for the closure if we take care
  1896. advice.append(
  1897. munger.getAdviceArgSetup(
  1898. this,
  1899. null,
  1900. (munger.getConcreteAspect().isAnnotationStyleAspect())?
  1901. this.loadThisJoinPoint():
  1902. new InstructionList(InstructionConstants.ACONST_NULL)));
  1903. // adviceMethodInvocation =
  1904. advice.append(
  1905. Utility.createInvoke(fact, localAdviceMethod)); //(fact, getWorld(), munger.getSignature()));
  1906. advice.append(
  1907. Utility.createConversion(
  1908. getFactory(),
  1909. BcelWorld.makeBcelType(munger.getSignature().getReturnType()),
  1910. extractedMethod.getReturnType()));
  1911. if (! isFallsThrough()) {
  1912. advice.append(InstructionFactory.createReturn(extractedMethod.getReturnType()));
  1913. }
  1914. }
  1915. // now, situate the call inside the possible dynamic tests,
  1916. // and actually add the whole mess to the shadow
  1917. if (! hasDynamicTest) {
  1918. range.append(advice);
  1919. } else {
  1920. InstructionList afterThingie = new InstructionList(InstructionConstants.NOP);
  1921. InstructionList callback = makeCallToCallback(extractedMethod);
  1922. if (terminatesWithReturn()) {
  1923. callback.append(
  1924. InstructionFactory.createReturn(extractedMethod.getReturnType()));
  1925. } else {
  1926. //InstructionHandle endNop = range.insert(fact.NOP, Range.InsideAfter);
  1927. advice.append(
  1928. InstructionFactory.createBranchInstruction(
  1929. Constants.GOTO,
  1930. afterThingie.getStart()));
  1931. }
  1932. range.append(
  1933. munger.getTestInstructions(
  1934. this,
  1935. advice.getStart(),
  1936. callback.getStart(),
  1937. advice.getStart()));
  1938. range.append(advice);
  1939. range.append(callback);
  1940. range.append(afterThingie);
  1941. }
  1942. // now search through the advice, looking for a call to PROCEED.
  1943. // Then we replace the call to proceed with some argument setup, and a
  1944. // call to the extracted method.
  1945. // inlining support for code style aspects
  1946. if (!munger.getConcreteAspect().isAnnotationStyleAspect()) {
  1947. String proceedName =
  1948. NameMangler.proceedMethodName(munger.getSignature().getName());
  1949. InstructionHandle curr = localAdviceMethod.getBody().getStart();
  1950. InstructionHandle end = localAdviceMethod.getBody().getEnd();
  1951. ConstantPoolGen cpg = localAdviceMethod.getEnclosingClass().getConstantPoolGen();
  1952. while (curr != end) {
  1953. InstructionHandle next = curr.getNext();
  1954. Instruction inst = curr.getInstruction();
  1955. if ((inst instanceof INVOKESTATIC)
  1956. && proceedName.equals(((INVOKESTATIC) inst).getMethodName(cpg))) {
  1957. localAdviceMethod.getBody().append(
  1958. curr,
  1959. getRedoneProceedCall(
  1960. fact,
  1961. extractedMethod,
  1962. munger,
  1963. localAdviceMethod,
  1964. proceedVarList));
  1965. Utility.deleteInstruction(curr, localAdviceMethod);
  1966. }
  1967. curr = next;
  1968. }
  1969. // and that's it.
  1970. } else {
  1971. //ATAJ inlining support for @AJ aspects
  1972. // [TODO document @AJ code rule: don't manipulate 2 jps proceed at the same time.. in an advice body]
  1973. InstructionHandle curr = localAdviceMethod.getBody().getStart();
  1974. InstructionHandle end = localAdviceMethod.getBody().getEnd();
  1975. ConstantPoolGen cpg = localAdviceMethod.getEnclosingClass().getConstantPoolGen();
  1976. while (curr != end) {
  1977. InstructionHandle next = curr.getNext();
  1978. Instruction inst = curr.getInstruction();
  1979. if ((inst instanceof INVOKEINTERFACE)
  1980. && "proceed".equals(((INVOKEINTERFACE) inst).getMethodName(cpg))) {
  1981. final boolean isProceedWithArgs;
  1982. if (((INVOKEINTERFACE) inst).getArgumentTypes(cpg).length == 1) {
  1983. // proceed with args as a boxed Object[]
  1984. isProceedWithArgs = true;
  1985. } else {
  1986. isProceedWithArgs = false;
  1987. }
  1988. InstructionList insteadProceedIl = getRedoneProceedCallForAnnotationStyle(
  1989. fact,
  1990. extractedMethod,
  1991. munger,
  1992. localAdviceMethod,
  1993. proceedVarList,
  1994. isProceedWithArgs
  1995. );
  1996. localAdviceMethod.getBody().append(curr, insteadProceedIl);
  1997. Utility.deleteInstruction(curr, localAdviceMethod);
  1998. }
  1999. curr = next;
  2000. }
  2001. }
  2002. }
  2003. private InstructionList getRedoneProceedCall(
  2004. InstructionFactory fact,
  2005. LazyMethodGen callbackMethod,
  2006. BcelAdvice munger,
  2007. LazyMethodGen localAdviceMethod,
  2008. List argVarList)
  2009. {
  2010. InstructionList ret = new InstructionList();
  2011. // we have on stack all the arguments for the ADVICE call.
  2012. // we have in frame somewhere all the arguments for the non-advice call.
  2013. BcelVar[] adviceVars = munger.getExposedStateAsBcelVars();
  2014. IntMap proceedMap = makeProceedArgumentMap(adviceVars);
  2015. // System.out.println(proceedMap + " for " + this);
  2016. // System.out.println(argVarList);
  2017. ResolvedType[] proceedParamTypes =
  2018. world.resolve(munger.getSignature().getParameterTypes());
  2019. // remove this*JoinPoint* as arguments to proceed
  2020. if (munger.getBaseParameterCount()+1 < proceedParamTypes.length) {
  2021. int len = munger.getBaseParameterCount()+1;
  2022. ResolvedType[] newTypes = new ResolvedType[len];
  2023. System.arraycopy(proceedParamTypes, 0, newTypes, 0, len);
  2024. proceedParamTypes = newTypes;
  2025. }
  2026. //System.out.println("stateTypes: " + Arrays.asList(stateTypes));
  2027. BcelVar[] proceedVars =
  2028. Utility.pushAndReturnArrayOfVars(proceedParamTypes, ret, fact, localAdviceMethod);
  2029. Type[] stateTypes = callbackMethod.getArgumentTypes();
  2030. // System.out.println("stateTypes: " + Arrays.asList(stateTypes));
  2031. for (int i=0, len=stateTypes.length; i < len; i++) {
  2032. Type stateType = stateTypes[i];
  2033. ResolvedType stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
  2034. if (proceedMap.hasKey(i)) {
  2035. //throw new RuntimeException("unimplemented");
  2036. proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX);
  2037. } else {
  2038. ((BcelVar) argVarList.get(i)).appendLoad(ret, fact);
  2039. }
  2040. }
  2041. ret.append(Utility.createInvoke(fact, callbackMethod));
  2042. ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(),
  2043. BcelWorld.makeBcelType(munger.getSignature().getReturnType())));
  2044. return ret;
  2045. }
  2046. /**
  2047. * ATAJ Handle the inlining for @AJ aspects
  2048. *
  2049. * @param fact
  2050. * @param callbackMethod
  2051. * @param munger
  2052. * @param localAdviceMethod
  2053. * @param argVarList
  2054. * @param isProceedWithArgs
  2055. * @return
  2056. */
  2057. private InstructionList getRedoneProceedCallForAnnotationStyle(
  2058. InstructionFactory fact,
  2059. LazyMethodGen callbackMethod,
  2060. BcelAdvice munger,
  2061. LazyMethodGen localAdviceMethod,
  2062. List argVarList,
  2063. boolean isProceedWithArgs)
  2064. {
  2065. // Notes:
  2066. // proceedingjp is on stack (since user was calling pjp.proceed(...)
  2067. // the boxed args to proceed() are on stack as well (Object[]) unless
  2068. // the call is to pjp.proceed(<noarg>)
  2069. // new Object[]{new Integer(argAdvice1-1)};// arg of proceed
  2070. // call to proceed(..) is NOT made
  2071. // instead we do
  2072. // itar callback args i
  2073. // get from array i, convert it to the callback arg i
  2074. // if ask for JP, push the one we got on the stack
  2075. // invoke callback, create conversion back to Object/Integer
  2076. // rest of method -- (hence all those conversions)
  2077. // intValue() from original code
  2078. // int res = .. from original code
  2079. //Note: we just don't care about the proceed map etc
  2080. InstructionList ret = new InstructionList();
  2081. // store the Object[] array on stack if proceed with args
  2082. if (isProceedWithArgs) {
  2083. Type objectArrayType = Type.getType("[Ljava/lang/Object;");
  2084. int localProceedArgArray = localAdviceMethod.allocateLocal(objectArrayType);
  2085. ret.append(InstructionFactory.createStore(objectArrayType, localProceedArgArray));
  2086. Type proceedingJpType = Type.getType("Lorg/aspectj/lang/ProceedingJoinPoint;");
  2087. int localJp = localAdviceMethod.allocateLocal(proceedingJpType);
  2088. ret.append(InstructionFactory.createStore(proceedingJpType, localJp));
  2089. // push on stack each element of the object array
  2090. // that is assumed to be consistent with the callback argument (ie munger args)
  2091. // TODO do we want to try catch ClassCast and AOOBE exception ?
  2092. // special logic when withincode is static or not
  2093. int startIndex = 0;
  2094. if (thisVar != null) {
  2095. startIndex = 1;
  2096. //TODO this logic is actually depending on target as well - test me
  2097. ret.append(new ALOAD(0));//thisVar
  2098. }
  2099. for (int i = startIndex, len=callbackMethod.getArgumentTypes().length; i < len; i++) {
  2100. Type stateType = callbackMethod.getArgumentTypes()[i];
  2101. ResolvedType stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
  2102. if ("Lorg/aspectj/lang/JoinPoint;".equals(stateType.getSignature())) {
  2103. ret.append(new ALOAD(localJp));// from localAdvice signature
  2104. } else {
  2105. ret.append(InstructionFactory.createLoad(objectArrayType, localProceedArgArray));
  2106. ret.append(Utility.createConstant(fact, i-startIndex));
  2107. ret.append(InstructionFactory.createArrayLoad(Type.OBJECT));
  2108. ret.append(Utility.createConversion(
  2109. fact,
  2110. Type.OBJECT,
  2111. stateType
  2112. ));
  2113. }
  2114. }
  2115. } else {
  2116. Type proceedingJpType = Type.getType("Lorg/aspectj/lang/ProceedingJoinPoint;");
  2117. int localJp = localAdviceMethod.allocateLocal(proceedingJpType);
  2118. ret.append(InstructionFactory.createStore(proceedingJpType, localJp));
  2119. for (int i = 0, len=callbackMethod.getArgumentTypes().length; i < len; i++) {
  2120. Type stateType = callbackMethod.getArgumentTypes()[i];
  2121. ResolvedType stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
  2122. if ("Lorg/aspectj/lang/JoinPoint;".equals(stateType.getSignature())) {
  2123. ret.append(new ALOAD(localJp));// from localAdvice signature
  2124. // } else if ("Lorg/aspectj/lang/ProceedingJoinPoint;".equals(stateType.getSignature())) {
  2125. // //FIXME ALEX?
  2126. // ret.append(new ALOAD(localJp));// from localAdvice signature
  2127. //// ret.append(fact.createCheckCast(
  2128. //// (ReferenceType) BcelWorld.makeBcelType(stateTypeX)
  2129. //// ));
  2130. // // cast ?
  2131. //
  2132. } else {
  2133. ret.append(InstructionFactory.createLoad(stateType, i));
  2134. }
  2135. }
  2136. }
  2137. // do the callback invoke
  2138. ret.append(Utility.createInvoke(fact, callbackMethod));
  2139. // box it again. Handles cases where around advice does return something else than Object
  2140. if (!UnresolvedType.OBJECT.equals(munger.getSignature().getReturnType())) {
  2141. ret.append(Utility.createConversion(
  2142. fact,
  2143. callbackMethod.getReturnType(),
  2144. Type.OBJECT
  2145. ));
  2146. }
  2147. ret.append(Utility.createConversion(
  2148. fact,
  2149. callbackMethod.getReturnType(),
  2150. BcelWorld.makeBcelType(munger.getSignature().getReturnType())
  2151. ));
  2152. return ret;
  2153. //
  2154. //
  2155. //
  2156. // if (proceedMap.hasKey(i)) {
  2157. // ret.append(new ALOAD(i));
  2158. // //throw new RuntimeException("unimplemented");
  2159. // //proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX);
  2160. // } else {
  2161. // //((BcelVar) argVarList.get(i)).appendLoad(ret, fact);
  2162. // //ret.append(new ALOAD(i));
  2163. // if ("Lorg/aspectj/lang/JoinPoint;".equals(stateType.getSignature())) {
  2164. // ret.append(new ALOAD(i));
  2165. // } else {
  2166. // ret.append(new ALOAD(i));
  2167. // }
  2168. // }
  2169. // }
  2170. //
  2171. // ret.append(Utility.createInvoke(fact, callbackMethod));
  2172. // ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(),
  2173. // BcelWorld.makeBcelType(munger.getSignature().getReturnType())));
  2174. //
  2175. // //ret.append(new ACONST_NULL());//will be POPed
  2176. // if (true) return ret;
  2177. //
  2178. //
  2179. //
  2180. // // we have on stack all the arguments for the ADVICE call.
  2181. // // we have in frame somewhere all the arguments for the non-advice call.
  2182. //
  2183. // BcelVar[] adviceVars = munger.getExposedStateAsBcelVars();
  2184. // IntMap proceedMap = makeProceedArgumentMap(adviceVars);
  2185. //
  2186. // System.out.println(proceedMap + " for " + this);
  2187. // System.out.println(argVarList);
  2188. //
  2189. // ResolvedType[] proceedParamTypes =
  2190. // world.resolve(munger.getSignature().getParameterTypes());
  2191. // // remove this*JoinPoint* as arguments to proceed
  2192. // if (munger.getBaseParameterCount()+1 < proceedParamTypes.length) {
  2193. // int len = munger.getBaseParameterCount()+1;
  2194. // ResolvedType[] newTypes = new ResolvedType[len];
  2195. // System.arraycopy(proceedParamTypes, 0, newTypes, 0, len);
  2196. // proceedParamTypes = newTypes;
  2197. // }
  2198. //
  2199. // //System.out.println("stateTypes: " + Arrays.asList(stateTypes));
  2200. // BcelVar[] proceedVars =
  2201. // Utility.pushAndReturnArrayOfVars(proceedParamTypes, ret, fact, localAdviceMethod);
  2202. //
  2203. // Type[] stateTypes = callbackMethod.getArgumentTypes();
  2204. //// System.out.println("stateTypes: " + Arrays.asList(stateTypes));
  2205. //
  2206. // for (int i=0, len=stateTypes.length; i < len; i++) {
  2207. // Type stateType = stateTypes[i];
  2208. // ResolvedType stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
  2209. // if (proceedMap.hasKey(i)) {
  2210. // //throw new RuntimeException("unimplemented");
  2211. // proceedVars[proceedMap.get(i)].appendLoadAndConvert(ret, fact, stateTypeX);
  2212. // } else {
  2213. // ((BcelVar) argVarList.get(i)).appendLoad(ret, fact);
  2214. // }
  2215. // }
  2216. //
  2217. // ret.append(Utility.createInvoke(fact, callbackMethod));
  2218. // ret.append(Utility.createConversion(fact, callbackMethod.getReturnType(),
  2219. // BcelWorld.makeBcelType(munger.getSignature().getReturnType())));
  2220. // return ret;
  2221. }
  2222. public void weaveAroundClosure(BcelAdvice munger, boolean hasDynamicTest) {
  2223. InstructionFactory fact = getFactory();
  2224. enclosingMethod.setCanInline(false);
  2225. // MOVE OUT ALL THE INSTRUCTIONS IN MY SHADOW INTO ANOTHER METHOD!
  2226. LazyMethodGen callbackMethod =
  2227. extractMethod(
  2228. NameMangler.aroundCallbackMethodName(
  2229. getSignature(),
  2230. getEnclosingClass()),
  2231. 0,
  2232. munger);
  2233. BcelVar[] adviceVars = munger.getExposedStateAsBcelVars();
  2234. String closureClassName =
  2235. NameMangler.makeClosureClassName(
  2236. getEnclosingClass().getType(),
  2237. getEnclosingClass().getNewGeneratedNameTag());
  2238. Member constructorSig = new MemberImpl(Member.CONSTRUCTOR,
  2239. UnresolvedType.forName(closureClassName), 0, "<init>",
  2240. "([Ljava/lang/Object;)V");
  2241. BcelVar closureHolder = null;
  2242. // This is not being used currently since getKind() == preinitializaiton
  2243. // cannot happen in around advice
  2244. if (getKind() == PreInitialization) {
  2245. closureHolder = genTempVar(AjcMemberMaker.AROUND_CLOSURE_TYPE);
  2246. }
  2247. InstructionList closureInstantiation =
  2248. makeClosureInstantiation(constructorSig, closureHolder);
  2249. /*LazyMethodGen constructor = */
  2250. makeClosureClassAndReturnConstructor(
  2251. closureClassName,
  2252. callbackMethod,
  2253. makeProceedArgumentMap(adviceVars)
  2254. );
  2255. InstructionList returnConversionCode;
  2256. if (getKind() == PreInitialization) {
  2257. returnConversionCode = new InstructionList();
  2258. BcelVar stateTempVar = genTempVar(UnresolvedType.OBJECTARRAY);
  2259. closureHolder.appendLoad(returnConversionCode, fact);
  2260. returnConversionCode.append(
  2261. Utility.createInvoke(
  2262. fact,
  2263. world,
  2264. AjcMemberMaker.aroundClosurePreInitializationGetter()));
  2265. stateTempVar.appendStore(returnConversionCode, fact);
  2266. Type[] stateTypes = getSuperConstructorParameterTypes();
  2267. returnConversionCode.append(InstructionConstants.ALOAD_0); // put "this" back on the stack
  2268. for (int i = 0, len = stateTypes.length; i < len; i++) {
  2269. UnresolvedType bcelTX = BcelWorld.fromBcel(stateTypes[i]);
  2270. ResolvedType stateRTX = world.resolve(bcelTX,true);
  2271. if (stateRTX == ResolvedType.MISSING) {
  2272. IMessage msg = new Message(
  2273. WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE_DURING_AROUND_WEAVE_PREINIT,bcelTX.getClassName()),
  2274. "",IMessage.ERROR,getSourceLocation(),null,
  2275. new ISourceLocation[]{ munger.getSourceLocation()});
  2276. world.getMessageHandler().handleMessage(msg);
  2277. }
  2278. stateTempVar.appendConvertableArrayLoad(
  2279. returnConversionCode,
  2280. fact,
  2281. i,
  2282. stateRTX);
  2283. }
  2284. } else {
  2285. returnConversionCode =
  2286. Utility.createConversion(
  2287. getFactory(),
  2288. BcelWorld.makeBcelType(munger.getSignature().getReturnType()),
  2289. callbackMethod.getReturnType());
  2290. if (!isFallsThrough()) {
  2291. returnConversionCode.append(
  2292. InstructionFactory.createReturn(callbackMethod.getReturnType()));
  2293. }
  2294. }
  2295. // ATAJ for @AJ aspect we need to link the closure with the joinpoint instance
  2296. if (munger.getConcreteAspect()!=null && munger.getConcreteAspect().isAnnotationStyleAspect()) {
  2297. closureInstantiation.append(Utility.createInvoke(
  2298. getFactory(),
  2299. getWorld(),
  2300. new MemberImpl(
  2301. Member.METHOD,
  2302. UnresolvedType.forName("org.aspectj.runtime.internal.AroundClosure"),
  2303. Modifier.PUBLIC,
  2304. "linkClosureAndJoinPoint",
  2305. "()Lorg/aspectj/lang/ProceedingJoinPoint;"
  2306. )
  2307. ));
  2308. }
  2309. InstructionList advice = new InstructionList();
  2310. advice.append(munger.getAdviceArgSetup(this, null, closureInstantiation));
  2311. // invoke the advice
  2312. advice.append(munger.getNonTestAdviceInstructions(this));
  2313. advice.append(returnConversionCode);
  2314. if (!hasDynamicTest) {
  2315. range.append(advice);
  2316. } else {
  2317. InstructionList callback = makeCallToCallback(callbackMethod);
  2318. InstructionList postCallback = new InstructionList();
  2319. if (terminatesWithReturn()) {
  2320. callback.append(
  2321. InstructionFactory.createReturn(callbackMethod.getReturnType()));
  2322. } else {
  2323. advice.append(
  2324. InstructionFactory.createBranchInstruction(
  2325. Constants.GOTO,
  2326. postCallback.append(InstructionConstants.NOP)));
  2327. }
  2328. range.append(
  2329. munger.getTestInstructions(
  2330. this,
  2331. advice.getStart(),
  2332. callback.getStart(),
  2333. advice.getStart()));
  2334. range.append(advice);
  2335. range.append(callback);
  2336. range.append(postCallback);
  2337. }
  2338. }
  2339. // exposed for testing
  2340. InstructionList makeCallToCallback(LazyMethodGen callbackMethod) {
  2341. InstructionFactory fact = getFactory();
  2342. InstructionList callback = new InstructionList();
  2343. if (thisVar != null) {
  2344. callback.append(InstructionConstants.ALOAD_0);
  2345. }
  2346. if (targetVar != null && targetVar != thisVar) {
  2347. callback.append(BcelRenderer.renderExpr(fact, world, targetVar));
  2348. }
  2349. callback.append(BcelRenderer.renderExprs(fact, world, argVars));
  2350. // remember to render tjps
  2351. if (thisJoinPointVar != null) {
  2352. callback.append(BcelRenderer.renderExpr(fact, world, thisJoinPointVar));
  2353. }
  2354. callback.append(Utility.createInvoke(fact, callbackMethod));
  2355. return callback;
  2356. }
  2357. /** side-effect-free */
  2358. private InstructionList makeClosureInstantiation(Member constructor, BcelVar holder) {
  2359. // LazyMethodGen constructor) {
  2360. InstructionFactory fact = getFactory();
  2361. BcelVar arrayVar = genTempVar(UnresolvedType.OBJECTARRAY);
  2362. //final Type objectArrayType = new ArrayType(Type.OBJECT, 1);
  2363. final InstructionList il = new InstructionList();
  2364. int alen = getArgCount() + (thisVar == null ? 0 : 1) +
  2365. ((targetVar != null && targetVar != thisVar) ? 1 : 0) +
  2366. (thisJoinPointVar == null ? 0 : 1);
  2367. il.append(Utility.createConstant(fact, alen));
  2368. il.append((Instruction)fact.createNewArray(Type.OBJECT, (short)1));
  2369. arrayVar.appendStore(il, fact);
  2370. int stateIndex = 0;
  2371. if (thisVar != null) {
  2372. arrayVar.appendConvertableArrayStore(il, fact, stateIndex, thisVar);
  2373. thisVar.setPositionInAroundState(stateIndex);
  2374. stateIndex++;
  2375. }
  2376. if (targetVar != null && targetVar != thisVar) {
  2377. arrayVar.appendConvertableArrayStore(il, fact, stateIndex, targetVar);
  2378. targetVar.setPositionInAroundState(stateIndex);
  2379. stateIndex++;
  2380. }
  2381. for (int i = 0, len = getArgCount(); i<len; i++) {
  2382. arrayVar.appendConvertableArrayStore(il, fact, stateIndex, argVars[i]);
  2383. argVars[i].setPositionInAroundState(stateIndex);
  2384. stateIndex++;
  2385. }
  2386. if (thisJoinPointVar != null) {
  2387. arrayVar.appendConvertableArrayStore(il, fact, stateIndex, thisJoinPointVar);
  2388. thisJoinPointVar.setPositionInAroundState(stateIndex);
  2389. stateIndex++;
  2390. }
  2391. il.append(fact.createNew(new ObjectType(constructor.getDeclaringType().getName())));
  2392. il.append(new DUP());
  2393. arrayVar.appendLoad(il, fact);
  2394. il.append(Utility.createInvoke(fact, world, constructor));
  2395. if (getKind() == PreInitialization) {
  2396. il.append(InstructionConstants.DUP);
  2397. holder.appendStore(il, fact);
  2398. }
  2399. return il;
  2400. }
  2401. private IntMap makeProceedArgumentMap(BcelVar[] adviceArgs) {
  2402. //System.err.println("coming in with " + Arrays.asList(adviceArgs));
  2403. IntMap ret = new IntMap();
  2404. for(int i = 0, len = adviceArgs.length; i < len; i++) {
  2405. BcelVar v = (BcelVar) adviceArgs[i];
  2406. if (v == null) continue; // XXX we don't know why this is required
  2407. int pos = v.getPositionInAroundState();
  2408. if (pos >= 0) { // need this test to avoid args bound via cflow
  2409. ret.put(pos, i);
  2410. }
  2411. }
  2412. //System.err.println("returning " + ret);
  2413. return ret;
  2414. }
  2415. /**
  2416. *
  2417. *
  2418. * @param callbackMethod the method we will call back to when our run method gets called.
  2419. *
  2420. * @param proceedMap A map from state position to proceed argument position. May be
  2421. * non covering on state position.
  2422. */
  2423. private LazyMethodGen makeClosureClassAndReturnConstructor(
  2424. String closureClassName,
  2425. LazyMethodGen callbackMethod,
  2426. IntMap proceedMap)
  2427. {
  2428. String superClassName = "org.aspectj.runtime.internal.AroundClosure";
  2429. Type objectArrayType = new ArrayType(Type.OBJECT, 1);
  2430. LazyClassGen closureClass = new LazyClassGen(closureClassName,
  2431. superClassName,
  2432. getEnclosingClass().getFileName(),
  2433. Modifier.PUBLIC,
  2434. new String[] {},
  2435. getWorld());
  2436. InstructionFactory fact = new InstructionFactory(closureClass.getConstantPoolGen());
  2437. // constructor
  2438. LazyMethodGen constructor = new LazyMethodGen(Modifier.PUBLIC,
  2439. Type.VOID,
  2440. "<init>",
  2441. new Type[] {objectArrayType},
  2442. new String[] {},
  2443. closureClass);
  2444. InstructionList cbody = constructor.getBody();
  2445. cbody.append(InstructionFactory.createLoad(Type.OBJECT, 0));
  2446. cbody.append(InstructionFactory.createLoad(objectArrayType, 1));
  2447. cbody.append(fact.createInvoke(superClassName, "<init>", Type.VOID,
  2448. new Type[] {objectArrayType}, Constants.INVOKESPECIAL));
  2449. cbody.append(InstructionFactory.createReturn(Type.VOID));
  2450. closureClass.addMethodGen(constructor);
  2451. // method
  2452. LazyMethodGen runMethod = new LazyMethodGen(Modifier.PUBLIC,
  2453. Type.OBJECT,
  2454. "run",
  2455. new Type[] {objectArrayType},
  2456. new String[] {},
  2457. closureClass);
  2458. InstructionList mbody = runMethod.getBody();
  2459. BcelVar proceedVar = new BcelVar(UnresolvedType.OBJECTARRAY.resolve(world), 1);
  2460. // int proceedVarIndex = 1;
  2461. BcelVar stateVar =
  2462. new BcelVar(UnresolvedType.OBJECTARRAY.resolve(world), runMethod.allocateLocal(1));
  2463. // int stateVarIndex = runMethod.allocateLocal(1);
  2464. mbody.append(InstructionFactory.createThis());
  2465. mbody.append(fact.createGetField(superClassName, "state", objectArrayType));
  2466. mbody.append(stateVar.createStore(fact));
  2467. // mbody.append(fact.createStore(objectArrayType, stateVarIndex));
  2468. Type[] stateTypes = callbackMethod.getArgumentTypes();
  2469. for (int i=0, len=stateTypes.length; i < len; i++) {
  2470. Type stateType = stateTypes[i];
  2471. ResolvedType stateTypeX = BcelWorld.fromBcel(stateType).resolve(world);
  2472. if (proceedMap.hasKey(i)) {
  2473. mbody.append(
  2474. proceedVar.createConvertableArrayLoad(fact, proceedMap.get(i),
  2475. stateTypeX));
  2476. } else {
  2477. mbody.append(
  2478. stateVar.createConvertableArrayLoad(fact, i,
  2479. stateTypeX));
  2480. }
  2481. }
  2482. mbody.append(Utility.createInvoke(fact, callbackMethod));
  2483. if (getKind() == PreInitialization) {
  2484. mbody.append(Utility.createSet(
  2485. fact,
  2486. AjcMemberMaker.aroundClosurePreInitializationField()));
  2487. mbody.append(InstructionConstants.ACONST_NULL);
  2488. } else {
  2489. mbody.append(
  2490. Utility.createConversion(
  2491. fact,
  2492. callbackMethod.getReturnType(),
  2493. Type.OBJECT));
  2494. }
  2495. mbody.append(InstructionFactory.createReturn(Type.OBJECT));
  2496. closureClass.addMethodGen(runMethod);
  2497. // class
  2498. getEnclosingClass().addGeneratedInner(closureClass);
  2499. return constructor;
  2500. }
  2501. // ---- extraction methods
  2502. public LazyMethodGen extractMethod(String newMethodName, int visibilityModifier, ShadowMunger munger) {
  2503. LazyMethodGen.assertGoodBody(range.getBody(), newMethodName);
  2504. if (!getKind().allowsExtraction()) throw new BCException("Attempt to extract method from a shadow kind that does not support this operation (" + getKind() + ")");
  2505. LazyMethodGen freshMethod = createMethodGen(newMethodName,visibilityModifier);
  2506. // System.err.println("******");
  2507. // System.err.println("ABOUT TO EXTRACT METHOD for" + this);
  2508. // enclosingMethod.print(System.err);
  2509. // System.err.println("INTO");
  2510. // freshMethod.print(System.err);
  2511. // System.err.println("WITH REMAP");
  2512. // System.err.println(makeRemap());
  2513. range.extractInstructionsInto(freshMethod, makeRemap(),
  2514. (getKind() != PreInitialization) &&
  2515. isFallsThrough());
  2516. if (getKind() == PreInitialization) {
  2517. addPreInitializationReturnCode(
  2518. freshMethod,
  2519. getSuperConstructorParameterTypes());
  2520. }
  2521. getEnclosingClass().addMethodGen(freshMethod,munger.getSourceLocation());
  2522. return freshMethod;
  2523. }
  2524. private void addPreInitializationReturnCode(
  2525. LazyMethodGen extractedMethod,
  2526. Type[] superConstructorTypes)
  2527. {
  2528. InstructionList body = extractedMethod.getBody();
  2529. final InstructionFactory fact = getFactory();
  2530. BcelVar arrayVar = new BcelVar(
  2531. world.getCoreType(UnresolvedType.OBJECTARRAY),
  2532. extractedMethod.allocateLocal(1));
  2533. int len = superConstructorTypes.length;
  2534. body.append(Utility.createConstant(fact, len));
  2535. body.append((Instruction)fact.createNewArray(Type.OBJECT, (short)1));
  2536. arrayVar.appendStore(body, fact);
  2537. for (int i = len - 1; i >= 0; i++) {
  2538. // convert thing on top of stack to object
  2539. body.append(
  2540. Utility.createConversion(fact, superConstructorTypes[i], Type.OBJECT));
  2541. // push object array
  2542. arrayVar.appendLoad(body, fact);
  2543. // swap
  2544. body.append(InstructionConstants.SWAP);
  2545. // do object array store.
  2546. body.append(Utility.createConstant(fact, i));
  2547. body.append(InstructionConstants.SWAP);
  2548. body.append(InstructionFactory.createArrayStore(Type.OBJECT));
  2549. }
  2550. arrayVar.appendLoad(body, fact);
  2551. body.append(InstructionConstants.ARETURN);
  2552. }
  2553. private Type[] getSuperConstructorParameterTypes() {
  2554. // assert getKind() == PreInitialization
  2555. InstructionHandle superCallHandle = getRange().getEnd().getNext();
  2556. InvokeInstruction superCallInstruction =
  2557. (InvokeInstruction) superCallHandle.getInstruction();
  2558. return superCallInstruction.getArgumentTypes(
  2559. getEnclosingClass().getConstantPoolGen());
  2560. }
  2561. /** make a map from old frame location to new frame location. Any unkeyed frame
  2562. * location picks out a copied local */
  2563. private IntMap makeRemap() {
  2564. IntMap ret = new IntMap(5);
  2565. int reti = 0;
  2566. if (thisVar != null) {
  2567. ret.put(0, reti++); // thisVar guaranteed to be 0
  2568. }
  2569. if (targetVar != null && targetVar != thisVar) {
  2570. ret.put(targetVar.getSlot(), reti++);
  2571. }
  2572. for (int i = 0, len = argVars.length; i < len; i++) {
  2573. ret.put(argVars[i].getSlot(), reti);
  2574. reti += argVars[i].getType().getSize();
  2575. }
  2576. if (thisJoinPointVar != null) {
  2577. ret.put(thisJoinPointVar.getSlot(), reti++);
  2578. }
  2579. // we not only need to put the arguments, we also need to remap their
  2580. // aliases, which we so helpfully put into temps at the beginning of this join
  2581. // point.
  2582. if (! getKind().argsOnStack()) {
  2583. int oldi = 0;
  2584. int newi = 0;
  2585. // if we're passing in a this and we're not argsOnStack we're always
  2586. // passing in a target too
  2587. if (arg0HoldsThis()) { ret.put(0, 0); oldi++; newi+=1; }
  2588. //assert targetVar == thisVar
  2589. for (int i = 0; i < getArgCount(); i++) {
  2590. UnresolvedType type = getArgType(i);
  2591. ret.put(oldi, newi);
  2592. oldi += type.getSize();
  2593. newi += type.getSize();
  2594. }
  2595. }
  2596. // System.err.println("making remap for : " + this);
  2597. // if (targetVar != null) System.err.println("target slot : " + targetVar.getSlot());
  2598. // if (thisVar != null) System.err.println(" this slot : " + thisVar.getSlot());
  2599. // System.err.println(ret);
  2600. return ret;
  2601. }
  2602. /**
  2603. * The new method always static.
  2604. * It may take some extra arguments: this, target.
  2605. * If it's argsOnStack, then it must take both this/target
  2606. * If it's argsOnFrame, it shares this and target.
  2607. * ??? rewrite this to do less array munging, please
  2608. */
  2609. private LazyMethodGen createMethodGen(String newMethodName, int visibilityModifier) {
  2610. Type[] parameterTypes = BcelWorld.makeBcelTypes(getArgTypes());
  2611. int modifiers = Modifier.FINAL | visibilityModifier;
  2612. // XXX some bug
  2613. // if (! isExpressionKind() && getSignature().isStrict(world)) {
  2614. // modifiers |= Modifier.STRICT;
  2615. // }
  2616. modifiers |= Modifier.STATIC;
  2617. if (targetVar != null && targetVar != thisVar) {
  2618. UnresolvedType targetType = getTargetType();
  2619. targetType = ensureTargetTypeIsCorrect(targetType);
  2620. // see pr109728 - this fixes the case when the declaring class is sometype 'X' but the getfield
  2621. // in the bytecode refers to a subtype of 'X'. This makes sure we use the type originally
  2622. // mentioned in the fieldget instruction as the method parameter and *not* the type upon which the
  2623. // field is declared because when the instructions are extracted into the new around body,
  2624. // they will still refer to the subtype.
  2625. if (getKind()==FieldGet && getActualTargetType()!=null &&
  2626. !getActualTargetType().equals(targetType.getName())) {
  2627. targetType = UnresolvedType.forName(getActualTargetType()).resolve(world);
  2628. }
  2629. ResolvedMember resolvedMember = getSignature().resolve(world);
  2630. if (resolvedMember != null && Modifier.isProtected(resolvedMember.getModifiers()) &&
  2631. !samePackage(targetType.getPackageName(), getEnclosingType().getPackageName()) &&
  2632. !resolvedMember.getName().equals("clone"))
  2633. {
  2634. if (!targetType.resolve(world).isAssignableFrom(getThisType().resolve(world))) {
  2635. throw new BCException("bad bytecode");
  2636. }
  2637. targetType = getThisType();
  2638. }
  2639. parameterTypes = addType(BcelWorld.makeBcelType(targetType), parameterTypes);
  2640. }
  2641. if (thisVar != null) {
  2642. UnresolvedType thisType = getThisType();
  2643. parameterTypes = addType(BcelWorld.makeBcelType(thisType), parameterTypes);
  2644. }
  2645. // We always want to pass down thisJoinPoint in case we have already woven
  2646. // some advice in here. If we only have a single piece of around advice on a
  2647. // join point, it is unnecessary to accept (and pass) tjp.
  2648. if (thisJoinPointVar != null) {
  2649. parameterTypes = addTypeToEnd(LazyClassGen.tjpType, parameterTypes);
  2650. //FIXME ALEX? which one
  2651. //parameterTypes = addTypeToEnd(LazyClassGen.proceedingTjpType, parameterTypes);
  2652. }
  2653. UnresolvedType returnType;
  2654. if (getKind() == PreInitialization) {
  2655. returnType = UnresolvedType.OBJECTARRAY;
  2656. } else {
  2657. returnType = getReturnType();
  2658. }
  2659. return
  2660. new LazyMethodGen(
  2661. modifiers,
  2662. BcelWorld.makeBcelType(returnType),
  2663. newMethodName,
  2664. parameterTypes,
  2665. new String[0],
  2666. // XXX again, we need to look up methods!
  2667. // UnresolvedType.getNames(getSignature().getExceptions(world)),
  2668. getEnclosingClass());
  2669. }
  2670. private boolean samePackage(String p1, String p2) {
  2671. if (p1 == null) return p2 == null;
  2672. if (p2 == null) return false;
  2673. return p1.equals(p2);
  2674. }
  2675. private Type[] addType(Type type, Type[] types) {
  2676. int len = types.length;
  2677. Type[] ret = new Type[len+1];
  2678. ret[0] = type;
  2679. System.arraycopy(types, 0, ret, 1, len);
  2680. return ret;
  2681. }
  2682. private Type[] addTypeToEnd(Type type, Type[] types) {
  2683. int len = types.length;
  2684. Type[] ret = new Type[len+1];
  2685. ret[len] = type;
  2686. System.arraycopy(types, 0, ret, 0, len);
  2687. return ret;
  2688. }
  2689. public BcelVar genTempVar(UnresolvedType typeX) {
  2690. return new BcelVar(typeX.resolve(world), genTempVarIndex(typeX.getSize()));
  2691. }
  2692. // public static final boolean CREATE_TEMP_NAMES = true;
  2693. public BcelVar genTempVar(UnresolvedType typeX, String localName) {
  2694. BcelVar tv = genTempVar(typeX);
  2695. // if (CREATE_TEMP_NAMES) {
  2696. // for (InstructionHandle ih = range.getStart(); ih != range.getEnd(); ih = ih.getNext()) {
  2697. // if (Range.isRangeHandle(ih)) continue;
  2698. // ih.addTargeter(new LocalVariableTag(typeX, localName, tv.getSlot()));
  2699. // }
  2700. // }
  2701. return tv;
  2702. }
  2703. // eh doesn't think we need to garbage collect these (64K is a big number...)
  2704. private int genTempVarIndex(int size) {
  2705. return enclosingMethod.allocateLocal(size);
  2706. }
  2707. public InstructionFactory getFactory() {
  2708. return getEnclosingClass().getFactory();
  2709. }
  2710. public ISourceLocation getSourceLocation() {
  2711. int sourceLine = getSourceLine();
  2712. if (sourceLine == 0 || sourceLine == -1) {
  2713. // Thread.currentThread().dumpStack();
  2714. // System.err.println(this + ": " + range);
  2715. return getEnclosingClass().getType().getSourceLocation();
  2716. } else {
  2717. // For staticinitialization, if we have a nice offset, don't build a new source loc
  2718. if (getKind()==Shadow.StaticInitialization && getEnclosingClass().getType().getSourceLocation().getOffset()!=0) {
  2719. return getEnclosingClass().getType().getSourceLocation();
  2720. } else {
  2721. int offset = 0;
  2722. Kind kind = getKind();
  2723. if ( (kind == MethodExecution) ||
  2724. (kind == ConstructorExecution) ||
  2725. (kind == AdviceExecution) ||
  2726. (kind == StaticInitialization) ||
  2727. (kind == PreInitialization) ||
  2728. (kind == Initialization)) {
  2729. if (getEnclosingMethod().hasDeclaredLineNumberInfo()) {
  2730. offset = getEnclosingMethod().getDeclarationOffset();
  2731. }
  2732. }
  2733. return getEnclosingClass().getType().getSourceContext().makeSourceLocation(sourceLine, offset);
  2734. }
  2735. }
  2736. }
  2737. public Shadow getEnclosingShadow() {
  2738. return enclosingShadow;
  2739. }
  2740. public LazyMethodGen getEnclosingMethod() {
  2741. return enclosingMethod;
  2742. }
  2743. public boolean isFallsThrough() {
  2744. return !terminatesWithReturn(); //fallsThrough;
  2745. }
  2746. public void setActualTargetType(String className) {
  2747. this.actualInstructionTargetType = className;
  2748. }
  2749. public String getActualTargetType() {
  2750. return actualInstructionTargetType;
  2751. }
  2752. }