-
Notifications
You must be signed in to change notification settings - Fork 65
/
EncoderForNewsqueakV4.class.st
1288 lines (1162 loc) · 53.7 KB
/
EncoderForNewsqueakV4.class.st
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
"
EncoderForNewsqueakV4 encodes a bytecode set for Squeak and Newspeak that lifts limits on number of literals and branch distances, has a single bytecode for send to implicit receiver and extended push integer and push character bytecodes. Byteodes are ordered by length to make decoding easier. Bytecodes marked with an * are extensible via a prefix bytecode.
N.B. Extension bytecodes can only come before extensible bytecodes, and only if valid (one cannot extend a bytecode extensible by Ext A with an Ext B). An extensible bytecode consumes (and zeros) its extension(s). Hence the hidden implicit variables holding extensions are always zero except after a valid sequence of extension bytecodes.
1 Byte Bytecodes
0-15 0000 i i i i Push Receiver Variable #iiii
16-31 0001 i i i i Push Literal Variable #iiii
32-63 001 i i i i i Push Literal #iiiii
64-71 01000 i i i Push Temporary Variable #iii
72-75 010010 i i Push Temporary Variable #ii + 8
76 01001100 Push Receiver
* 77 01001101 Push false [* 1:true, 2:nil, 3:thisContext, ..., -N: pushExplicitOuter: N, N = Extend B]
78 01001110 Push 0
79 01001111 Push 1
80-95 0101 i i i i Send Arithmetic Message #iiii
96-111 0110 i i i i Send Special Message #iiii
112-127 0111 i i i i Send Literal Selector #iiii With 0 Arguments
128-143 1000 i i i i Send Literal Selector #iiii With 1 Argument
144-159 1001 i i i i Send Literal Selector #iiii With 2 Arguments
160-175 1010 i i i i Send To Absent Implicit Receiver Literal Selector #iiii With 0 Arguments
176-183 10110 i i i Pop and Store Receiver Variable #iii
184-191 10111 i i i Pop and Store Temporary Variable #iii
192-199 11000 i i i Jump iii + 1 (i.e., 1 through 8)
200-207 11001 i i i Pop and Jump 0n True iii +1 (i.e., 1 through 8)
208-215 11010 i i i Pop and Jump 0n False iii +1 (i.e., 1 through 8)
216 11011000 Return Receiver From Message
217 11011001 Return Stack Top From Message
* 218 11011010 Return Stack Top From Block [* return from enclosing block N, N = Extend A]
219 11011011 Duplicate Stack Top
220 11011100 Pop Stack Top
* 221 11011101 Nop
222 11011110 break ? could have blockCopy: send break, but need pushReceiver & pop result
223 11011111 UNASSIGNED
2 Byte Bytecodes
* 224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
* 225 11100001 sbbbbbbb Extend B (Ext B = Ext B prev * 256 + Ext B)
* 226 11100010 i i i i i i i i Push Receiver Variable #iiiiiiii (+ Extend A * 256)
* 227 11100011 i i i i i i i i Push Literal Variable #iiiiiiii (+ Extend A * 256)
* 228 11100100 i i i i i i i i Push Literal #iiiiiiii (+ Extend A * 256)
* 229 11100101 i i i i i i i i Push Integer #iiiiiiii (+ Extend B * 256, where bbbbbbbb = sddddddd, e.g. -32768 = i=0, a=0, s=1)
230 11100110 i i i i i i i i Push Temporary Variable #iiiiiiii
231 11100111 jkkkkkkk Push (Array new: kkkkkkk) (j = 0)
& Pop kkkkkkk elements into: (Array new: kkkkkkk) (j = 1)
* 232 11101000 i i i i i i i i Store Receiver Variable #iiiiiii (+ Extend A * 256)
* 233 11101001 i i i i i i i i Store Literal Variable #iiiiiiii (+ Extend A * 256)
234 11101010 i i i i i i i i Store Temporary Variable #iiiiiiii
* 235 11101011 i i i i i i i i Pop and Store Receiver Variable #iiiiiii (+ Extend A * 256)
* 236 11101100 i i i i i i i i Pop and Store Literal Variable #iiiiiiii (+ Extend A * 256)
237 11101101 i i i i i i i i Pop and Store Temporary Variable #iiiiiiii
** 238 11101110 i i i i i j j j Send Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
** 239 11101111 i i i i i j j j Send To Superclass Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
** 240 11110000 i i i i i j j j Send To Absent Implicit Receiver Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
** 241 11110001 i i i i i j j j Send To Absent Dynamic Superclass Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
* 242 11110010 i i i i i i i i Jump i i i i i i i i (+ Extend B * 256, where bbbbbbbb = sddddddd, e.g. -32768 = i=0, a=0, s=1)
* 243 11110011 i i i i i i i i Pop and Jump 0n True i i i i i i i i (+ Extend B * 256, where Extend B >= 0)
* 244 11110100 i i i i i i i i Pop and Jump 0n False i i i i i i i i (+ Extend B * 256, where Extend B >= 0)
245 11110101 xxxxxxxx UNASSIGNED
246-247 1111011 i xxxxxxxx UNASSIGNED
248 11111000 xxxxxxxx UNASSIGNED
3 Byte Bytecodes
249 11111001 i i i i i i i i jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256)
250 11111010 kkkkkkkk jjjjjjjj Push Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
251 11111011 kkkkkkkk jjjjjjjj Store Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
252 11111100 kkkkkkkk jjjjjjjj Pop and Store Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
** 253 11111101 eei i i kkk jjjjjjjj Push Closure Num Copied iii (+ Ext A // 16 * 8) Num Args kkk (+ Ext A \\ 16 * 8) BlockSize jjjjjjjj (+ Ext B * 256). ee = num extensions
254-255 1111111 i xxxxxxxx yyyyyyyy UNASSIGNED
"
Class {
#name : #EncoderForNewsqueakV4,
#superclass : #BytecodeEncoder,
#category : #'BytecodeSets-NewsqueakV4'
}
{ #category : #'compiled method support' }
EncoderForNewsqueakV4 class >> bindingReadScanBlockFor: litVarIndex using: scanner [
"Answer a block argument for InstructionStream>>scanFor: that answers true
for reads of the value of the binding with zero-relative index litVarIndex.
N.B. Don't assume the compiler uses the most compact encoding available."
" 16-31 0001 i i i i Push Literal Variable #iiii
* 224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
* 227 11100011 i i i i i i i i Push Literal Variable #iiiiiiii (+ Extend A * 256)"
| extension |
extension := 0.
^[:b| | prevext |
prevext := extension.
extension := b = 224 ifTrue: [scanner followingByte bitShift: 8] ifFalse: [0].
(b < 32 and: [b >= 16 and: [b - 16 = litVarIndex]])
or: [b = 227
and: [scanner followingByte + prevext = litVarIndex]]]
]
{ #category : #'compiled method support' }
EncoderForNewsqueakV4 class >> bindingWriteScanBlockFor: litVarIndex using: scanner [
"Answer a block argument for InstructionStream>>scanFor: that answers true
for writes of the value of the binding with zero-relative index litVarIndex.
N.B. Don't assume the compiler uses the most compact encoding available."
"* 224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
* 233 11101001 i i i i i i i i Store Literal Variable #iiiiiiii (+ Extend A * 256)
* 236 11101100 i i i i i i i i Pop and Store Literal Variable #iiiiiiii (+ Extend A * 256)"
| extension |
extension := 0.
^[:b| | prevext |
prevext := extension.
extension := b = 224 ifTrue: [scanner followingByte bitShift: 8] ifFalse: [0].
(b = 233 or: [b = 236])
and: [scanner followingByte + prevext = litVarIndex]]
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> bytecodeSize: bytecode [
"Answer the number of bytes in the bytecode."
bytecode < 224 ifTrue: [^1].
bytecode < 249 ifTrue: [^2].
^3
]
{ #category : #'bytecode decoding' }
EncoderForNewsqueakV4 class >> callPrimitiveCode [
"Answer the call primitive bytecode, if it exists in the encoder's bytecode set, or nil if not.
249 11111001 i i i i i i i i jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256)"
^249
]
{ #category : #'compiled method support' }
EncoderForNewsqueakV4 class >> createClosureScanBlock [
"Answer a block argument for InstructionStream>>scanFor: that answers true
for block closure creation bytecodes. ote that with this interface we can't answer
true for the extension in front of a push closure bytecode and so the interface may
have to change at some point."
"* 224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
* 225 11100001 sbbbbbbb Extend B (Ext B = Ext B prev * 256 + Ext B)
** 253 11111101 eei i i kkk jjjjjjjj Push Closure Num Copied iii (+ Ext A // 16 * 8) Num Args kkk (+ Ext A \\ 16 * 8) BlockSize jjjjjjjj (+ Ext B * 256). ee = num extensions"
^[:b| b = 253]
]
{ #category : #'compiled method support' }
EncoderForNewsqueakV4 class >> extensionsAt: bcpc in: method into: aTrinaryBlock [
"If the bytecode at pc is an extension then evaluate aBinaryBlock with the values of extA and extB and number of extension *bytes*.
If the bytecode at pc is not extended then evaluate aBinaryBlock with 0 and 0.
224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
225 11100001 sbbbbbbb Extend B (Ext B = Ext B prev * 256 + Ext B)"
| scanpc byte extByte extA extB |
scanpc := bcpc.
"There may be an extension (it could be a false positive). We must scan as fast as possible..."
extA := extB := 0.
[byte := method at: scanpc.
byte >= 224 and: [byte <= 225]] whileTrue:
[extByte := method at: scanpc + 1.
scanpc := scanpc + 2.
byte = 224
ifTrue:
[extA := (extA bitShift: 8) + extByte]
ifFalse:
[extB := (extB = 0 and: [extByte > 127])
ifTrue: [extByte - 256]
ifFalse: [(extB bitShift: 8) + extByte]]].
^aTrinaryBlock value: extA value: extB value: scanpc - bcpc
"Why use
byte >= 224 and: [byte <= 225]
and not
(byte bitAnd: 16rFE) = 16rE0
?
| n |
n := 100000000.
#(0 224) collect:
[:byte|
{ Time millisecondsToRun: [1 to: n do: [:i| (byte >= 224 and: [byte <= 225]) ifTrue: []]].
Time millisecondsToRun: [1 to: n do: [:i| (byte bitAnd: 16rFE) = 16rE0 ifTrue: []]] }] #(#(297 599) #(702 671))"
]
{ #category : #'compiled method support' }
EncoderForNewsqueakV4 class >> instVarReadScanBlockFor: varIndexCode using: scanner [
"Answer a block argument for InstructionStream>>scanFor: that answers true
for reads of the inst var with zero-relative index varIndexCode.
N.B. Don't assume the compiler uses the most compact encoding available."
" 0-15 0000 i i i i Push Receiver Variable #iiii
* 224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
* 226 11100010 i i i i i i i i Push Receiver Variable #iiiiiiii (+ Extend A * 256)"
| extension |
extension := 0.
^[:b| | prevext |
prevext := extension.
extension := b = 224 ifTrue: [scanner followingByte bitShift: 8] ifFalse: [0].
(b < 16 and: [b = varIndexCode])
or: [b = 226
and: [scanner followingByte + prevext = varIndexCode]]]
]
{ #category : #'compiled method support' }
EncoderForNewsqueakV4 class >> instVarWriteScanBlockFor: varIndexCode using: scanner [
"Answer a block argument for InstructionStream>>scanFor: that answers true
for writes of the inst var with zero-relative index varIndexCode.
N.B. Don't assume the compiler uses the most compact encoding available."
" 176-183 10110 i i i Pop and Store Receiver Variable #iii
* 224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
* 232 11101000 i i i i i i i i Store Receiver Variable #iiiiiii (+ Extend A * 256)
* 235 11101011 i i i i i i i i Pop and Store Receiver Variable #iiiiiii (+ Extend A * 256)"
| extension |
extension := 0.
^[:b| | prevext |
prevext := extension.
extension := b = 224 ifTrue: [scanner followingByte bitShift: 8] ifFalse: [0].
(b >= 176
and: [b < 184
and: [b - 176 = varIndexCode]])
or: [(b = 232 or: [b = 235])
and: [scanner followingByte + prevext = varIndexCode]]]
]
{ #category : #'compiled method support' }
EncoderForNewsqueakV4 class >> interpretJumpIfCondIn: anInstructionStream [
"Double-dispatch through the encoder to select the correct conditional jump decoder for the instruction set."
^anInstructionStream interpretNSV4JumpIfCond
]
{ #category : #'compiled method support' }
EncoderForNewsqueakV4 class >> interpretJumpIn: anInstructionStream [
"Double-dispatch through the encoder to select the correct unconditional jump decoder for the instruction set."
^anInstructionStream interpretNSV4Jump
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> interpretNextInstructionFor: aClient in: anInstructionStream [
"Double-dispatch through the encoder to select the correct instruction set decoder."
^anInstructionStream interpretNextNSV4InstructionFor: aClient
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> isBlockReturnAt: pc in: method [
"Answer whether the bytecode at pc is a return from block."
"218 11011010 Return Stack Top From Block [* return from enclosing block N, N = Extend A]"
^(self nonExtensionBytecodeAt: pc in: method) = 218
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> isBranchIfFalseAt: pc in: method [
"Answer whether the bytecode at pc is a conditional branch-if-false."
" 208-215 11010 i i i Pop and Jump 0n False iii +1 (i.e., 1 through 8)
* 244 11110100 i i i i i i i i Pop and Jump 0n False i i i i i i i i (+ Extend B * 256, where Extend B >= 0)"
| byte |
byte := self nonExtensionBytecodeAt: pc in: method.
^byte >= 208 and: [byte <= 215 or: [byte = 244]]
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> isBranchIfTrueAt: pc in: method [
"Answer whether the bytecode at pc is a conditional branch-if-true."
" 200-207 11001 i i i Pop and Jump 0n True iii +1 (i.e., 1 through 8)
* 243 11110011 i i i i i i i i Pop and Jump 0n True i i i i i i i i (+ Extend B * 256, where Extend B >= 0)"
| byte |
byte := self nonExtensionBytecodeAt: pc in: method.
^byte >= 200 and: [byte <= 207 or: [byte = 243]]
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> isExtension: bytecode [
"Answer if the bytecode is an extension bytecode, i.e. one that extends
the range of the following bytecode."
^bytecode >= 16rE0 and: [bytecode <= 16rE1]
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> isJumpAt: pc in: method [
"Answer whether the bytecode at pc is an (unconditional) jump."
" 192-199 11000 i i i Jump iii + 1 (i.e., 1 through 8)
* 225 11100001 sbbbbbbb Extend B (Ext B = Ext B prev * 256 + Ext B)
* 242 11110010 i i i i i i i i Jump i i i i i i i i (+ Extend B * 256, where bbbbbbbb = sddddddd, e.g. -32768 = i=0, a=0, s=1)"
| byte |
byte := self nonExtensionBytecodeAt: pc in: method.
^byte >= 192 and: [byte <= 199 or: [byte = 242]]
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> isJustPopAt: pc in: method [
"Answer whether the bytecode at pc is a pop."
^(method at: pc) = 220 "220 11011100 Pop Stack Top"
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> isRealSendAt: pc in: method [
"Answer whether the bytecode at pc is a real message-send, not blockCopy:."
^self isSendAt: pc in: method
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> isReturnAt: pc in: method [
"Answer whether the bytecode at pc is a return from block."
"216 11011000 Return Receiver From Message
217 11011001 Return Stack Top From Message
218 11011010 Return Stack Top From Block [* return from enclosing block N, N = Extend A]"
^(self nonExtensionBytecodeAt: pc in: method) between: 216 and: 218
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> isReturnTopFromMethodAt: pc in: method [
"Answer whether the bytecode at pc is a return stack top from method."
^(method at: pc) = 217
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> isSendAt: pc in: method [
"Answer whether the bytecode at pc is a message-send."
" 80-95 0101 i i i i Send Arithmetic Message #iiii
96-111 0110 i i i i Send Special Message #iiii
112-127 0111 i i i i Send Literal Selector #iiii With 0 Arguments
128-143 1000 i i i i Send Literal Selector #iiii With 1 Argument
144-159 1001 i i i i Send Literal Selector #iiii With 2 Arguments
160-175 1010 i i i i Send To Absent Implicit Receiver Literal Selector #iiii With 0 Arguments
* 224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
* 225 11100001 sbbbbbbb Extend B (Ext B = Ext B prev * 256 + Ext B)
** 238 11101110 i i i i i j j j Send Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
** 239 11101111 i i i i i j j j Send To Superclass Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
** 240 11110000 i i i i i j j j Send To Absent Implicit Receiver Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
** 241 11110001 i i i i i j j j Send To Absent Dynamic Superclass Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
** 245 11110101 i i i i i j j j Send To Absent Self Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
** 254 11111110 i i i i i j j j kkkkkkkk Send To Absent Outer Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments Depth kkkkkkkk"
| byte |
byte := self nonExtensionBytecodeAt: pc in: method.
^(((byte >= 80 and: [byte <= 175])
or: [byte <= 241 and: [byte >= 238]])
or: [byte == 245] or: [byte == 254])
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> isStoreAt: pc in: method [
"Answer whether the bytecode at pc is a store or store-pop."
" 176-183 10110 i i i Pop and Store Receiver Variable #iii
184-191 10111 i i i Pop and Store Temporary Variable #iii
* 224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
* 232 11101000 i i i i i i i i Store Receiver Variable #iiiiiii (+ Extend A * 256)
* 233 11101001 i i i i i i i i Store Literal Variable #iiiiiiii (+ Extend A * 256)
234 11101010 i i i i i i i i Store Temporary Variable #iiiiiiii
* 235 11101011 i i i i i i i i Pop and Store Receiver Variable #iiiiiii (+ Extend A * 256)
* 236 11101100 i i i i i i i i Pop and Store Literal Variable #iiiiiiii (+ Extend A * 256)
237 11101101 i i i i i i i i Pop and Store Temporary Variable #iiiiiiii
251 11111011 kkkkkkkk jjjjjjjj Store Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
252 11111100 kkkkkkkk jjjjjjjj Pop and Store Temp At kkkkkkkk In Temp Vector At: jjjjjjjj"
| byte |
byte := self nonExtensionBytecodeAt: pc in: method.
^byte >= 176
and: [byte <= 191
or: [(byte between: 232 and: 237)
or: [(byte between: 251 and: 252)]]]
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> isStorePopAt: pc in: method [
"Answer whether the bytecode at pc is a store-pop."
" 176-183 10110 i i i Pop and Store Receiver Variable #iii
184-191 10111 i i i Pop and Store Temporary Variable #iii
* 224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
* 235 11101011 i i i i i i i i Pop and Store Receiver Variable #iiiiiii (+ Extend A * 256)
* 236 11101100 i i i i i i i i Pop and Store Literal Variable #iiiiiiii (+ Extend A * 256)
237 11101101 i i i i i i i i Pop and Store Temporary Variable #iiiiiiii
252 11111100 kkkkkkkk jjjjjjjj Pop and Store Temp At kkkkkkkk In Temp Vector At: jjjjjjjj"
| byte |
byte := self nonExtensionBytecodeAt: pc in: method.
^byte >= 176
and: [byte <= 191
or: [(byte between: 235 and: 237)
or: [byte = 252]]]
]
{ #category : #scanning }
EncoderForNewsqueakV4 class >> method: method refersInBytecodeToLiteral: aLiteral specialSelectorIndex: specialOrNil [
"Answer if method refers to the literal aLiteral in the bytecode, as opposed to in its literal frame."
"* 77 01001101 Push false [* 1:true, 2:nil, 3:thisContext, ..., -N: pushExplicitOuter: N, N = Extend B]
78 01001110 Push 0
79 01001111 Push 1
80-95 0101 i i i i Send Arithmetic Message #iiii
96-111 0110 i i i i Send Special Message #iiii
* 225 11100001 sbbbbbbb Extend B (Ext B = Ext B prev * 256 + Ext B)
* 229 11100101 i i i i i i i i Push Integer #iiiiiiii (+ Extend B * 256, where bbbbbbbb = sddddddd, e.g. -32768 = i=0, a=0, s=1)"
| byte extended scanner |
specialOrNil ifNotNil:
[byte := specialOrNil + 79.
^(InstructionStream on: method) scanFor: [:b| b = byte]].
extended := false.
aLiteral isInteger ifTrue:
[(aLiteral >= -32768 and: [aLiteral <= 32767]) ifFalse: [^false].
scanner := InstructionStream on: method.
(aLiteral >= 0 and: [aLiteral <= 255]) ifTrue:
[aLiteral <= 1 ifTrue:
[byte := aLiteral + 80.
^scanner scanFor: [:b| b = byte]].
^scanner scanFor:
[:b|
(b = 229
and: [extended not
and: [scanner followingByte = aLiteral]])
or: [extended := b = 225.
false]]].
byte := (aLiteral bitShift: -8) bitAnd: 255.
^scanner scanFor:
[:b|
(b = 229
and: [extended
and: [scanner followingByte = (aLiteral bitAnd: 255)]])
or: [extended := b = 225 and: [scanner followingByte = byte].
false]]].
byte := #(false true nil) identityIndexOf: aLiteral ifAbsent: 0.
byte = 0 ifTrue:
[^false].
scanner := InstructionStream on: method.
byte = 1 ifTrue:
[^scanner scanFor:
[:b|
(b = 77
and: [extended not])
or: [extended := b = 225.
false]]].
byte := byte - 1.
^scanner scanFor:
[:b|
(b = 77
and: [extended])
or: [extended := b = 225 and: [scanner followingByte = byte].
false]]
]
{ #category : #scanning }
EncoderForNewsqueakV4 class >> method: method writesField: varIndex [
"Answer if method stores into the instance variable indexed by varIndex.
N.B. Don't assume the compiler uses the most compact encoding available.
176-183 10110 i i i Pop and Store Receiver Variable #iii
* 224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
* 232 11101000 i i i i i i i i Store Receiver Variable #iiiiiii (+ Extend A * 256)
* 235 11101011 i i i i i i i i Pop and Store Receiver Variable #iiiiiii (+ Extend A * 256)"
| varIndexCode scanner extension |
method isQuick ifTrue: [^false].
varIndexCode := varIndex - 1.
extension := 0.
^(scanner := InstructionStream on: method) scanFor:
[:b| | prevext |
prevext := extension.
extension := b = 224 ifTrue: [scanner followingByte bitShift: 8] ifFalse: [0].
b >= 176
and: [b - 176 = varIndexCode
or: [(b = 232 or: [b = 235])
and: [scanner followingByte + prevext = varIndexCode]]]]
]
{ #category : #'bytecode decoding' }
EncoderForNewsqueakV4 class >> pcOfBlockCreationBytecodeForBlockStartingAt: startpc in: method [
"Answer the pc of the push closure bytecode whose block starts at startpc in method.
May need to back up to include extension bytecodes.
253 11111101 eei i i kkk jjjjjjjj Push Closure Num Copied iii (+ Ext A // 16 * 8) Num Args kkk (+ Ext A \\ 16 * 8) BlockSize jjjjjjjj (+ Ext B * 256). ee = num extensions"
| numExtensions |
self assert: (method at: startpc - 3) = 253.
numExtensions := (method at: startpc - 2) >> 6.
^startpc - 3 - (numExtensions * 2)
]
{ #category : #'bytecode decoding' }
EncoderForNewsqueakV4 class >> pushClosureBytecodeSize [
"Answer the size of the push closure bytecode.
253 11111101 eei i i kkk jjjjjjjj Push Closure Num Copied iii (+ Ext A // 16 * 8) Num Args kkk (+ Ext A \\ 16 * 8) BlockSize jjjjjjjj (+ Ext B * 256). ee = num extensions"
^3
]
{ #category : #scanning }
EncoderForNewsqueakV4 class >> scanBlockOrNilForLiteral: aLiteral [
"Answer a block argument for CompiledMethod>>#scanFor: that answers
if the method refers to the literal implicitly via a special bytecode.
If the literal is not accessible via a special bytecode, answer nil."
| value |
"80-95 0101 i i i i Send Arithmetic Message #iiii
96-111 0110 i i i i Send Special Message #iiii"
aLiteral isSymbol ifTrue:
[value := 80 + ((Smalltalk specialSelectors indexOf: aLiteral ifAbsent: [^nil]) // 2).
^[:byte| byte = value]].
"78 01001110 Push 0
79 01001111 Push 1"
aLiteral isInteger ifTrue:
[(aLiteral between: 0 and: 1) ifFalse: [^nil].
value := aLiteral + 78.
^[:byte| byte = value]].
"77 01001101 Push false [* 1:true, 2:nil, 3:thisContext, ..., -N: pushExplicitOuter: N, N = Extend B]"
aLiteral == false ifTrue:
[^[:byte| byte = 77]].
aLiteral == true ifTrue:
[^[:b1 :b2 :b3| b1 = 16rE1 and: [b2 = 1 and: [b3 = 77]]]].
aLiteral == nil ifTrue:
[^[:b1 :b2 :b3| b1 = 16rE1 and: [b2 = 2 and: [b3 = 77]]]].
^nil
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> selectorToSendOrItselfFor: anInstructionStream in: method at: pc [
"If anInstructionStream is at a send bytecode then answer the send's selector,
otherwise answer anInstructionStream itself. The rationale for answering
anInstructionStream instead of, say, nil, is that potentially any existing object
can be used as a selector, but since anInstructionStream postdates the method,
it can't be one of them.
The compilcation is that for convenience we assume the pc could be
pointing to the raw send bytecode after its extensions, or at the extension
preceeding the raw send bytecode.
80-95 0101 i i i i Send Arithmetic Message #iiii
96-111 0110 i i i i Send Special Message #iiii
112-127 0111 i i i i Send Literal Selector #iiii With 0 Arguments
128-143 1000 i i i i Send Literal Selector #iiii With 1 Argument
144-159 1001 i i i i Send Literal Selector #iiii With 2 Arguments
160-175 1010 i i i i Send To Absent Implicit Receiver Literal Selector #iiii With 0 Arguments
224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
225 11100001 sbbbbbbb Extend B (Ext B = Ext B prev * 256 + Ext B)
238 11101110 i i i i i j j j Send Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
239 11101111 i i i i i j j j Send To Superclass Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
240 11110000 i i i i i j j j Send To Absent Implicit Receiver Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
241 11110001 i i i i i j j j Send To Absent Dynamic Superclass Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
245 11110101 i i i i i j j j Send To Absent Self Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
254 11111110 i i i i i j j j kkkkkkkk Send To Absent Outer Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments Depth kkkkkkkk"
| byte |
byte := method at: pc.
byte < 80 ifTrue:
[^anInstructionStream].
byte <= 175 ifTrue:
["special byte or short send"
^byte >= 112
ifTrue: [method literalAt: (byte bitAnd: 15) + 1]
ifFalse: [Smalltalk specialSelectorAt: byte - 79]].
byte < 238 ifTrue:
[(byte >= 224 and: [byte <= 225]) ifTrue:
[^self extensionsAt: pc in: method into:
[:extA :extB :nExtBytes| | byteAfter index |
byteAfter := method at: pc + nExtBytes.
(byteAfter >= 238 and: [byteAfter <= 241])
ifTrue:
[index := ((method at: pc + nExtBytes + 1) bitShift: -3) + (extA bitShift: 5).
method literalAt: index + 1]
ifFalse: [anInstructionStream]]].
^anInstructionStream].
(byte <= 241 or: [byte == 245 or: [byte == 254]])
ifFalse: [^anInstructionStream].
"they could be extended..."
^self extensionsFor: pc in: method into:
[:extA :extB :nExtBytes| | index |
index := ((method at: pc + 1) bitShift: -3) + (extA bitShift: 5).
method literalAt: index + 1]
]
{ #category : #'instruction stream support' }
EncoderForNewsqueakV4 class >> superSendScanBlockUsing: scanner [
"Answer a block argument for InstructionStream>>scanFor:
that answers true for super sends."
"* 224 11100000 aaaaaaaa Extend A (Ext A = Ext A prev * 256 + Ext A)
* 225 11100001 sbbbbbbb Extend B (Ext B = Ext B prev * 256 + Ext B)
** 239 11101111 i i i i i j j j Send To Superclass Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments
** 241 11110001 i i i i i j j j Send To Absent Dynamic Superclass Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"
^[:instr | instr = 239 or: [instr = 241]]
]
{ #category : #'compiled method support' }
EncoderForNewsqueakV4 class >> supportsClosures [
"Answer if the instruction set supports closures (contains
closure creation and indirect temp access bytecodes)."
^true
]
{ #category : #'bytecode decoding' }
EncoderForNewsqueakV4 class >> unusedBytecode [
"Answer the opcode of a single-byte unused bytecode, if it exists in the encoder's bytecode set, or nil if not."
^223
]
{ #category : #'method encoding' }
EncoderForNewsqueakV4 >> computeMethodHeaderForNumArgs: numArgs numTemps: numTemps numLits: numLits primitive: primitiveIndex accessModifier: accessModifier [
numArgs > 15 ifTrue:
[^self error: 'Cannot compile -- too many arguments'].
numTemps > 63 ifTrue:
[^self error: 'Cannot compile -- too many temporary variables'].
numLits > 65535 ifTrue:
[^self error: 'Cannot compile -- too many literals'].
^(CompiledMethod headerFlagForEncoder: self)
+ (accessModifier = #protected ifTrue: [1 bitShift: 29] ifFalse: [0])
+ (accessModifier = #private ifTrue: [1 bitShift: 28] ifFalse: [0])
+ (numArgs bitShift: 24)
+ (numTemps bitShift: 18)
"+ (largeBit bitShift: 17)" "largeBit gets filled in later"
+ (primitiveIndex > 0 ifTrue: [1 bitShift: 16] ifFalse: [0])
+ numLits
]
{ #category : #encoding }
EncoderForNewsqueakV4 >> encodeLiteral: object [
| literal |
literal := class literalScannedAs: object notifying: self.
^(self isSpecialLiteral: literal)
ifTrue:
[SpecialLiteralNode new
name: object
key: literal
index: nil
type: LdLitType]
ifFalse:
[self
name: object
key: literal
class: LiteralNode
type: LdLitType
set: litSet]
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genBranchPopFalse: distance [
(distance > 0 and: [distance < 9]) ifTrue:
["208-215 11010 i i i Pop and Jump 0n False iii +1 (i.e., 1 through 8)"
stream nextPut: 207 + distance.
^self].
^self genBranchPopFalseLong: distance
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genBranchPopFalseLong: distance [
"244 11110100 i i i i i i i i Pop and Jump 0n False i i i i i i i i (+ Extend B * 256)"
| distanceMod256 |
(distance < 0 or: [distance > 32767]) ifTrue:
[^self outOfRangeError: 'distance' index: distance range: 0 to: 32767].
distanceMod256 := (distance < 0 or: [distance > 255])
ifTrue:
[self genUnsignedSingleExtendB: (distance bitShift: -8).
distance bitAnd: 255]
ifFalse: [distance].
stream
nextPut: 244;
nextPut: distanceMod256
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genBranchPopTrue: distance [
(distance > 0 and: [distance < 9]) ifTrue:
["200-207 11001 i i i Pop and Jump 0n True iii +1 (i.e., 1 through 8)"
stream nextPut: 199 + distance.
^self].
^self genBranchPopTrueLong: distance
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genBranchPopTrueLong: distance [
"243 11110011 i i i i i i i i Pop and Jump 0n True i i i i i i i i (+ Extend B * 256)"
| distanceMod256 |
(distance < 0 or: [distance > 32767]) ifTrue:
[^self outOfRangeError: 'distance' index: distance range: 0 to: 32767].
(distance > 0 and: [distance < 9]) ifTrue:
["200-207 11001 i i i Pop and Jump 0n True iii +1 (i.e., 1 through 8)"
stream nextPut: 199 + distance.
^self].
distanceMod256 := (distance < 0 or: [distance > 255])
ifTrue:
[self genUnsignedSingleExtendB: (distance bitShift: -8).
distance bitAnd: 255]
ifFalse: [distance].
stream
nextPut: 243;
nextPut: distanceMod256
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genCallPrimitive: primitiveIndex [
"249 11111001 i i i i i i i i jjjjjjjj Call Primitive #iiiiiiii + (jjjjjjjj * 256)"
"N.B. We could have made CallPrimitive a 2-byte code taking an extension, but that would
complicate the VM's determination of the primitive number and the primitive error code
store since the extension, being optional, would make the sequence variable length."
(primitiveIndex < 1 or: [primitiveIndex > 65535]) ifTrue:
[self outOfRangeError: 'primitive index' index: primitiveIndex range: 1 to: 65535].
stream
nextPut: 249;
nextPut: (primitiveIndex bitAnd: 255);
nextPut: (primitiveIndex bitShift: -8)
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genDup [
"219 11011011 Duplicate Stack Top"
stream nextPut: 219
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genExt1: aSmallInteger [
self shouldBeImplemented
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genJump: distance [
(distance > 0 and: [distance < 9]) ifTrue:
["192-199 11000 i i i Jump iii + 1 (i.e., 1 through 8)"
stream nextPut: 191 + distance.
^self].
"243 11110011 i i i i i i i i Jump i i i i i i i i (+ Extend B * 256, where bbbbbbbb = sddddddd, e.g. -32768 = i=0, a=0, s=1)"
^self genJumpLong: distance
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genJumpLong: distance [
"242 11110010 i i i i i i i i Jump i i i i i i i i (+ Extend B * 256, where bbbbbbbb = sddddddd, e.g. -32768 = i=0, a=0, s=1)"
(distance between: -32768 and: 32767) ifFalse:
[^self outOfRangeError: 'index' index: distance range: -32768 to: 32767].
(distance < 0 or: [distance > 255]) ifTrue:
[self genSignedSingleExtendB: (distance bitShift: -8)].
stream
nextPut: 242;
nextPut: (distance bitAnd: 255)
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genNop [
"221 11011101 Nop"
stream nextPut: 221
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPop [
"220 11011100 Pop Stack Top"
stream nextPut: 220
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushClosureCopyNumCopiedValues: numCopied numArgs: numArgs jumpSize: jumpSize [
"253 11111101 eeiiikkk jjjjjjjj Push Closure Num Copied iii (+ Ext A // 16 * 8) Num Args kkk (+ Ext A \\ 16 * 8) BlockSize jjjjjjjj (+ Ext B * 256). ee = num extensions"
"Including numExtensions makes decoding the bytecode quicker since it obviates having to scan from the beginning of a method."
| numExtensions numCopiedMod8 numArgsMod8 extA |
(jumpSize < 0 or: [jumpSize > 65535]) ifTrue:
[^self outOfRangeError: 'block size' index: jumpSize range: 0 to: 65535].
(numCopied < 0 or: [numCopied > 127]) ifTrue:
[^self outOfRangeError: 'num copied' index: numCopied range: 0 to: 127].
(numArgs < 0 or: [numArgs > 127]) ifTrue:
[^self outOfRangeError: 'num args' index: numArgs range: 0 to: 127].
extA := numExtensions := 0.
(numArgsMod8 := numArgs) > 7 ifTrue:
[extA := numArgs // 8.
numArgsMod8 := numArgsMod8 \\ 8].
(numCopiedMod8 := numCopied) > 7 ifTrue:
[extA := extA + (numCopied // 8 * 16).
numCopiedMod8 := numCopiedMod8 \\ 8].
extA ~= 0 ifTrue:
[self genUnsignedSingleExtendA: extA.
numExtensions := 1].
jumpSize > 255 ifTrue:
[numExtensions := numExtensions + 1.
self genUnsignedSingleExtendB: jumpSize // 256].
stream
nextPut: 253;
nextPut: (numExtensions bitShift: 6) + (numCopiedMod8 bitShift: 3) + numArgsMod8;
nextPut: (jumpSize bitAnd: 16rFF)
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushConsArray: size [
(size < 0 or: [size > 127]) ifTrue:
[^self outOfRangeError: 'size' index: size range: 0 to: 127].
"231 11100111 jkkkkkkk Push (Array new: kkkkkkk) (j = 0)
& Pop kkkkkkk elements into: (Array new: kkkkkkk) (j = 1)"
stream
nextPut: 231;
nextPut: size + 128
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushExplicitOuter: level [
"77 01001101 Push false [* 1:true, 2:nil, 3:thisContext, ..., -N: pushExplicitOuter: N, N = Extend B]"
(level > 0 and: [level <= 127]) ifTrue:
[^self outOfRangeError: 'level' index: level range: 1 to: 127].
self genSignedSingleExtendB: level negated.
stream nextPut: 77
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushInstVar: instVarIndex [
(instVarIndex between: 0 and: 15) ifTrue:
["0-15 0000iiii Push Receiver Variable #iiii"
stream nextPut: 0 + instVarIndex.
^self].
self genPushInstVarLong: instVarIndex
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushInstVarLong: instVarIndex [
"226 11100010 i i i i i i i i Push Receiver Variable #iiiiiiii (+ Extend A * 256)"
"See also MaybeContextInstanceVariableNode"
(instVarIndex < 0 or: [instVarIndex > 4095]) ifTrue:
[^self outOfRangeError: 'index' index: instVarIndex range: 0 to: 4095].
instVarIndex > 255 ifTrue:
[self genUnsignedSingleExtendA: instVarIndex // 256].
stream
nextPut: 226;
nextPut: instVarIndex \\ 256
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushInteger: anInteger [
"78 01001110 Push 0
79 01001111 Push 1
229 11100101 i i i i i i i i Push Integer #iiiiiiii (+ Extend B * 256, where bbbbbbbb = sddddddd, e.g. -32768 = i=0, a=0, s=1)"
"Why restrict the range to 16 bits when we could encode arbitrarily large integers?
Well, 16 bits requires 4 bytes (extB + byte, 78 + byte) and so beyond this range we lose space
verses a single-byte pushLiteral and a 4 byte integer literal on 32-bits. And generating the same
bytecode on 64-bit and 32-bit is important if we want to be able to load binary code from one to
the other (e.g. via Fuel)."
anInteger = 0 ifTrue:
[stream nextPut: 78.
^self].
anInteger = 1 ifTrue:
[stream nextPut: 79.
^self].
(anInteger < -32768 or: [anInteger > 32767]) ifTrue:
[^self outOfRangeError: 'integer' index: anInteger range: -32768 to: 32767].
(anInteger < 0 or: [anInteger > 255]) ifTrue:
[self genSignedSingleExtendB: (anInteger bitShift: -8)].
stream
nextPut: 229;
nextPut: (anInteger bitAnd: 255)
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushLiteral: literalIndex [
| extendedIndex |
(literalIndex < 0 or: [literalIndex > 65535]) ifTrue:
[^self outOfRangeError: 'index' index: literalIndex range: 0 to: 65536].
literalIndex < 32 ifTrue:
["32-63 001iiiii Push Literal #iiiii"
stream nextPut: 32 + literalIndex.
^self].
"228 11100100 i i i i i i i i Push Literal #iiiiiiii (+ Extend A * 256)"
(extendedIndex := literalIndex) > 255 ifTrue:
[self genUnsignedSingleExtendA: extendedIndex // 256.
extendedIndex := extendedIndex \\ 256].
stream
nextPut: 228;
nextPut: extendedIndex
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushLiteralVar: literalIndex [
| extendedIndex |
(literalIndex < 0 or: [literalIndex > 65535]) ifTrue:
[^self outOfRangeError: 'index' index: literalIndex range: 0 to: 65535].
literalIndex < 16 ifTrue:
["16-31 0001 i i i i Push Literal Variable #iiii"
stream nextPut: 16 + literalIndex.
^self].
"227 11100011 i i i i i i i i Push Literal Variable #iiiiiiii (+ Extend A * 256)"
(extendedIndex := literalIndex) > 255 ifTrue:
[self genUnsignedSingleExtendA: extendedIndex // 256.
extendedIndex := extendedIndex \\ 256].
stream
nextPut: 227;
nextPut: extendedIndex
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushNewArray: size [
(size < 0 or: [size > 127]) ifTrue:
[^self outOfRangeError: 'size' index: size range: 0 to: 127].
"231 11100111 jkkkkkkk Push (Array new: kkkkkkk) (j = 0)
& Pop kkkkkkk elements into: (Array new: kkkkkkk) (j = 1)"
stream
nextPut: 231;
nextPut: size
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushReceiver [
"76 01001100 Push Receiver"
stream nextPut: 76
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushRemoteTemp: tempIndex inVectorAt: tempVectorIndex [
"250 11111010 kkkkkkkk jjjjjjjj Push Temp At kkkkkkkk In Temp Vector At: jjjjjjjj"
(tempIndex < 0 or: [tempIndex >= 256]) ifTrue:
[^self outOfRangeError: 'remoteTempIndex' index: tempIndex range: 0 to: 255].
(tempVectorIndex < 0 or: [tempVectorIndex >= 256]) ifTrue:
[^self outOfRangeError: 'tempVectorIndex' index: tempVectorIndex range: 0 to: 255].
stream
nextPut: 250;
nextPut: tempIndex;
nextPut: tempVectorIndex
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushSpecialLiteral: aLiteral [
"77 01001101 Push false [* 1:true, 2:nil, 3:thisContext, ..., -N: pushExplicitOuter: N, N = Extend B]
229 11100101 i i i i i i i i Push Integer #iiiiiiii (+ Extend B * 256, where bbbbbbbb = sddddddd, e.g. -32768 = i=0, a=0, s=1)"
| index |
aLiteral isInteger ifTrue:
[^self genPushInteger: aLiteral].
index := #(false true nil)
indexOf: aLiteral
ifAbsent: [^self error: 'push special literal: ', aLiteral printString, ' is not one of true false nil'].
index > 1 ifTrue:
[self genUnsignedSingleExtendB: index - 1].
stream nextPut: 77
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushTemp: tempIndex [
(tempIndex < 0 or: [tempIndex > 63]) ifTrue:
[^self outOfRangeError: 'index' index: tempIndex range: 0 to: 63].
tempIndex < 12 ifTrue:
["64-71 01000 i i i Push Temporary Variable #iii
72-75 010010 i i Push Temporary Variable #ii + 8"
stream nextPut: 64 + tempIndex.
^self].
"230 11100110 i i i i i i i i Push Temporary Variable #iiiiiiii"
stream
nextPut: 230;
nextPut: tempIndex
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genPushThisContext [
"77 01001101 Push false [* 1:true, 2:nil, 3:thisContext, ..., -N: pushExplicitOuter: N, N = Extend B]"
self genSignedSingleExtendB: 3.
stream nextPut: 77
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genReturnReceiver [
"216 11011000 Return Receiver From Message"
stream nextPut: 216
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genReturnSpecialLiteral: aLiteral [
self shouldNotImplement
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genReturnTop [
"217 11011001 Return Stack Top From Message"
stream nextPut: 217
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genReturnTopToCaller [
"218 11011010 Return Stack Top From Block [* return from enclosing block N]"
stream nextPut: 218
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genSend: selectorLiteralIndex numArgs: nArgs [
| extendedIndex extendedNArgs |
(selectorLiteralIndex < 0 or: [selectorLiteralIndex > 65535]) ifTrue:
[^self outOfRangeError: 'selectorLiteralIndex' index: selectorLiteralIndex range: 0 to: 65535].
(nArgs < 0 or: [nArgs > 31]) ifTrue:
[^self outOfRangeError: 'numArgs' index: nArgs range: 0 to: 31 "!!"].
(selectorLiteralIndex < 16 and: [nArgs < 3]) ifTrue:
["112-127 0111 i i i i Send Literal Selector #iiii With 0 Arguments
128-143 1000 i i i i Send Literal Selector #iiii With 1 Argument
144-159 1001 i i i i Send Literal Selector #iiii With 2 Arguments"
stream nextPut: 112 + (nArgs * 16) + selectorLiteralIndex.
^self].
(extendedIndex := selectorLiteralIndex) > 31 ifTrue:
[self genUnsignedSingleExtendA: extendedIndex // 32.
extendedIndex := extendedIndex \\ 32].
(extendedNArgs := nArgs) > 7 ifTrue:
[self genUnsignedSingleExtendB: extendedNArgs // 8.
extendedNArgs := extendedNArgs \\ 8].
"238 11101110 i i i i i j j j Send Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"
stream
nextPut: 238;
nextPut: extendedNArgs + (extendedIndex * 8)
]
{ #category : #'bytecode generation' }
EncoderForNewsqueakV4 >> genSendAbsentDynamicSuper: selectorLiteralIndex numArgs: nArgs [
| extendedIndex extendedNArgs |