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.

BcelClassWeaver.java 40KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181
  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. * ******************************************************************/
  12. package org.aspectj.weaver.bcel;
  13. import java.lang.reflect.Modifier;
  14. import java.util.ArrayList;
  15. import java.util.Collections;
  16. import java.util.Comparator;
  17. import java.util.HashMap;
  18. import java.util.HashSet;
  19. import java.util.Iterator;
  20. import java.util.List;
  21. import java.util.Map;
  22. import java.util.Set;
  23. import org.apache.bcel.Constants;
  24. import org.apache.bcel.generic.BranchInstruction;
  25. import org.apache.bcel.generic.CPInstruction;
  26. import org.apache.bcel.generic.ConstantPoolGen;
  27. import org.apache.bcel.generic.FieldInstruction;
  28. import org.apache.bcel.generic.INVOKESPECIAL;
  29. import org.apache.bcel.generic.IndexedInstruction;
  30. import org.apache.bcel.generic.Instruction;
  31. import org.apache.bcel.generic.InstructionConstants;
  32. import org.apache.bcel.generic.InstructionFactory;
  33. import org.apache.bcel.generic.InstructionHandle;
  34. import org.apache.bcel.generic.InstructionList;
  35. import org.apache.bcel.generic.InstructionTargeter;
  36. import org.apache.bcel.generic.InvokeInstruction;
  37. import org.apache.bcel.generic.LocalVariableInstruction;
  38. import org.apache.bcel.generic.NEW;
  39. import org.apache.bcel.generic.ObjectType;
  40. import org.apache.bcel.generic.PUTFIELD;
  41. import org.apache.bcel.generic.PUTSTATIC;
  42. import org.apache.bcel.generic.RET;
  43. import org.apache.bcel.generic.ReturnInstruction;
  44. import org.apache.bcel.generic.Select;
  45. import org.apache.bcel.generic.Type;
  46. import org.aspectj.bridge.IMessage;
  47. import org.aspectj.util.FuzzyBoolean;
  48. import org.aspectj.util.PartialOrder;
  49. import org.aspectj.weaver.AjAttribute;
  50. import org.aspectj.weaver.AjcMemberMaker;
  51. import org.aspectj.weaver.BCException;
  52. import org.aspectj.weaver.ConcreteTypeMunger;
  53. import org.aspectj.weaver.IClassWeaver;
  54. import org.aspectj.weaver.IntMap;
  55. import org.aspectj.weaver.Member;
  56. import org.aspectj.weaver.WeaverMetrics;
  57. import org.aspectj.weaver.NameMangler;
  58. import org.aspectj.weaver.NewFieldTypeMunger;
  59. import org.aspectj.weaver.ResolvedMember;
  60. import org.aspectj.weaver.ResolvedTypeX;
  61. import org.aspectj.weaver.Shadow;
  62. import org.aspectj.weaver.ShadowMunger;
  63. import org.aspectj.weaver.WeaverMessages;
  64. import org.aspectj.weaver.WeaverStateInfo;
  65. import org.aspectj.weaver.Shadow.Kind;
  66. import org.aspectj.weaver.patterns.FastMatchInfo;
  67. class BcelClassWeaver implements IClassWeaver {
  68. /**
  69. * This is called from {@link BcelWeaver} to perform the per-class weaving process.
  70. */
  71. public static boolean weave(
  72. BcelWorld world,
  73. LazyClassGen clazz,
  74. List shadowMungers,
  75. List typeMungers)
  76. {
  77. boolean b = new BcelClassWeaver(world, clazz, shadowMungers, typeMungers).weave();
  78. //System.out.println(clazz.getClassName() + ", " + clazz.getType().getWeaverState());
  79. //clazz.print();
  80. return b;
  81. }
  82. // --------------------------------------------
  83. private final LazyClassGen clazz;
  84. private final List shadowMungers;
  85. private final List typeMungers;
  86. private final BcelObjectType ty; // alias of clazz.getType()
  87. private final BcelWorld world; // alias of ty.getWorld()
  88. private final ConstantPoolGen cpg; // alias of clazz.getConstantPoolGen()
  89. private final InstructionFactory fact; // alias of clazz.getFactory();
  90. private final List addedLazyMethodGens = new ArrayList();
  91. private final Set addedDispatchTargets = new HashSet();
  92. // Static setting across BcelClassWeavers
  93. private static boolean inReweavableMode = false;
  94. private static boolean compressReweavableAttributes = false;
  95. private List addedSuperInitializersAsList = null; // List<IfaceInitList>
  96. private final Map addedSuperInitializers = new HashMap(); // Interface -> IfaceInitList
  97. private List addedThisInitializers = new ArrayList(); // List<NewFieldMunger>
  98. private List addedClassInitializers = new ArrayList(); // List<NewFieldMunger>
  99. private BcelShadow clinitShadow = null;
  100. /**
  101. * This holds the initialization and pre-initialization shadows for this class
  102. * that were actually matched by mungers (if no match, then we don't even create the
  103. * shadows really).
  104. */
  105. private final List initializationShadows = new ArrayList(1);
  106. private BcelClassWeaver(
  107. BcelWorld world,
  108. LazyClassGen clazz,
  109. List shadowMungers,
  110. List typeMungers)
  111. {
  112. super();
  113. // assert world == clazz.getType().getWorld()
  114. this.world = world;
  115. this.clazz = clazz;
  116. this.shadowMungers = shadowMungers;
  117. this.typeMungers = typeMungers;
  118. this.ty = clazz.getBcelObjectType();
  119. this.cpg = clazz.getConstantPoolGen();
  120. this.fact = clazz.getFactory();
  121. fastMatchShadowMungers(shadowMungers);
  122. initializeSuperInitializerMap(ty.getResolvedTypeX());
  123. }
  124. private List[] perKindShadowMungers;
  125. private boolean canMatchBodyShadows = false;
  126. private boolean canMatchInitialization = false;
  127. private void fastMatchShadowMungers(List shadowMungers) {
  128. perKindShadowMungers = new List[Shadow.MAX_SHADOW_KIND+1];
  129. for (int i = 0; i < Shadow.SHADOW_KINDS.length; i++) {
  130. Shadow.Kind kind = Shadow.SHADOW_KINDS[i];
  131. ArrayList mungers = new ArrayList(0);
  132. perKindShadowMungers[kind.getKey()] = mungers;
  133. fastMatchShadowMungers(shadowMungers, mungers, kind);
  134. if (mungers.isEmpty()) {
  135. perKindShadowMungers[kind.getKey()] = null;
  136. } else {
  137. if (kind == Shadow.Initialization) {
  138. canMatchInitialization = true;
  139. } else if (!kind.isEnclosingKind()) {
  140. canMatchBodyShadows = true;
  141. }
  142. }
  143. }
  144. }
  145. private boolean canMatch(Shadow.Kind kind) {
  146. return perKindShadowMungers[kind.getKey()] != null;
  147. }
  148. private void fastMatchShadowMungers(List shadowMungers, ArrayList mungers, Kind kind) {
  149. FastMatchInfo info = new FastMatchInfo(clazz.getType(), kind);
  150. for (Iterator i = shadowMungers.iterator(); i.hasNext();) {
  151. ShadowMunger munger = (ShadowMunger) i.next();
  152. FuzzyBoolean fb = munger.getPointcut().fastMatch(info);
  153. WeaverMetrics.recordFastMatchResult(fb);// Could pass: munger.getPointcut().toString()
  154. if (fb.maybeTrue()) mungers.add(munger);
  155. }
  156. }
  157. private void initializeSuperInitializerMap(ResolvedTypeX child) {
  158. ResolvedTypeX[] superInterfaces = child.getDeclaredInterfaces();
  159. for (int i=0, len=superInterfaces.length; i < len; i++) {
  160. if (ty.getResolvedTypeX().isTopmostImplementor(superInterfaces[i])) {
  161. if (addSuperInitializer(superInterfaces[i])) {
  162. initializeSuperInitializerMap(superInterfaces[i]);
  163. }
  164. }
  165. }
  166. }
  167. private boolean addSuperInitializer(ResolvedTypeX onType) {
  168. IfaceInitList l = (IfaceInitList) addedSuperInitializers.get(onType);
  169. if (l != null) return false;
  170. l = new IfaceInitList(onType);
  171. addedSuperInitializers.put(onType, l);
  172. return true;
  173. }
  174. public void addInitializer(ConcreteTypeMunger cm) {
  175. NewFieldTypeMunger m = (NewFieldTypeMunger) cm.getMunger();
  176. ResolvedTypeX onType = m.getSignature().getDeclaringType().resolve(world);
  177. if (m.getSignature().isStatic()) {
  178. addedClassInitializers.add(cm);
  179. } else {
  180. if (onType == ty.getResolvedTypeX()) {
  181. addedThisInitializers.add(cm);
  182. } else {
  183. IfaceInitList l = (IfaceInitList) addedSuperInitializers.get(onType);
  184. l.list.add(cm);
  185. }
  186. }
  187. }
  188. private static class IfaceInitList implements PartialOrder.PartialComparable {
  189. final ResolvedTypeX onType;
  190. List list = new ArrayList();
  191. IfaceInitList(ResolvedTypeX onType) {
  192. this.onType = onType;
  193. }
  194. public int compareTo(Object other) {
  195. IfaceInitList o = (IfaceInitList)other;
  196. if (onType.isAssignableFrom(o.onType)) return +1;
  197. else if (o.onType.isAssignableFrom(onType)) return -1;
  198. else return 0;
  199. }
  200. public int fallbackCompareTo(Object other) {
  201. return 0;
  202. }
  203. }
  204. // XXX this is being called, but the result doesn't seem to be being used
  205. public boolean addDispatchTarget(ResolvedMember m) {
  206. return addedDispatchTargets.add(m);
  207. }
  208. public void addLazyMethodGen(LazyMethodGen gen) {
  209. addedLazyMethodGens.add(gen);
  210. }
  211. public void addOrReplaceLazyMethodGen(LazyMethodGen mg) {
  212. if (alreadyDefined(clazz, mg)) return;
  213. for (Iterator i = addedLazyMethodGens.iterator(); i.hasNext(); ) {
  214. LazyMethodGen existing = (LazyMethodGen)i.next();
  215. if (signaturesMatch(mg, existing)) {
  216. if (existing.definingType == null) {
  217. // this means existing was introduced on the class itself
  218. return;
  219. } else if (mg.definingType.isAssignableFrom(existing.definingType)) {
  220. // existing is mg's subtype and dominates mg
  221. return;
  222. } else if (existing.definingType.isAssignableFrom(mg.definingType)) {
  223. // mg is existing's subtype and dominates existing
  224. i.remove();
  225. addedLazyMethodGens.add(mg);
  226. return;
  227. } else {
  228. throw new BCException("conflict between: " + mg + " and " + existing);
  229. }
  230. }
  231. }
  232. addedLazyMethodGens.add(mg);
  233. }
  234. private boolean alreadyDefined(LazyClassGen clazz, LazyMethodGen mg) {
  235. for (Iterator i = clazz.getMethodGens().iterator(); i.hasNext(); ) {
  236. LazyMethodGen existing = (LazyMethodGen)i.next();
  237. if (signaturesMatch(mg, existing)) {
  238. if (!mg.isAbstract() && existing.isAbstract()) {
  239. i.remove();
  240. return false;
  241. }
  242. return true;
  243. }
  244. }
  245. return false;
  246. }
  247. private boolean signaturesMatch(LazyMethodGen mg, LazyMethodGen existing) {
  248. return mg.getName().equals(existing.getName()) &&
  249. mg.getSignature().equals(existing.getSignature());
  250. }
  251. // ----
  252. public boolean weave() {
  253. if (clazz.isWoven() && !clazz.isReweavable()) {
  254. world.showMessage(IMessage.ERROR,
  255. WeaverMessages.format(WeaverMessages.ALREADY_WOVEN,clazz.getType().getName()),
  256. ty.getSourceLocation(), null);
  257. return false;
  258. }
  259. Set aspectsAffectingType = null;
  260. if (inReweavableMode) aspectsAffectingType = new HashSet();
  261. boolean isChanged = false;
  262. // we want to "touch" all aspects
  263. if (clazz.getType().isAspect()) isChanged = true;
  264. // start by munging all typeMungers
  265. for (Iterator i = typeMungers.iterator(); i.hasNext(); ) {
  266. Object o = i.next();
  267. if ( !(o instanceof BcelTypeMunger) ) {
  268. //???System.err.println("surprising: " + o);
  269. continue;
  270. }
  271. BcelTypeMunger munger = (BcelTypeMunger)o;
  272. boolean typeMungerAffectedType = munger.munge(this);
  273. if (typeMungerAffectedType) {
  274. isChanged = true;
  275. if (inReweavableMode) aspectsAffectingType.add(munger.getAspectType().getName());
  276. }
  277. }
  278. // XXX do major sort of stuff
  279. // sort according to: Major: type hierarchy
  280. // within each list: dominates
  281. // don't forget to sort addedThisInitialiers according to dominates
  282. addedSuperInitializersAsList = new ArrayList(addedSuperInitializers.values());
  283. addedSuperInitializersAsList = PartialOrder.sort(addedSuperInitializersAsList);
  284. if (addedSuperInitializersAsList == null) {
  285. throw new BCException("circularity in inter-types");
  286. }
  287. // this will create a static initializer if there isn't one
  288. // this is in just as bad taste as NOPs
  289. LazyMethodGen staticInit = clazz.getStaticInitializer();
  290. staticInit.getBody().insert(genInitInstructions(addedClassInitializers, true));
  291. // now go through each method, and match against each method. This
  292. // sets up each method's {@link LazyMethodGen#matchedShadows} field,
  293. // and it also possibly adds to {@link #initializationShadows}.
  294. List methodGens = new ArrayList(clazz.getMethodGens());
  295. for (Iterator i = methodGens.iterator(); i.hasNext();) {
  296. LazyMethodGen mg = (LazyMethodGen)i.next();
  297. //mg.getBody();
  298. if (! mg.hasBody()) continue;
  299. boolean shadowMungerMatched = match(mg);
  300. if (shadowMungerMatched) {
  301. // For matching mungers, add their declaring aspects to the list that affected this type
  302. if (inReweavableMode) aspectsAffectingType.addAll(findAspectsForMungers(mg));
  303. isChanged = true;
  304. }
  305. }
  306. if (! isChanged) return false;
  307. // now we weave all but the initialization shadows
  308. for (Iterator i = methodGens.iterator(); i.hasNext();) {
  309. LazyMethodGen mg = (LazyMethodGen)i.next();
  310. if (! mg.hasBody()) continue;
  311. implement(mg);
  312. }
  313. // if we matched any initialization shadows, we inline and weave
  314. if (! initializationShadows.isEmpty()) {
  315. // Repeat next step until nothing left to inline...cant go on
  316. // infinetly as compiler will have detected and reported
  317. // "Recursive constructor invocation"
  318. while (inlineSelfConstructors(methodGens));
  319. positionAndImplement(initializationShadows);
  320. }
  321. // finally, if we changed, we add in the introduced methods.
  322. if (isChanged) {
  323. clazz.getOrCreateWeaverStateInfo();
  324. weaveInAddedMethods();
  325. }
  326. if (inReweavableMode) {
  327. WeaverStateInfo wsi = clazz.getOrCreateWeaverStateInfo();
  328. wsi.addAspectsAffectingType(aspectsAffectingType);
  329. wsi.setUnwovenClassFileData(ty.getJavaClass().getBytes());
  330. wsi.setReweavable(true,compressReweavableAttributes);
  331. } else {
  332. clazz.getOrCreateWeaverStateInfo().setReweavable(false,false);
  333. }
  334. return isChanged;
  335. }
  336. private Set findAspectsForMungers(LazyMethodGen mg) {
  337. Set aspectsAffectingType = new HashSet();
  338. for (Iterator iter = mg.matchedShadows.iterator(); iter.hasNext();) {
  339. BcelShadow aShadow = (BcelShadow) iter.next();
  340. // Mungers in effect on that shadow
  341. for (Iterator iter2 = aShadow.getMungers().iterator();iter2.hasNext();) {
  342. ShadowMunger aMunger = (ShadowMunger) iter2.next();
  343. if (aMunger instanceof BcelAdvice) {
  344. BcelAdvice bAdvice = (BcelAdvice)aMunger;
  345. aspectsAffectingType.add(bAdvice.getConcreteAspect().getName());
  346. } else {
  347. // It is a 'Checker' - we don't need to remember aspects that only contributed Checkers...
  348. }
  349. }
  350. }
  351. return aspectsAffectingType;
  352. }
  353. private boolean inlineSelfConstructors(List methodGens) {
  354. boolean inlinedSomething = false;
  355. for (Iterator i = methodGens.iterator(); i.hasNext();) {
  356. LazyMethodGen mg = (LazyMethodGen) i.next();
  357. if (! mg.getName().equals("<init>")) continue;
  358. InstructionHandle ih = findSuperOrThisCall(mg);
  359. if (ih != null && isThisCall(ih)) {
  360. LazyMethodGen donor = getCalledMethod(ih);
  361. inlineMethod(donor, mg, ih);
  362. inlinedSomething = true;
  363. }
  364. }
  365. return inlinedSomething;
  366. }
  367. private void positionAndImplement(List initializationShadows) {
  368. for (Iterator i = initializationShadows.iterator(); i.hasNext(); ) {
  369. BcelShadow s = (BcelShadow) i.next();
  370. positionInitializationShadow(s);
  371. //s.getEnclosingMethod().print();
  372. s.implement();
  373. }
  374. }
  375. private void positionInitializationShadow(BcelShadow s) {
  376. LazyMethodGen mg = s.getEnclosingMethod();
  377. InstructionHandle call = findSuperOrThisCall(mg);
  378. InstructionList body = mg.getBody();
  379. ShadowRange r = new ShadowRange(body);
  380. r.associateWithShadow((BcelShadow) s);
  381. if (s.getKind() == Shadow.PreInitialization) {
  382. // XXX assert first instruction is an ALOAD_0.
  383. // a pre shadow goes from AFTER the first instruction (which we believe to
  384. // be an ALOAD_0) to just before the call to super
  385. r.associateWithTargets(
  386. Range.genStart(body, body.getStart().getNext()),
  387. Range.genEnd(body, call.getPrev()));
  388. } else {
  389. // assert s.getKind() == Shadow.Initialization
  390. r.associateWithTargets(
  391. Range.genStart(body, call.getNext()),
  392. Range.genEnd(body));
  393. }
  394. }
  395. private boolean isThisCall(InstructionHandle ih) {
  396. INVOKESPECIAL inst = (INVOKESPECIAL) ih.getInstruction();
  397. return inst.getClassName(cpg).equals(clazz.getName());
  398. }
  399. /** inline a particular call in bytecode.
  400. *
  401. * @param donor the method we want to inline
  402. * @param recipient the method containing the call we want to inline
  403. * @param call the instructionHandle in recipient's body holding the call we want to
  404. * inline.
  405. */
  406. public static void inlineMethod(
  407. LazyMethodGen donor,
  408. LazyMethodGen recipient,
  409. InstructionHandle call)
  410. {
  411. // assert recipient.contains(call)
  412. /* Implementation notes:
  413. *
  414. * We allocate two slots for every tempvar so we don't screw up
  415. * longs and doubles which may share space. This could be conservatively avoided
  416. * (no reference to a long/double instruction, don't do it) or packed later.
  417. * Right now we don't bother to pack.
  418. *
  419. * Allocate a new var for each formal param of the inlined. Fill with stack
  420. * contents. Then copy the inlined instructions in with the appropriate remap
  421. * table. Any framelocs used by locals in inlined are reallocated to top of
  422. * frame,
  423. */
  424. final InstructionFactory fact = recipient.getEnclosingClass().getFactory();
  425. IntMap frameEnv = new IntMap();
  426. // this also sets up the initial environment
  427. InstructionList argumentStores =
  428. genArgumentStores(donor, recipient, frameEnv, fact);
  429. InstructionList inlineInstructions =
  430. genInlineInstructions(donor, recipient, frameEnv, fact, false);
  431. inlineInstructions.insert(argumentStores);
  432. recipient.getBody().append(call, inlineInstructions);
  433. Utility.deleteInstruction(call, recipient);
  434. }
  435. /** generate the instructions to be inlined.
  436. *
  437. * @param donor the method from which we will copy (and adjust frame and jumps)
  438. * instructions.
  439. * @param recipient the method the instructions will go into. Used to get the frame
  440. * size so we can allocate new frame locations for locals in donor.
  441. * @param frameEnv an environment to map from donor frame to recipient frame,
  442. * initially populated with argument locations.
  443. * @param fact an instruction factory for recipient
  444. */
  445. static InstructionList genInlineInstructions(
  446. LazyMethodGen donor,
  447. LazyMethodGen recipient,
  448. IntMap frameEnv,
  449. InstructionFactory fact,
  450. boolean keepReturns)
  451. {
  452. InstructionList footer = new InstructionList();
  453. InstructionHandle end = footer.append(InstructionConstants.NOP);
  454. InstructionList ret = new InstructionList();
  455. InstructionList sourceList = donor.getBody();
  456. Map srcToDest = new HashMap();
  457. ConstantPoolGen donorCpg = donor.getEnclosingClass().getConstantPoolGen();
  458. ConstantPoolGen recipientCpg = recipient.getEnclosingClass().getConstantPoolGen();
  459. boolean isAcrossClass = donorCpg != recipientCpg;
  460. // first pass: copy the instructions directly, populate the srcToDest map,
  461. // fix frame instructions
  462. for (InstructionHandle src = sourceList.getStart();
  463. src != null;
  464. src = src.getNext())
  465. {
  466. Instruction fresh = Utility.copyInstruction(src.getInstruction());
  467. InstructionHandle dest;
  468. if (fresh instanceof CPInstruction) {
  469. // need to reset index to go to new constant pool. This is totally
  470. // a computation leak... we're testing this LOTS of times. Sigh.
  471. if (isAcrossClass) {
  472. CPInstruction cpi = (CPInstruction) fresh;
  473. cpi.setIndex(
  474. recipientCpg.addConstant(
  475. donorCpg.getConstant(cpi.getIndex()),
  476. donorCpg));
  477. }
  478. }
  479. if (src.getInstruction() == Range.RANGEINSTRUCTION) {
  480. dest = ret.append(Range.RANGEINSTRUCTION);
  481. } else if (fresh instanceof ReturnInstruction) {
  482. if (keepReturns) {
  483. dest = ret.append(fresh);
  484. } else {
  485. dest =
  486. ret.append(InstructionFactory.createBranchInstruction(Constants.GOTO, end));
  487. }
  488. } else if (fresh instanceof BranchInstruction) {
  489. dest = ret.append((BranchInstruction) fresh);
  490. } else if (
  491. fresh instanceof LocalVariableInstruction || fresh instanceof RET) {
  492. IndexedInstruction indexed = (IndexedInstruction) fresh;
  493. int oldIndex = indexed.getIndex();
  494. int freshIndex;
  495. if (!frameEnv.hasKey(oldIndex)) {
  496. freshIndex = recipient.allocateLocal(2);
  497. frameEnv.put(oldIndex, freshIndex);
  498. } else {
  499. freshIndex = frameEnv.get(oldIndex);
  500. }
  501. indexed.setIndex(freshIndex);
  502. dest = ret.append(fresh);
  503. } else {
  504. dest = ret.append(fresh);
  505. }
  506. srcToDest.put(src, dest);
  507. }
  508. // second pass: retarget branch instructions, copy ranges and tags
  509. Map tagMap = new HashMap();
  510. Map shadowMap = new HashMap();
  511. for (InstructionHandle dest = ret.getStart(), src = sourceList.getStart();
  512. dest != null;
  513. dest = dest.getNext(), src = src.getNext()) {
  514. Instruction inst = dest.getInstruction();
  515. // retarget branches
  516. if (inst instanceof BranchInstruction) {
  517. BranchInstruction branch = (BranchInstruction) inst;
  518. InstructionHandle oldTarget = branch.getTarget();
  519. InstructionHandle newTarget =
  520. (InstructionHandle) srcToDest.get(oldTarget);
  521. if (newTarget == null) {
  522. // assert this is a GOTO
  523. // this was a return instruction we previously replaced
  524. } else {
  525. branch.setTarget(newTarget);
  526. if (branch instanceof Select) {
  527. Select select = (Select) branch;
  528. InstructionHandle[] oldTargets = select.getTargets();
  529. for (int k = oldTargets.length - 1; k >= 0; k--) {
  530. select.setTarget(
  531. k,
  532. (InstructionHandle) srcToDest.get(oldTargets[k]));
  533. }
  534. }
  535. }
  536. }
  537. //copy over tags and range attributes
  538. InstructionTargeter[] srcTargeters = src.getTargeters();
  539. if (srcTargeters != null) {
  540. for (int j = srcTargeters.length - 1; j >= 0; j--) {
  541. InstructionTargeter old = srcTargeters[j];
  542. if (old instanceof Tag) {
  543. Tag oldTag = (Tag) old;
  544. Tag fresh = (Tag) tagMap.get(oldTag);
  545. if (fresh == null) {
  546. fresh = oldTag.copy();
  547. tagMap.put(oldTag, fresh);
  548. }
  549. dest.addTargeter(fresh);
  550. } else if (old instanceof ExceptionRange) {
  551. ExceptionRange er = (ExceptionRange) old;
  552. if (er.getStart() == src) {
  553. ExceptionRange freshEr =
  554. new ExceptionRange(
  555. recipient.getBody(),
  556. er.getCatchType(),
  557. er.getPriority());
  558. freshEr.associateWithTargets(
  559. dest,
  560. (InstructionHandle)srcToDest.get(er.getEnd()),
  561. (InstructionHandle)srcToDest.get(er.getHandler()));
  562. }
  563. } else if (old instanceof ShadowRange) {
  564. ShadowRange oldRange = (ShadowRange) old;
  565. if (oldRange.getStart() == src) {
  566. BcelShadow oldShadow = oldRange.getShadow();
  567. BcelShadow freshEnclosing =
  568. oldShadow.getEnclosingShadow() == null
  569. ? null
  570. : (BcelShadow) shadowMap.get(oldShadow.getEnclosingShadow());
  571. BcelShadow freshShadow =
  572. oldShadow.copyInto(recipient, freshEnclosing);
  573. ShadowRange freshRange = new ShadowRange(recipient.getBody());
  574. freshRange.associateWithShadow(freshShadow);
  575. freshRange.associateWithTargets(
  576. dest,
  577. (InstructionHandle) srcToDest.get(oldRange.getEnd()));
  578. shadowMap.put(oldRange, freshRange);
  579. //recipient.matchedShadows.add(freshShadow);
  580. // XXX should go through the NEW copied shadow and update
  581. // the thisVar, targetVar, and argsVar
  582. // ??? Might want to also go through at this time and add
  583. // "extra" vars to the shadow.
  584. }
  585. }
  586. }
  587. }
  588. }
  589. if (!keepReturns) ret.append(footer);
  590. return ret;
  591. }
  592. /** generate the argument stores in preparation for inlining.
  593. *
  594. * @param donor the method we will inline from. Used to get the signature.
  595. * @param recipient the method we will inline into. Used to get the frame size
  596. * so we can allocate fresh locations.
  597. * @param frameEnv an empty environment we populate with a map from donor frame to
  598. * recipient frame.
  599. * @param fact an instruction factory for recipient
  600. */
  601. private static InstructionList genArgumentStores(
  602. LazyMethodGen donor,
  603. LazyMethodGen recipient,
  604. IntMap frameEnv,
  605. InstructionFactory fact)
  606. {
  607. InstructionList ret = new InstructionList();
  608. int donorFramePos = 0;
  609. // writing ret back to front because we're popping.
  610. if (! donor.isStatic()) {
  611. int targetSlot = recipient.allocateLocal(Type.OBJECT);
  612. ret.insert(InstructionFactory.createStore(Type.OBJECT, targetSlot));
  613. frameEnv.put(donorFramePos, targetSlot);
  614. donorFramePos += 1;
  615. }
  616. Type[] argTypes = donor.getArgumentTypes();
  617. for (int i = 0, len = argTypes.length; i < len; i++) {
  618. Type argType = argTypes[i];
  619. int argSlot = recipient.allocateLocal(argType);
  620. ret.insert(InstructionFactory.createStore(argType, argSlot));
  621. frameEnv.put(donorFramePos, argSlot);
  622. donorFramePos += argType.getSize();
  623. }
  624. return ret;
  625. }
  626. /** get a called method: Assumes the called method is in this class,
  627. * and the reference to it is exact (a la INVOKESPECIAL).
  628. *
  629. * @param ih The InvokeInstruction instructionHandle pointing to the called method.
  630. */
  631. private LazyMethodGen getCalledMethod(
  632. InstructionHandle ih)
  633. {
  634. InvokeInstruction inst = (InvokeInstruction) ih.getInstruction();
  635. String methodName = inst.getName(cpg);
  636. String signature = inst.getSignature(cpg);
  637. return clazz.getLazyMethodGen(methodName, signature);
  638. }
  639. private void weaveInAddedMethods() {
  640. Collections.sort(addedLazyMethodGens,
  641. new Comparator() {
  642. public int compare(Object a, Object b) {
  643. LazyMethodGen aa = (LazyMethodGen) a;
  644. LazyMethodGen bb = (LazyMethodGen) b;
  645. int i = aa.getName().compareTo(bb.getName());
  646. if (i != 0) return i;
  647. return aa.getSignature().compareTo(bb.getSignature());
  648. }
  649. }
  650. );
  651. for (Iterator i = addedLazyMethodGens.iterator(); i.hasNext(); ) {
  652. clazz.addMethodGen((LazyMethodGen)i.next());
  653. }
  654. }
  655. void addPerSingletonField(Member field) {
  656. ObjectType aspectType = (ObjectType) BcelWorld.makeBcelType(field.getReturnType());
  657. String aspectName = field.getReturnType().getName();
  658. LazyMethodGen clinit = clazz.getStaticInitializer();
  659. InstructionList setup = new InstructionList();
  660. InstructionFactory fact = clazz.getFactory();
  661. setup.append(fact.createNew(aspectType));
  662. setup.append(InstructionFactory.createDup(1));
  663. setup.append(fact.createInvoke(
  664. aspectName,
  665. "<init>",
  666. Type.VOID,
  667. new Type[0],
  668. Constants.INVOKESPECIAL));
  669. setup.append(
  670. fact.createFieldAccess(
  671. aspectName,
  672. field.getName(),
  673. aspectType,
  674. Constants.PUTSTATIC));
  675. clinit.getBody().insert(setup);
  676. }
  677. /**
  678. * Returns null if this is not a Java constructor, and then we won't
  679. * weave into it at all
  680. */
  681. private InstructionHandle findSuperOrThisCall(LazyMethodGen mg) {
  682. int depth = 1;
  683. InstructionHandle start = mg.getBody().getStart();
  684. while (true) {
  685. if (start == null) return null;
  686. Instruction inst = start.getInstruction();
  687. if (inst instanceof INVOKESPECIAL
  688. && ((INVOKESPECIAL) inst).getName(cpg).equals("<init>")) {
  689. depth--;
  690. if (depth == 0) return start;
  691. } else if (inst instanceof NEW) {
  692. depth++;
  693. }
  694. start = start.getNext();
  695. }
  696. }
  697. // ----
  698. private boolean match(LazyMethodGen mg) {
  699. BcelShadow enclosingShadow;
  700. List shadowAccumulator = new ArrayList();
  701. // we want to match ajsynthetic constructors...
  702. if (mg.getName().equals("<init>")) {
  703. return matchInit(mg, shadowAccumulator);
  704. } else if (!shouldWeaveBody(mg)) { //.isAjSynthetic()) {
  705. return false;
  706. } else {
  707. if (mg.getName().equals("<clinit>")) {
  708. clinitShadow = enclosingShadow = BcelShadow.makeStaticInitialization(world, mg);
  709. //System.err.println(enclosingShadow);
  710. } else if (mg.isAdviceMethod()) {
  711. enclosingShadow = BcelShadow.makeAdviceExecution(world, mg);
  712. } else {
  713. AjAttribute.EffectiveSignatureAttribute effective = mg.getEffectiveSignature();
  714. if (effective == null) {
  715. enclosingShadow = BcelShadow.makeMethodExecution(world, mg, !canMatchBodyShadows);
  716. } else if (effective.isWeaveBody()) {
  717. enclosingShadow =
  718. BcelShadow.makeShadowForMethod(
  719. world,
  720. mg,
  721. effective.getShadowKind(),
  722. effective.getEffectiveSignature());
  723. } else {
  724. return false;
  725. }
  726. }
  727. if (canMatchBodyShadows) {
  728. for (InstructionHandle h = mg.getBody().getStart();
  729. h != null;
  730. h = h.getNext()) {
  731. match(mg, h, enclosingShadow, shadowAccumulator);
  732. }
  733. }
  734. if (match(enclosingShadow, shadowAccumulator)) {
  735. enclosingShadow.init();
  736. }
  737. mg.matchedShadows = shadowAccumulator;
  738. return !shadowAccumulator.isEmpty();
  739. }
  740. }
  741. private boolean matchInit(LazyMethodGen mg, List shadowAccumulator) {
  742. BcelShadow enclosingShadow;
  743. // XXX the enclosing join point is wrong for things before ignoreMe.
  744. InstructionHandle superOrThisCall = findSuperOrThisCall(mg);
  745. // we don't walk bodies of things where it's a wrong constructor thingie
  746. if (superOrThisCall == null) return false;
  747. enclosingShadow = BcelShadow.makeConstructorExecution(world, mg, superOrThisCall);
  748. // walk the body
  749. boolean beforeSuperOrThisCall = true;
  750. if (shouldWeaveBody(mg)) {
  751. if (canMatchBodyShadows) {
  752. for (InstructionHandle h = mg.getBody().getStart();
  753. h != null;
  754. h = h.getNext()) {
  755. if (h == superOrThisCall) {
  756. beforeSuperOrThisCall = false;
  757. continue;
  758. }
  759. match(mg, h, beforeSuperOrThisCall ? null : enclosingShadow, shadowAccumulator);
  760. }
  761. }
  762. match(enclosingShadow, shadowAccumulator);
  763. }
  764. // XXX we don't do pre-inits of interfaces
  765. // now add interface inits
  766. if (superOrThisCall != null && ! isThisCall(superOrThisCall)) {
  767. InstructionHandle curr = enclosingShadow.getRange().getStart();
  768. for (Iterator i = addedSuperInitializersAsList.iterator(); i.hasNext(); ) {
  769. IfaceInitList l = (IfaceInitList) i.next();
  770. Member ifaceInitSig = AjcMemberMaker.interfaceConstructor(l.onType);
  771. BcelShadow initShadow =
  772. BcelShadow.makeIfaceInitialization(world, mg, ifaceInitSig);
  773. // insert code in place
  774. InstructionList inits = genInitInstructions(l.list, false);
  775. if (match(initShadow, shadowAccumulator) || !inits.isEmpty()) {
  776. initShadow.initIfaceInitializer(curr);
  777. initShadow.getRange().insert(inits, Range.OutsideBefore);
  778. }
  779. }
  780. // now we add our initialization code
  781. InstructionList inits = genInitInstructions(addedThisInitializers, false);
  782. enclosingShadow.getRange().insert(inits, Range.OutsideBefore);
  783. }
  784. // actually, you only need to inline the self constructors that are
  785. // in a particular group (partition the constructors into groups where members
  786. // call or are called only by those in the group). Then only inline
  787. // constructors
  788. // in groups where at least one initialization jp matched. Future work.
  789. boolean addedInitialization =
  790. match(
  791. BcelShadow.makeUnfinishedInitialization(world, mg),
  792. initializationShadows);
  793. addedInitialization |=
  794. match(
  795. BcelShadow.makeUnfinishedPreinitialization(world, mg),
  796. initializationShadows);
  797. mg.matchedShadows = shadowAccumulator;
  798. return addedInitialization || !shadowAccumulator.isEmpty();
  799. }
  800. private boolean shouldWeaveBody(LazyMethodGen mg) {
  801. if (mg.isAjSynthetic()) return mg.getName().equals("<clinit>");
  802. AjAttribute.EffectiveSignatureAttribute a = mg.getEffectiveSignature();
  803. if (a != null) return a.isWeaveBody();
  804. return true;
  805. }
  806. /**
  807. * first sorts the mungers, then gens the initializers in the right order
  808. */
  809. private InstructionList genInitInstructions(List list, boolean isStatic) {
  810. list = PartialOrder.sort(list);
  811. if (list == null) {
  812. throw new BCException("circularity in inter-types");
  813. }
  814. InstructionList ret = new InstructionList();
  815. for (Iterator i = list.iterator(); i.hasNext();) {
  816. ConcreteTypeMunger cmunger = (ConcreteTypeMunger) i.next();
  817. NewFieldTypeMunger munger = (NewFieldTypeMunger) cmunger.getMunger();
  818. ResolvedMember initMethod = munger.getInitMethod(cmunger.getAspectType());
  819. if (!isStatic) ret.append(InstructionConstants.ALOAD_0);
  820. ret.append(Utility.createInvoke(fact, world, initMethod));
  821. }
  822. return ret;
  823. }
  824. private void match(
  825. LazyMethodGen mg,
  826. InstructionHandle ih,
  827. BcelShadow enclosingShadow,
  828. List shadowAccumulator)
  829. {
  830. Instruction i = ih.getInstruction();
  831. if (i instanceof FieldInstruction) {
  832. FieldInstruction fi = (FieldInstruction) i;
  833. if (fi instanceof PUTFIELD || fi instanceof PUTSTATIC) {
  834. // check for sets of constant fields. We first check the previous
  835. // instruction. If the previous instruction is a LD_WHATEVER (push
  836. // constant on the stack) then we must resolve the field to determine
  837. // if it's final. If it is final, then we don't generate a shadow.
  838. InstructionHandle prevHandle = ih.getPrev();
  839. Instruction prevI = prevHandle.getInstruction();
  840. if (Utility.isConstantPushInstruction(prevI)) {
  841. Member field = BcelWorld.makeFieldSignature(clazz, (FieldInstruction) i);
  842. ResolvedMember resolvedField = field.resolve(world);
  843. if (resolvedField == null) {
  844. // we can't find the field, so it's not a join point.
  845. } else if (Modifier.isFinal(resolvedField.getModifiers())) {
  846. // it's final, so it's the set of a final constant, so it's
  847. // not a join point according to 1.0.6 and 1.1.
  848. } else {
  849. matchSetInstruction(mg, ih, enclosingShadow, shadowAccumulator);
  850. }
  851. } else {
  852. matchSetInstruction(mg, ih, enclosingShadow, shadowAccumulator);
  853. }
  854. } else {
  855. matchGetInstruction(mg, ih, enclosingShadow, shadowAccumulator);
  856. }
  857. } else if (i instanceof InvokeInstruction) {
  858. InvokeInstruction ii = (InvokeInstruction) i;
  859. if (ii.getMethodName(clazz.getConstantPoolGen()).equals("<init>")) {
  860. match(
  861. BcelShadow.makeConstructorCall(world, mg, ih, enclosingShadow),
  862. shadowAccumulator);
  863. } else if (ii instanceof INVOKESPECIAL) {
  864. String onTypeName = ii.getClassName(cpg);
  865. if (onTypeName.equals(mg.getEnclosingClass().getName())) {
  866. // we are private
  867. matchInvokeInstruction(mg, ih, ii, enclosingShadow, shadowAccumulator);
  868. } else {
  869. // we are a super call, and this is not a join point in AspectJ-1.{0,1}
  870. }
  871. } else {
  872. matchInvokeInstruction(mg, ih, ii, enclosingShadow, shadowAccumulator);
  873. }
  874. }
  875. // performance optimization... we only actually care about ASTORE instructions,
  876. // since that's what every javac type thing ever uses to start a handler, but for
  877. // now we'll do this for everybody.
  878. if (Range.isRangeHandle(ih)) return;
  879. InstructionTargeter[] targeters = ih.getTargeters();
  880. if (targeters != null) {
  881. for (int j = 0; j < targeters.length; j++) {
  882. InstructionTargeter t = targeters[j];
  883. if (t instanceof ExceptionRange) {
  884. // assert t.getHandler() == ih
  885. ExceptionRange er = (ExceptionRange) t;
  886. if (er.getCatchType() == null) continue;
  887. if (isInitFailureHandler(ih)) return;
  888. match(
  889. BcelShadow.makeExceptionHandler(
  890. world,
  891. er,
  892. mg, ih, enclosingShadow),
  893. shadowAccumulator);
  894. }
  895. }
  896. }
  897. }
  898. private boolean isInitFailureHandler(InstructionHandle ih) {
  899. // Skip the astore_0 and aload_0 at the start of the handler and
  900. // then check if the instruction following these is
  901. // 'putstatic ajc$initFailureCause'. If it is then we are
  902. // in the handler we created in AspectClinit.generatePostSyntheticCode()
  903. InstructionHandle twoInstructionsAway = ih.getNext().getNext();
  904. if (twoInstructionsAway.getInstruction() instanceof PUTSTATIC) {
  905. String name = ((PUTSTATIC)twoInstructionsAway.getInstruction()).getFieldName(cpg);
  906. if (name.equals(NameMangler.INITFAILURECAUSE_FIELD_NAME)) return true;
  907. }
  908. return false;
  909. }
  910. private void matchSetInstruction(
  911. LazyMethodGen mg,
  912. InstructionHandle ih,
  913. BcelShadow enclosingShadow,
  914. List shadowAccumulator) {
  915. FieldInstruction fi = (FieldInstruction) ih.getInstruction();
  916. Member field = BcelWorld.makeFieldSignature(clazz, fi);
  917. // synthetic fields are never join points
  918. if (field.getName().startsWith(NameMangler.PREFIX)) return;
  919. ResolvedMember resolvedField = field.resolve(world);
  920. if (resolvedField == null) {
  921. // we can't find the field, so it's not a join point.
  922. return;
  923. } else if (
  924. Modifier.isFinal(resolvedField.getModifiers())
  925. && Utility.isConstantPushInstruction(ih.getPrev().getInstruction())) {
  926. // it's the set of a final constant, so it's
  927. // not a join point according to 1.0.6 and 1.1.
  928. return;
  929. } else if (resolvedField.isSynthetic()) {
  930. // sets of synthetics aren't join points in 1.1
  931. return;
  932. } else {
  933. match(
  934. BcelShadow.makeFieldSet(world, mg, ih, enclosingShadow),
  935. shadowAccumulator);
  936. }
  937. }
  938. private void matchGetInstruction(LazyMethodGen mg, InstructionHandle ih, BcelShadow enclosingShadow, List shadowAccumulator) {
  939. FieldInstruction fi = (FieldInstruction) ih.getInstruction();
  940. Member field = BcelWorld.makeFieldSignature(clazz, fi);
  941. // synthetic fields are never join points
  942. if (field.getName().startsWith(NameMangler.PREFIX)) return;
  943. ResolvedMember resolvedField = field.resolve(world);
  944. if (resolvedField == null) {
  945. // we can't find the field, so it's not a join point.
  946. return;
  947. } else if (resolvedField.isSynthetic()) {
  948. // sets of synthetics aren't join points in 1.1
  949. return;
  950. } else {
  951. match(BcelShadow.makeFieldGet(world, mg, ih, enclosingShadow), shadowAccumulator);
  952. }
  953. }
  954. private void matchInvokeInstruction(LazyMethodGen mg,
  955. InstructionHandle ih,
  956. InvokeInstruction invoke,
  957. BcelShadow enclosingShadow,
  958. List shadowAccumulator)
  959. {
  960. String methodName = invoke.getName(cpg);
  961. if (methodName.startsWith(NameMangler.PREFIX)) {
  962. Member method =
  963. BcelWorld.makeMethodSignature(clazz, invoke);
  964. ResolvedMember declaredSig = method.resolve(world);
  965. //System.err.println(method + ", declaredSig: " +declaredSig);
  966. if (declaredSig == null) return;
  967. if (declaredSig.getKind() == Member.FIELD) {
  968. Shadow.Kind kind;
  969. if (method.getReturnType().equals(ResolvedTypeX.VOID)) {
  970. kind = Shadow.FieldSet;
  971. } else {
  972. kind = Shadow.FieldGet;
  973. }
  974. match(BcelShadow.makeShadowForMethodCall(world, mg, ih, enclosingShadow,
  975. kind, declaredSig),
  976. shadowAccumulator);
  977. } else {
  978. AjAttribute.EffectiveSignatureAttribute effectiveSig =
  979. declaredSig.getEffectiveSignature();
  980. if (effectiveSig == null) return;
  981. //System.err.println("call to inter-type member: " + effectiveSig);
  982. if (effectiveSig.isWeaveBody()) return;
  983. match(BcelShadow.makeShadowForMethodCall(world, mg, ih, enclosingShadow,
  984. effectiveSig.getShadowKind(), effectiveSig.getEffectiveSignature()),
  985. shadowAccumulator);
  986. }
  987. } else {
  988. match(
  989. BcelShadow.makeMethodCall(world, mg, ih, enclosingShadow),
  990. shadowAccumulator);
  991. }
  992. }
  993. private boolean match(BcelShadow shadow, List shadowAccumulator) {
  994. //System.err.println("match: " + shadow);
  995. boolean isMatched = false;
  996. for (Iterator i = shadowMungers.iterator(); i.hasNext(); ) {
  997. ShadowMunger munger = (ShadowMunger)i.next();
  998. if (munger.match(shadow, world)) {
  999. WeaverMetrics.recordMatchResult(true);// Could pass: munger
  1000. shadow.addMunger(munger);
  1001. isMatched = true;
  1002. if (shadow.getKind() == Shadow.StaticInitialization) {
  1003. clazz.warnOnAddedStaticInitializer(shadow,munger.getSourceLocation());
  1004. }
  1005. } else {
  1006. WeaverMetrics.recordMatchResult(false); // Could pass: munger
  1007. }
  1008. }
  1009. if (isMatched) shadowAccumulator.add(shadow);
  1010. return isMatched;
  1011. }
  1012. // ----
  1013. private void implement(LazyMethodGen mg) {
  1014. List shadows = mg.matchedShadows;
  1015. if (shadows == null) return;
  1016. // We depend on a partial order such that inner shadows are earlier on the list
  1017. // than outer shadows. That's fine. This order is preserved if:
  1018. // A preceeds B iff B.getStart() is LATER THAN A.getStart().
  1019. for (Iterator i = shadows.iterator(); i.hasNext(); ) {
  1020. BcelShadow shadow = (BcelShadow)i.next();
  1021. shadow.implement();
  1022. }
  1023. mg.matchedShadows = null;
  1024. }
  1025. // ----
  1026. public LazyClassGen getLazyClassGen() {
  1027. return clazz;
  1028. }
  1029. public List getShadowMungers() {
  1030. return shadowMungers;
  1031. }
  1032. public BcelWorld getWorld() {
  1033. return world;
  1034. }
  1035. // Called by the BcelWeaver to let us know all BcelClassWeavers need to collect reweavable info
  1036. public static void setReweavableMode(boolean mode,boolean compress) {
  1037. inReweavableMode = mode;
  1038. compressReweavableAttributes = compress;
  1039. }
  1040. }