author | Claus Gittinger <cg@exept.de> |
Fri, 21 Feb 2020 20:48:14 +0100 | |
changeset 1231 | b7d945ef967a |
parent 1227 | 3210fc572401 |
permissions | -rw-r--r-- |
155 | 1 |
" |
2 |
COPYRIGHT (c) 2005 by eXept Software AG |
|
818 | 3 |
All Rights Reserved |
155 | 4 |
|
5 |
This software is furnished under a license and may be used |
|
6 |
only in accordance with the terms of that license and with the |
|
7 |
inclusion of the above copyright notice. This software may not |
|
8 |
be provided or otherwise made available to, or used by, any |
|
9 |
other person. No title to or ownership of the software is |
|
10 |
hereby transferred. |
|
11 |
" |
|
37 | 12 |
"{ Package: 'stx:libjavascript' }" |
13 |
||
857 | 14 |
"{ NameSpace: Smalltalk }" |
15 |
||
37 | 16 |
JavaScriptParser subclass:#JavaScriptCompiler |
396 | 17 |
instanceVariableNames:'codeBytes codeIndex litArray stackDelta extra lineno extraLiteral |
18 |
maxStackDepth relocList methodTempVars numTemp maxNumTemp |
|
601 | 19 |
methodClass loopStack currentLineNumber' |
354
108ea96ce6b6
missing absJumpFromJump: (long JS-functions crash report from swisscom)
Claus Gittinger <cg@exept.de>
parents:
248
diff
changeset
|
20 |
classVariableNames:'JumpToAbsJump' |
37 | 21 |
poolDictionaries:'' |
47 | 22 |
category:'Languages-JavaScript-Compiling & Parsing' |
37 | 23 |
! |
24 |
||
73 | 25 |
Object subclass:#LoopDescription |
26 |
instanceVariableNames:'breakLabel continueLabel backPatchListForBreak |
|
27 |
backPatchListForContinue' |
|
28 |
classVariableNames:'' |
|
29 |
poolDictionaries:'' |
|
30 |
privateIn:JavaScriptCompiler |
|
31 |
! |
|
32 |
||
719 | 33 |
Object subclass:#LoopDescriptionForBlock |
726 | 34 |
instanceVariableNames:'deltaScope' |
719 | 35 |
classVariableNames:'' |
36 |
poolDictionaries:'' |
|
37 |
privateIn:JavaScriptCompiler |
|
38 |
! |
|
39 |
||
143 | 40 |
JavaScriptCompiler::LoopDescription subclass:#SwitchDescription |
41 |
instanceVariableNames:'' |
|
42 |
classVariableNames:'' |
|
43 |
poolDictionaries:'' |
|
44 |
privateIn:JavaScriptCompiler |
|
45 |
! |
|
46 |
||
50 | 47 |
!JavaScriptCompiler class methodsFor:'documentation'! |
48 |
||
155 | 49 |
copyright |
50 |
" |
|
51 |
COPYRIGHT (c) 2005 by eXept Software AG |
|
818 | 52 |
All Rights Reserved |
155 | 53 |
|
54 |
This software is furnished under a license and may be used |
|
55 |
only in accordance with the terms of that license and with the |
|
56 |
inclusion of the above copyright notice. This software may not |
|
57 |
be provided or otherwise made available to, or used by, any |
|
58 |
other person. No title to or ownership of the software is |
|
59 |
hereby transferred. |
|
60 |
" |
|
61 |
! |
|
62 |
||
592 | 63 |
documentation |
64 |
" |
|
65 |
JavaScriptCompiler has a lot of stuff copied from ByteCodeCompiler. |
|
66 |
This is a very BAD SMELL!! |
|
67 |
" |
|
68 |
! |
|
69 |
||
50 | 70 |
examples |
71 |
" |
|
818 | 72 |
[exBegin] |
50 | 73 |
|f| |
74 |
||
75 |
f := JavaScriptCompiler |
|
818 | 76 |
compile:'max(a, b) { |
77 |
if (a > b) return a; |
|
78 |
return b; |
|
79 |
}' |
|
80 |
forClass:nil |
|
81 |
inCategory:nil |
|
82 |
notifying:nil. |
|
83 |
f valueWithReceiver:nil arguments:#(10 20). |
|
84 |
[exEnd] |
|
50 | 85 |
|
86 |
||
87 |
||
818 | 88 |
[exBegin] |
50 | 89 |
|f| |
90 |
||
91 |
f := JavaScriptCompiler |
|
818 | 92 |
compile:'max(a, b) { |
93 |
if (a > b) ; |
|
94 |
else return b; |
|
95 |
return a; |
|
96 |
}' |
|
97 |
forClass:nil |
|
98 |
inCategory:nil |
|
99 |
notifying:nil. |
|
100 |
f valueWithReceiver:nil arguments:#(10 20). |
|
101 |
[exEnd] |
|
50 | 102 |
|
103 |
||
104 |
||
105 |
||
818 | 106 |
[exBegin] |
50 | 107 |
|f| |
108 |
||
109 |
f := JavaScriptCompiler |
|
818 | 110 |
compile:'max(a, b) { |
111 |
if (a > b) return a; |
|
112 |
else return b; |
|
113 |
}' |
|
114 |
forClass:nil |
|
115 |
inCategory:nil |
|
116 |
notifying:nil. |
|
117 |
f valueWithReceiver:nil arguments:#(20 10). |
|
118 |
[exEnd] |
|
51 | 119 |
|
120 |
||
121 |
||
818 | 122 |
[exBegin] |
51 | 123 |
|f| |
124 |
||
125 |
f := JavaScriptCompiler |
|
818 | 126 |
compile:('test(arg) { |
127 |
var n; |
|
51 | 128 |
|
818 | 129 |
n = arg; |
130 |
while (n > 0) { |
|
131 |
n--; |
|
132 |
Transcript.showCR(#hello#); |
|
133 |
} |
|
134 |
}' replaceAll:$# with:Character doubleQuote) |
|
135 |
forClass:nil |
|
136 |
inCategory:nil |
|
137 |
notifying:nil. |
|
138 |
f valueWithReceiver:nil arguments:#(5). |
|
139 |
[exEnd] |
|
51 | 140 |
|
141 |
||
818 | 142 |
[exBegin] |
51 | 143 |
|f| |
144 |
||
145 |
f := JavaScriptCompiler |
|
818 | 146 |
compile:('test(arg) { |
147 |
var n; |
|
51 | 148 |
|
818 | 149 |
n = 1; |
150 |
while (n <= arg) { |
|
151 |
n++; |
|
152 |
Transcript.showCR(#hello#); |
|
153 |
} |
|
154 |
}' replaceAll:$# with:Character doubleQuote) |
|
155 |
forClass:nil |
|
156 |
inCategory:nil |
|
157 |
notifying:nil. |
|
158 |
f valueWithReceiver:nil arguments:#(5). |
|
159 |
[exEnd] |
|
51 | 160 |
|
161 |
||
818 | 162 |
[exBegin] |
51 | 163 |
|f| |
164 |
||
165 |
f := JavaScriptCompiler |
|
818 | 166 |
compile:'test(arg) { |
167 |
var n; |
|
51 | 168 |
|
818 | 169 |
n = 1; |
170 |
while (n <= arg) { |
|
171 |
Transcript.showCR(n++); |
|
172 |
} |
|
173 |
}' |
|
174 |
forClass:nil |
|
175 |
inCategory:nil |
|
176 |
notifying:nil. |
|
177 |
f valueWithReceiver:nil arguments:#(5). |
|
178 |
[exEnd] |
|
51 | 179 |
|
818 | 180 |
[exBegin] |
51 | 181 |
|f| |
182 |
||
183 |
f := JavaScriptCompiler |
|
818 | 184 |
compile:'test(arg) { |
185 |
var n; |
|
51 | 186 |
|
818 | 187 |
n = 1; |
188 |
while (n++ <= arg) { |
|
189 |
Transcript.showCR(n); |
|
190 |
} |
|
191 |
}' |
|
192 |
forClass:nil |
|
193 |
inCategory:nil |
|
194 |
notifying:nil. |
|
195 |
f valueWithReceiver:nil arguments:#(5). |
|
196 |
[exEnd] |
|
171 | 197 |
|
818 | 198 |
[exBegin] |
171 | 199 |
|f| |
200 |
||
201 |
f := JavaScriptCompiler |
|
818 | 202 |
compile:'foo() { |
203 |
Transcript.showCR(''start''); |
|
204 |
try { |
|
205 |
Error.raise(); |
|
206 |
} catch(Error) { |
|
207 |
Transcript.showCR(''caught error''); |
|
208 |
}; |
|
209 |
Transcript.showCR(''end''); |
|
210 |
}' |
|
211 |
forClass:nil |
|
212 |
inCategory:nil |
|
213 |
notifying:nil. |
|
214 |
f valueWithReceiver:nil arguments:#(). |
|
215 |
[exEnd] |
|
50 | 216 |
" |
217 |
! ! |
|
37 | 218 |
|
748
78d0788cea93
Added breakpoint support.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
726
diff
changeset
|
219 |
!JavaScriptCompiler class methodsFor:'instance creation'! |
78d0788cea93
Added breakpoint support.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
726
diff
changeset
|
220 |
|
78d0788cea93
Added breakpoint support.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
726
diff
changeset
|
221 |
new |
78d0788cea93
Added breakpoint support.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
726
diff
changeset
|
222 |
"/ Pretty ugly hack. A caller to compiler may provide a set of breakpoints |
78d0788cea93
Added breakpoint support.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
726
diff
changeset
|
223 |
"/ that has to be injected to the code. However, since breakpoint injection |
78d0788cea93
Added breakpoint support.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
726
diff
changeset
|
224 |
"/ is actually done by a subclass or me, so we have to return this subclass here. |
1095 | 225 |
"/ This subclass-to-transform API is bit unfortunate. |
226 |
||
227 |
| breakpoints | |
|
748
78d0788cea93
Added breakpoint support.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
726
diff
changeset
|
228 |
|
1095 | 229 |
self == JavaScriptCompiler ifTrue:[ |
230 |
breakpoints := BreakpointQuery query. |
|
231 |
breakpoints notEmptyOrNil ifTrue:[ |
|
232 |
^ JavaScriptCompilerWithBreakpointSupport new |
|
233 |
breakpoints: breakpoints; |
|
234 |
yourself. |
|
235 |
]. |
|
748
78d0788cea93
Added breakpoint support.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
726
diff
changeset
|
236 |
]. |
1095 | 237 |
^ super new. |
748
78d0788cea93
Added breakpoint support.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
726
diff
changeset
|
238 |
|
78d0788cea93
Added breakpoint support.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
726
diff
changeset
|
239 |
"Created: / 08-05-2014 / 11:01:29 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
78d0788cea93
Added breakpoint support.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
726
diff
changeset
|
240 |
"Modified (comment): / 08-05-2014 / 13:56:18 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
1095 | 241 |
"Modified: / 27-06-2019 / 10:05:48 / Claus Gittinger" |
748
78d0788cea93
Added breakpoint support.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
726
diff
changeset
|
242 |
! ! |
78d0788cea93
Added breakpoint support.
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
726
diff
changeset
|
243 |
|
38 | 244 |
!JavaScriptCompiler class methodsFor:'compiling methods'! |
245 |
||
501
b6ec5ca2dacd
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
462
diff
changeset
|
246 |
compile:aString forClass:aClass inCategory:cat |
818 | 247 |
^ self |
248 |
compile:aString |
|
249 |
forClass:aClass |
|
250 |
inCategory:cat |
|
251 |
notifying:nil |
|
252 |
install:true |
|
253 |
skipIfSame:false |
|
254 |
silent:false |
|
255 |
foldConstants:true |
|
501
b6ec5ca2dacd
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
462
diff
changeset
|
256 |
|
b6ec5ca2dacd
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
462
diff
changeset
|
257 |
"Created: / 30-01-2011 / 16:59:00 / cg" |
b6ec5ca2dacd
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
462
diff
changeset
|
258 |
! |
b6ec5ca2dacd
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
462
diff
changeset
|
259 |
|
38 | 260 |
compile:aString forClass:aClass inCategory:cat notifying:requestor |
261 |
"compile a source-string for a method in classToCompileFor. |
|
262 |
errors are forwarded to requestor. |
|
263 |
The method will get cat as category. |
|
264 |
Returns the new method, #Error or nil." |
|
265 |
||
818 | 266 |
^ self |
40 | 267 |
compile:aString |
268 |
forClass:aClass |
|
269 |
inCategory:cat |
|
270 |
notifying:requestor |
|
271 |
install:true |
|
272 |
skipIfSame:false |
|
273 |
silent:false |
|
274 |
foldConstants:true |
|
38 | 275 |
! |
276 |
||
93 | 277 |
compile:aString forClass:aClass inCategory:cat notifying:requestor install:install |
818 | 278 |
^ self |
279 |
compile:aString |
|
280 |
forClass:aClass |
|
281 |
inCategory:cat |
|
282 |
notifying:requestor |
|
283 |
install:install |
|
284 |
skipIfSame:false |
|
285 |
silent:false |
|
93 | 286 |
! |
287 |
||
38 | 288 |
compile:aString forClass:aClass inCategory:cat notifying:requestor |
818 | 289 |
install:install skipIfSame:skipIfSame silent:silent |
49 | 290 |
"compile a source-string for a method in aClass. |
291 |
errors are forwarded to requestor. |
|
292 |
The method will get cat as category. |
|
293 |
if install is true, the method is installed in the class. |
|
294 |
if skipIfSame, the method is not installed if there is no change |
|
295 |
(used when filing in). |
|
296 |
if silent is true, no warnings are output. |
|
297 |
Returns the new method, #Error or nil." |
|
298 |
||
299 |
^ self |
|
818 | 300 |
compile:aString |
301 |
forClass:aClass |
|
302 |
inCategory:cat |
|
303 |
notifying:requestor |
|
304 |
install:install |
|
305 |
skipIfSame:skipIfSame |
|
306 |
silent:silent |
|
307 |
foldConstants:true |
|
49 | 308 |
! |
309 |
||
310 |
compile:aString forClass:aClass inCategory:cat notifying:requestor |
|
818 | 311 |
install:install skipIfSame:skipIfSame silent:silent foldConstants:fold |
86 | 312 |
|compiler | |
38 | 313 |
|
509
2f9173d9bbe4
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
501
diff
changeset
|
314 |
compiler := self new. |
2f9173d9bbe4
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
501
diff
changeset
|
315 |
"/ not needed... |
2f9173d9bbe4
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
501
diff
changeset
|
316 |
"/ compiler := self for:(ReadStream on:aString). |
2f9173d9bbe4
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
501
diff
changeset
|
317 |
"/ compiler setClassToCompileFor:aClass. |
2f9173d9bbe4
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
501
diff
changeset
|
318 |
"/ compiler nextToken. |
58 | 319 |
|
86 | 320 |
^ compiler |
818 | 321 |
compile:aString |
322 |
forClass:aClass |
|
323 |
inCategory:cat |
|
324 |
notifying:requestor |
|
325 |
install:install |
|
326 |
skipIfSame:skipIfSame |
|
327 |
silent:silent |
|
328 |
foldConstants:fold |
|
509
2f9173d9bbe4
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
501
diff
changeset
|
329 |
|
2f9173d9bbe4
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
501
diff
changeset
|
330 |
"Modified: / 30-09-2011 / 12:49:29 / cg" |
86 | 331 |
! |
38 | 332 |
|
86 | 333 |
compile:aString in:aClass notifying:requestor ifFail:failBlock |
334 |
|newMethod| |
|
38 | 335 |
|
818 | 336 |
newMethod := self |
337 |
compile:aString |
|
338 |
forClass:aClass |
|
339 |
inCategory:'no category' |
|
340 |
notifying:requestor |
|
341 |
install:true |
|
342 |
skipIfSame:false |
|
343 |
silent:false |
|
344 |
foldConstants:true. |
|
86 | 345 |
newMethod == #Error ifTrue:[ |
818 | 346 |
^ failBlock value |
38 | 347 |
]. |
348 |
^ newMethod |
|
349 |
! |
|
350 |
||
351 |
evaluate:aString notifying:requestor compile:doCompile |
|
352 |
"used to install new classes" |
|
353 |
||
354 |
|tree| |
|
355 |
||
356 |
tree := self parseClassDefinition:aString. |
|
357 |
^ tree evaluate. |
|
49 | 358 |
! |
359 |
||
360 |
newCodeSet |
|
818 | 361 |
^ true |
38 | 362 |
! ! |
363 |
||
364 |
!JavaScriptCompiler class methodsFor:'private'! |
|
365 |
||
366 |
selectorFor:functionName numArgs:nargs |
|
367 |
(nargs == 1) ifTrue:[ |
|
1118 | 368 |
^ (functionName , ':') asSymbol. |
38 | 369 |
]. |
370 |
(nargs == 2) ifTrue:[ |
|
1118 | 371 |
^ (functionName , ':_:') asSymbol. |
38 | 372 |
]. |
373 |
(nargs == 3) ifTrue:[ |
|
1118 | 374 |
^ (functionName , ':_:_:') asSymbol. |
38 | 375 |
]. |
376 |
^ (functionName , (':_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:_:' copyTo:nargs*2-1)) asSymbol. |
|
377 |
! ! |
|
378 |
||
608 | 379 |
!JavaScriptCompiler methodsFor:'accessing'! |
380 |
||
381 |
methodClass:something |
|
382 |
methodClass := something. |
|
383 |
! ! |
|
384 |
||
38 | 385 |
!JavaScriptCompiler methodsFor:'code generation'! |
386 |
||
354
108ea96ce6b6
missing absJumpFromJump: (long JS-functions crash report from swisscom)
Claus Gittinger <cg@exept.de>
parents:
248
diff
changeset
|
387 |
absJumpFromJump:code |
108ea96ce6b6
missing absJumpFromJump: (long JS-functions crash report from swisscom)
Claus Gittinger <cg@exept.de>
parents:
248
diff
changeset
|
388 |
"given a jump-symbolic code, return corresponding absolute jump" |
108ea96ce6b6
missing absJumpFromJump: (long JS-functions crash report from swisscom)
Claus Gittinger <cg@exept.de>
parents:
248
diff
changeset
|
389 |
|
108ea96ce6b6
missing absJumpFromJump: (long JS-functions crash report from swisscom)
Claus Gittinger <cg@exept.de>
parents:
248
diff
changeset
|
390 |
JumpToAbsJump isNil ifTrue:[ |
818 | 391 |
JumpToAbsJump := IdentityDictionary new. |
392 |
JumpToAbsJump at:#jump put:#jumpabs. |
|
393 |
JumpToAbsJump at:#trueJump put:#trueJumpabs. |
|
394 |
JumpToAbsJump at:#falseJump put:#falseJumpabs. |
|
395 |
JumpToAbsJump at:#nilJump put:#nilJumpabs. |
|
396 |
JumpToAbsJump at:#notNilJump put:#notNilJumpabs. |
|
397 |
JumpToAbsJump at:#eqJump put:#eqJumpabs. |
|
398 |
JumpToAbsJump at:#notEqJump put:#notEqJumpabs. |
|
399 |
JumpToAbsJump at:#zeroJump put:#zeroJumpabs. |
|
400 |
JumpToAbsJump at:#notZeroJump put:#notZeroJumpabs. |
|
401 |
JumpToAbsJump at:#makeBlock put:#makeBlockabs. |
|
354
108ea96ce6b6
missing absJumpFromJump: (long JS-functions crash report from swisscom)
Claus Gittinger <cg@exept.de>
parents:
248
diff
changeset
|
402 |
]. |
108ea96ce6b6
missing absJumpFromJump: (long JS-functions crash report from swisscom)
Claus Gittinger <cg@exept.de>
parents:
248
diff
changeset
|
403 |
^ JumpToAbsJump at:code |
108ea96ce6b6
missing absJumpFromJump: (long JS-functions crash report from swisscom)
Claus Gittinger <cg@exept.de>
parents:
248
diff
changeset
|
404 |
! |
108ea96ce6b6
missing absJumpFromJump: (long JS-functions crash report from swisscom)
Claus Gittinger <cg@exept.de>
parents:
248
diff
changeset
|
405 |
|
49 | 406 |
addLiteral:anObject |
407 |
"add a literal to the literalArray - watch for and eliminate |
|
408 |
duplicates. return the index of the literal in the Array" |
|
409 |
||
410 |
|index "{ Class: SmallInteger }" oldLit class| |
|
411 |
||
412 |
litArray isNil ifTrue:[ |
|
818 | 413 |
litArray := Array with:anObject. |
414 |
^ 1 |
|
49 | 415 |
]. |
416 |
index := litArray identityIndexOf:anObject. |
|
417 |
(index == 0) ifTrue:[ |
|
818 | 418 |
" |
419 |
reuse constants if same value and same class |
|
420 |
" |
|
421 |
class := anObject class. |
|
422 |
((class == Float) |
|
423 |
or:[class == Fraction |
|
424 |
or:[class == LargeInteger |
|
425 |
"or:[class == String] --only if literalString option has been added---" ]]) ifTrue:[ |
|
426 |
index := litArray indexOf:anObject. |
|
427 |
index ~~ 0 ifTrue:[ |
|
428 |
oldLit := litArray at:index. |
|
429 |
oldLit class == class ifFalse:[ |
|
430 |
index := 0. |
|
431 |
] ifTrue:[ |
|
432 |
"/ dont mess up negative with positive zeros |
|
433 |
anObject = 0.0 ifTrue:[ |
|
434 |
anObject isNegativeZero ~~ oldLit isNegativeZero ifTrue:[ |
|
435 |
index := 0 |
|
436 |
] |
|
437 |
] |
|
438 |
]. |
|
439 |
]. |
|
440 |
]. |
|
441 |
(index == 0) ifTrue:[ |
|
442 |
litArray := litArray copyWith:anObject. |
|
443 |
^ litArray size |
|
444 |
]. |
|
49 | 445 |
]. |
446 |
^ index |
|
447 |
||
448 |
"Modified: / 12.11.1997 / 18:49:43 / cg" |
|
449 |
! |
|
450 |
||
50 | 451 |
addReloc:symIndex |
452 |
"remember to relocate offset at symIndex later ..." |
|
453 |
||
454 |
relocList isNil ifTrue:[ |
|
818 | 455 |
relocList := OrderedCollection new. |
50 | 456 |
]. |
457 |
relocList add:symIndex |
|
458 |
! |
|
459 |
||
49 | 460 |
appendByte:aByte |
461 |
"append a byte to the code-Array, checking for byte-range (debug-only)" |
|
462 |
||
463 |
|idx "{Class: SmallInteger }"| |
|
464 |
||
465 |
idx := codeIndex. |
|
466 |
(aByte between:0 and:255) ifTrue:[ |
|
818 | 467 |
codeBytes at:idx put:aByte. |
468 |
codeIndex := idx + 1 |
|
49 | 469 |
] ifFalse:[ |
818 | 470 |
self error:'byte range error'. |
471 |
errorFlag := #Error |
|
49 | 472 |
] |
473 |
! |
|
474 |
||
475 |
appendByteCodeFor:codeSymbol |
|
476 |
"append the byteCode for an instructionSymbol to the code-Array" |
|
477 |
||
478 |
|idx "{Class: SmallInteger }"| |
|
479 |
||
480 |
idx := codeIndex. |
|
481 |
codeBytes at:idx put:(self byteCodeFor:codeSymbol). |
|
482 |
codeIndex := idx + 1 |
|
483 |
! |
|
484 |
||
124 | 485 |
appendEmptyByte |
486 |
"append an empty byte to the code-Array" |
|
487 |
||
488 |
|idx "{Class: SmallInteger }"| |
|
489 |
||
490 |
idx := codeIndex. |
|
491 |
codeBytes at:idx put:0. |
|
492 |
codeIndex := idx + 1 |
|
493 |
! |
|
494 |
||
57 | 495 |
appendSignedByte:aByte |
496 |
"append a signedbyte (as in jump-offsets) to the code-Array, |
|
497 |
check range and report an error if invalid" |
|
498 |
||
818 | 499 |
|b "{Class: SmallInteger }" |
57 | 500 |
idx "{Class: SmallInteger }"| |
501 |
||
502 |
idx := codeIndex. |
|
503 |
b := aByte. |
|
504 |
(b >= 0) ifTrue:[ |
|
505 |
(b > 127) ifTrue:[ |
|
506 |
self error:'jump-range error'. |
|
507 |
errorFlag := #Error |
|
508 |
]. |
|
509 |
codeBytes at:idx put:b |
|
510 |
] ifFalse:[ |
|
511 |
(b < -128) ifTrue:[ |
|
512 |
self error:'jump-range error'. |
|
513 |
errorFlag := #Error |
|
514 |
]. |
|
515 |
b := 256 + b |
|
516 |
]. |
|
517 |
codeBytes at:idx put:b. |
|
518 |
codeIndex := idx + 1 |
|
519 |
! |
|
520 |
||
156 | 521 |
appendSignedWord:aWord |
522 |
"append a signed word to the code-Array, |
|
523 |
check range and report an error if invalid" |
|
524 |
||
525 |
|w "{Class: SmallInteger }"| |
|
526 |
||
527 |
w := aWord. |
|
528 |
(w >= 0) ifTrue:[ |
|
1059 | 529 |
(w > 16r7FFF) ifTrue:[ |
818 | 530 |
self error:'word-range error'. |
531 |
errorFlag := #Error |
|
532 |
]. |
|
156 | 533 |
] ifFalse:[ |
818 | 534 |
(w < 16r-8000) ifTrue:[ |
535 |
self error:'word-range error'. |
|
536 |
errorFlag := #Error |
|
537 |
]. |
|
538 |
w := (16r10000 + w). |
|
156 | 539 |
]. |
540 |
self appendWord:w |
|
541 |
! |
|
542 |
||
543 |
appendWord:aWord |
|
818 | 544 |
"append an unsigned word (low-high) to the code-Array, |
156 | 545 |
checking for word-range (debug-only)" |
546 |
||
547 |
|idx "{Class: SmallInteger }"| |
|
548 |
||
549 |
idx := codeIndex. |
|
550 |
(aWord between:0 and:16rFFFF) ifTrue:[ |
|
818 | 551 |
codeBytes at:idx put:(aWord bitAnd:16rFF). |
552 |
idx := idx + 1. |
|
553 |
codeBytes at:idx put:(aWord bitShift:-8). |
|
554 |
codeIndex := idx + 1 |
|
156 | 555 |
] ifFalse:[ |
818 | 556 |
self error:'word range error'. |
557 |
errorFlag := #Error |
|
156 | 558 |
] |
559 |
! |
|
560 |
||
49 | 561 |
byteCodeFor:aSymbol |
562 |
"given a symbolic instruction, return the corresponding bytecode. |
|
563 |
as a side-effect, leave number of bytes pushed/popped by this instr. |
|
564 |
in stackDelta, and, if the instruction needs extra arguments, leave |
|
565 |
this info in extra. Also lineno is set to true, if this code has line |
|
566 |
information and extraLiteral is set if any hidden send is performed by it." |
|
567 |
||
568 |
"standard bytecodes" |
|
569 |
||
570 |
(aSymbol == #pushNil) ifTrue:[stackDelta := 1. ^ 10]. |
|
571 |
(aSymbol == #pushTrue) ifTrue:[stackDelta := 1. ^ 11]. |
|
572 |
(aSymbol == #pushFalse) ifTrue:[stackDelta := 1. ^ 12]. |
|
573 |
(aSymbol == #pushLit) ifTrue:[stackDelta := 1. extra := #lit. ^ 14]. |
|
574 |
(aSymbol == #pushLitS) ifTrue:[stackDelta := 1. extra := #index. ^ 14]. |
|
575 |
(aSymbol == #pushSelf) ifTrue:[stackDelta := 1. ^ 15]. |
|
576 |
(aSymbol == #pushNum) ifTrue:[stackDelta := 1. extra := #number. ^ 16]. |
|
577 |
||
578 |
(aSymbol == #pushMethodArg) ifTrue:[stackDelta := 1. extra := #index. ^ 30]. |
|
579 |
(aSymbol == #pushMethodVar) ifTrue:[stackDelta := 1. extra := #index. ^ 31]. |
|
580 |
(aSymbol == #pushBlockArg) ifTrue:[stackDelta := 1. extra := #index. ^ 32]. |
|
581 |
(aSymbol == #pushBlockVar) ifTrue:[stackDelta := 1. extra := #index. ^ 33]. |
|
582 |
(aSymbol == #pushInstVar) ifTrue:[stackDelta := 1. extra := #index. ^ 34]. |
|
583 |
(aSymbol == #pushOuterBlockArg) ifTrue:[stackDelta := 1. extra := #indexLevel. ^ 42]. |
|
584 |
(aSymbol == #pushOuterBlockVar) ifTrue:[stackDelta := 1. extra := #indexLevel. ^ 128]. |
|
585 |
||
586 |
(aSymbol == #retTop) ifTrue:[stackDelta := -1. ^ 0]. |
|
587 |
(aSymbol == #retSelf) ifTrue:[^5]. |
|
588 |
||
589 |
(aSymbol == #==) ifTrue:[stackDelta := -1. extraLiteral := aSymbol. ^ 45]. |
|
590 |
(aSymbol == #~~) ifTrue:[stackDelta := -1. extraLiteral := aSymbol. ^ 46]. |
|
591 |
||
592 |
(aSymbol == #falseJump) ifTrue:[stackDelta := -1. extra := #offset. ^ 50]. |
|
593 |
(aSymbol == #trueJump) ifTrue:[stackDelta := -1. extra := #offset. ^ 51]. |
|
594 |
(aSymbol == #nilJump) ifTrue:[stackDelta := -1. extra := #offset. ^ 52]. |
|
595 |
(aSymbol == #notNilJump) ifTrue:[stackDelta := -1. extra := #offset. ^ 53]. |
|
596 |
(aSymbol == #jump) ifTrue:[extra := #offset. ^ 54]. |
|
597 |
(aSymbol == #makeBlock) ifTrue:[stackDelta := 1. extra := #offsetNvarNarg. ^ 55]. |
|
598 |
(aSymbol == #zeroJump) ifTrue:[stackDelta := -1. extra := #offset. ^ 56]. |
|
599 |
(aSymbol == #notZeroJump) ifTrue:[stackDelta := -1. extra := #offset. ^ 57]. |
|
600 |
(aSymbol == #eqJump) ifTrue:[stackDelta := -2. extra := #offset. ^ 58]. |
|
601 |
(aSymbol == #notEqJump) ifTrue:[stackDelta := -2. extra := #offset. ^ 59]. |
|
602 |
||
603 |
(aSymbol == #lineno) ifTrue:[lineno := true. ^ 8]. |
|
604 |
(aSymbol == #lineno16) ifTrue:[lineno := true. ^ 9]. |
|
605 |
||
606 |
(aSymbol == #send) ifTrue:[lineno := true. extra := #special. ^ 19]. |
|
607 |
(aSymbol == #superSend) ifTrue:[lineno := true. extra := #special. ^ 20]. |
|
608 |
(aSymbol == #hereSend) ifTrue:[lineno := true. extra := #special. ^ 20]. |
|
609 |
(aSymbol == #sendSelf) ifTrue:[lineno := true. extra := #special. ^ 13]. |
|
610 |
||
611 |
(aSymbol == #drop) ifTrue:[stackDelta := -1. ^ 18]. |
|
612 |
(aSymbol == #dup) ifTrue:[stackDelta := 1. ^ 47]. |
|
613 |
||
614 |
(aSymbol == #storeMethodVar) ifTrue:[extra := #index. stackDelta := -1. ^ 37]. |
|
615 |
(aSymbol == #storeBlockVar) ifTrue:[extra := #index. stackDelta := -1. ^ 38]. |
|
616 |
(aSymbol == #storeInstVar) ifTrue:[extra := #index. stackDelta := -1. ^ 39]. |
|
519 | 617 |
|
618 |
"/ the next 2 are to be obsoleted soon (renamed as MethodLocal) |
|
619 |
(aSymbol == #pushLocal) ifTrue:[ stackDelta := 1. extra := #index. ^ 239]. |
|
620 |
(aSymbol == #storeLocal) ifTrue:[ stackDelta := -1. extra := #index. ^ 240]. |
|
621 |
||
622 |
(aSymbol == #pushMethodLocal) ifTrue:[ stackDelta := 1. extra := #index. ^ 239]. |
|
623 |
(aSymbol == #storeMethodLocal) ifTrue:[ stackDelta := -1. extra := #index. ^ 240]. |
|
624 |
(aSymbol == #storeBlockLocal) ifTrue:[ stackDelta := -1. extra := #index. ^ 241]. |
|
625 |
(aSymbol == #storeOuterBlockLocal) ifTrue:[ stackDelta := -1. extra := #indexLevel. ^ 242]. |
|
49 | 626 |
|
627 |
(aSymbol == #pushClassVarS) ifTrue:[stackDelta := 1. extra := #speciallitS. ^ 35]. |
|
628 |
(aSymbol == #pushGlobalS) ifTrue:[stackDelta := 1. extra := #speciallitS. ^ 36]. |
|
629 |
||
630 |
(aSymbol == #storeClassVarS) ifTrue:[extra := #speciallitS.stackDelta := -1. ^ 40]. |
|
631 |
(aSymbol == #storeGlobalS) ifTrue:[extra := #speciallitS. stackDelta := -1. ^ 41]. |
|
632 |
(aSymbol == #pushSpecialGlobal) ifTrue:[stackDelta := 1. extra := #index. ^ 200]. |
|
633 |
||
634 |
(aSymbol == #storeOuterBlockVar) ifTrue:[stackDelta := -1. extra := #indexLevel. ^ 129]. |
|
635 |
||
636 |
(aSymbol == #pushClassInstVar) ifTrue:[stackDelta := 1. extra := #index. ^ 176]. |
|
637 |
(aSymbol == #storeClassInstVar) ifTrue:[extra := #index.stackDelta := -1. ^ 177]. |
|
638 |
||
639 |
"optimized bytecodes" |
|
640 |
||
641 |
(aSymbol == #retNil) ifTrue:[^ 1]. |
|
642 |
(aSymbol == #retTrue) ifTrue:[^ 2]. |
|
643 |
(aSymbol == #retFalse) ifTrue:[^ 3]. |
|
644 |
(aSymbol == #ret0) ifTrue:[^ 4]. |
|
645 |
(aSymbol == #retNum) ifTrue:[extra := #number. ^ 127]. |
|
646 |
(aSymbol == #homeRetTop) ifTrue:[^ 7]. |
|
647 |
||
648 |
(aSymbol == #pushNum16) ifTrue:[stackDelta := 1. extra := #number16. ^ 17]. |
|
649 |
(aSymbol == #push0) ifTrue:[stackDelta := 1. ^120]. |
|
650 |
(aSymbol == #push1) ifTrue:[stackDelta := 1. ^121]. |
|
651 |
(aSymbol == #push2) ifTrue:[stackDelta := 1. ^139]. |
|
652 |
(aSymbol == #pushMinus1) ifTrue:[stackDelta := 1. ^122]. |
|
653 |
||
654 |
(aSymbol == #send0) ifTrue:[lineno := true. extra := #index. ^21]. |
|
655 |
(aSymbol == #send1) ifTrue:[lineno := true. extra := #index. stackDelta := -1. ^22]. |
|
656 |
(aSymbol == #send2) ifTrue:[lineno := true. extra := #index. stackDelta := -2. ^23]. |
|
657 |
(aSymbol == #send3) ifTrue:[lineno := true. extra := #index. stackDelta := -3. ^24]. |
|
658 |
||
659 |
(aSymbol == #sendSelf0) ifTrue:[lineno := true. extra := #index. stackDelta := 1. ^180]. |
|
660 |
(aSymbol == #sendSelf1) ifTrue:[lineno := true. extra := #index. ^181]. |
|
661 |
(aSymbol == #sendSelf2) ifTrue:[lineno := true. extra := #index. stackDelta := -1. ^182]. |
|
662 |
(aSymbol == #sendSelf3) ifTrue:[lineno := true. extra := #index. stackDelta := -2. ^183]. |
|
663 |
(aSymbol == #sendSelfDrop0) ifTrue:[lineno := true. extra := #index. ^184]. |
|
664 |
(aSymbol == #sendSelfDrop1) ifTrue:[lineno := true. extra := #index. stackDelta := -1. ^185]. |
|
665 |
(aSymbol == #sendSelfDrop2) ifTrue:[lineno := true. extra := #index. stackDelta := -2. ^186]. |
|
666 |
(aSymbol == #sendSelfDrop3) ifTrue:[lineno := true. extra := #index. stackDelta := -3. ^187]. |
|
667 |
||
668 |
(aSymbol == #sendDrop) ifTrue:[lineno := true. extra := #special. ^25]. |
|
669 |
(aSymbol == #sendDrop0) ifTrue:[lineno := true. extra := #index. stackDelta := -1. ^26]. |
|
670 |
(aSymbol == #sendDrop1) ifTrue:[lineno := true. extra := #index. stackDelta := -2. ^27]. |
|
671 |
(aSymbol == #sendDrop2) ifTrue:[lineno := true. extra := #index. stackDelta := -3. ^28]. |
|
672 |
(aSymbol == #sendDrop3) ifTrue:[lineno := true. extra := #index. stackDelta := -4. ^29]. |
|
673 |
||
674 |
(aSymbol == #pushMethodVar1) ifTrue:[stackDelta := 1. ^80]. |
|
675 |
(aSymbol == #pushMethodVar2) ifTrue:[stackDelta := 1. ^81]. |
|
676 |
(aSymbol == #pushMethodVar3) ifTrue:[stackDelta := 1. ^82]. |
|
677 |
(aSymbol == #pushMethodVar4) ifTrue:[stackDelta := 1. ^83]. |
|
678 |
(aSymbol == #pushMethodVar5) ifTrue:[stackDelta := 1. ^84]. |
|
679 |
(aSymbol == #pushMethodVar6) ifTrue:[stackDelta := 1. ^85]. |
|
680 |
||
681 |
(aSymbol == #pushMethodArg1) ifTrue:[stackDelta := 1. ^86]. |
|
682 |
(aSymbol == #pushMethodArg2) ifTrue:[stackDelta := 1. ^87]. |
|
683 |
(aSymbol == #pushMethodArg3) ifTrue:[stackDelta := 1. ^88]. |
|
684 |
(aSymbol == #pushMethodArg4) ifTrue:[stackDelta := 1. ^89]. |
|
685 |
||
686 |
(aSymbol == #pushInstVar1) ifTrue:[stackDelta := 1. ^90]. |
|
687 |
(aSymbol == #pushInstVar2) ifTrue:[stackDelta := 1. ^91]. |
|
688 |
(aSymbol == #pushInstVar3) ifTrue:[stackDelta := 1. ^92]. |
|
689 |
(aSymbol == #pushInstVar4) ifTrue:[stackDelta := 1. ^93]. |
|
690 |
(aSymbol == #pushInstVar5) ifTrue:[stackDelta := 1. ^94]. |
|
691 |
(aSymbol == #pushInstVar6) ifTrue:[stackDelta := 1. ^95]. |
|
692 |
(aSymbol == #pushInstVar7) ifTrue:[stackDelta := 1. ^96]. |
|
693 |
(aSymbol == #pushInstVar8) ifTrue:[stackDelta := 1. ^97]. |
|
694 |
(aSymbol == #pushInstVar9) ifTrue:[stackDelta := 1. ^98]. |
|
695 |
(aSymbol == #pushInstVar10) ifTrue:[stackDelta := 1. ^99]. |
|
696 |
||
697 |
(aSymbol == #storeMethodVar1) ifTrue:[stackDelta := -1. ^100]. |
|
698 |
(aSymbol == #storeMethodVar2) ifTrue:[stackDelta := -1. ^101]. |
|
699 |
(aSymbol == #storeMethodVar3) ifTrue:[stackDelta := -1. ^102]. |
|
700 |
(aSymbol == #storeMethodVar4) ifTrue:[stackDelta := -1. ^103]. |
|
701 |
(aSymbol == #storeMethodVar5) ifTrue:[stackDelta := -1. ^104]. |
|
702 |
(aSymbol == #storeMethodVar6) ifTrue:[stackDelta := -1. ^105]. |
|
703 |
||
704 |
(aSymbol == #storeInstVar1) ifTrue:[stackDelta := -1. ^110]. |
|
705 |
(aSymbol == #storeInstVar2) ifTrue:[stackDelta := -1. ^111]. |
|
706 |
(aSymbol == #storeInstVar3) ifTrue:[stackDelta := -1. ^112]. |
|
707 |
(aSymbol == #storeInstVar4) ifTrue:[stackDelta := -1. ^113]. |
|
708 |
(aSymbol == #storeInstVar5) ifTrue:[stackDelta := -1. ^114]. |
|
709 |
(aSymbol == #storeInstVar6) ifTrue:[stackDelta := -1. ^115]. |
|
710 |
(aSymbol == #storeInstVar7) ifTrue:[stackDelta := -1. ^116]. |
|
711 |
(aSymbol == #storeInstVar8) ifTrue:[stackDelta := -1. ^117]. |
|
712 |
(aSymbol == #storeInstVar9) ifTrue:[stackDelta := -1. ^118]. |
|
713 |
(aSymbol == #storeInstVar10) ifTrue:[stackDelta := -1. ^119]. |
|
714 |
||
715 |
(aSymbol == #pushLit1) ifTrue:[stackDelta := 1. ^ 222]. |
|
716 |
(aSymbol == #pushLit2) ifTrue:[stackDelta := 1. ^ 223]. |
|
717 |
(aSymbol == #pushLit3) ifTrue:[stackDelta := 1. ^ 224]. |
|
718 |
(aSymbol == #pushLit4) ifTrue:[stackDelta := 1. ^ 225]. |
|
719 |
(aSymbol == #pushLit5) ifTrue:[stackDelta := 1. ^ 226]. |
|
720 |
(aSymbol == #pushLit6) ifTrue:[stackDelta := 1. ^ 227]. |
|
721 |
(aSymbol == #pushLit7) ifTrue:[stackDelta := 1. ^ 228]. |
|
722 |
(aSymbol == #pushLit8) ifTrue:[stackDelta := 1. ^ 229]. |
|
723 |
||
724 |
(aSymbol == #retMethodVar1) ifTrue:[^160]. |
|
725 |
(aSymbol == #retMethodVar2) ifTrue:[^161]. |
|
726 |
(aSymbol == #retMethodVar3) ifTrue:[^162]. |
|
727 |
(aSymbol == #retMethodVar4) ifTrue:[^163]. |
|
728 |
(aSymbol == #retMethodVar5) ifTrue:[^164]. |
|
729 |
(aSymbol == #retMethodVar6) ifTrue:[^165]. |
|
730 |
||
731 |
(aSymbol == #retInstVar1) ifTrue:[^166]. |
|
732 |
(aSymbol == #retInstVar2) ifTrue:[^167]. |
|
733 |
(aSymbol == #retInstVar3) ifTrue:[^168]. |
|
734 |
(aSymbol == #retInstVar4) ifTrue:[^169]. |
|
735 |
(aSymbol == #retInstVar5) ifTrue:[^170]. |
|
736 |
(aSymbol == #retInstVar6) ifTrue:[^171]. |
|
737 |
(aSymbol == #retInstVar7) ifTrue:[^172]. |
|
738 |
(aSymbol == #retInstVar8) ifTrue:[^173]. |
|
739 |
||
740 |
(aSymbol == #retMethodArg1) ifTrue:[^174]. |
|
741 |
(aSymbol == #retMethodArg2) ifTrue:[^175]. |
|
742 |
||
743 |
(aSymbol == #pushBlockArg1) ifTrue:[stackDelta := 1. ^140]. |
|
744 |
(aSymbol == #pushBlockArg2) ifTrue:[stackDelta := 1. ^141]. |
|
745 |
(aSymbol == #pushBlockArg3) ifTrue:[stackDelta := 1. ^142]. |
|
746 |
(aSymbol == #pushBlockArg4) ifTrue:[stackDelta := 1. ^143]. |
|
747 |
||
748 |
(aSymbol == #pushOuter1BlockArg) ifTrue:[stackDelta := 1. extra := #index. ^ 43]. |
|
749 |
(aSymbol == #pushOuter2BlockArg) ifTrue:[stackDelta := 1. extra := #index. ^ 44]. |
|
750 |
||
751 |
(aSymbol == #=) ifTrue:[lineno := true. stackDelta := -1. extraLiteral := aSymbol. ^130]. |
|
752 |
(aSymbol == #+) ifTrue:[lineno := true. stackDelta := -1. extraLiteral := aSymbol. ^131]. |
|
753 |
(aSymbol == #~=) ifTrue:[lineno := true. stackDelta := -1. extraLiteral := aSymbol. ^132]. |
|
754 |
(aSymbol == #-) ifTrue:[lineno := true. stackDelta := -1. extraLiteral := aSymbol. ^133]. |
|
755 |
(aSymbol == #*) ifTrue:[lineno := true. stackDelta := -1. extraLiteral := aSymbol. ^230]. |
|
756 |
(aSymbol == #class) ifTrue:[extraLiteral := aSymbol. ^134]. |
|
757 |
"/ (aSymbol == #x) ifTrue:[lineno := true. extraLiteral := aSymbol. ^106]. |
|
758 |
"/ (aSymbol == #y) ifTrue:[lineno := true. extraLiteral := aSymbol. ^107]. |
|
759 |
"/ (aSymbol == #width) ifTrue:[lineno := true. extraLiteral := aSymbol. ^108]. |
|
760 |
"/ (aSymbol == #height) ifTrue:[lineno := true. extraLiteral := aSymbol. ^109]. |
|
761 |
"/ (aSymbol == #origin) ifTrue:[lineno := true. extraLiteral := aSymbol. ^154]. |
|
762 |
"/ (aSymbol == #extent) ifTrue:[lineno := true. extraLiteral := aSymbol. ^155]. |
|
763 |
(aSymbol == #at:) ifTrue:[lineno := true. stackDelta := -1. extraLiteral := aSymbol. ^135]. |
|
764 |
(aSymbol == #at:put:)ifTrue:[lineno := true. stackDelta := -2. extraLiteral := aSymbol. ^136]. |
|
765 |
(aSymbol == #bitAnd:) ifTrue:[lineno := true. stackDelta := -1. extraLiteral := aSymbol. ^137]. |
|
766 |
(aSymbol == #bitOr:) ifTrue:[lineno := true. stackDelta := -1. extraLiteral := aSymbol. ^138]. |
|
767 |
(aSymbol == #plus1) ifTrue:[lineno := true. extraLiteral := #+. ^123]. |
|
768 |
(aSymbol == #minus1) ifTrue:[lineno := true. extraLiteral := #-. ^124]. |
|
769 |
||
770 |
(aSymbol == #incMethodVar) ifTrue:[lineno := true. extraLiteral := #+. extra := #index. ^125]. |
|
771 |
(aSymbol == #decMethodVar) ifTrue:[lineno := true. extraLiteral := #-. extra := #index. ^126]. |
|
772 |
||
773 |
(aSymbol == #eq0) ifTrue:[extraLiteral := #==. ^48]. |
|
774 |
(aSymbol == #ne0) ifTrue:[extraLiteral := #~~. ^49]. |
|
775 |
||
776 |
(aSymbol == #>) ifTrue:[lineno := true. extraLiteral := aSymbol. stackDelta := -1. ^ 145]. |
|
777 |
(aSymbol == #>=) ifTrue:[lineno := true. extraLiteral := aSymbol. stackDelta := -1. ^ 146]. |
|
778 |
(aSymbol == #<) ifTrue:[lineno := true. extraLiteral := aSymbol. stackDelta := -1. ^ 147]. |
|
779 |
(aSymbol == #<=) ifTrue:[lineno := true. extraLiteral := aSymbol. stackDelta := -1. ^ 148]. |
|
780 |
"/ (aSymbol == #next) ifTrue:[lineno := true. extraLiteral := aSymbol. ^ 149]. |
|
781 |
"/ (aSymbol == #peek) ifTrue:[lineno := true. extraLiteral := aSymbol. ^ 150]. |
|
782 |
(aSymbol == #value) ifTrue:[lineno := true. extraLiteral := aSymbol. ^ 151]. |
|
783 |
(aSymbol == #value:) ifTrue:[lineno := true. extraLiteral := aSymbol. stackDelta := -1. ^ 152]. |
|
784 |
(aSymbol == #value:value:) ifTrue:[lineno := true. extraLiteral := aSymbol. stackDelta := -2. ^ 178]. |
|
785 |
(aSymbol == #size) ifTrue:[lineno := true. extraLiteral := aSymbol. ^ 153]. |
|
786 |
"/ (aSymbol == #asInteger) ifTrue:[lineno := true. extraLiteral := aSymbol. ^ 158]. |
|
787 |
"/ (aSymbol == #rounded) ifTrue:[lineno := true. extraLiteral := aSymbol. ^ 159]. |
|
788 |
(aSymbol == #mk0Block) ifTrue:[^ 156]. |
|
789 |
(aSymbol == #mkNilBlock) ifTrue:[^ 157]. |
|
790 |
||
791 |
(aSymbol == #gt0) ifTrue:[lineno := true. extraLiteral := #>. ^ 212]. |
|
792 |
(aSymbol == #pushgt0) ifTrue:[lineno := true. stackDelta := 1. extraLiteral := #>. ^ 208]. |
|
793 |
(aSymbol == #basicNew) ifTrue:[lineno := true. extraLiteral := aSymbol. ^ 211]. |
|
794 |
(aSymbol == #new) ifTrue:[lineno := true. extraLiteral := aSymbol. ^ 213]. |
|
795 |
(aSymbol == #basicNew:) ifTrue:[lineno := true. extraLiteral := aSymbol. ^ 214]. |
|
796 |
(aSymbol == #new:) ifTrue:[lineno := true. extraLiteral := aSymbol. ^ 215]. |
|
797 |
||
798 |
(aSymbol == #pushBlockVar1) ifTrue:[stackDelta := 1. ^ 232]. |
|
799 |
(aSymbol == #pushBlockVar2) ifTrue:[stackDelta := 1. ^ 233]. |
|
800 |
(aSymbol == #pushBlockVar3) ifTrue:[stackDelta := 1. ^ 234]. |
|
801 |
(aSymbol == #storeBlockVar1) ifTrue:[stackDelta := -1. ^ 235]. |
|
802 |
(aSymbol == #storeBlockVar2) ifTrue:[stackDelta := -1. ^ 236]. |
|
803 |
(aSymbol == #storeBlockVar3) ifTrue:[stackDelta := -1. ^ 237]. |
|
804 |
||
805 |
(aSymbol == #falseJumpabs) ifTrue:[stackDelta := -1. extra := #absoffset. ^ 190]. |
|
806 |
(aSymbol == #trueJumpabs) ifTrue:[stackDelta := -1. extra := #absoffset. ^ 191]. |
|
807 |
(aSymbol == #nilJumpabs) ifTrue:[stackDelta := -1. extra := #absoffset. ^ 192]. |
|
808 |
(aSymbol == #notNilJumpabs) ifTrue:[stackDelta := -1. extra := #absoffset. ^ 193]. |
|
809 |
(aSymbol == #jumpabs) ifTrue:[extra := #absoffset. ^ 194]. |
|
810 |
(aSymbol == #makeBlockabs) ifTrue:[stackDelta := 1. extra := #absoffsetNvarNarg. ^ 195]. |
|
811 |
(aSymbol == #zeroJumpabs) ifTrue:[stackDelta := -1. extra := #absoffset. ^ 196]. |
|
812 |
(aSymbol == #notZeroJumpabs) ifTrue:[stackDelta := -1. extra := #absoffset. ^ 197]. |
|
813 |
(aSymbol == #eqJumpabs) ifTrue:[stackDelta := -2. extra := #absoffset. ^ 198]. |
|
814 |
(aSymbol == #notEqJumpabs) ifTrue:[stackDelta := -2. extra := #absoffset. ^ 199]. |
|
815 |
||
816 |
(aSymbol == #pushThisContext) ifTrue:[stackDelta := 1. ^ 144]. |
|
817 |
||
818 |
(aSymbol == #isNil) ifTrue:[extraLiteral := aSymbol. ^ 188]. |
|
819 |
(aSymbol == #notNil) ifTrue:[extraLiteral := aSymbol. ^ 189]. |
|
820 |
(aSymbol == #not) ifTrue:[extraLiteral := aSymbol. lineno := true. ^ 179]. |
|
821 |
(aSymbol == #&) ifTrue:[extraLiteral := aSymbol. lineno := true. ^ 216]. |
|
822 |
(aSymbol == #|) ifTrue:[extraLiteral := aSymbol. lineno := true. ^ 217]. |
|
823 |
||
824 |
(aSymbol == #pushClassVarL) ifTrue:[stackDelta := 1. extra := #speciallitL. ^ 218]. |
|
825 |
(aSymbol == #pushGlobalL) ifTrue:[stackDelta := 1. extra := #speciallitL. ^ 218]. |
|
826 |
(aSymbol == #storeClassVarL) ifTrue:[extra := #speciallitL.stackDelta := -1. ^ 219]. |
|
827 |
(aSymbol == #storeGlobalL) ifTrue:[extra := #speciallitL. stackDelta := -1. ^ 219]. |
|
828 |
(aSymbol == #pushLitL) ifTrue:[stackDelta := 1. extra := #unsigned16. ^ 201]. |
|
829 |
||
830 |
(aSymbol == #sendL) ifTrue:[lineno := true. extra := #specialL. ^ 205]. |
|
831 |
(aSymbol == #sendSelfL) ifTrue:[lineno := true. extra := #specialL. ^ 207]. |
|
832 |
(aSymbol == #sendDropL) ifTrue:[lineno := true. extra := #specialL. ^ 204]. |
|
833 |
(aSymbol == #superSendL) ifTrue:[lineno := true. extra := #specialL. ^ 206]. |
|
834 |
(aSymbol == #hereSendL) ifTrue:[lineno := true. extra := #specialL. ^ 206]. |
|
835 |
||
836 |
(aSymbol == #top) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
837 |
(aSymbol == #bottom) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
838 |
(aSymbol == #left) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
839 |
(aSymbol == #right) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
840 |
||
841 |
(aSymbol == #x) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
842 |
(aSymbol == #y) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
843 |
(aSymbol == #width) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
844 |
(aSymbol == #height) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
845 |
(aSymbol == #origin) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
846 |
(aSymbol == #extent) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
847 |
(aSymbol == #next) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
848 |
(aSymbol == #peek) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
849 |
(aSymbol == #asInteger) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
850 |
(aSymbol == #rounded) ifTrue:[lineno := true. extraLiteral := aSymbol. extra := #specialSend. ^ 231]. |
|
851 |
||
852 |
(aSymbol == #blockRef) ifTrue:[stackDelta := 0. ^ 238]. |
|
853 |
(aSymbol == #over) ifTrue:[stackDelta := 1. ^ 6]. |
|
590
fbeea17273d2
class: JavaScriptCompiler
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
582
diff
changeset
|
854 |
(aSymbol == #swap) ifTrue:[stackDelta := 0. ^ 243]. |
fbeea17273d2
class: JavaScriptCompiler
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
582
diff
changeset
|
855 |
|
49 | 856 |
|
857 |
self error:'invalid code symbol'. |
|
858 |
errorFlag := #Error |
|
859 |
||
239 | 860 |
"Modified: / 03-09-1995 / 12:58:47 / claus" |
519 | 861 |
"Modified: / 31-10-2011 / 11:35:07 / cg" |
590
fbeea17273d2
class: JavaScriptCompiler
Jan Vrany <jan.vrany@fit.cvut.cz>
parents:
582
diff
changeset
|
862 |
"Modified: / 09-05-2013 / 12:12:52 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
49 | 863 |
! |
864 |
||
38 | 865 |
code |
49 | 866 |
^ codeBytes |
38 | 867 |
! |
868 |
||
601 | 869 |
codeLineNumber:nr on:codeStream |
870 |
"generate lineNumber information" |
|
871 |
||
872 |
"/ caveat: (currently) there is no separate lineNumber or symbol table; |
|
873 |
"/ the line numbers are coded right into the instruction stream. |
|
874 |
"/ This might change in the future. |
|
875 |
"/ (It is not a problem speed wise: the Jitter just skips them.) |
|
876 |
||
877 |
(currentLineNumber = nr or:[nr <= 0]) ifTrue:[ |
|
1059 | 878 |
^ self |
601 | 879 |
]. |
880 |
||
602 | 881 |
"don't need line number information, if still on same line" |
601 | 882 |
currentLineNumber := nr. |
883 |
||
884 |
nr <= 255 ifTrue:[ |
|
1059 | 885 |
codeStream |
886 |
nextPut:#lineno; |
|
887 |
nextPut:nr. |
|
601 | 888 |
] ifFalse:[ |
1059 | 889 |
nr <= 16rFFFF ifTrue:[ |
890 |
codeStream |
|
891 |
nextPut:#lineno16; |
|
892 |
nextPutInt16:nr MSB:true. |
|
893 |
] |
|
601 | 894 |
]. |
895 |
! |
|
896 |
||
38 | 897 |
contextMustBeReturnable |
898 |
^ false |
|
899 |
! |
|
900 |
||
901 |
correctedSource |
|
902 |
^ nil |
|
903 |
! |
|
904 |
||
905 |
createMethod |
|
906 |
|newMethod| |
|
907 |
||
908 |
newMethod := self methodClass new:(litArray size). |
|
127 | 909 |
newMethod mclass:classToCompileFor. |
38 | 910 |
litArray notNil ifTrue:[ |
860 | 911 |
"/ fixup CheapBlocks method-field in literal array, |
912 |
litArray do:[:aLiteral | |
|
913 |
(aLiteral isMemberOf:CheapBlock) ifTrue:[ |
|
914 |
aLiteral setMethod:newMethod. |
|
915 |
] |
|
916 |
]. |
|
917 |
newMethod literals:litArray |
|
38 | 918 |
]. |
919 |
||
920 |
newMethod numberOfVars:(self numberOfMethodVars + (maxNumTemp ? 0)). |
|
860 | 921 |
newMethod numberOfArgs:(self numberOfMethodArgs). |
38 | 922 |
newMethod stackSize:(self maxStackDepth). |
923 |
||
924 |
^ newMethod |
|
925 |
! |
|
926 |
||
49 | 927 |
genByteCodeFrom:symbolicCodeArray |
928 |
"convert symbolicCode into bytecodes" |
|
929 |
||
930 |
|symIndex "{Class: SmallInteger }" |
|
931 |
codeSize "{Class: SmallInteger }" |
|
932 |
symCodeSize "{Class: SmallInteger }" |
|
933 |
index nextSym addr |
|
934 |
codeSymbol nargs needRetry |
|
935 |
stackDepth relocInfo level nvars round |
|
443 | 936 |
lnoLO lnoHI | |
49 | 937 |
|
938 |
symbolicCodeArray isNil ifTrue:[^ self]. |
|
939 |
||
940 |
round := 0. |
|
941 |
needRetry := true. |
|
942 |
symCodeSize := symbolicCodeArray size. |
|
943 |
codeSize := symCodeSize. |
|
944 |
||
945 |
[needRetry] whileTrue:[ |
|
818 | 946 |
stackDepth := 0. |
947 |
maxStackDepth := 0. |
|
49 | 948 |
|
818 | 949 |
codeBytes := ByteArray uninitializedNew:codeSize. |
950 |
relocInfo := Array basicNew:(codeSize + 1). |
|
951 |
symIndex := 1. |
|
952 |
codeIndex := 1. |
|
49 | 953 |
|
818 | 954 |
needRetry := false. |
955 |
round := round + 1. |
|
49 | 956 |
|
818 | 957 |
[symIndex <= symCodeSize] whileTrue:[ |
958 |
relocInfo at:symIndex put:codeIndex. |
|
49 | 959 |
|
818 | 960 |
codeSymbol := symbolicCodeArray at:symIndex. |
961 |
symIndex := symIndex + 1. |
|
962 |
stackDelta := 0. |
|
963 |
extra := extraLiteral := nil. |
|
964 |
lineno := false. |
|
49 | 965 |
|
818 | 966 |
self appendByteCodeFor:codeSymbol. |
49 | 967 |
|
818 | 968 |
extraLiteral notNil ifTrue:[ |
969 |
self addLiteral:extraLiteral |
|
970 |
]. |
|
49 | 971 |
|
818 | 972 |
lineno ifTrue:[ |
973 |
lnoLO := (symbolicCodeArray at:symIndex) ? 0. |
|
974 |
self appendByte:(lnoLO min:255). |
|
975 |
symIndex := symIndex + 1. |
|
976 |
codeSymbol == #lineno16 ifTrue:[ |
|
977 |
lnoHI := (symbolicCodeArray at:symIndex) ? 0. |
|
978 |
self appendByte:(lnoHI min:255). |
|
979 |
symIndex := symIndex + 1 |
|
980 |
] |
|
981 |
]. |
|
49 | 982 |
|
818 | 983 |
extra notNil ifTrue:[ |
984 |
nextSym := symbolicCodeArray at:symIndex. |
|
49 | 985 |
|
818 | 986 |
(extra == #number) ifTrue:[ |
987 |
index := nextSym. |
|
988 |
symIndex := symIndex + 1. |
|
989 |
self appendSignedByte:index |
|
49 | 990 |
|
818 | 991 |
] ifFalse:[ (extra == #number16) ifTrue:[ |
992 |
index := nextSym. |
|
993 |
symIndex := symIndex + 2. |
|
994 |
self appendSignedWord:index |
|
49 | 995 |
|
818 | 996 |
] ifFalse:[ (extra == #unsigned16) ifTrue:[ |
997 |
index := nextSym. |
|
998 |
symIndex := symIndex + 2. |
|
999 |
self appendWord:index |
|
49 | 1000 |
|
818 | 1001 |
] ifFalse:[ (extra == #index) ifTrue:[ |
1002 |
index := nextSym. |
|
1003 |
symIndex := symIndex + 1. |
|
1004 |
self appendByte:index |
|
49 | 1005 |
|
818 | 1006 |
] ifFalse:[ (extra == #lit) ifTrue:[ |
1007 |
index := self addLiteral:nextSym. |
|
1008 |
symIndex := symIndex + 1. |
|
1009 |
self appendByte:index |
|
49 | 1010 |
|
818 | 1011 |
] ifFalse:[ (extra == #speciallit) ifTrue:[ |
1012 |
index := self addLiteral:nextSym. |
|
1013 |
index > 255 ifTrue:[ |
|
1014 |
self parseError:'too many globals (' , |
|
1015 |
(symbolicCodeArray at:symIndex) , |
|
1016 |
' index=' , index printString , |
|
1017 |
') in method - please simplify'. |
|
1018 |
^ #Error |
|
1019 |
]. |
|
1020 |
symIndex := symIndex + 1. |
|
1021 |
self appendByte:index. |
|
49 | 1022 |
|
818 | 1023 |
] ifFalse:[ (extra == #speciallitS) ifTrue:[ |
1024 |
index := nextSym. |
|
1025 |
symIndex := symIndex + 1. |
|
1026 |
self appendByte:index. |
|
49 | 1027 |
|
818 | 1028 |
] ifFalse:[ (extra == #speciallitL) ifTrue:[ |
1029 |
index := nextSym. |
|
1030 |
symIndex := symIndex + 2. |
|
1031 |
self appendWord:index. |
|
49 | 1032 |
|
818 | 1033 |
] ifFalse:[ (extra == #offset) ifTrue:[ |
1034 |
relocInfo at:symIndex put:codeIndex. |
|
1035 |
self addReloc:symIndex. |
|
1036 |
symIndex := symIndex + 1. |
|
1037 |
self appendByte:0 |
|
49 | 1038 |
|
818 | 1039 |
] ifFalse:[ (extra == #indexLevel) ifTrue:[ |
1040 |
index := nextSym. |
|
1041 |
symIndex := symIndex + 1. |
|
1042 |
self appendByte:index. |
|
1043 |
level := symbolicCodeArray at:symIndex. |
|
1044 |
symIndex := symIndex + 1. |
|
1045 |
self appendByte:level |
|
49 | 1046 |
|
818 | 1047 |
] ifFalse:[ (extra == #offsetNvarNarg) ifTrue:[ |
1048 |
relocInfo at:symIndex put:codeIndex. |
|
1049 |
self addReloc:symIndex. |
|
1050 |
symIndex := symIndex + 1. |
|
1051 |
self appendEmptyByte. |
|
1052 |
nvars := symbolicCodeArray at:symIndex. |
|
1053 |
symIndex := symIndex + 1. |
|
1054 |
self appendByte:nvars. |
|
1055 |
level := symbolicCodeArray at:symIndex. |
|
1056 |
symIndex := symIndex + 1. |
|
1057 |
self appendByte:level |
|
49 | 1058 |
|
818 | 1059 |
] ifFalse:[ (extra == #absoffset) ifTrue:[ |
1060 |
relocInfo at:symIndex put:codeIndex. |
|
1061 |
self addReloc:symIndex. |
|
1062 |
addr := symbolicCodeArray at:symIndex. |
|
1063 |
symIndex := symIndex + 1. |
|
1064 |
self appendByte:(addr bitAnd:16rFF). |
|
1065 |
self appendByte:((addr bitShift:-8) bitAnd:16rFF). |
|
49 | 1066 |
|
818 | 1067 |
] ifFalse:[ (extra == #absoffsetNvarNarg) ifTrue:[ |
1068 |
relocInfo at:symIndex put:codeIndex. |
|
1069 |
self addReloc:symIndex. |
|
1070 |
addr := symbolicCodeArray at:symIndex. |
|
1071 |
symIndex := symIndex + 1. |
|
1072 |
self appendByte:(addr bitAnd:16rFF). |
|
1073 |
self appendByte:((addr bitShift:-8) bitAnd:16rFF). |
|
1074 |
nvars := symbolicCodeArray at:symIndex. |
|
1075 |
symIndex := symIndex + 1. |
|
1076 |
self appendByte:nvars. |
|
1077 |
level := symbolicCodeArray at:symIndex. |
|
1078 |
symIndex := symIndex + 1. |
|
1079 |
self appendByte:level |
|
49 | 1080 |
|
818 | 1081 |
] ifFalse:[ (extra == #special) ifTrue:[ |
1082 |
((codeSymbol == #send) |
|
1083 |
or:[codeSymbol == #sendSelf |
|
1084 |
or:[codeSymbol == #superSend |
|
1085 |
or:[codeSymbol == #hereSend]]]) ifTrue:[ |
|
1086 |
index := nextSym. |
|
1087 |
symIndex := symIndex + 1. |
|
1088 |
nargs := symbolicCodeArray at:symIndex. |
|
1089 |
symIndex := symIndex + 1. |
|
1090 |
self appendByte:nargs. |
|
1091 |
self appendByte:index. |
|
49 | 1092 |
|
818 | 1093 |
(codeSymbol == #superSend |
1094 |
or:[codeSymbol == #hereSend]) ifTrue:[ |
|
1095 |
index := symbolicCodeArray at:symIndex. |
|
1096 |
symIndex := symIndex + 1. |
|
1097 |
self appendByte:index |
|
1098 |
]. |
|
1099 |
stackDelta := nargs negated. |
|
1100 |
codeSymbol == #sendSelf ifTrue:[ |
|
1101 |
stackDelta := stackDelta + 1 |
|
1102 |
] |
|
1103 |
] ifFalse:[ (codeSymbol == #sendDrop) ifTrue:[ |
|
1104 |
index := nextSym. |
|
1105 |
symIndex := symIndex + 1. |
|
1106 |
nargs := symbolicCodeArray at:symIndex. |
|
1107 |
symIndex := symIndex + 1. |
|
1108 |
self appendByte:nargs. |
|
1109 |
self appendByte:index. |
|
1110 |
stackDelta := (nargs + 1) negated |
|
1111 |
]] |
|
49 | 1112 |
|
818 | 1113 |
] ifFalse:[ (extra == #specialL) ifTrue:[ |
1114 |
((codeSymbol == #sendL) |
|
1115 |
or:[codeSymbol == #sendDropL |
|
1116 |
or:[codeSymbol == #sendSelfL |
|
1117 |
or:[codeSymbol == #superSendL |
|
1118 |
or:[codeSymbol == #hereSendL]]]]) ifTrue:[ |
|
1119 |
index := nextSym. |
|
1120 |
symIndex := symIndex + 2. |
|
1121 |
nargs := symbolicCodeArray at:symIndex. |
|
1122 |
symIndex := symIndex + 1. |
|
1123 |
self appendByte:nargs. |
|
1124 |
self appendWord:index. |
|
1125 |
(codeSymbol == #superSendL |
|
1126 |
or:[codeSymbol == #hereSendL]) ifTrue:[ |
|
1127 |
index := symbolicCodeArray at:symIndex. |
|
1128 |
symIndex := symIndex + 2. |
|
1129 |
self appendWord:index. |
|
1130 |
]. |
|
1131 |
stackDelta := nargs negated. |
|
1132 |
codeSymbol == #sendSelfL ifTrue:[ |
|
1133 |
stackDelta := stackDelta + 1 |
|
1134 |
] |
|
1135 |
] |
|
1136 |
] ifFalse:[ (extra == #specialSend) ifTrue:[ |
|
1137 |
index := nextSym. |
|
1138 |
symIndex := symIndex + 1. |
|
1139 |
self appendByte:index. |
|
49 | 1140 |
|
818 | 1141 |
] ifFalse:[ |
1142 |
"/ self halt:'internal error' |
|
49 | 1143 |
|
818 | 1144 |
]]]]]]]]]]]]]]]] |
1145 |
]. |
|
49 | 1146 |
|
818 | 1147 |
stackDepth := stackDepth + stackDelta. |
1148 |
(stackDepth > maxStackDepth) ifTrue:[ |
|
1149 |
maxStackDepth := stackDepth |
|
1150 |
] |
|
1151 |
]. |
|
1152 |
relocInfo at:symIndex put:codeIndex. |
|
49 | 1153 |
|
818 | 1154 |
needRetry ifFalse:[ |
1155 |
" |
|
1156 |
now relocate - returns true if ok, false if we have to do it again |
|
1157 |
(when short jumps have been changed to long jumps) |
|
1158 |
" |
|
1159 |
relocList notNil ifTrue:[ |
|
1160 |
needRetry := (self relocateWith:symbolicCodeArray relocInfo:relocInfo) not. |
|
1161 |
" |
|
1162 |
if returned with false, a relative jump was made into |
|
1163 |
an absolute jump - need to start over with one more byte space |
|
1164 |
" |
|
1165 |
needRetry ifTrue:[ |
|
1166 |
relocList := nil. |
|
1167 |
codeSize := codeSize + 1. |
|
1168 |
] |
|
1169 |
] |
|
1170 |
] ifTrue:[ |
|
1171 |
'Compiler [info]: compiling again ...' infoPrintCR. |
|
1172 |
] |
|
49 | 1173 |
]. |
1174 |
"code printNL." |
|
1175 |
^ errorFlag |
|
1176 |
||
443 | 1177 |
"Modified: / 03-09-1995 / 12:59:43 / claus" |
1178 |
"Modified: / 19-05-2010 / 12:55:53 / cg" |
|
38 | 1179 |
! |
1180 |
||
1181 |
genSymbolicCode |
|
49 | 1182 |
"traverse the parse-tree producing symbolicCode - return the codeArray" |
1183 |
||
754 | 1184 |
|codeStream code lastStatement| |
49 | 1185 |
|
1186 |
litArray := nil. |
|
1187 |
codeStream := WriteStream on:(OrderedCollection new:100). |
|
1188 |
||
1189 |
"/ primitiveContextInfo notNil ifTrue:[ |
|
1190 |
"/ (primitiveContextInfo includes:('exception:' -> #unwind)) ifTrue:[ |
|
1191 |
"/ self genSpecialStatement:#markForUnwind on:codeStream |
|
1192 |
"/ ]. |
|
1193 |
"/ (primitiveContextInfo includes:('exception:' -> #handle)) ifTrue:[ |
|
1194 |
"/ self genSpecialStatement:#markForHandle on:codeStream |
|
1195 |
"/ ]. |
|
1196 |
"/ (primitiveContextInfo includes:('exception:' -> #raise)) ifTrue:[ |
|
1197 |
"/ self genSpecialStatement:#markForRaise on:codeStream |
|
1198 |
"/ ]. |
|
1199 |
"/ ]. |
|
1200 |
||
61 | 1201 |
tree codeVariableSetupOn:codeStream for:self. |
49 | 1202 |
|
818 | 1203 |
(tree statements ? #()) do:[:thisStatement | |
1204 |
lastStatement := thisStatement. |
|
1205 |
thisStatement codeForSideEffectOn:codeStream inBlock:nil for:self. |
|
49 | 1206 |
]. |
1207 |
(lastStatement isNil or:[lastStatement isReturnNode not]) |
|
1208 |
ifTrue:[ |
|
818 | 1209 |
"not a return - add retNil" |
1210 |
" |
|
1211 |
if the last statement was a send for side-effect, |
|
1212 |
replace the previous drop by a retNil. |
|
1213 |
In this case we have to keep an extra retNil because |
|
1214 |
it could be a jump target. |
|
1215 |
" |
|
1216 |
(lastStatement notNil |
|
1217 |
and:[(code := codeStream contents) notNil |
|
1218 |
and:[code size > 0 |
|
1219 |
and:[code last == #drop]]]) ifTrue:[ |
|
1220 |
codeStream backStep. |
|
1221 |
codeStream nextPut:#retNil |
|
1222 |
]. |
|
1223 |
codeStream nextPut:#retNil |
|
49 | 1224 |
]. |
1225 |
^ codeStream contents |
|
239 | 1226 |
|
1227 |
"Modified: / 21-02-2007 / 12:30:44 / cg" |
|
49 | 1228 |
! |
1229 |
||
1230 |
generateVariables:varCollection on:codeStream |
|
1231 |
varCollection isNil ifTrue:[^ self]. |
|
1232 |
||
1233 |
varCollection do:[:eachVar | |
|
818 | 1234 |
"/ generate code to set it up. |
51 | 1235 |
|
818 | 1236 |
|initExpression setupExpr| |
49 | 1237 |
|
818 | 1238 |
initExpression := eachVar expressionForSetup. |
1239 |
initExpression notNil ifTrue:[ |
|
1240 |
setupExpr := AssignmentNode |
|
1241 |
variable:(self nodeForMethodVariable:eachVar name) |
|
1242 |
expression:initExpression. |
|
1243 |
setupExpr codeForSideEffectOn:codeStream inBlock:nil for:self. |
|
1244 |
] |
|
49 | 1245 |
] |
1246 |
! |
|
1247 |
||
209 | 1248 |
isBuiltInSelector:sel forReceiver:receiver |
61 | 1249 |
^ false |
1250 |
||
209 | 1251 |
"Created: / 10-08-2006 / 12:09:56 / cg" |
38 | 1252 |
! |
1253 |
||
1254 |
maxStackDepth |
|
1255 |
^ maxNumTemp ? 0 |
|
1256 |
! |
|
1257 |
||
1258 |
methodClass |
|
608 | 1259 |
^ methodClass ? JavaScriptFunction |
1260 |
||
1261 |
"Modified: / 22-07-2013 / 15:52:58 / cg" |
|
38 | 1262 |
! |
1263 |
||
1264 |
numberOfMethodArgs |
|
1265 |
^ tree _argVariables size. |
|
1266 |
! |
|
1267 |
||
1268 |
numberOfMethodVars |
|
1269 |
^ tree _localVariables size. |
|
49 | 1270 |
! |
1271 |
||
50 | 1272 |
relocateWith:symbolicCodeArray relocInfo:relocInfo |
1273 |
"helper for genByteCodeFrom - relocate code using relocInfo. |
|
1274 |
if relocation fails badly (due to long relative jumps) patch |
|
1275 |
symbolicCode to use absolute jumps instead and return false |
|
1276 |
(genByteCodeFrom will then try again). Otherwise return true. |
|
1277 |
Also, on the fly, jumps to jumps and jumps to return are handled." |
|
1278 |
||
1279 |
|delta "{Class: SmallInteger }" |
|
1280 |
codePos "{Class: SmallInteger }" |
|
1281 |
opCodePos "{Class: SmallInteger }" |
|
1282 |
codeOffset "{Class: SmallInteger }" |
|
818 | 1283 |
symOffset |
50 | 1284 |
opcode "{Class: SmallInteger }" |
1285 |
dstOpcode jumpTarget |
|
1286 |
jumpCode deleteSet| |
|
1287 |
||
1288 |
deleteSet := OrderedCollection new. |
|
1289 |
relocList do:[:sIndex | |
|
818 | 1290 |
"have to relocate symCode at sIndex ..." |
1291 |
symOffset := symbolicCodeArray at:sIndex. "the target in the symbolic code" |
|
1292 |
codePos := relocInfo at:sIndex. "position of the offet in byte code" |
|
1293 |
codeOffset := relocInfo at:symOffset. "position of the target in byte code" |
|
1294 |
delta := codeOffset - codePos - 1. |
|
1295 |
opCodePos := codePos - 1. |
|
1296 |
opcode := codeBytes at:opCodePos. |
|
50 | 1297 |
|
818 | 1298 |
(opcode between:190 and:199) ifTrue:[ |
1299 |
"an absolute jump/makeBlock" |
|
50 | 1300 |
|
818 | 1301 |
codeBytes at:codePos put:(codeOffset bitAnd:16rFF). |
1302 |
codeBytes at:(codePos + 1) put:(codeOffset bitShift:-8) |
|
1303 |
] ifFalse:[ |
|
1304 |
"get jump-code from long and vlong codes" |
|
1305 |
(opcode between:50 and:59) ifFalse:[ |
|
1306 |
(opcode between:60 and:69) ifTrue:[ |
|
1307 |
opcode := opcode - 10 |
|
1308 |
] ifFalse:[ |
|
1309 |
(opcode between:70 and:79) ifTrue:[ |
|
1310 |
opcode := opcode - 20 |
|
1311 |
] ifFalse:[ |
|
1312 |
self error:'invalid code to relocate' |
|
1313 |
] |
|
1314 |
]. |
|
1315 |
]. |
|
50 | 1316 |
|
818 | 1317 |
"optimize jump to return and jump to jump" |
50 | 1318 |
|
818 | 1319 |
(opcode == 54) ifTrue:[ |
1320 |
"a jump" |
|
1321 |
dstOpcode := symbolicCodeArray at:symOffset. |
|
50 | 1322 |
|
818 | 1323 |
(#(retSelf retTop retNil retTrue retFalse ret0 "blockRetTop") includes:dstOpcode) ifTrue:[ |
1324 |
"a jump to a return - put in the return instead jump" |
|
50 | 1325 |
|
818 | 1326 |
symbolicCodeArray at:(sIndex - 1) put:dstOpcode. |
1327 |
symbolicCodeArray at:sIndex put:dstOpcode. |
|
1328 |
codeBytes at:opCodePos put:(self byteCodeFor:dstOpcode). |
|
1329 |
delta := 0. |
|
1330 |
deleteSet add:sIndex. |
|
50 | 1331 |
|
818 | 1332 |
" |
50 | 1333 |
'jump to return at: ' print. (sIndex - 1) printNL. |
818 | 1334 |
" |
1335 |
] ifFalse:[ |
|
1336 |
(dstOpcode == #jump) ifTrue:[ |
|
1337 |
"jump to jump to be done soon" |
|
1338 |
jumpTarget := symbolicCodeArray at:(symOffset + 1). |
|
1339 |
" |
|
50 | 1340 |
'jump to jump at: ' print. (sIndex - 1) print. |
1341 |
' newTarget:' print. jumpTarget printNL. |
|
818 | 1342 |
" |
50 | 1343 |
|
818 | 1344 |
symbolicCodeArray at:sIndex put:jumpTarget. |
1345 |
symOffset := jumpTarget. |
|
1346 |
codeOffset := relocInfo at:symOffset. |
|
1347 |
delta := codeOffset - codePos - 1. |
|
50 | 1348 |
|
818 | 1349 |
"continue with new delta" |
1350 |
] |
|
1351 |
] |
|
1352 |
]. |
|
1353 |
(#(50 51 52 53 56 57 58 59) includes:opcode) ifTrue:[ |
|
1354 |
"a conditional jump" |
|
50 | 1355 |
|
818 | 1356 |
dstOpcode := symbolicCodeArray at:symOffset. |
1357 |
(dstOpcode == #jump) ifTrue:[ |
|
1358 |
"conditional jump to unconditional jump" |
|
1359 |
jumpTarget := symbolicCodeArray at:(symOffset + 1). |
|
1360 |
" |
|
50 | 1361 |
'cond jump to jump at: ' print. (sIndex - 1) print. |
1362 |
' newTarget:' print. jumpTarget printNL. |
|
818 | 1363 |
" |
50 | 1364 |
|
818 | 1365 |
symbolicCodeArray at:sIndex put:jumpTarget. |
1366 |
symOffset := jumpTarget. |
|
1367 |
codeOffset := relocInfo at:symOffset. |
|
1368 |
delta := codeOffset - codePos - 1. |
|
50 | 1369 |
|
818 | 1370 |
"continue with new delta" |
1371 |
]. |
|
1372 |
]. |
|
50 | 1373 |
|
818 | 1374 |
(delta >= 0) ifTrue:[ |
1375 |
(delta > 127) ifTrue:[ |
|
1376 |
(opcode between:50 and:59) ifFalse:[ |
|
1377 |
self error:'invalid code to relocate' |
|
1378 |
] ifTrue:[ |
|
1379 |
(delta > 255) ifTrue:[ |
|
1380 |
"change jmp into vljmp ..." |
|
1381 |
codeBytes at:opCodePos put:(opcode + 20). |
|
1382 |
delta := delta - 256 |
|
1383 |
] ifFalse:[ |
|
1384 |
"change jmp into ljmp ..." |
|
1385 |
codeBytes at:opCodePos put:(opcode + 10). |
|
1386 |
delta := delta - 128 |
|
1387 |
]. |
|
1388 |
(delta > 127) ifTrue:[ |
|
1389 |
"change symbolic into a jump absolute and fail" |
|
1390 |
jumpCode := symbolicCodeArray at:(sIndex - 1). |
|
1391 |
symbolicCodeArray at:(sIndex - 1) put:(self absJumpFromJump:jumpCode). |
|
1392 |
symbolicCodeArray at:sIndex put:symOffset. |
|
50 | 1393 |
" |
1394 |
'change short into abs jump' printNL. |
|
1395 |
" |
|
818 | 1396 |
deleteSet do:[:d | relocList remove:d]. |
1397 |
^ false |
|
1398 |
] |
|
1399 |
]. |
|
1400 |
]. |
|
1401 |
codeBytes at:codePos put:delta |
|
1402 |
] ifFalse:[ |
|
1403 |
(delta < -128) ifTrue:[ |
|
1404 |
(opcode between:50 and:59) ifFalse:[ |
|
1405 |
self error:'invalid code to relocate' |
|
1406 |
] ifTrue:[ |
|
1407 |
(delta < -256) ifTrue:[ |
|
1408 |
"change jmp into vljmp ..." |
|
1409 |
codeBytes at:opCodePos put:(opcode + 20). |
|
1410 |
delta := delta + 256 |
|
1411 |
] ifFalse:[ |
|
1412 |
"change jmp into ljmp ..." |
|
1413 |
codeBytes at:opCodePos put:(opcode + 10). |
|
1414 |
delta := delta + 128 |
|
1415 |
]. |
|
1416 |
(delta < -128) ifTrue:[ |
|
1417 |
"change symbolic into a jump absolute and fail" |
|
1418 |
jumpCode := symbolicCodeArray at:(sIndex - 1). |
|
1419 |
symbolicCodeArray at:(sIndex - 1) put:(self absJumpFromJump:jumpCode). |
|
1420 |
symbolicCodeArray at:sIndex put:symOffset. |
|
50 | 1421 |
" |
1422 |
'change short into abs jump' printNL. |
|
1423 |
" |
|
818 | 1424 |
deleteSet do:[:d | relocList remove:d]. |
1425 |
^ false |
|
1426 |
] |
|
1427 |
] |
|
1428 |
]. |
|
1429 |
codeBytes at:codePos put:(256 + delta) |
|
1430 |
] |
|
1431 |
] |
|
50 | 1432 |
]. |
1433 |
(errorFlag == #Error) ifTrue:[ |
|
818 | 1434 |
self error:'relocation range error' |
50 | 1435 |
]. |
1436 |
^ true |
|
1437 |
! |
|
1438 |
||
49 | 1439 |
specialGlobalCodeFor:aSymbol |
1440 |
^ nil. |
|
1441 |
! |
|
1442 |
||
1443 |
specialSendCodeFor:sel |
|
1444 |
"return the codeExtension for sends, |
|
1445 |
which can be performed by specialSend opCode" |
|
1446 |
||
1447 |
^ nil. |
|
1448 |
||
1449 |
"Modified: 4.6.1997 / 12:31:08 / cg" |
|
37 | 1450 |
! ! |
1451 |
||
86 | 1452 |
!JavaScriptCompiler methodsFor:'compiling'! |
1453 |
||
509
2f9173d9bbe4
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
501
diff
changeset
|
1454 |
compile:aString forClass:aClass inCategory:cat |
1055 | 1455 |
"compile from source code" |
818 | 1456 |
^ self |
1059 | 1457 |
compile:aString |
1458 |
forClass:aClass |
|
1459 |
inCategory:cat |
|
1460 |
notifying:nil |
|
1461 |
install:true |
|
1462 |
skipIfSame:false |
|
1463 |
silent:false |
|
1464 |
foldConstants:true |
|
509
2f9173d9bbe4
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
501
diff
changeset
|
1465 |
|
2f9173d9bbe4
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
501
diff
changeset
|
1466 |
"Created: / 30-09-2011 / 12:49:45 / cg" |
1055 | 1467 |
"Modified (comment): / 08-02-2019 / 11:26:00 / Claus Gittinger" |
509
2f9173d9bbe4
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
501
diff
changeset
|
1468 |
! |
2f9173d9bbe4
added: #compile:forClass:inCategory:
Claus Gittinger <cg@exept.de>
parents:
501
diff
changeset
|
1469 |
|
248 | 1470 |
compile:aString forClass:aClass inCategory:cat notifying:requestorArg |
1059 | 1471 |
install:install skipIfSame:skipIfSame silent:silent foldConstants:fold |
1055 | 1472 |
"compile from source code" |
633 | 1473 |
^ self |
1059 | 1474 |
compile:aString forClass:aClass inCategory:cat notifying:requestorArg |
1475 |
install:install skipIfSame:skipIfSame silent:silent foldConstants:fold |
|
1476 |
ifFail:[] |
|
633 | 1477 |
|
1478 |
"Modified: / 22-07-2013 / 16:07:23 / cg" |
|
1055 | 1479 |
"Modified (comment): / 08-02-2019 / 11:25:56 / Claus Gittinger" |
633 | 1480 |
! |
1481 |
||
1482 |
compile:sourceCodeString forClass:aClass inCategory:cat notifying:aRequestor |
|
1227 | 1483 |
install:install skipIfSame:skipIfSame silent:silent foldConstants:fold |
1484 |
ifFail:failBlock |
|
1055 | 1485 |
"compile from source code" |
1486 |
||
1487 |
|parseTree errMsg definedFunctionNames| |
|
86 | 1488 |
|
1489 |
self setClassToCompileFor:aClass. |
|
1490 |
self parseForCode. |
|
1055 | 1491 |
"/ fold ifFalse:[self foldConstants:nil]. |
633 | 1492 |
self notifying:requestor. |
1493 |
self source:sourceCodeString. |
|
462
7062e98dd382
changed: #compile:forClass:inCategory:notifying:install:skipIfSame:silent:foldConstants:
Claus Gittinger <cg@exept.de>
parents:
460
diff
changeset
|
1494 |
self nextToken. |
86 | 1495 |
|
818 | 1496 |
"/ the old code caught errors and returned #Error |
248 | 1497 |
"/ we now migrate towards letting the caller know about the exception. |
582 | 1498 |
"/ ParseError handle:[:ex | |
248 | 1499 |
"/ Transcript showCR:'JS translation error: ' , ex description "errorMessage". |
1500 |
"/ ^ #Error |
|
1501 |
"/ ] do:[ |
|
818 | 1502 |
|
809 | 1503 |
(tokenType == #Identifier and:[tokenName = 'static']) ifTrue:[ |
1227 | 1504 |
self nextToken. |
1505 |
self setClassToCompileFor:aClass theMetaclass. |
|
809 | 1506 |
]. |
1507 |
||
1227 | 1508 |
parseTree := self function. |
248 | 1509 |
"/ ]. |
86 | 1510 |
|
857 | 1511 |
tokenType == $; "16r3B" ifTrue:[ |
1227 | 1512 |
self nextToken. |
857 | 1513 |
]. |
1055 | 1514 |
|
1515 |
"/ multiple functions? |
|
1516 |
[tokenType ~~ #EOF |
|
1059 | 1517 |
and:[ parseTree notNil |
1055 | 1518 |
and:[ parseTree isFunctionNode |
1519 |
]]] whileTrue:[ |
|
1227 | 1520 |
definedFunctionNames isNil ifTrue:[ |
1521 |
definedFunctionNames := Set new. |
|
1522 |
]. |
|
1523 |
(definedFunctionNames includes:parseTree functionName) ifTrue:[ |
|
1524 |
self notifyError:('redefinition of function "%1"' bindWith:parseTree functionName) |
|
1525 |
position:(parseTree startPosition) to:(parseTree endPosition) |
|
1526 |
lineNr:(parseTree lineNumber) |
|
1527 |
]. |
|
1528 |
definedFunctionNames add:parseTree functionName. |
|
1059 | 1529 |
|
1227 | 1530 |
self |
1531 |
compileTree:parseTree |
|
1532 |
source:sourceCodeString |
|
1533 |
forClass:classToCompileFor |
|
1534 |
inCategory:cat notifying:requestor |
|
1535 |
install:true skipIfSame:skipIfSame silent:silent foldConstants:fold |
|
1536 |
ifFail:failBlock. |
|
1537 |
parseTree := self function. |
|
1538 |
tokenType == $; ifTrue:[ |
|
1539 |
self nextToken |
|
1540 |
]. |
|
1055 | 1541 |
]. |
1059 | 1542 |
|
1227 | 1543 |
tokenType ~~ #EOF ifTrue:[ |
1544 |
tokenType == $} ifTrue:[ |
|
1545 |
errMsg := 'unexpected "}" at end of function'. |
|
1546 |
] ifFalse:[ |
|
1547 |
errMsg := 'unexpected garbage at end of function'. |
|
1548 |
]. |
|
1549 |
self notifyError:errMsg position:tokenPosition to:source position |
|
837 | 1550 |
]. |
1551 |
||
248 | 1552 |
parseTree isNil ifTrue:[ |
1227 | 1553 |
ParseError raiseRequestErrorString:'empty function'. |
1554 |
"/ Transcript showCR:'JS translation error'. |
|
1555 |
failBlock value. |
|
1556 |
^ #Error |
|
86 | 1557 |
]. |
1558 |
^ self |
|
1227 | 1559 |
compileTree:parseTree |
1560 |
source:sourceCodeString |
|
1561 |
forClass:classToCompileFor |
|
1562 |
inCategory:cat notifying:requestor |
|
1563 |
install:install skipIfSame:skipIfSame silent:silent foldConstants:fold |
|
1564 |
ifFail:failBlock |
|
239 | 1565 |
|
633 | 1566 |
"Created: / 22-07-2013 / 16:05:41 / cg" |
1058 | 1567 |
"Modified: / 08-02-2019 / 12:44:24 / Claus Gittinger" |
1227 | 1568 |
"Modified: / 30-01-2020 / 12:45:24 / Stefan Vogel" |
86 | 1569 |
! |
1570 |
||
1571 |
compileTree:tree source:sourceString forClass:aClass inCategory:cat notifying:requestor |
|
1059 | 1572 |
install:install skipIfSame:skipIfSame silent:silent foldConstants:fold |
1055 | 1573 |
"compile from a parsetree" |
633 | 1574 |
^ self |
1059 | 1575 |
compileTree:tree |
1576 |
source:sourceString forClass:aClass inCategory:cat notifying:requestor |
|
1577 |
install:install skipIfSame:skipIfSame silent:silent foldConstants:fold |
|
1578 |
ifFail:[] |
|
633 | 1579 |
|
1580 |
"Modified: / 22-07-2013 / 16:06:58 / cg" |
|
1055 | 1581 |
"Modified (comment): / 08-02-2019 / 11:25:33 / Claus Gittinger" |
633 | 1582 |
! |
1583 |
||
1584 |
compileTree:tree source:sourceString forClass:aClass inCategory:cat notifying:requestor |
|
1118 | 1585 |
install:install skipIfSame:skipIfSame silent:silent foldConstants:fold |
1586 |
ifFail:failBlock |
|
1055 | 1587 |
"compile from a parsetree" |
1059 | 1588 |
|
1118 | 1589 |
|sel newMethod newSource pkg symbolicCodeArray fn| |
86 | 1590 |
|
1591 |
self setClassToCompileFor:aClass. |
|
1592 |
self parseForCode. |
|
1593 |
fold ifFalse:[self foldConstants:nil]. |
|
1594 |
self notifying:requestor. |
|
1595 |
||
1596 |
tree isNil ifTrue:[ |
|
1118 | 1597 |
Transcript showCR:'JS translation error'. |
1598 |
failBlock value. |
|
1599 |
^ #Error |
|
86 | 1600 |
]. |
1601 |
||
1602 |
self tree:tree. |
|
1118 | 1603 |
fn := tree functionName ? 'unimplementedFunction'. |
1604 |
sel := self class selectorFor:fn numArgs:self numberOfMethodArgs. |
|
86 | 1605 |
|
1606 |
" |
|
1607 |
produce symbolic code first |
|
1608 |
" |
|
582 | 1609 |
ParseError handle:[:ex | |
1118 | 1610 |
ex reject. |
460
b18bba05f8a9
changed: #fileOutAllDefinitionsOn:
Claus Gittinger <cg@exept.de>
parents:
443
diff
changeset
|
1611 |
"/ self halt. |
1118 | 1612 |
Transcript showCR:'JS translation error: ' , ex errorMessage. |
1613 |
failBlock value. |
|
1614 |
^ #Error |
|
86 | 1615 |
] do:[ |
1118 | 1616 |
symbolicCodeArray := self genSymbolicCode. |
86 | 1617 |
]. |
1618 |
(symbolicCodeArray == #Error) ifTrue:[ |
|
1118 | 1619 |
Transcript show:' '. |
1620 |
sel notNil ifTrue:[ |
|
1621 |
Transcript show:(sel ,' ') |
|
1622 |
]. |
|
1623 |
Transcript showCR:'JS translation error'. |
|
1624 |
failBlock value. |
|
1625 |
^ #Error |
|
86 | 1626 |
]. |
1627 |
||
1628 |
" |
|
818 | 1629 |
take this, producing bytecode |
86 | 1630 |
" |
1631 |
((self genByteCodeFrom:symbolicCodeArray) == #Error) ifTrue:[ |
|
1118 | 1632 |
Transcript show:' '. |
1633 |
sel notNil ifTrue:[ |
|
1634 |
Transcript show:(sel ,' ') |
|
1635 |
]. |
|
1636 |
Transcript showCR:'relocation error - must be simplified'. |
|
1637 |
failBlock value. |
|
1638 |
^ #Error |
|
86 | 1639 |
]. |
1640 |
" |
|
1641 |
finally create the new method-object |
|
1642 |
" |
|
1643 |
newMethod := self createMethod. |
|
1644 |
newMethod byteCode:(self code). |
|
1645 |
||
1646 |
" |
|
1647 |
if there where any corrections, install the updated source |
|
1648 |
" |
|
1649 |
(newSource := self correctedSource) notNil ifTrue:[ |
|
1118 | 1650 |
newMethod source:newSource string |
86 | 1651 |
] ifFalse:[ |
1118 | 1652 |
newMethod source:sourceString string. |
86 | 1653 |
]. |
111 | 1654 |
|
1655 |
newMethod mclass:aClass. |
|
1656 |
newMethod setCategory:cat. |
|
86 | 1657 |
(aClass isNil or:[aClass owningClass isNil]) ifTrue:[ |
1118 | 1658 |
pkg := Class packageQuerySignal query. |
86 | 1659 |
] ifFalse:[ |
1118 | 1660 |
pkg := aClass owningClass package |
86 | 1661 |
]. |
111 | 1662 |
newMethod setPackage:pkg. |
86 | 1663 |
|
1664 |
(self contextMustBeReturnable) ifTrue:[ |
|
1118 | 1665 |
newMethod contextMustBeReturnable:true |
86 | 1666 |
]. |
1667 |
install ifTrue:[ |
|
1118 | 1668 |
aClass notNil ifTrue:[ |
1669 |
aClass addSelector:sel withMethod:newMethod |
|
1670 |
] |
|
86 | 1671 |
]. |
1672 |
||
94 | 1673 |
"/ silent ifFalse:[ |
1674 |
"/ aClass isNil ifTrue:[ |
|
1675 |
"/ Transcript showCR:(' compiled: <nil> ', sel) |
|
1676 |
"/ ] ifFalse:[ |
|
1677 |
"/ Transcript showCR:(' compiled: ', aClass name,' ', sel) |
|
1678 |
"/ ] |
|
1679 |
"/ ]. |
|
86 | 1680 |
|
1681 |
^ newMethod |
|
239 | 1682 |
|
633 | 1683 |
"Created: / 22-07-2013 / 16:06:29 / cg" |
1055 | 1684 |
"Modified (comment): / 08-02-2019 / 11:25:27 / Claus Gittinger" |
86 | 1685 |
! ! |
1686 |
||
808 | 1687 |
!JavaScriptCompiler methodsFor:'initialization'! |
1688 |
||
1689 |
reset |
|
1690 |
"needed between functions, when reading multiple functions" |
|
1691 |
||
1692 |
usesSuper := false. |
|
1693 |
gotAnyRealStatement := false. |
|
1694 |
staticVars := nil. |
|
1695 |
moreSharedPools := nil. |
|
1696 |
modifiedVars := modifiedGlobals := modifiedInstVars := modifiedClassVars := nil. |
|
1697 |
usedVars := usedGlobals := usedInstVars := usedClassVars := nil. |
|
1698 |
currentEnvironment := nil. |
|
1699 |
inArrayLiteral := false. |
|
1700 |
collectedSource := nil. |
|
1701 |
currentComments := nil. |
|
1702 |
errorFlag := false. |
|
1703 |
||
1704 |
relocList := codeBytes := litArray := stackDelta := extraLiteral := maxStackDepth := nil. |
|
1705 |
methodTempVars := maxNumTemp := loopStack := nil. |
|
813 | 1706 |
|
922 | 1707 |
tokenPosition := outCol := 1. |
813 | 1708 |
tokenLineNr := lineNr := 1. |
808 | 1709 |
! ! |
1710 |
||
143 | 1711 |
!JavaScriptCompiler methodsFor:'loops'! |
1712 |
||
1713 |
loopDescription |
|
1714 |
loopStack isNil ifTrue:[^ nil]. |
|
1715 |
||
1716 |
^ loopStack last |
|
1717 |
! |
|
1718 |
||
1719 |
newLoopDescription |
|
1720 |
^ LoopDescription new |
|
1721 |
! |
|
1722 |
||
719 | 1723 |
newLoopDescriptionForBlock |
1724 |
^ LoopDescriptionForBlock new |
|
1725 |
! |
|
1726 |
||
143 | 1727 |
newSwitchDescription |
1728 |
^ SwitchDescription new |
|
1729 |
! |
|
1730 |
||
1731 |
popLoopDescription |
|
1732 |
^ loopStack removeFirst |
|
1733 |
! |
|
1734 |
||
1735 |
pushLoopDescription:aDescription |
|
1736 |
loopStack isNil ifTrue:[ |
|
818 | 1737 |
loopStack := OrderedCollection new. |
143 | 1738 |
]. |
1739 |
||
1740 |
loopStack addFirst:aDescription |
|
1741 |
! ! |
|
1742 |
||
922 | 1743 |
!JavaScriptCompiler methodsFor:'parsing'! |
1744 |
||
1745 |
compileFunctionDefinitions |
|
1746 |
|classToCompileForBefore| |
|
1747 |
||
1748 |
classToCompileForBefore := classToCompileFor. |
|
1749 |
||
1750 |
[ tokenType ~~ #EOF ] whileTrue:[ |
|
1059 | 1751 |
|cat mthd sourceString| |
1752 |
||
1753 |
outStream := WriteStream on:(String new:100). |
|
1754 |
"/ because the first token ('function') has already been read, |
|
1755 |
"/ we have to manually shift it into the source collecting stream (sigh) |
|
1756 |
outStream nextPutAll:self token. |
|
1757 |
self reset. |
|
1758 |
||
1759 |
classToCompileFor := classToCompileForBefore. |
|
1760 |
tree := self functionOrStaticFunction:false. |
|
1761 |
cat := self methodCategory. |
|
922 | 1762 |
|
1059 | 1763 |
"/ the collected source of this function |
1764 |
sourceString := outStream contents. |
|
922 | 1765 |
|
1059 | 1766 |
mthd := self |
1767 |
compileTree:tree source:sourceString |
|
1768 |
forClass:classToCompileFor inCategory:(cat ? 'no category') |
|
1769 |
notifying:nil |
|
1770 |
install:true |
|
1771 |
skipIfSame:false |
|
1772 |
silent:false |
|
1773 |
foldConstants:true. |
|
922 | 1774 |
|
1059 | 1775 |
token = $} ifTrue:[ |
1776 |
self nextToken. |
|
1777 |
]. |
|
922 | 1778 |
] |
1779 |
! ! |
|
1780 |
||
73 | 1781 |
!JavaScriptCompiler::LoopDescription methodsFor:'accessing'! |
1782 |
||
1783 |
breakLabel |
|
1784 |
"return the value of the instance variable 'breakLabel' (automatically generated)" |
|
1785 |
||
1786 |
^ breakLabel |
|
1787 |
! |
|
1788 |
||
1789 |
breakLabel:something |
|
1790 |
"set the value of the instance variable 'breakLabel' (automatically generated)" |
|
1791 |
||
1792 |
breakLabel := something. |
|
1793 |
! |
|
1794 |
||
1795 |
continueLabel |
|
1796 |
"return the value of the instance variable 'continueLabel' (automatically generated)" |
|
1797 |
||
1798 |
^ continueLabel |
|
1799 |
! |
|
1800 |
||
1801 |
continueLabel:something |
|
1802 |
"set the value of the instance variable 'continueLabel' (automatically generated)" |
|
1803 |
||
1804 |
continueLabel := something. |
|
143 | 1805 |
! ! |
1806 |
||
1807 |
!JavaScriptCompiler::LoopDescription methodsFor:'backpatching'! |
|
73 | 1808 |
|
1809 |
patchBreaksTo:breakPosition in:codeStream |
|
1810 |
|code| |
|
1811 |
||
1812 |
backPatchListForBreak isEmptyOrNil ifTrue:[^ self]. |
|
1813 |
||
1814 |
code := codeStream contents. |
|
1815 |
backPatchListForBreak do:[:eachPatchPos | |
|
818 | 1816 |
code at:eachPatchPos put:breakPosition |
73 | 1817 |
]. |
1818 |
! |
|
1819 |
||
77 | 1820 |
patchContinuesTo:continuePosition in:codeStream |
73 | 1821 |
|code| |
1822 |
||
1823 |
backPatchListForContinue isEmptyOrNil ifTrue:[^ self]. |
|
77 | 1824 |
|
73 | 1825 |
code := codeStream contents. |
77 | 1826 |
backPatchListForContinue do:[:eachPatchPos | |
818 | 1827 |
code at:eachPatchPos put:continuePosition |
73 | 1828 |
]. |
1829 |
! |
|
1830 |
||
1831 |
rememberToBackPatchForBreak:position |
|
1832 |
backPatchListForBreak isNil ifTrue:[ |
|
818 | 1833 |
backPatchListForBreak := OrderedCollection new |
73 | 1834 |
]. |
1835 |
backPatchListForBreak add:position |
|
1836 |
! |
|
1837 |
||
1838 |
rememberToBackPatchForContinue:position |
|
1839 |
backPatchListForContinue isNil ifTrue:[ |
|
818 | 1840 |
backPatchListForContinue := OrderedCollection new |
73 | 1841 |
]. |
1842 |
backPatchListForContinue add:position |
|
1843 |
! ! |
|
1844 |
||
719 | 1845 |
!JavaScriptCompiler::LoopDescription methodsFor:'code generation'! |
1846 |
||
726 | 1847 |
codeForBreakOn:aStream at:lineNr for:aCompiler |
719 | 1848 |
|jmpDeltaPos| |
1849 |
||
1850 |
breakLabel notNil ifTrue:[ |
|
818 | 1851 |
aStream nextPut:#jump. |
1852 |
aStream nextPut:breakLabel. |
|
719 | 1853 |
] ifFalse:[ |
818 | 1854 |
aStream nextPut:#jump. |
1855 |
jmpDeltaPos := aStream position + 1. |
|
1856 |
aStream nextPut:0. |
|
1857 |
self rememberToBackPatchForBreak:jmpDeltaPos. |
|
719 | 1858 |
]. |
726 | 1859 |
|
1860 |
"Created: / 06-11-2013 / 21:18:36 / cg" |
|
719 | 1861 |
! |
1862 |
||
726 | 1863 |
codeForContinueOn:aStream at:lineNr for:aCompiler |
719 | 1864 |
|jmpDeltaPos| |
1865 |
||
1866 |
continueLabel notNil ifTrue:[ |
|
818 | 1867 |
aStream nextPut:#jump. |
1868 |
aStream nextPut:continueLabel. |
|
719 | 1869 |
] ifFalse:[ |
818 | 1870 |
aStream nextPut:#jump. |
1871 |
jmpDeltaPos := aStream position + 1. |
|
1872 |
aStream nextPut:0. |
|
1873 |
self rememberToBackPatchForContinue:jmpDeltaPos. |
|
719 | 1874 |
]. |
726 | 1875 |
|
1876 |
"Created: / 06-11-2013 / 21:19:27 / cg" |
|
719 | 1877 |
! ! |
1878 |
||
143 | 1879 |
!JavaScriptCompiler::LoopDescription methodsFor:'queries'! |
1880 |
||
1881 |
isLoop |
|
1882 |
^ true |
|
1883 |
! ! |
|
1884 |
||
726 | 1885 |
!JavaScriptCompiler::LoopDescriptionForBlock methodsFor:'accessing'! |
1886 |
||
1887 |
deltaScope |
|
1888 |
^ deltaScope ? 1 |
|
1889 |
||
1890 |
"Created: / 06-11-2013 / 20:34:51 / cg" |
|
1891 |
! |
|
1892 |
||
1893 |
deltaScope:something |
|
1894 |
deltaScope := something. |
|
1895 |
! ! |
|
1896 |
||
719 | 1897 |
!JavaScriptCompiler::LoopDescriptionForBlock methodsFor:'code generation'! |
1898 |
||
726 | 1899 |
codeForBreakOn:aStream at:lineNr for:aCompiler |
719 | 1900 |
|thisContextVar node| |
1901 |
||
1902 |
thisContextVar := VariableNode type:#ThisContext name:#thisContext. |
|
1903 |
node := MessageNode |
|
818 | 1904 |
receiver:thisContextVar |
1905 |
selector:#sender |
|
1906 |
args:#(). |
|
726 | 1907 |
node lineNumber:lineNr. |
1908 |
self deltaScope timesRepeat:[ |
|
818 | 1909 |
node := MessageNode |
1910 |
receiver:node |
|
1911 |
selector:#sender |
|
1912 |
args:#(). |
|
1913 |
node lineNumber:lineNr. |
|
726 | 1914 |
]. |
719 | 1915 |
node := MessageNode |
818 | 1916 |
receiver:node |
1917 |
selector:#return |
|
1918 |
args:#(). |
|
726 | 1919 |
node lineNumber:lineNr. |
719 | 1920 |
node codeForSideEffectOn:aStream inBlock:nil for:aCompiler. |
726 | 1921 |
|
1922 |
"Created: / 06-11-2013 / 21:18:31 / cg" |
|
719 | 1923 |
! |
1924 |
||
726 | 1925 |
codeForContinueOn:aStream at:lineNr for:aCompiler |
719 | 1926 |
|thisContextVar node| |
1927 |
||
1928 |
thisContextVar := VariableNode type:#ThisContext name:#thisContext. |
|
1929 |
node := MessageNode |
|
818 | 1930 |
receiver:thisContextVar |
1931 |
selector:#return |
|
1932 |
args:#(). |
|
719 | 1933 |
"/ node lineNumber:lineNr. |
1934 |
node codeForSideEffectOn:aStream inBlock:nil for:aCompiler. |
|
726 | 1935 |
|
1936 |
"Created: / 06-11-2013 / 21:19:21 / cg" |
|
719 | 1937 |
! ! |
1938 |
||
1939 |
!JavaScriptCompiler::LoopDescriptionForBlock methodsFor:'queries'! |
|
1940 |
||
1941 |
isLoop |
|
1942 |
^ true |
|
1943 |
! ! |
|
1944 |
||
143 | 1945 |
!JavaScriptCompiler::SwitchDescription methodsFor:'backpatching'! |
1946 |
||
1947 |
rememberToBackPatchForContinue:position |
|
1948 |
self error:'invalid continue in switch' |
|
1949 |
! ! |
|
1950 |
||
719 | 1951 |
!JavaScriptCompiler::SwitchDescription methodsFor:'code generation'! |
1952 |
||
726 | 1953 |
codeForContinueOn:aStream at:lineNr for:aCompiler |
719 | 1954 |
aCompiler parseError:'continue not within a loop (continue in switch not allowed)'. |
726 | 1955 |
|
1956 |
"Created: / 06-11-2013 / 21:19:10 / cg" |
|
719 | 1957 |
! ! |
1958 |
||
143 | 1959 |
!JavaScriptCompiler::SwitchDescription methodsFor:'queries'! |
1960 |
||
1961 |
isLoop |
|
1962 |
^ false |
|
1963 |
! ! |
|
1964 |
||
37 | 1965 |
!JavaScriptCompiler class methodsFor:'documentation'! |
1966 |
||
1967 |
version |
|
1968 |
^ '$Header$' |
|
396 | 1969 |
! |
1970 |
||
1971 |
version_CVS |
|
1972 |
^ '$Header$' |
|
37 | 1973 |
! ! |
1095 | 1974 |