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.txt 14KB

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