|
1 "{ Package: 'stx:goodies/newcompiler' }" |
|
2 |
|
3 IRInterpreter subclass:#IRTranslator |
|
4 instanceVariableNames:'pending gen currentInstr trailerBytes' |
|
5 classVariableNames:'' |
|
6 poolDictionaries:'' |
|
7 category:'NewCompiler-IR' |
|
8 ! |
|
9 |
|
10 IRTranslator comment:'I interpret IRMethod instructions, sending the appropriate bytecode messages to my BytecodeGenerator (gen). I hold some messages back in pending awaiting certain sequences of them that can be consolidated into single bytecode instructions, otherwise the pending messages are executed in order as if they were executed when they first appeared.' |
|
11 ! |
|
12 |
|
13 |
|
14 !IRTranslator class methodsFor:'instance creation'! |
|
15 |
|
16 new |
|
17 ^ self basicNew initialize. |
|
18 |
|
19 "Created: / 11-06-2008 / 09:24:01 / Jan Vrany <vranyj1@fel.cvut.cz>" |
|
20 ! ! |
|
21 |
|
22 !IRTranslator methodsFor:'initialization'! |
|
23 |
|
24 initialize |
|
25 "Invoked when a new instance is created." |
|
26 |
|
27 "/ please change as required (and remove this comment) |
|
28 pending := OrderedCollection new. |
|
29 gen := IRBytecodeGenerator new. |
|
30 "/ currentInstr := nil. |
|
31 "/ trailerBytes := nil. |
|
32 |
|
33 "/ super initialize. -- commented since inherited method does nothing |
|
34 |
|
35 "Created: / 11-06-2008 / 13:46:17 / Jan Vrany <vranyj1@fel.cvut.cz>" |
|
36 ! ! |
|
37 |
|
38 !IRTranslator methodsFor:'instructions'! |
|
39 |
|
40 addLiteral: literal |
|
41 gen addLiteral: literal. |
|
42 ! |
|
43 |
|
44 blockReturnTop |
|
45 |
|
46 self doPending. |
|
47 gen blockReturnTop. |
|
48 ! |
|
49 |
|
50 goto: seqNum |
|
51 |
|
52 self doPending. |
|
53 gen goto: seqNum. |
|
54 ! |
|
55 |
|
56 if: bool goto: seqNum1 otherwise: seqNum2 |
|
57 |
|
58 self doPending. |
|
59 gen if: bool goto: seqNum1 otherwise: seqNum2. |
|
60 ! |
|
61 |
|
62 jumpOverBlock: blockNum to: seqNum |
|
63 |
|
64 self doPending. |
|
65 gen jumpOverBlock: seqNum. |
|
66 ! |
|
67 |
|
68 label: seqNum |
|
69 |
|
70 pending := OrderedCollection new. |
|
71 gen label: seqNum. |
|
72 |
|
73 "Modified: / 11-06-2008 / 10:13:28 / Jan Vrany <vranyj1@fel.cvut.cz>" |
|
74 ! |
|
75 |
|
76 popTop |
|
77 |
|
78 "if last was storeTemp, storeInstVar storeIntoLiteralVariable then convert to storePopTemp, storePopInstVar storePopIntoLiteralVariable" |
|
79 #storeTemp: == self pendingSelector ifTrue: [ |
|
80 ^ self pendingSelector: #storePopTemp:]. |
|
81 #storeInstVar: == self pendingSelector ifTrue: [ |
|
82 ^ self pendingSelector: #storePopInstVar:]. |
|
83 #storeIntoLiteralVariable: == self pendingSelector ifTrue:[ |
|
84 ^self pendingSelector: #storePopIntoLiteralVariable:]. |
|
85 "otherwise do normal pop" |
|
86 self doPending. |
|
87 gen popTop. |
|
88 ! |
|
89 |
|
90 pushBlock: irMethod |
|
91 |
|
92 | meth block | |
|
93 meth _ irMethod compiledMethodWith: trailerBytes. |
|
94 meth isBlockMethod: true. |
|
95 block _ meth createBlock: nil. |
|
96 self addPending: (Message selector: #pushLiteral: argument: block) |
|
97 ! |
|
98 |
|
99 pushBlockMethod: irMethod |
|
100 |
|
101 | meth | |
|
102 meth _ irMethod compiledMethodWith: trailerBytes. |
|
103 meth isBlockMethod: true. |
|
104 self addPending: (Message selector: #pushLiteral: argument: meth) |
|
105 ! |
|
106 |
|
107 pushDup |
|
108 |
|
109 self doPending. |
|
110 gen pushDup. |
|
111 ! |
|
112 |
|
113 pushInstVar: index |
|
114 |
|
115 "self doPending. |
|
116 gen pushInstVar: index." |
|
117 self addPending: (Message selector: #pushInstVar: argument: index) |
|
118 ! |
|
119 |
|
120 pushLiteral: object |
|
121 |
|
122 self addPending: (Message selector: #pushLiteral: argument: object) |
|
123 ! |
|
124 |
|
125 pushLiteralVariable: object |
|
126 |
|
127 self addPending: (Message selector: #pushLiteralVariable: argument: object) |
|
128 ! |
|
129 |
|
130 pushTemp: index |
|
131 |
|
132 index = 0 ifTrue: [^ self addPending: (Message selector: #pushReceiver)]. |
|
133 |
|
134 (self pendingMatches: { |
|
135 [:m | m selector == #storePopTemp: and: [m argument = index]]} |
|
136 ) ifTrue: [^ self pendingSelector: #storeTemp:]. |
|
137 |
|
138 self doPending. |
|
139 |
|
140 index = -2 ifTrue: [^ gen pushThisContext]. |
|
141 index = -1 ifTrue: [ |
|
142 ^ gen pushThisContext; |
|
143 pushLiteral: MethodContext myEnvFieldIndex; |
|
144 send: #privGetInstVar:]. |
|
145 |
|
146 gen pushTemp: index. |
|
147 ! |
|
148 |
|
149 remoteReturn |
|
150 |
|
151 self doPending. |
|
152 gen remoteReturn. |
|
153 ! |
|
154 |
|
155 returnTop |
|
156 |
|
157 #pushReceiver == self pendingSelector ifTrue: [ |
|
158 self pendingSelector: #returnReceiver. |
|
159 ^ self doPending |
|
160 ]. |
|
161 #pushLiteral: == self pendingSelector ifTrue: [ |
|
162 self pendingSelector: #returnConstant:. |
|
163 ^ self doPending |
|
164 ]. |
|
165 #pushInstVar: == self pendingSelector ifTrue: [ |
|
166 self pendingSelector: #returnInstVar:. |
|
167 ^ self doPending |
|
168 ]. |
|
169 self doPending. |
|
170 gen returnTop. |
|
171 ! |
|
172 |
|
173 send: selector |
|
174 |
|
175 "If get/set inst var, access it directly" |
|
176 | index | |
|
177 |
|
178 ((#(privGetInstVar: #privStoreIn:instVar:) identityIncludes: selector) and: |
|
179 [self pendingMatches: { |
|
180 [:m | m selector == #pushReceiver]. |
|
181 [:m | m selector == #pushLiteral: and: [m argument isInteger]]}] |
|
182 ) ifTrue: [ |
|
183 index _ self popPending argument. |
|
184 self popPending. "pop pushReceiver" |
|
185 self addPending: (Message |
|
186 selector: (selector == #privGetInstVar: |
|
187 ifTrue: [#pushInstVar:] ifFalse: [#storeInstVar:]) |
|
188 argument: index). |
|
189 (self pendingMatches: { |
|
190 [:m | m selector == #storePopInstVar: and: [m argument = index]]. |
|
191 [:m | m selector == #pushInstVar: and: [m argument = index]]} |
|
192 ) ifTrue: [ |
|
193 self popPending. |
|
194 self pendingSelector: #storeInstVar:. |
|
195 ]. |
|
196 ^ self |
|
197 ]. |
|
198 "otherwise do normal send" |
|
199 self doPending. |
|
200 gen send: selector. |
|
201 ! |
|
202 |
|
203 send: selector toSuperOf: behavior |
|
204 |
|
205 self doPending. |
|
206 gen send: selector toSuperOf: behavior. |
|
207 ! |
|
208 |
|
209 storeInstVar: index |
|
210 "self doPending. |
|
211 gen storeInstVar: index" |
|
212 self addPending: (Message selector: #storeInstVar: argument: index) |
|
213 ! |
|
214 |
|
215 storeIntoLiteralVariable: assoc |
|
216 |
|
217 "self doPending. |
|
218 gen storeIntoLiteralVariable: assoc." |
|
219 |
|
220 self addPending: (Message selector: #storeIntoLiteralVariable: argument: assoc) |
|
221 ! |
|
222 |
|
223 storeTemp: index |
|
224 |
|
225 index = -1 "thisEnv" ifTrue: [ |
|
226 self doPending. |
|
227 ^ gen pushThisContext; |
|
228 pushLiteral: MethodContext myEnvFieldIndex; |
|
229 send: #privStoreIn:instVar:]. |
|
230 |
|
231 self addPending: (Message selector: #storeTemp: argument: index) |
|
232 ! ! |
|
233 |
|
234 !IRTranslator methodsFor:'interpret'! |
|
235 |
|
236 interpret: ir |
|
237 |
|
238 ir optimize. |
|
239 gen numArgs: ir numArgs. |
|
240 ir additionalLiterals do: [:lit | gen addLiteral: lit]. |
|
241 super interpret: ir. |
|
242 |
|
243 "Modified: / 11-06-2008 / 13:52:20 / Jan Vrany <vranyj1@fel.cvut.cz>" |
|
244 ! |
|
245 |
|
246 interpretAll: irSequences |
|
247 |
|
248 irSequences withIndexDo: [:seq :i | seq orderNumber: i]. |
|
249 super interpretAll: irSequences. |
|
250 ! |
|
251 |
|
252 interpretInstruction: irInstruction |
|
253 |
|
254 currentInstr := irInstruction. |
|
255 super interpretInstruction: irInstruction. |
|
256 |
|
257 "Modified: / 11-06-2008 / 09:20:30 / Jan Vrany <vranyj1@fel.cvut.cz>" |
|
258 ! ! |
|
259 |
|
260 !IRTranslator methodsFor:'priv pending'! |
|
261 |
|
262 addPending: message |
|
263 |
|
264 pending addLast: currentInstr -> message |
|
265 ! |
|
266 |
|
267 doPending |
|
268 "execute pending instructions" |
|
269 |
|
270 | assoc | |
|
271 [pending isEmpty] whileFalse: [ |
|
272 assoc _ pending removeFirst. |
|
273 gen mapBytesTo: assoc key "instr". |
|
274 assoc value "message" sendTo: gen. |
|
275 ]. |
|
276 gen mapBytesTo: currentInstr. |
|
277 ! |
|
278 |
|
279 pendingMatches: blocks |
|
280 "Return true if each message at end of pending list satisfies its corresponding block. The number of elements tested equals the number of blocks. If not enough elements return false" |
|
281 |
|
282 | messages i | |
|
283 messages _ pending collect: [:assoc | assoc value]. |
|
284 blocks size > messages size ifTrue: [^ false]. |
|
285 i _ messages size - blocks size. |
|
286 blocks do: [:b | |
|
287 (b value: (messages at: (i _ i + 1))) ifFalse: [^ false]. |
|
288 ]. |
|
289 ^ true |
|
290 ! |
|
291 |
|
292 pendingSelector |
|
293 |
|
294 pending isEmpty ifTrue: [^ nil]. |
|
295 ^ pending last value "message" selector |
|
296 ! |
|
297 |
|
298 pendingSelector: selector |
|
299 |
|
300 pending last value "message" setSelector: selector |
|
301 ! |
|
302 |
|
303 popPending |
|
304 |
|
305 ^ pending removeLast value "message" |
|
306 ! ! |
|
307 |
|
308 !IRTranslator methodsFor:'private - literals'! |
|
309 |
|
310 indexOfLiteral: object |
|
311 |
|
312 | idx | |
|
313 idx := literalFrame identityIndexOf: object. |
|
314 idx = 0 ifTrue: |
|
315 [literalFrame add: object. |
|
316 idx := literalFrame identityIndexOf: object]. |
|
317 ^idx |
|
318 |
|
319 "Created: / 11-06-2008 / 10:56:24 / Jan Vrany <vranyj1@fel.cvut.cz>" |
|
320 ! ! |
|
321 |
|
322 !IRTranslator methodsFor:'results'! |
|
323 |
|
324 compiledMethod |
|
325 |
|
326 ^ gen compiledMethodWith: trailerBytes |
|
327 ! |
|
328 |
|
329 compiledMethodUsing: aCompiledMethodClass |
|
330 |
|
331 ^ gen compiledMethodUsing: aCompiledMethodClass |
|
332 |
|
333 "Modified: / 11-06-2008 / 14:08:02 / Jan Vrany <vranyj1@fel.cvut.cz>" |
|
334 ! ! |
|
335 |
|
336 !IRTranslator class methodsFor:'documentation'! |
|
337 |
|
338 version |
|
339 ^'$Id$' |
|
340 ! ! |