Compiler-Inlining.st 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. Smalltalk createPackage: 'Compiler-Inlining'!
  2. NodeVisitor subclass: #ASTPreInliner
  3. slots: {}
  4. package: 'Compiler-Inlining'!
  5. !ASTPreInliner methodsFor: 'visiting'!
  6. visitSendNode: aNode
  7. aNode superSend ifFalse: [
  8. (IRSendInliner inlinedSelectors includes: aNode selector) ifTrue: [
  9. aNode shouldBeAliased: true.
  10. aNode receiver ifNotNil: [ :receiver |
  11. (IRSendInliner inlinedSelectorsNeedingIdempotentReceiver includes: aNode selector) ifTrue: [
  12. receiver shouldBeAliased: true ] ] ] ].
  13. ^ super visitSendNode: aNode
  14. ! !
  15. IRClosure subclass: #IRInlinedClosure
  16. slots: {}
  17. package: 'Compiler-Inlining'!
  18. !IRInlinedClosure commentStamp!
  19. I represent an inlined closure instruction.!
  20. !IRInlinedClosure methodsFor: 'testing'!
  21. isInlined
  22. ^ true
  23. ! !
  24. !IRInlinedClosure methodsFor: 'visiting'!
  25. acceptDagVisitor: aVisitor
  26. aVisitor visitIRInlinedClosure: self
  27. ! !
  28. IRSend subclass: #IRInlinedSend
  29. slots: {}
  30. package: 'Compiler-Inlining'!
  31. !IRInlinedSend commentStamp!
  32. I am the abstract super class of inlined message send instructions.!
  33. !IRInlinedSend methodsFor: 'accessing'!
  34. internalVariables
  35. "Answer a collection of internal variables required
  36. to perform the inlining"
  37. ^ #()
  38. ! !
  39. !IRInlinedSend methodsFor: 'testing'!
  40. isInlined
  41. ^ true
  42. ! !
  43. !IRInlinedSend methodsFor: 'visiting'!
  44. acceptDagVisitor: aVisitor
  45. aVisitor visitInlinedSend: self
  46. ! !
  47. IRInlinedSend subclass: #IRInlinedIfFalse
  48. slots: {}
  49. package: 'Compiler-Inlining'!
  50. !IRInlinedIfFalse commentStamp!
  51. I represent an inlined `#ifFalse:` message send instruction.!
  52. !IRInlinedIfFalse methodsFor: 'visiting'!
  53. acceptDagVisitor: aVisitor
  54. aVisitor visitIRInlinedIfFalse: self
  55. ! !
  56. IRInlinedSend subclass: #IRInlinedIfNil
  57. slots: {}
  58. package: 'Compiler-Inlining'!
  59. !IRInlinedIfNil commentStamp!
  60. I represent an inlined `#ifNil:ifNotNil:` message send instruction.!
  61. !IRInlinedIfNil methodsFor: 'visiting'!
  62. acceptDagVisitor: aVisitor
  63. aVisitor visitIRInlinedIfNil: self
  64. ! !
  65. IRInlinedSend subclass: #IRInlinedIfNilIfNotNil
  66. slots: {}
  67. package: 'Compiler-Inlining'!
  68. !IRInlinedIfNilIfNotNil commentStamp!
  69. I represent an inlined `#ifNil:ifNotNil:` message send instruction.!
  70. !IRInlinedIfNilIfNotNil methodsFor: 'visiting'!
  71. acceptDagVisitor: aVisitor
  72. aVisitor visitIRInlinedIfNilIfNotNil: self
  73. ! !
  74. IRInlinedSend subclass: #IRInlinedIfNotNil
  75. slots: {}
  76. package: 'Compiler-Inlining'!
  77. !IRInlinedIfNotNil commentStamp!
  78. I represent an inlined `#ifNil:ifNotNil:` message send instruction.!
  79. !IRInlinedIfNotNil methodsFor: 'visiting'!
  80. acceptDagVisitor: aVisitor
  81. aVisitor visitIRInlinedIfNotNil: self
  82. ! !
  83. IRInlinedSend subclass: #IRInlinedIfTrue
  84. slots: {}
  85. package: 'Compiler-Inlining'!
  86. !IRInlinedIfTrue commentStamp!
  87. I represent an inlined `#ifTrue:` message send instruction.!
  88. !IRInlinedIfTrue methodsFor: 'visiting'!
  89. acceptDagVisitor: aVisitor
  90. aVisitor visitIRInlinedIfTrue: self
  91. ! !
  92. IRInlinedSend subclass: #IRInlinedIfTrueIfFalse
  93. slots: {}
  94. package: 'Compiler-Inlining'!
  95. !IRInlinedIfTrueIfFalse commentStamp!
  96. I represent an inlined `#ifTrue:ifFalse:` message send instruction.!
  97. !IRInlinedIfTrueIfFalse methodsFor: 'visiting'!
  98. acceptDagVisitor: aVisitor
  99. aVisitor visitIRInlinedIfTrueIfFalse: self
  100. ! !
  101. IRBlockSequence subclass: #IRInlinedSequence
  102. slots: {}
  103. package: 'Compiler-Inlining'!
  104. !IRInlinedSequence commentStamp!
  105. I represent a (block) sequence inside an inlined closure instruction (instance of `IRInlinedClosure`).!
  106. !IRInlinedSequence methodsFor: 'testing'!
  107. isInlined
  108. ^ true
  109. ! !
  110. !IRInlinedSequence methodsFor: 'visiting'!
  111. acceptDagVisitor: aVisitor
  112. aVisitor visitIRInlinedSequence: self
  113. ! !
  114. IRVisitor subclass: #IRInliner
  115. slots: {}
  116. package: 'Compiler-Inlining'!
  117. !IRInliner commentStamp!
  118. I visit an IR tree, inlining message sends and block closures.
  119. Message selectors that can be inlined are answered by `IRSendInliner >> #inlinedSelectors`!
  120. !IRInliner methodsFor: 'factory'!
  121. assignmentInliner
  122. ^ IRAssignmentInliner new
  123. translator: self;
  124. yourself
  125. !
  126. nonLocalReturnInliner
  127. ^ IRNonLocalReturnInliner new
  128. translator: self;
  129. yourself
  130. !
  131. returnInliner
  132. ^ IRReturnInliner new
  133. translator: self;
  134. yourself
  135. !
  136. sendInliner
  137. ^ IRSendInliner new
  138. translator: self;
  139. yourself
  140. ! !
  141. !IRInliner methodsFor: 'testing'!
  142. shouldInlineAssignment: anIRAssignment
  143. ^ anIRAssignment isInlined not and: [
  144. anIRAssignment right isSend and: [
  145. self shouldInlineSend: anIRAssignment right ]]
  146. !
  147. shouldInlineReturn: anIRReturn
  148. ^ anIRReturn isInlined not and: [
  149. anIRReturn expression isSend and: [
  150. self shouldInlineSend: anIRReturn expression ]]
  151. !
  152. shouldInlineSend: anIRSend
  153. ^ anIRSend isInlined not and: [
  154. IRSendInliner shouldInline: anIRSend ]
  155. ! !
  156. !IRInliner methodsFor: 'visiting'!
  157. flattenedReturn: anIRNonLocalReturn
  158. | localReturn |
  159. localReturn := IRReturn new
  160. scope: anIRNonLocalReturn scope;
  161. yourself.
  162. anIRNonLocalReturn dagChildren do: [ :each | localReturn add: each ].
  163. ^ localReturn
  164. !
  165. visitIRAssignment: anIRAssignment
  166. ^ (self shouldInlineAssignment: anIRAssignment)
  167. ifTrue: [ self assignmentInliner inlineAssignment: anIRAssignment ]
  168. ifFalse: [ super visitIRAssignment: anIRAssignment ]
  169. !
  170. visitIRNonLocalReturn: anIRNonLocalReturn
  171. anIRNonLocalReturn scope canFlattenNonLocalReturns ifTrue: [
  172. | localReturn |
  173. anIRNonLocalReturn scope methodScope removeNonLocalReturn: anIRNonLocalReturn scope.
  174. localReturn := self flattenedReturn: anIRNonLocalReturn.
  175. anIRNonLocalReturn replaceWith: localReturn.
  176. ^ self visitIRReturn: localReturn ].
  177. ^ (self shouldInlineReturn: anIRNonLocalReturn)
  178. ifTrue: [ self nonLocalReturnInliner inlineReturn: anIRNonLocalReturn ]
  179. ifFalse: [ super visitIRNonLocalReturn: anIRNonLocalReturn ]
  180. !
  181. visitIRReturn: anIRReturn
  182. ^ (self shouldInlineReturn: anIRReturn)
  183. ifTrue: [ self returnInliner inlineReturn: anIRReturn ]
  184. ifFalse: [ super visitIRReturn: anIRReturn ]
  185. !
  186. visitIRSend: anIRSend
  187. ^ (self shouldInlineSend: anIRSend)
  188. ifTrue: [ self sendInliner inlineSend: anIRSend ]
  189. ifFalse: [ super visitIRSend: anIRSend ]
  190. ! !
  191. IRJSTranslator subclass: #IRInliningJSTranslator
  192. slots: {}
  193. package: 'Compiler-Inlining'!
  194. !IRInliningJSTranslator commentStamp!
  195. I am a specialized JavaScript translator able to write inlined IR instructions to JavaScript stream (`JSStream` instance).!
  196. !IRInliningJSTranslator methodsFor: 'visiting'!
  197. visitIRInlinedClosure: anIRInlinedClosure
  198. self stream nextPutVars: (anIRInlinedClosure tempDeclarations collect: [ :each |
  199. each name asVariableName ]).
  200. self visitAllChildren: anIRInlinedClosure
  201. !
  202. visitIRInlinedIfFalse: anIRInlinedIfFalse
  203. self stream nextPutIf: [
  204. self stream nextPutAll: '!!$core.assert('.
  205. self visit: anIRInlinedIfFalse dagChildren first.
  206. self stream nextPutAll: ')' ]
  207. then: [ self visit: anIRInlinedIfFalse dagChildren last ]
  208. !
  209. visitIRInlinedIfNil: anIRInlinedIfNil
  210. self stream
  211. nextPutIf: [
  212. self visit: anIRInlinedIfNil dagChildren first.
  213. self stream nextPutAll: ' == null || '.
  214. self visit: anIRInlinedIfNil dagChildren first.
  215. self stream nextPutAll: '.a$nil' ]
  216. then: [ self visit: anIRInlinedIfNil dagChildren second ]
  217. !
  218. visitIRInlinedIfNilIfNotNil: anIRInlinedIfNilIfNotNil
  219. self stream
  220. nextPutIf: [
  221. self visit: anIRInlinedIfNilIfNotNil dagChildren first.
  222. self stream nextPutAll: ' == null || '.
  223. self visit: anIRInlinedIfNilIfNotNil dagChildren first.
  224. self stream nextPutAll: '.a$nil' ]
  225. then: [ self visit: anIRInlinedIfNilIfNotNil dagChildren second ]
  226. else: [ self visit: anIRInlinedIfNilIfNotNil dagChildren third ]
  227. !
  228. visitIRInlinedIfNotNil: anIRInlinedIfNotNil
  229. self stream
  230. nextPutIf: [
  231. self visit: anIRInlinedIfNotNil dagChildren first.
  232. self stream nextPutAll: ' !!= null && !!'.
  233. self visit: anIRInlinedIfNotNil dagChildren first.
  234. self stream nextPutAll: '.a$nil' ]
  235. then: [ self visit: anIRInlinedIfNotNil dagChildren second ]
  236. !
  237. visitIRInlinedIfTrue: anIRInlinedIfTrue
  238. self stream nextPutIf: [
  239. self stream nextPutAll: '$core.assert('.
  240. self visit: anIRInlinedIfTrue dagChildren first.
  241. self stream nextPutAll: ')' ]
  242. then: [ self visit: anIRInlinedIfTrue dagChildren last ]
  243. !
  244. visitIRInlinedIfTrueIfFalse: anIRInlinedIfTrueIfFalse
  245. self stream
  246. nextPutIf: [
  247. self stream nextPutAll: '$core.assert('.
  248. self visit: anIRInlinedIfTrueIfFalse dagChildren first.
  249. self stream nextPutAll: ')' ]
  250. then: [ self visit: anIRInlinedIfTrueIfFalse dagChildren second ]
  251. else: [ self visit: anIRInlinedIfTrueIfFalse dagChildren third ]
  252. ! !
  253. Object subclass: #IRSendInliner
  254. slots: {#send. #translator}
  255. package: 'Compiler-Inlining'!
  256. !IRSendInliner commentStamp!
  257. I inline some message sends and block closure arguments. I heavily rely on #perform: to dispatch inlining methods.!
  258. !IRSendInliner methodsFor: 'accessing'!
  259. send
  260. ^ send
  261. !
  262. send: anIRSend
  263. send := anIRSend
  264. !
  265. translator
  266. ^ translator
  267. !
  268. translator: anASTTranslator
  269. translator := anASTTranslator
  270. ! !
  271. !IRSendInliner methodsFor: 'error handling'!
  272. inliningError: aString
  273. InliningError signal: aString
  274. ! !
  275. !IRSendInliner methodsFor: 'factory'!
  276. inlinedClosure
  277. ^ IRInlinedClosure new
  278. !
  279. inlinedSequence
  280. ^ IRInlinedSequence new
  281. ! !
  282. !IRSendInliner methodsFor: 'inlining'!
  283. and: anIRInstruction
  284. self mustBeNiladicClosure: anIRInstruction.
  285. ^ self
  286. inlinedSend: IRInlinedIfTrueIfFalse new
  287. withBlock: anIRInstruction
  288. withBlock: (IRClosure new
  289. scope: anIRInstruction scope copy;
  290. add: (IRBlockSequence new
  291. add: (IRValue new value: false; yourself);
  292. yourself);
  293. yourself)
  294. !
  295. ifFalse: anIRInstruction
  296. self mustBeNiladicClosure: anIRInstruction.
  297. ^ self inlinedSend: IRInlinedIfFalse new withBlock: anIRInstruction
  298. !
  299. ifFalse: anIRInstruction ifTrue: anotherIRInstruction
  300. self mustBeNiladicClosure: anIRInstruction.
  301. self mustBeNiladicClosure: anotherIRInstruction.
  302. ^ self inlinedSend: IRInlinedIfTrueIfFalse new withBlock: anotherIRInstruction withBlock: anIRInstruction
  303. !
  304. ifNil: anIRInstruction
  305. self mustBeNiladicClosure: anIRInstruction.
  306. ^ self inlinedSend: IRInlinedIfNil new withBlock: anIRInstruction
  307. !
  308. ifNil: anIRInstruction ifNotNil: anotherIRInstruction
  309. self mustBeNiladicClosure: anIRInstruction.
  310. self mustBeNiladicOrUnaryClosure: anotherIRInstruction.
  311. ^ self inlinedSend: IRInlinedIfNilIfNotNil new withBlock: anIRInstruction withBlock: anotherIRInstruction
  312. !
  313. ifNotNil: anIRInstruction
  314. self mustBeNiladicOrUnaryClosure: anIRInstruction.
  315. ^ self inlinedSend: IRInlinedIfNotNil new withBlock: anIRInstruction
  316. !
  317. ifNotNil: anIRInstruction ifNil: anotherIRInstruction
  318. self mustBeNiladicOrUnaryClosure: anIRInstruction.
  319. self mustBeNiladicClosure: anotherIRInstruction.
  320. ^ self inlinedSend: IRInlinedIfNilIfNotNil new withBlock: anotherIRInstruction withBlock: anIRInstruction
  321. !
  322. ifTrue: anIRInstruction
  323. self mustBeNiladicClosure: anIRInstruction.
  324. ^ self inlinedSend: IRInlinedIfTrue new withBlock: anIRInstruction
  325. !
  326. ifTrue: anIRInstruction ifFalse: anotherIRInstruction
  327. self mustBeNiladicClosure: anIRInstruction.
  328. self mustBeNiladicClosure: anotherIRInstruction.
  329. ^ self inlinedSend: IRInlinedIfTrueIfFalse new withBlock: anIRInstruction withBlock: anotherIRInstruction
  330. !
  331. inlineClosure: anIRClosure
  332. | inlinedClosure sequence statements |
  333. inlinedClosure := self inlinedClosure.
  334. inlinedClosure
  335. scope: anIRClosure scope;
  336. parent: anIRClosure parent.
  337. "Add the possible temp declarations"
  338. anIRClosure tempDeclarations do: [ :each |
  339. inlinedClosure add: each ].
  340. "Add a block sequence"
  341. sequence := self inlinedSequence.
  342. "Map the closure arguments to the receiver of the message send"
  343. anIRClosure arguments do: [ :each |
  344. inlinedClosure add: (IRTempDeclaration new name: each; yourself).
  345. sequence add: (IRAssignment new
  346. add: (IRVariable new variable: (ArgVar new scope: inlinedClosure scope; name: each; yourself));
  347. add: self send receiver;
  348. yourself) ].
  349. "To ensure the correct order of the closure instructions: first the temps then the sequence"
  350. inlinedClosure add: sequence.
  351. "Get all the statements"
  352. statements := anIRClosure sequence dagChildren.
  353. statements ifNotEmpty: [
  354. statements allButLast do: [ :each | sequence add: each ].
  355. "Inlined closures change local returns into result value itself"
  356. sequence add: statements last asInlinedBlockResult ].
  357. ^ inlinedClosure
  358. !
  359. inlineSend: anIRSend
  360. self send: anIRSend.
  361. ^ self
  362. perform: self send selector
  363. withArguments: self send arguments
  364. !
  365. or: anIRInstruction
  366. self mustBeNiladicClosure: anIRInstruction.
  367. ^ self
  368. inlinedSend: IRInlinedIfTrueIfFalse new
  369. withBlock: (IRClosure new
  370. scope: anIRInstruction scope copy;
  371. add: (IRBlockSequence new
  372. add: (IRValue new value: true; yourself);
  373. yourself);
  374. yourself)
  375. withBlock: anIRInstruction
  376. ! !
  377. !IRSendInliner methodsFor: 'private'!
  378. inlineSend: anIRSend andReplace: anIRInstruction
  379. anIRInstruction replaceWith: anIRSend.
  380. ^ self inlineSend: anIRSend
  381. !
  382. inlinedSend: inlinedSend withBlock: anIRInstruction
  383. | inlinedClosure |
  384. inlinedClosure := self translator visit: (self inlineClosure: anIRInstruction).
  385. inlinedSend
  386. add: self send receiver;
  387. add: inlinedClosure.
  388. self send replaceWith: inlinedSend.
  389. inlinedSend method internalVariables
  390. addAll: inlinedSend internalVariables.
  391. ^ inlinedSend
  392. !
  393. inlinedSend: inlinedSend withBlock: anIRInstruction withBlock: anotherIRInstruction
  394. | inlinedClosure1 inlinedClosure2 |
  395. inlinedClosure1 := self translator visit: (self inlineClosure: anIRInstruction).
  396. inlinedClosure2 := self translator visit: (self inlineClosure: anotherIRInstruction).
  397. inlinedSend
  398. add: self send receiver;
  399. add: inlinedClosure1;
  400. add: inlinedClosure2.
  401. self send replaceWith: inlinedSend.
  402. inlinedSend method internalVariables
  403. addAll: inlinedSend internalVariables.
  404. ^ inlinedSend
  405. ! !
  406. !IRSendInliner methodsFor: 'testing'!
  407. mustBeNiladicClosure: anIRInstruction
  408. anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
  409. anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ]
  410. !
  411. mustBeNiladicOrUnaryClosure: anIRInstruction
  412. anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
  413. anIRInstruction arguments size <= 1 ifFalse: [ self inliningError: 'Inlined block should have at most one argument' ]
  414. ! !
  415. !IRSendInliner class methodsFor: 'accessing'!
  416. inlinedSelectors
  417. ^ #(
  418. ifTrue: ifFalse: ifTrue:ifFalse: ifFalse:ifTrue:
  419. ifNil: ifNotNil: ifNil:ifNotNil: ifNotNil:ifNil:
  420. and: or:
  421. )
  422. !
  423. inlinedSelectorsNeedingIdempotentReceiver
  424. ^ #(
  425. ifNil: ifNotNil: ifNil:ifNotNil: ifNotNil:ifNil:
  426. )
  427. !
  428. shouldInline: anIRSend
  429. ^ (self inlinedSelectors includes: anIRSend selector) and: [
  430. anIRSend receiver isSuper not and: [
  431. anIRSend arguments allSatisfy: [ :each | each isClosure ] ] ]
  432. ! !
  433. IRSendInliner subclass: #IRWrappingSendInliner
  434. slots: {}
  435. package: 'Compiler-Inlining'!
  436. !IRWrappingSendInliner commentStamp!
  437. I inline some message sends and block closure arguments. I heavily rely on #perform: to dispatch inlining methods.!
  438. !IRWrappingSendInliner methodsFor: 'inlining'!
  439. ifFalse: anIRInstruction
  440. self mustBeNiladicClosure: anIRInstruction.
  441. ^ self inlinedSend:
  442. IRInlinedIfTrueIfFalse new
  443. withBlock: (IRClosure new
  444. scope: anIRInstruction scope copy;
  445. add: IRBlockSequence new
  446. yourself)
  447. withBlock: anIRInstruction
  448. !
  449. ifNil: anIRInstruction
  450. self mustBeNiladicClosure: anIRInstruction.
  451. ^ self
  452. inlinedSend: IRInlinedIfNilIfNotNil new
  453. withBlock: anIRInstruction
  454. withBlock: (IRClosure new
  455. scope: anIRInstruction scope copy;
  456. add: (IRBlockSequence new
  457. add: self send receiver;
  458. yourself);
  459. yourself)
  460. !
  461. ifNotNil: anIRInstruction
  462. self mustBeNiladicOrUnaryClosure: anIRInstruction.
  463. ^ self
  464. inlinedSend: IRInlinedIfNilIfNotNil new
  465. withBlock: (IRClosure new
  466. scope: anIRInstruction scope copy;
  467. add: (IRBlockSequence new
  468. add: self send receiver;
  469. yourself);
  470. yourself)
  471. withBlock: anIRInstruction
  472. !
  473. ifTrue: anIRInstruction
  474. self mustBeNiladicClosure: anIRInstruction.
  475. ^ self inlinedSend:
  476. IRInlinedIfTrueIfFalse new
  477. withBlock: anIRInstruction
  478. withBlock: (IRClosure new
  479. scope: anIRInstruction scope copy;
  480. add: IRBlockSequence new
  481. yourself)
  482. !
  483. inlinedClosure: closure wrapFinalValueIn: aBlock
  484. | sequence final |
  485. sequence := closure sequence.
  486. sequence dagChildren ifEmpty: [ sequence add: (IRVariable new
  487. variable: (closure scope pseudoVars at: 'nil');
  488. yourself) ].
  489. final := sequence dagChildren last.
  490. final yieldsValue ifTrue: [ sequence replace: final with: (aBlock value: final) ].
  491. ^ closure
  492. ! !
  493. IRWrappingSendInliner subclass: #IRAssignmentInliner
  494. slots: {#target}
  495. package: 'Compiler-Inlining'!
  496. !IRAssignmentInliner commentStamp!
  497. I inline message sends together with assignments by moving them around into the inline closure instructions.
  498. ##Example
  499. foo
  500. | a |
  501. a := true ifTrue: [ 1 ]
  502. Will produce:
  503. if($core.assert(true) {
  504. a = 1;
  505. };!
  506. !IRAssignmentInliner methodsFor: 'accessing'!
  507. target
  508. ^ target
  509. !
  510. target: anObject
  511. target := anObject
  512. ! !
  513. !IRAssignmentInliner methodsFor: 'inlining'!
  514. inlineAssignment: anIRAssignment
  515. self target: anIRAssignment left.
  516. ^ self inlineSend: anIRAssignment right andReplace: anIRAssignment
  517. !
  518. inlineClosure: anIRClosure
  519. ^ self
  520. inlinedClosure: (super inlineClosure: anIRClosure)
  521. wrapFinalValueIn: [ :final |
  522. IRAssignment new
  523. add: self target;
  524. add: final copy;
  525. yourself ]
  526. ! !
  527. IRWrappingSendInliner subclass: #IRNonLocalReturnInliner
  528. slots: {}
  529. package: 'Compiler-Inlining'!
  530. !IRNonLocalReturnInliner commentStamp!
  531. I inline message sends with inlined closure together with a return instruction.!
  532. !IRNonLocalReturnInliner methodsFor: 'inlining'!
  533. inlineClosure: anIRClosure
  534. ^ self
  535. inlinedClosure: (super inlineClosure: anIRClosure)
  536. wrapFinalValueIn: [ :final |
  537. IRNonLocalReturn new
  538. add: final copy;
  539. yourself ]
  540. !
  541. inlineReturn: anIRReturn
  542. ^ self inlineSend: anIRReturn expression andReplace: anIRReturn
  543. ! !
  544. IRWrappingSendInliner subclass: #IRReturnInliner
  545. slots: {}
  546. package: 'Compiler-Inlining'!
  547. !IRReturnInliner commentStamp!
  548. I inline message sends with inlined closure together with a return instruction.!
  549. !IRReturnInliner methodsFor: 'inlining'!
  550. inlineClosure: anIRClosure
  551. ^ self
  552. inlinedClosure: (super inlineClosure: anIRClosure)
  553. wrapFinalValueIn: [ :final |
  554. IRReturn new
  555. add: final copy;
  556. yourself ]
  557. !
  558. inlineReturn: anIRReturn
  559. ^ self inlineSend: anIRReturn expression andReplace: anIRReturn
  560. ! !
  561. CodeGenerator subclass: #InliningCodeGenerator
  562. slots: {}
  563. package: 'Compiler-Inlining'!
  564. !InliningCodeGenerator commentStamp!
  565. I am a specialized code generator that uses inlining to produce more optimized JavaScript output!
  566. !InliningCodeGenerator methodsFor: 'compiling'!
  567. inliner
  568. ^ IRInliner new
  569. !
  570. irTranslatorClass
  571. ^ IRInliningJSTranslator
  572. !
  573. preInliner
  574. ^ ASTPreInliner new
  575. !
  576. transformersDictionary
  577. ^ transformersDictionary ifNil: [ transformersDictionary := super transformersDictionary
  578. at: '3000-inlinerTagging' put: self preInliner;
  579. at: '6000-inliner' put: self inliner;
  580. at: '8000-irToJs' put: self irTranslator;
  581. yourself ]
  582. ! !
  583. SemanticError subclass: #InliningError
  584. slots: {}
  585. package: 'Compiler-Inlining'!
  586. !InliningError commentStamp!
  587. Instances of InliningError are signaled when using an `InliningCodeGenerator`in a `Compiler`.!
  588. Trait named: #TIRInlinedVisitor
  589. package: 'Compiler-Inlining'!
  590. !TIRInlinedVisitor methodsFor: 'visiting'!
  591. visitIRInlinedClosure: anIRInlinedClosure
  592. ^ self visitIRClosure: anIRInlinedClosure
  593. !
  594. visitIRInlinedSequence: anIRInlinedSequence
  595. ^ self visitIRSequence: anIRInlinedSequence
  596. ! !
  597. IRInliner setTraitComposition: {TIRInlinedVisitor} asTraitComposition!
  598. IRInliningJSTranslator setTraitComposition: {TIRInlinedVisitor} asTraitComposition!
  599. ! !
  600. !IRBlockReturn methodsFor: '*Compiler-Inlining'!
  601. asInlinedBlockResult
  602. ^ self expression
  603. ! !
  604. !IRInstruction methodsFor: '*Compiler-Inlining'!
  605. asInlinedBlockResult
  606. ^ self
  607. ! !