Compiler-Inlining.st 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. Smalltalk current createPackage: 'Compiler-Inlining' properties: #{}!
  2. IRAssignment subclass: #IRInlinedAssignment
  3. instanceVariableNames: ''
  4. package: 'Compiler-Inlining'!
  5. !IRInlinedAssignment methodsFor: 'testing'!
  6. isInlined
  7. ^ true
  8. ! !
  9. !IRInlinedAssignment methodsFor: 'visiting'!
  10. accept: aVisitor
  11. ^ aVisitor visitIRInlinedAssignment: self
  12. ! !
  13. IRClosure subclass: #IRInlinedClosure
  14. instanceVariableNames: 'assignTo'
  15. package: 'Compiler-Inlining'!
  16. !IRInlinedClosure methodsFor: 'accessing'!
  17. assignTo
  18. ^ assignTo
  19. !
  20. assignTo: aScopeVar
  21. assignTo := aScopeVar
  22. ! !
  23. !IRInlinedClosure methodsFor: 'testing'!
  24. isInlined
  25. ^ true
  26. ! !
  27. !IRInlinedClosure methodsFor: 'visiting'!
  28. accept: aVisitor
  29. aVisitor visitIRInlinedClosure: self
  30. ! !
  31. IRNonLocalReturn subclass: #IRInlinedNonLocalReturn
  32. instanceVariableNames: ''
  33. package: 'Compiler-Inlining'!
  34. !IRInlinedNonLocalReturn methodsFor: 'testing'!
  35. isInlined
  36. ^ true
  37. ! !
  38. !IRInlinedNonLocalReturn methodsFor: 'visiting'!
  39. accept: aVisitor
  40. ^ aVisitor visitIRInlinedNonLocalReturn: self
  41. ! !
  42. IRSend subclass: #IRInlinedSend
  43. instanceVariableNames: ''
  44. package: 'Compiler-Inlining'!
  45. !IRInlinedSend methodsFor: 'testing'!
  46. isInlined
  47. ^ true
  48. ! !
  49. !IRInlinedSend methodsFor: 'visiting'!
  50. accept: aVisitor
  51. aVisitor visitInlinedSend: self
  52. ! !
  53. IRInlinedSend subclass: #IRInlinedIfTrue
  54. instanceVariableNames: ''
  55. package: 'Compiler-Inlining'!
  56. !IRInlinedIfTrue methodsFor: 'visiting'!
  57. accept: aVisitor
  58. aVisitor visitIRInlinedIfTrue: self
  59. ! !
  60. IRVisitor subclass: #IRInliner
  61. instanceVariableNames: ''
  62. package: 'Compiler-Inlining'!
  63. !IRInliner methodsFor: 'testing'!
  64. shouldInlineAssignment: anIRAssignment
  65. ^ anIRAssignment isInlined not and: [
  66. anIRAssignment instructions last isSend and: [
  67. self shouldInlineSend: (anIRAssignment instructions last) ]]
  68. !
  69. shouldInlineSend: anIRSend
  70. ^ anIRSend isInlined not and: [
  71. IRSendInliner inlinedSelectors includes: anIRSend selector ]
  72. ! !
  73. !IRInliner methodsFor: 'visiting'!
  74. assignmentInliner
  75. ^ IRAssignmentInliner new
  76. translator: self;
  77. yourself
  78. !
  79. sendInliner
  80. ^ IRSendInliner new
  81. translator: self;
  82. yourself
  83. !
  84. visitIRAssignment: anIRAssignment
  85. ^ (self shouldInlineAssignment: anIRAssignment)
  86. ifTrue: [ self assignmentInliner inlineAssignment: anIRAssignment ]
  87. ifFalse: [ super visitIRAssignment: anIRAssignment ]
  88. !
  89. visitIRSend: anIRSend
  90. ^ (self shouldInlineSend: anIRSend)
  91. ifTrue: [ self sendInliner inlineSend: anIRSend ]
  92. ifFalse: [ super visitIRSend: anIRSend ]
  93. !
  94. visitSendNode: aNode
  95. aNode canBeInlined
  96. ifTrue: [ self sendInliner inlineSend: aNode ]
  97. ifFalse: [ super visitSendNode: aNode ]
  98. ! !
  99. IRJSTranslator subclass: #IRInliningJSTranslator
  100. instanceVariableNames: ''
  101. package: 'Compiler-Inlining'!
  102. !IRInliningJSTranslator methodsFor: 'visiting'!
  103. visitIRInlinedAssignment: anIRInlinedAssignment
  104. self visit: anIRInlinedAssignment instructions last
  105. !
  106. visitIRInlinedClosure: anIRInlinedClosure
  107. anIRInlinedClosure instructions allButLast do: [ :each | self visit: each ].
  108. anIRInlinedClosure assignTo ifNotNil: [
  109. self stream nextPutAll: anIRInlinedClosure assignTo variable alias.
  110. self stream nextPutAssignment ].
  111. self visit: anIRInlinedClosure instructions last
  112. !
  113. visitIRInlinedIfTrue: anIRInlinedIfTrue
  114. self stream
  115. nextPutIf: [ self visit: anIRInlinedIfTrue instructions first ]
  116. with: [ self visit: anIRInlinedIfTrue instructions last ]
  117. ! !
  118. Object subclass: #IRSendInliner
  119. instanceVariableNames: 'send translator'
  120. package: 'Compiler-Inlining'!
  121. !IRSendInliner commentStamp!
  122. I inline some message sends and block closure arguments. I heavily rely on #perform: to dispatch inlining methods.!
  123. !IRSendInliner methodsFor: 'accessing'!
  124. inlinedClosure
  125. ^ IRInlinedClosure new
  126. !
  127. send
  128. ^ send
  129. !
  130. send: anIRSend
  131. send := anIRSend
  132. !
  133. translator
  134. ^ translator
  135. !
  136. translator: anASTTranslator
  137. translator := anASTTranslator
  138. ! !
  139. !IRSendInliner methodsFor: 'error handling'!
  140. inliningError: aString
  141. InliningError signal: aString
  142. ! !
  143. !IRSendInliner methodsFor: 'inlining'!
  144. ifTrue: anIRInstruction
  145. | inlinedSend inlinedClosure |
  146. anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
  147. anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
  148. inlinedClosure := self inlinedClosure.
  149. anIRInstruction instructions do: [ :each |
  150. instruction := (self translator visit: each) first.
  151. inlinedClosure add: instruction ].
  152. inlinedSend := IRInlinedIfTrue new.
  153. inlinedSend
  154. add: self send instructions first;
  155. add: inlinedClosure.
  156. self send replaceWith: inlinedSend.
  157. ^ inlinedSend
  158. !
  159. inlineSend: anIRSend
  160. self send: anIRSend.
  161. self perform: self send selector withArguments: self send instructions allButFirst
  162. ! !
  163. !IRSendInliner class methodsFor: 'accessing'!
  164. inlinedSelectors
  165. ^ #('ifTrue:')
  166. ! !
  167. IRSendInliner subclass: #IRAssignmentInliner
  168. instanceVariableNames: 'assignment'
  169. package: 'Compiler-Inlining'!
  170. !IRAssignmentInliner methodsFor: 'accessing'!
  171. assignment
  172. ^ assignment
  173. !
  174. assignment: aNode
  175. assignment := aNode
  176. !
  177. inlinedClosure
  178. ^ super inlinedClosure
  179. assignTo: self assignment instructions first;
  180. yourself
  181. ! !
  182. !IRAssignmentInliner methodsFor: 'inlining'!
  183. inlineAssignment: anIRAssignment
  184. | inlinedAssignment |
  185. self assignment: anIRAssignment.
  186. inlinedAssignment := IRInlinedAssignment new.
  187. anIRAssignment instructions do: [ :each |
  188. inlinedAssignment add: each ].
  189. anIRAssignment replaceWith: inlinedAssignment.
  190. self inlineSend: inlinedAssignment instructions last.
  191. ^ inlinedAssignment
  192. ! !
  193. CodeGenerator subclass: #InliningCodeGenerator
  194. instanceVariableNames: ''
  195. package: 'Compiler-Inlining'!
  196. !InliningCodeGenerator methodsFor: 'compiling'!
  197. compileNode: aNode
  198. | ir stream |
  199. self semanticAnalyzer visit: aNode.
  200. ir := self translator visit: aNode.
  201. self inliner visit: ir.
  202. ^ self irTranslator
  203. visit: ir;
  204. contents
  205. !
  206. inliner
  207. ^ IRInliner new
  208. !
  209. irTranslator
  210. ^ IRInliningJSTranslator new
  211. ! !