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.

amcDesignNotes.adoc 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. = AspectJ compilation
  2. _Last updated: 2004-03-15 by acolyer_
  3. == How Compilation Progresses in the JDT
  4. [source, text]
  5. ....
  6. Compiler.compile(ICompilationUnit[] sourceUnits) {
  7. foreach sourceUnit
  8. create a new CompilationUnitResult
  9. CompilationUnitDeclaration = parser.parse(sourceUnit, result)
  10. remember CompilationUnitDeclaration (holds ref to result) in
  11. "unitsToProcess"
  12. end
  13. foreach unitToProcess
  14. resolve
  15. analyse
  16. generateCode
  17. puts class files (plural) into CompilationUnitResult
  18. unit.cleanup (discards AST info etc.)
  19. requestor.acceptResult(result) -- each requestor does there own thing
  20. discard CompilationUnitDeclaration
  21. end
  22. }
  23. ....
  24. Some portions of the JDT call the resolve method instead of compile,
  25. this works the same way except that there is only a single sourceUnit
  26. passed to the compiler, and the code generation phase is optional
  27. (controlled by flag passed by caller).
  28. == How (batch) Compilation Progresses in AspectJ 1.1.x
  29. [source, text]
  30. ....
  31. AjBuildManager.doBuild() {
  32. init phase
  33. ----------
  34. new AjState().prepareForNextBuild()
  35. builds empty lists to hold classes etc.
  36. setUpModel() // this stage should be omitted unless s.one wants it
  37. new BcelWorld(classpath)
  38. new BcelWeaver(world)
  39. add all aspectpath entries to weaver
  40. add all injars to weaver
  41. add all inpath entries to weaver
  42. add all source path *resources* to weaver
  43. compile phase
  44. -------------
  45. build name environment, lookup environment, problem reporter and
  46. compiler
  47. compiler.compile()
  48. proceeds as above, we pass in a requestor that adds the
  49. resulting class files in the result into a list of addedClassFiles
  50. in AjState
  51. weave phase
  52. -----------
  53. add the addedClassFiles to the weaver
  54. pass over all class files known to weaver, building xcut set
  55. pass over all types, adding interTypeMungers to them
  56. pass over all aspects, weave them
  57. pass over all classes, weave them
  58. write out any resources added to weaver
  59. }
  60. ....
  61. == How we want (batch) compilation to proceed in AspectJ 1.2
  62. The key design goal is to do all the work inside the compile method of
  63. the compiler (this makes life much easier for integration with the
  64. rest of the JDT that, quite reasonably, expects the class files to be
  65. ready for action once a compile has completed). The second design goal
  66. is that it should be up to the requestor passed into the compiler
  67. whether or not the class files actually get written out to disk
  68. (different parts of the JDT pass in many different kinds of requestors
  69. that do different things).
  70. This simple model ignores aspectpath, inpath, injars, outjar,
  71. sourceDirs for now.
  72. [source, text]
  73. ....
  74. Compiler.compile(ICompilationUnit[] sourceUnits) {
  75. initial parse phase
  76. -------------------
  77. foreach sourceUnit
  78. create a new CompilationUnitResult
  79. CompilationUnitDeclaration = parser.parse(sourceUnit, result)
  80. remember CompilationUnitDeclaration (holds ref to result) in
  81. "unitsToProcess"
  82. end
  83. generate phase
  84. --------------
  85. foreach unitToProcess
  86. resolve
  87. analyse
  88. generateCode
  89. puts class files (plural) into CompilationUnitResult
  90. unit.cleanup (discards AST info etc.)
  91. // up to this point we are identical to JDT current behaviour,
  92. // from now on we deviate
  93. resultsPendingWeave.add(result)
  94. discard CompilationUnitDeclaration
  95. end
  96. weave phase
  97. -----------
  98. //createWorldAndWeaver(classpath)
  99. //the world and weaver have to be passed into the compiler, to
  100. //support incremental use cases.
  101. buildXCutSet(resultsPendingWeave)
  102. addTypeMungers(resultsPendingWeave)
  103. weaveAspects(resultsPendingWeave)
  104. weaveClasses(resultsPendingWeave)
  105. completion phase
  106. ----------------
  107. foreach resultPendingWeave
  108. requestor.acceptResult(result) -- each requestor does their own
  109. thing
  110. end
  111. // note : movement of any resouces is moved to outside of compile
  112. // altogether. In eclipse, the xxxImageBuilders handle this.
  113. }
  114. buildXCutSet(resultsPendingWeave) {
  115. foreach resultPendingWeave
  116. foreach classfile
  117. resolve
  118. if aspect, add to xcut set.
  119. end
  120. end
  121. }
  122. addTypeMungers(resultsPendingWeave) {
  123. foreach resultPendingWeave
  124. foreach classfile
  125. resolve
  126. addTypeMungers
  127. end
  128. end
  129. }
  130. weaveAspect(resultsPendingWeave) {
  131. foreach resultPendingWeave
  132. foreach classfile
  133. get corresponding BcelObjectType
  134. weave
  135. update classfile held in result
  136. end
  137. end
  138. }
  139. weaveClass(resultsPendingWeave) {
  140. foreach resultPendingWeave
  141. foreach classfile
  142. get corresponding BcelObjectType
  143. weave
  144. update classfile held in result
  145. end
  146. end
  147. }
  148. ....
  149. *Note on createWorldAndWeaver(classpath):*
  150. We can probably avoid having to turn the Eclipse nameEnvironment
  151. into an externalized classpath by extending
  152. weaver.bcel.ClasspathManager to cope with "third party" managed
  153. classpath entries. On the eclipse side we can implement some
  154. interface and map it back into a call to INameEnvironment.findType -
  155. will need to cast returned IBinaryType into ClassFileReader, this is
  156. the only nasty. Much better than doing classpath nonsense though.
  157. *Note on handling the outjar option:*
  158. This will be addressed by the requestor, if they want the results
  159. to go into an outjar, they can do so when accepting results. It will
  160. also have to be known by the piece of logic that moves resources (but
  161. that is outside of compile anyway).
  162. *Note on handling sourceDirs:*
  163. This is a command-line option only, and is handled by adding all
  164. the source files in the directories to the list of sourceUnits passed
  165. into compile.
  166. *Note on handling aspectpath:*
  167. This is a list of directories and jar files containing class files
  168. to be added to the list of aspects. These class files will be added
  169. to the weaver's list of added aspects at the start of the weave phase
  170. *Note on handling injars, inpath:*
  171. These contain a set of class files that were not generated via
  172. parsing source, but instead are read directly from disk. We build a
  173. dummy CompilationResult in which getClassFiles() returns ClassFile
  174. objects for each of the class files. (Note, may need to define a
  175. ClassFile subclass with that just takes byte[] - this is a horrid
  176. hack but contained, and keeps the rest of the design clean).
  177. *Note on handling -XnoWeave:*
  178. Just skip the weave phase!
  179. == Handling Batch Compiles From Eclipse Using the New Model
  180. Eclipse is responsible for building the name enviroment and list of
  181. ICompilationUnits to be compiled (does this already today). Eclipse is
  182. also responsible for creating and passing in the desired requestor
  183. (does this already today too).
  184. We will add a new BcelWorld constructor that takes an
  185. org.aspectj.weaver.IManagedClasspath or similar in place of a
  186. List of String classpath entries. ClasspathManager will be extended to
  187. do the right thing with this, and on the Eclipse side we will
  188. implement the interface backed by an INameEnvironment as discussed in
  189. the notes above.
  190. The AspectJ specific options (aspectpath etc) are stored in an
  191. extension of IJavaProject, IAspectJProject, and persisted in .ajpath
  192. (analagous to .classpath) in the AspectJ project.
  193. The AbstractImageBuilder handles resource copying, and we don't need
  194. to change this logic in any way.
  195. That's all folks!
  196. == Handling Batch Compiles From ajc Using the New Model
  197. AjBuildManager creates the list of ICompilationUnits to be compiled in
  198. the same way that it does today.
  199. It could obtain a classpath to give to the weaver from AjBuildConfig
  200. in the same way that it does today - but it might be simpler and more
  201. consistent to pass across an IManagedClasspath built from the
  202. FileSystem (INameEnvironment) built from the classpath - this will
  203. give consistency across inside and outside Eclipse compiles.
  204. The compiler is constructed with a requestor that writes class files
  205. in CompilationUnitResults out to disk at the output location (or jar
  206. file) in the AjBuildConfig.
  207. The AspectJ specific options (aspectpath etc) are obtained from
  208. AjBuildConfig as today.
  209. Resource copying will ideally be handled outside of the weaver (from
  210. source dirs and inpath dirs only) inside AjBuildManager.
  211. == How Incremental Compilation Works in the JDT
  212. Incremental compilation begins in the JavaBuilder with a request to
  213. perform an incremental build. If the classpath of the project has
  214. changed, or a binary project member (jar or .class file) has changed,
  215. it reverts to a full build.
  216. An IncrementalImageBuilder is then created and asked to build the
  217. deltas since the last build. If this succeeds the new build state is
  218. recorded for the next compile, otherwise we revert to a full build.
  219. The IncrementalImageBuilder algorithm proceeds as follows:
  220. * initialize builder
  221. * walk this project's deltas, find changed source files
  222. * walk prereq projects' deltas, find changed class files & add
  223. * affected source files
  224. ** use the build state # to skip the deltas for certain prereq projects
  225. ** ignore changed zip/jar files since they caused a full build
  226. * compile the source files & acceptResult()
  227. * compare the produced class files against the existing ones on disk
  228. * recompile all dependent source files of any type with structural
  229. * changes or new/removed secondary type
  230. * keep a loop counter to abort & perform a full build (after 5 attempts)
  231. == How Incremental Compilation Works in AspectJ 1.1.x
  232. As per batch building, except that:
  233. * if previous built state (AjState) exists, we do not create a new
  234. bcelWorld (will use existing one).
  235. * create list of source files to compile by looking at all source
  236. files modified since last build date
  237. * delete any class files that resulted from now deleted files, tell
  238. the weaver about them
  239. * extend list of source files to compile with files containing types
  240. that reference types defined in modified source files
  241. * ask the compiler to compile the source files
  242. * find the list of source files that refer to things we changed, if
  243. its non-empty, defer to a batch build (this is like the eclipse
  244. algorithm, but with a loop count of 1).
  245. Now hand-off to weaver...
  246. * tell the weaver about every class file we wrote
  247. * weaver determines whether or not it needs to reweave everything by
  248. looking at added and deleted classes and searching for aspects
  249. (slight simplification)
  250. * weave proceeds as before, weaving either only the added classes, or
  251. everything, as required.
  252. == How we want Incremental Compilation to proceed in AspectJ 1.2
  253. This is harder to get right than batch (surprise). We still want the
  254. same two statements to hold at the end of the compilation of an
  255. individual source file:
  256. . all the class files have been written out and are ready to be used
  257. . all errors in any type defined in the file have been reported
  258. In both cases, the real 'incremental' logic is outside of the Compiler
  259. itself (in IncrementalImageBuilder and in AjBuildManager). In the
  260. current ajc case though, all compilation iterations have completed
  261. before entering a single back-end weave phase. Pushing weaving inside
  262. compile (as outlined in the proposal for batch building) makes this
  263. design harder to accomplish in the new world. We are saved by the fact
  264. that the current AspectJ incremental implementation currently only
  265. supports one go round the loop before bailing out to a full build, and
  266. we can mimic that behaviour easily.
  267. The logic in AjState that currently updates the weaver with
  268. addedClassFiles as compilation results are produced will have to be
  269. moved into the compiler (adaptor), to occur between the intermediate
  270. class file generation and the weaving phase.
  271. == Incremental AspectJ Compilation in Eclipse
  272. The JavaBuilder (one per project) will be responsible for managing the
  273. bcelWorld and bcelWeaver. These will be passed to the Compiler
  274. (Adaptor) prior to calling compile. The incremental build manager
  275. which processes deltas will be responsible for informing the weaver of
  276. deleted class files. Added class files are determined as compilation
  277. progresses. Weaving will happen inside the compile method, as
  278. described for batch, with the twist that the whole world may be
  279. rewoven if the weaver feels this is necessary. To keep things
  280. initially as close to the current AspectJ implementation as possible,
  281. we will set the maximum loop limit to 1 in the IncrementalImageBuilder
  282. so that we bail out to a full build if we don't compile everything we
  283. need in the first go. With a suitable test suite in place, there's no
  284. conceptual reason why we couldn't put that back up to 5 (the JDT
  285. default) as far as I can see right now.
  286. When performing a whole world weave, the compiler may end up asking
  287. requestors to acceptResult()s that they didn't request to be compiled,
  288. but this is no different to the dependency analysis done on
  289. referencing types that may then get added into subsequent incremental
  290. loops in the JDT today.
  291. == Incremental AspectJ Compilation in ajc
  292. AjBuildManager manages the bcelWorld and weaver as it does today, and
  293. passes them to the compiler adaptor for it to call the weave method
  294. rather than AjBuildManager calling weave directly as it does
  295. today.
  296. *Note on handling aspectpath:*
  297. If the JavaBuilder detects that the aspectpath itself has changed in
  298. any way, it will request a full build. If delta analysis during the
  299. first phase of incremental compilation detects that a jar or class
  300. file in an aspectpath has changed, it will bail out to a full build.
  301. *Note on handling injars, inpath:*
  302. We must make sure that the delta analysis allows a project with only
  303. an inpath change to proceed to building (rather than thinking that
  304. there is nothing to do). Any changed jars or class files will have
  305. their classes added to the weaver, and the weaver will be notified of
  306. deletions too. We need to ensure that we still continue on to
  307. compilation even when there are no "source files" in the work queue -
  308. will need some design.
  309. *For tomorrow:* start looking at refactoring AspectJ codebase itself to
  310. fit the new shape, ahead of trying to do ImageBuilder integration at
  311. the same time (in AspectJ, I have the test harness to guide me).