Compiler-Inlining.st 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. Smalltalk current createPackage: 'Compiler-Inlining' properties: #{}!
  2. IRAssignment subclass: #IRInlinedAssignment
  3. instanceVariableNames: ''
  4. package: 'Compiler-Inlining'!
  5. !IRInlinedAssignment commentStamp!
  6. I represent an inlined assignment instruction.!
  7. !IRInlinedAssignment methodsFor: 'testing'!
  8. isInlined
  9. ^ true
  10. ! !
  11. !IRInlinedAssignment methodsFor: 'visiting'!
  12. accept: aVisitor
  13. ^ aVisitor visitIRInlinedAssignment: self
  14. ! !
  15. IRClosure subclass: #IRInlinedClosure
  16. instanceVariableNames: ''
  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. accept: aVisitor
  26. aVisitor visitIRInlinedClosure: self
  27. ! !
  28. IRReturn subclass: #IRInlinedReturn
  29. instanceVariableNames: ''
  30. package: 'Compiler-Inlining'!
  31. !IRInlinedReturn commentStamp!
  32. I represent an inlined local return instruction.!
  33. !IRInlinedReturn methodsFor: 'testing'!
  34. isInlined
  35. ^ true
  36. ! !
  37. !IRInlinedReturn methodsFor: 'visiting'!
  38. accept: aVisitor
  39. ^ aVisitor visitIRInlinedReturn: self
  40. ! !
  41. IRInlinedReturn subclass: #IRInlinedNonLocalReturn
  42. instanceVariableNames: ''
  43. package: 'Compiler-Inlining'!
  44. !IRInlinedNonLocalReturn commentStamp!
  45. I represent an inlined non local return instruction.!
  46. !IRInlinedNonLocalReturn methodsFor: 'testing'!
  47. isInlined
  48. ^ true
  49. ! !
  50. !IRInlinedNonLocalReturn methodsFor: 'visiting'!
  51. accept: aVisitor
  52. ^ aVisitor visitIRInlinedNonLocalReturn: self
  53. ! !
  54. IRSend subclass: #IRInlinedSend
  55. instanceVariableNames: ''
  56. package: 'Compiler-Inlining'!
  57. !IRInlinedSend commentStamp!
  58. I am the abstract super class of inlined message send instructions.!
  59. !IRInlinedSend methodsFor: 'testing'!
  60. isInlined
  61. ^ true
  62. ! !
  63. !IRInlinedSend methodsFor: 'visiting'!
  64. accept: aVisitor
  65. aVisitor visitInlinedSend: self
  66. ! !
  67. IRInlinedSend subclass: #IRInlinedIfFalse
  68. instanceVariableNames: ''
  69. package: 'Compiler-Inlining'!
  70. !IRInlinedIfFalse methodsFor: 'visiting'!
  71. accept: aVisitor
  72. aVisitor visitIRInlinedIfFalse: self
  73. ! !
  74. IRInlinedSend subclass: #IRInlinedIfNilIfNotNil
  75. instanceVariableNames: ''
  76. package: 'Compiler-Inlining'!
  77. !IRInlinedIfNilIfNotNil methodsFor: 'visiting'!
  78. accept: aVisitor
  79. aVisitor visitIRInlinedIfNilIfNotNil: self
  80. ! !
  81. IRInlinedSend subclass: #IRInlinedIfTrue
  82. instanceVariableNames: ''
  83. package: 'Compiler-Inlining'!
  84. !IRInlinedIfTrue methodsFor: 'visiting'!
  85. accept: aVisitor
  86. aVisitor visitIRInlinedIfTrue: self
  87. ! !
  88. IRInlinedSend subclass: #IRInlinedIfTrueIfFalse
  89. instanceVariableNames: ''
  90. package: 'Compiler-Inlining'!
  91. !IRInlinedIfTrueIfFalse methodsFor: 'visiting'!
  92. accept: aVisitor
  93. aVisitor visitIRInlinedIfTrueIfFalse: self
  94. ! !
  95. IRBlockSequence subclass: #IRInlinedSequence
  96. instanceVariableNames: ''
  97. package: 'Compiler-Inlining'!
  98. !IRInlinedSequence commentStamp!
  99. I represent a (block) sequence inside an inlined closure instruction (instance of `IRInlinedClosure`).!
  100. !IRInlinedSequence methodsFor: 'testing'!
  101. isInlined
  102. ^ true
  103. ! !
  104. !IRInlinedSequence methodsFor: 'visiting'!
  105. accept: aVisitor
  106. aVisitor visitIRInlinedSequence: self
  107. ! !
  108. IRInlinedSequence subclass: #IRAssigningInlinedSequence
  109. instanceVariableNames: 'assignTo'
  110. package: 'Compiler-Inlining'!
  111. !IRAssigningInlinedSequence methodsFor: 'accessing'!
  112. accept: aVisitor
  113. ^ aVisitor visitIRAssigningInlinedSequence: self
  114. !
  115. assignTo
  116. ^ assignTo
  117. !
  118. assignTo: anIRInstruction
  119. assignTo := anIRInstruction
  120. ! !
  121. IRInlinedSequence subclass: #IRReturningInlinedSequence
  122. instanceVariableNames: ''
  123. package: 'Compiler-Inlining'!
  124. !IRReturningInlinedSequence methodsFor: 'visiting'!
  125. accept: aVisitor
  126. ^ aVisitor visitIRReturningInlinedSequence: self
  127. ! !
  128. IRReturningInlinedSequence subclass: #IRNonLocalReturningInlinedSequence
  129. instanceVariableNames: ''
  130. package: 'Compiler-Inlining'!
  131. !IRNonLocalReturningInlinedSequence methodsFor: 'visiting'!
  132. accept: aVisitor
  133. ^ aVisitor visitIRNonLocalReturningInlinedSequence: self
  134. ! !
  135. IRVisitor subclass: #IRInliner
  136. instanceVariableNames: ''
  137. package: 'Compiler-Inlining'!
  138. !IRInliner commentStamp!
  139. I visit an IR tree, inlining message sends and block closures.
  140. Message selectors that can be inlined are answered by `IRSendInliner >> #inlinedSelectors`!
  141. !IRInliner methodsFor: 'factory'!
  142. assignmentInliner
  143. ^ IRAssignmentInliner new
  144. translator: self;
  145. yourself
  146. !
  147. nonLocalReturnInliner
  148. ^ IRNonLocalReturnInliner new
  149. translator: self;
  150. yourself
  151. !
  152. returnInliner
  153. ^ IRReturnInliner new
  154. translator: self;
  155. yourself
  156. !
  157. sendInliner
  158. ^ IRSendInliner new
  159. translator: self;
  160. yourself
  161. ! !
  162. !IRInliner methodsFor: 'testing'!
  163. shouldInlineAssignment: anIRAssignment
  164. ^ anIRAssignment isInlined not and: [
  165. anIRAssignment instructions last isSend and: [
  166. self shouldInlineSend: (anIRAssignment instructions last) ]]
  167. !
  168. shouldInlineReturn: anIRReturn
  169. ^ anIRReturn isInlined not and: [
  170. anIRReturn instructions first isSend and: [
  171. self shouldInlineSend: (anIRReturn instructions first) ]]
  172. !
  173. shouldInlineSend: anIRSend
  174. ^ anIRSend isInlined not and: [
  175. IRSendInliner shouldInline: anIRSend ]
  176. ! !
  177. !IRInliner methodsFor: 'visiting'!
  178. transformNonLocalReturn: anIRNonLocalReturn
  179. "Replace a non local return into a local return"
  180. | localReturn |
  181. anIRNonLocalReturn scope canInlineNonLocalReturns ifTrue: [
  182. anIRNonLocalReturn scope methodScope removeNonLocalReturn: anIRNonLocalReturn scope.
  183. localReturn := IRReturn new
  184. scope: anIRNonLocalReturn scope;
  185. yourself.
  186. anIRNonLocalReturn instructions do: [ :each |
  187. localReturn add: each ].
  188. anIRNonLocalReturn replaceWith: localReturn.
  189. ^ localReturn ].
  190. ^ super visitIRNonLocalReturn: anIRNonLocalReturn
  191. !
  192. visitIRAssignment: anIRAssignment
  193. ^ (self shouldInlineAssignment: anIRAssignment)
  194. ifTrue: [ self assignmentInliner inlineAssignment: anIRAssignment ]
  195. ifFalse: [ super visitIRAssignment: anIRAssignment ]
  196. !
  197. visitIRNonLocalReturn: anIRNonLocalReturn
  198. ^ (self shouldInlineReturn: anIRNonLocalReturn)
  199. ifTrue: [ self nonLocalReturnInliner inlineReturn: anIRNonLocalReturn ]
  200. ifFalse: [ self transformNonLocalReturn: anIRNonLocalReturn ]
  201. !
  202. visitIRReturn: anIRReturn
  203. ^ (self shouldInlineReturn: anIRReturn)
  204. ifTrue: [ self returnInliner inlineReturn: anIRReturn ]
  205. ifFalse: [ super visitIRReturn: anIRReturn ]
  206. !
  207. visitIRSend: anIRSend
  208. ^ (self shouldInlineSend: anIRSend)
  209. ifTrue: [ self sendInliner inlineSend: anIRSend ]
  210. ifFalse: [ super visitIRSend: anIRSend ]
  211. ! !
  212. IRJSTranslator subclass: #IRInliningJSTranslator
  213. instanceVariableNames: ''
  214. package: 'Compiler-Inlining'!
  215. !IRInliningJSTranslator commentStamp!
  216. I am a specialized JavaScript translator able to write inlined IR instructions to JavaScript stream (`JSStream` instance).!
  217. !IRInliningJSTranslator methodsFor: 'visiting'!
  218. visitIRAssigningInlinedSequence: anIRInlinedSequence
  219. anIRInlinedSequence instructions allButLast do: [ :each |
  220. self stream nextPutStatementWith: [ self visit: each ]].
  221. self stream nextPutStatementWith: [
  222. anIRInlinedSequence instructions last canBeAssigned
  223. ifTrue: [
  224. self stream
  225. nextPutAll: anIRInlinedSequence assignTo variable alias;
  226. nextPutAssignment.
  227. self visit: anIRInlinedSequence instructions last ]
  228. ifFalse: [ self visit: anIRInlinedSequence instructions last ]]
  229. !
  230. visitIRInlinedAssignment: anIRInlinedAssignment
  231. self visit: anIRInlinedAssignment instructions last
  232. !
  233. visitIRInlinedClosure: anIRInlinedClosure
  234. anIRInlinedClosure instructions do: [ :each |
  235. self visit: each ]
  236. !
  237. visitIRInlinedIfFalse: anIRInlinedIfFalse
  238. self stream nextPutIf: [
  239. self stream nextPutAll: '!! smalltalk.assert('.
  240. self visit: anIRInlinedIfFalse instructions first.
  241. self stream nextPutAll: ')' ]
  242. with: [ self visit: anIRInlinedIfFalse instructions last ]
  243. !
  244. visitIRInlinedIfNil: anIRInlinedIfNil
  245. self stream nextPutIf: [
  246. self stream nextPutAll: '($receiver = '.
  247. self visit: anIRInlinedIfNil instructions first.
  248. self stream nextPutAll: ') == nil || $receiver == undefined' ]
  249. with: [ self visit: anIRInlinedIfNil instructions last ]
  250. !
  251. visitIRInlinedIfNilIfNotNil: anIRInlinedIfNilIfNotNil
  252. self stream
  253. nextPutIfElse: [
  254. self stream nextPutAll: '($receiver = '.
  255. self visit: anIRInlinedIfNilIfNotNil instructions first.
  256. self stream nextPutAll: ') == nil || $receiver == undefined' ]
  257. with: [ self visit: anIRInlinedIfNilIfNotNil instructions second ]
  258. with: [ self visit: anIRInlinedIfNilIfNotNil instructions third ]
  259. !
  260. visitIRInlinedIfTrue: anIRInlinedIfTrue
  261. self stream nextPutIf: [
  262. self stream nextPutAll: 'smalltalk.assert('.
  263. self visit: anIRInlinedIfTrue instructions first.
  264. self stream nextPutAll: ')' ]
  265. with: [ self visit: anIRInlinedIfTrue instructions last ]
  266. !
  267. visitIRInlinedIfTrueIfFalse: anIRInlinedIfTrueIfFalse
  268. self stream
  269. nextPutIfElse: [
  270. self stream nextPutAll: 'smalltalk.assert('.
  271. self visit: anIRInlinedIfTrueIfFalse instructions first.
  272. self stream nextPutAll: ')' ]
  273. with: [ self visit: anIRInlinedIfTrueIfFalse instructions second ]
  274. with: [ self visit: anIRInlinedIfTrueIfFalse instructions third ]
  275. !
  276. visitIRInlinedNonLocalReturn: anIRInlinedReturn
  277. self stream nextPutStatementWith: [
  278. self visit: anIRInlinedReturn instructions last ].
  279. self stream nextPutNonLocalReturnWith: [ ]
  280. !
  281. visitIRInlinedReturn: anIRInlinedReturn
  282. self visit: anIRInlinedReturn instructions last
  283. !
  284. visitIRInlinedSequence: anIRInlinedSequence
  285. anIRInlinedSequence instructions do: [ :each |
  286. self stream nextPutStatementWith: [ self visit: each ]]
  287. !
  288. visitIRNonLocalReturningInlinedSequence: anIRInlinedSequence
  289. anIRInlinedSequence instructions allButLast do: [ :each |
  290. self stream nextPutStatementWith: [ self visit: each ]].
  291. self stream nextPutStatementWith: [
  292. anIRInlinedSequence instructions last canBeAssigned
  293. ifTrue: [
  294. self stream nextPutNonLocalReturnWith: [
  295. self visit: anIRInlinedSequence instructions last ]]
  296. ifFalse: [ self visit: anIRInlinedSequence instructions last ]]
  297. !
  298. visitIRReturningInlinedSequence: anIRInlinedSequence
  299. anIRInlinedSequence instructions allButLast do: [ :each |
  300. self stream nextPutStatementWith: [ self visit: each ]].
  301. self stream nextPutStatementWith: [
  302. anIRInlinedSequence instructions last canBeAssigned
  303. ifTrue: [
  304. self stream nextPutReturn.
  305. self visit: anIRInlinedSequence instructions last ]
  306. ifFalse: [ self visit: anIRInlinedSequence instructions last ]]
  307. ! !
  308. Object subclass: #IRSendInliner
  309. instanceVariableNames: 'send translator'
  310. package: 'Compiler-Inlining'!
  311. !IRSendInliner commentStamp!
  312. I inline some message sends and block closure arguments. I heavily rely on #perform: to dispatch inlining methods.!
  313. !IRSendInliner methodsFor: 'accessing'!
  314. send
  315. ^ send
  316. !
  317. send: anIRSend
  318. send := anIRSend
  319. !
  320. translator
  321. ^ translator
  322. !
  323. translator: anASTTranslator
  324. translator := anASTTranslator
  325. ! !
  326. !IRSendInliner methodsFor: 'error handling'!
  327. inliningError: aString
  328. InliningError signal: aString
  329. ! !
  330. !IRSendInliner methodsFor: 'factory'!
  331. inlinedClosure
  332. ^ IRInlinedClosure new
  333. !
  334. inlinedSequence
  335. ^ IRInlinedSequence new
  336. ! !
  337. !IRSendInliner methodsFor: 'inlining'!
  338. ifFalse: anIRInstruction
  339. ^ self inlinedSend: IRInlinedIfFalse new with: anIRInstruction
  340. !
  341. ifFalse: anIRInstruction ifTrue: anotherIRInstruction
  342. ^ self perform: #ifTrue:ifFalse: withArguments: { anotherIRInstruction. anIRInstruction }
  343. !
  344. ifNil: anIRInstruction
  345. ^ self
  346. inlinedSend: IRInlinedIfNilIfNotNil new
  347. with: anIRInstruction
  348. with: (IRClosure new
  349. scope: anIRInstruction scope copy;
  350. add: (IRBlockSequence new
  351. add: self send instructions first;
  352. yourself);
  353. yourself)
  354. !
  355. ifNil: anIRInstruction ifNotNil: anotherIRInstruction
  356. ^ self inlinedSend: IRInlinedIfNilIfNotNil new with: anIRInstruction with: anotherIRInstruction
  357. !
  358. ifNotNil: anIRInstruction
  359. ^ self
  360. inlinedSend: IRInlinedIfNilIfNotNil new
  361. with: (IRClosure new
  362. scope: anIRInstruction scope copy;
  363. add: (IRBlockSequence new
  364. add: self send instructions first;
  365. yourself);
  366. yourself)
  367. with: anIRInstruction
  368. !
  369. ifNotNil: anIRInstruction ifNil: anotherIRInstruction
  370. ^ self inlinedSend: IRInlinedIfNilIfNotNil new with: anotherIRInstruction with: anIRInstruction
  371. !
  372. ifTrue: anIRInstruction
  373. ^ self inlinedSend: IRInlinedIfTrue new with: anIRInstruction
  374. !
  375. ifTrue: anIRInstruction ifFalse: anotherIRInstruction
  376. ^ self inlinedSend: IRInlinedIfTrueIfFalse new with: anIRInstruction with: anotherIRInstruction
  377. !
  378. inlineClosure: anIRClosure
  379. | inlinedClosure sequence statements |
  380. inlinedClosure := self inlinedClosure.
  381. inlinedClosure scope: anIRClosure scope.
  382. "Add the possible temp declarations"
  383. anIRClosure instructions do: [ :each |
  384. each isSequence ifFalse: [
  385. inlinedClosure add: each ]].
  386. "Add a block sequence"
  387. sequence := self inlinedSequence.
  388. inlinedClosure add: sequence.
  389. "Get all the statements"
  390. statements := anIRClosure instructions last instructions.
  391. statements ifNotEmpty: [
  392. statements allButLast do: [ :each | sequence add: (self translator visit: each) ].
  393. "Inlined closures don't have implicit local returns"
  394. statements last isLocalReturn
  395. ifTrue: [ sequence add: (self translator visit: statements last instructions first) ]
  396. ifFalse: [ sequence add: (self translator visit: statements last) ]].
  397. ^ inlinedClosure
  398. !
  399. inlineMessageBlock: anIRInstruction with: anotherIRInstruction
  400. | inlinedSend inlinedClosure |
  401. anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
  402. anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
  403. inlinedClosure := self inlineClosure: anIRInstruction.
  404. inlinedSend := anotherIRInstruction.
  405. inlinedSend
  406. add: self send instructions first;
  407. add: inlinedClosure.
  408. self send replaceWith: inlinedSend.
  409. ^ inlinedSend
  410. !
  411. inlineSend: anIRSend
  412. self send: anIRSend.
  413. ^ self perform: self send selector withArguments: self send instructions allButFirst
  414. !
  415. inlinedSend: inlinedSend with: anIRInstruction
  416. | inlinedClosure |
  417. anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
  418. anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
  419. inlinedClosure := self inlineClosure: anIRInstruction.
  420. inlinedSend
  421. add: self send instructions first;
  422. add: inlinedClosure.
  423. self send replaceWith: inlinedSend.
  424. ^ inlinedSend
  425. !
  426. inlinedSend: inlinedSend with: anIRInstruction with: anotherIRInstruction
  427. | inlinedClosure1 inclinedClosure2 |
  428. anIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
  429. anIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
  430. anotherIRInstruction isClosure ifFalse: [ self inliningError: 'Message argument should be a block' ].
  431. anotherIRInstruction arguments size = 0 ifFalse: [ self inliningError: 'Inlined block should have zero argument' ].
  432. inlinedClosure := self inlineClosure: anIRInstruction.
  433. inlinedClosure2 := self inlineClosure: anotherIRInstruction.
  434. inlinedSend
  435. add: self send instructions first;
  436. add: inlinedClosure;
  437. add: inlinedClosure2.
  438. self send replaceWith: inlinedSend.
  439. ^ inlinedSend
  440. ! !
  441. !IRSendInliner class methodsFor: 'accessing'!
  442. inlinedSelectors
  443. ^ #('ifTrue:' 'ifFalse:' 'ifTrue:ifFalse:' 'ifFalse:ifTrue:' 'ifNil:' 'ifNotNil:' 'ifNil:ifNotNil:' 'ifNotNil:ifNil')
  444. !
  445. shouldInline: anIRInstruction
  446. (self inlinedSelectors includes: anIRInstruction selector) ifFalse: [ ^ false ].
  447. anIRInstruction instructions allButFirst do: [ :each |
  448. each isClosure ifFalse: [ ^ false ]].
  449. ^ true
  450. ! !
  451. IRSendInliner subclass: #IRAssignmentInliner
  452. instanceVariableNames: 'assignment'
  453. package: 'Compiler-Inlining'!
  454. !IRAssignmentInliner commentStamp!
  455. I inline message sends together with assignments by moving them around into the inline closure instructions.
  456. ##Example
  457. foo
  458. | a |
  459. a := true ifTrue: [ 1 ]
  460. Will produce:
  461. if(smalltalk.assert(true) {
  462. a = 1;
  463. };!
  464. !IRAssignmentInliner methodsFor: 'accessing'!
  465. assignment
  466. ^ assignment
  467. !
  468. assignment: aNode
  469. assignment := aNode
  470. ! !
  471. !IRAssignmentInliner methodsFor: 'factory'!
  472. inlinedSequence
  473. ^ IRAssigningInlinedSequence new
  474. assignTo: self assignment instructions first;
  475. yourself
  476. ! !
  477. !IRAssignmentInliner methodsFor: 'inlining'!
  478. inlineAssignment: anIRAssignment
  479. | inlinedAssignment |
  480. self assignment: anIRAssignment.
  481. inlinedAssignment := IRInlinedAssignment new.
  482. anIRAssignment instructions do: [ :each |
  483. inlinedAssignment add: each ].
  484. anIRAssignment replaceWith: inlinedAssignment.
  485. self inlineSend: inlinedAssignment instructions last.
  486. ^ inlinedAssignment
  487. ! !
  488. IRSendInliner subclass: #IRReturnInliner
  489. instanceVariableNames: ''
  490. package: 'Compiler-Inlining'!
  491. !IRReturnInliner commentStamp!
  492. I inline message sends with inlined closure together with a return instruction.!
  493. !IRReturnInliner methodsFor: 'factory'!
  494. inlinedReturn
  495. ^ IRInlinedReturn new
  496. !
  497. inlinedSequence
  498. ^ IRReturningInlinedSequence new
  499. ! !
  500. !IRReturnInliner methodsFor: 'inlining'!
  501. inlineReturn: anIRReturn
  502. | return |
  503. return := self inlinedReturn.
  504. anIRReturn instructions do: [ :each |
  505. return add: each ].
  506. anIRReturn replaceWith: return.
  507. self inlineSend: return instructions last.
  508. ^ return
  509. ! !
  510. IRReturnInliner subclass: #IRNonLocalReturnInliner
  511. instanceVariableNames: ''
  512. package: 'Compiler-Inlining'!
  513. !IRNonLocalReturnInliner methodsFor: 'factory'!
  514. inlinedReturn
  515. ^ IRInlinedNonLocalReturn new
  516. !
  517. inlinedSequence
  518. ^ IRNonLocalReturningInlinedSequence new
  519. ! !
  520. CodeGenerator subclass: #InliningCodeGenerator
  521. instanceVariableNames: ''
  522. package: 'Compiler-Inlining'!
  523. !InliningCodeGenerator commentStamp!
  524. I am a specialized code generator that uses inlining to produce more optimized JavaScript output!
  525. !InliningCodeGenerator methodsFor: 'compiling'!
  526. compileNode: aNode
  527. | ir stream |
  528. self semanticAnalyzer visit: aNode.
  529. ir := self translator visit: aNode.
  530. self inliner visit: ir.
  531. ^ self irTranslator
  532. visit: ir;
  533. contents
  534. !
  535. inliner
  536. ^ IRInliner new
  537. !
  538. irTranslator
  539. ^ IRInliningJSTranslator new
  540. ! !