-
Notifications
You must be signed in to change notification settings - Fork 65
/
CogObjectRepresentationFor32BitSpur.class.st
1680 lines (1522 loc) · 69 KB
/
CogObjectRepresentationFor32BitSpur.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
Class {
#name : #CogObjectRepresentationFor32BitSpur,
#superclass : #CogObjectRepresentationForSpur,
#instVars : [
'ceSigned32BitIntegerTrampoline',
'ceSigned32BitValueOfTrampoline',
'cePositive32BitValueOfTrampoline',
'cePositive32BitIntegerTrampoline'
],
#category : #'VMMaker-JIT'
}
{ #category : #'sista support' }
CogObjectRepresentationFor32BitSpur >> allImmediate: immediateMask branchIf: reg instanceOfBehaviors: arrayObj target: targetFixUp [
< inline: true>
<var: #targetFixUp type: #'AbstractInstruction *'>
self assert: immediateMask = objectMemory tagMask.
(self genJumpImmediate: reg) jmpTarget: targetFixUp.
^0
]
{ #category : #'sista support' }
CogObjectRepresentationFor32BitSpur >> allImmediate: immediateMask branchIf: reg notInstanceOfBehaviors: arrayObj target: targetFixUp [
< inline: true>
<var: #targetFixUp type: #'AbstractInstruction *'>
self assert: immediateMask = objectMemory tagMask.
(self genJumpNotImmediate: reg) jmpTarget: targetFixUp.
^0
]
{ #category : #'sista support' }
CogObjectRepresentationFor32BitSpur >> allocateCounters: nCounters [
"On Spur allocate the counters on the heap as pinned objects.
Each counter occupies 32-bits. The number of counters can
be derived from the number of slots in the obj."
<inline: true>
| objOop |
objOop := objectMemory allocatePinnedSlots: nCounters.
^objOop
ifNil: [0]
ifNotNil: [objOop + objectMemory baseHeaderSize]
]
{ #category : #'sista support' }
CogObjectRepresentationFor32BitSpur >> branch2CasesIf: reg instanceOfBehaviors: arrayObj target: targetFixUp [
<inline: true>
self Jump: targetFixUp
]
{ #category : #'sista support' }
CogObjectRepresentationFor32BitSpur >> branch2CasesIf: reg notInstanceOfBehaviors: arrayObj target: targetFixUp [
"nothing to do, 2 immediates so all immediates are allowed"
<inline: true>
]
{ #category : #'sista support' }
CogObjectRepresentationFor32BitSpur >> branchIf: reg hasImmediateTag: classIndex target: targetFixUp [
<var: #targetFixUp type: #'AbstractInstruction *'>
| jmpImmediate|
<inline: true>
classIndex = objectMemory smallIntegerTag ifTrue:
[jmpImmediate := self genJumpSmallInteger: reg].
classIndex = objectMemory characterTag ifTrue:
[cogit MoveR: reg R: TempReg.
jmpImmediate := self genJumpCharacterInScratchReg: reg].
jmpImmediate jmpTarget: targetFixUp
]
{ #category : #'sista support' }
CogObjectRepresentationFor32BitSpur >> branchIf: reg hasNotImmediateTag: classIndex target: targetFixUp [
<var: #targetFixUp type: #'AbstractInstruction *'>
| jmpImmediate |
<inline: true>
classIndex = objectMemory smallIntegerTag ifTrue:
[jmpImmediate := self genJumpNotSmallInteger: reg].
classIndex = objectMemory characterTag ifTrue:
["Character test destroy register value in Spur"
cogit MoveR: reg R: TempReg.
jmpImmediate := self genJumpNotCharacterInScratchReg: TempReg].
jmpImmediate jmpTarget: targetFixUp
]
{ #category : #'in-line cacheing' }
CogObjectRepresentationFor32BitSpur >> classForInlineCacheTag: inlineCacheTag [
"Character gets mapped to zero. See inlineCacheTagForInstance:."
^objectMemory classOrNilAtIndex: (inlineCacheTag = 0
ifTrue: [objectMemory characterTag]
ifFalse: [inlineCacheTag])
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genAddSmallIntegerTagsTo: aRegister [
cogit AddCq: 1 R: aRegister.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genClearAndSetSmallIntegerTagsIn: scratchReg [
"Set the SmallInteger tag bits when the tag bits may be filled with garbage."
^self genSetSmallIntegerTagsIn: scratchReg
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genConvertCharacterToSmallIntegerInReg: reg [
"Convert the Character in reg to a SmallInteger, assuming
the Character's value is a valid character."
"self assume: objectMemory smallIntegerTag = 1"
self assert: (objectMemory characterTag = 2
and: [self numCharacterBits + 1 = self numSmallIntegerBits]).
cogit LogicalShiftRightCq: 1 R: reg
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genConvertIntegerToSmallIntegerInReg: reg [
cogit LogicalShiftLeftCq: 1 R: reg.
cogit AddCq: 1 R: reg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genConvertSmallIntegerToCharacterInReg: reg [
"Convert the SmallInteger in reg to a Character, assuming
the SmallInteger's value is a valid character."
"self assume: objectMemory smallIntegerTag = 1"
self assert: (objectMemory characterTag = 2
and: [self numCharacterBits + 1 = self numSmallIntegerBits]).
cogit LogicalShiftLeftCq: 1 R: reg
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genConvertSmallIntegerToIntegerInReg: reg [
cogit ArithmeticShiftRightCq: 1 R: reg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genFetchIndexRegister: indexReg from: tableObj into: destReg [
"indexReg contains the 1-relative index of an element in tableObj.
Since BaseHeaderSize > BytesPerOop we must adjust it to use
it as a zero-relative index from the beginning of the object."
self assert: indexReg ~= destReg.
cogit AddCq: objectMemory baseHeaderSize / objectMemory wordSize - 1 R: indexReg.
cogit genMoveConstant: tableObj R: destReg.
cogit MoveXwr: indexReg R: destReg R: destReg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genGetHashFieldNonImmOf: instReg asSmallIntegerInto: destReg [
"Fetch the instance's identity hash into destReg, encoded as a SmallInteger."
"Get header word in scratchReg"
cogit MoveMw: 4 r: instReg R: destReg.
"Shift and mask the field leaving room for the SmallInteger tag."
cogit AndCq: objectMemory identityHashHalfWordMask R: destReg.
self genConvertIntegerToSmallIntegerInReg: destReg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genGetHashFieldNonImmOf: instReg into: destReg [
"Fetch the instance's identity hash into destReg, unencoded."
cogit MoveMw: 4 r: instReg R: destReg.
cogit AndCq: objectMemory identityHashHalfWordMask R: destReg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genGetInlineCacheClassTagFrom: sourceReg into: destReg forEntry: forEntry [
"Extract the inline cache tag for the object in sourceReg into destReg. The inline
cache tag for a given object is the value loaded in inline caches to distinguish
objects of different classes. In Spur this is either the tags for immediates, (with
1 & 3 collapsed to 1 for SmallIntegers, and 2 collapsed to 0 for Characters), or
the receiver's classIndex.
If forEntry is true answer the entry label at which control is to enter (cmEntryOffset).
If forEntry is false, control enters at the start.
If forEntry is true, generate something like this:
Limm:
andl $0x1, rDest
j Lcmp
Lentry:
movl rSource, rDest
andl $0x3, rDest
jnz Limm
movl 0(%edx), rDest
andl $0x3fffff, rDest
Lcmp:
If forEntry is false, generate something like the following.
At least on a 2.2GHz Intel Core i7 the following is slightly faster than the above,
136m sends/sec vs 130m sends/sec for nfib in tinyBenchmarks
Lentry:
movl rSource, rDest
andl $0x3, rDest
jz LnotImm
andl $1, rDest
j Lcmp
LnotImm:
movl 0(%edx), rDest
andl $0x3fffff, rDest
Lcmp:
But we expect most SmallInteger arithmetic to be performed in-line and so prefer the
version that is faster for non-immediates (because it branches for immediates only)."
| immLabel jumpNotImm entryLabel jumpCompare |
<var: #immLabel type: #'AbstractInstruction *'>
<var: #jumpNotImm type: #'AbstractInstruction *'>
<var: #entryLabel type: #'AbstractInstruction *'>
<var: #jumpCompare type: #'AbstractInstruction *'>
forEntry
ifFalse:
[entryLabel := cogit Label.
cogit AndCq: objectMemory tagMask R: sourceReg R: destReg.
jumpNotImm := cogit JumpZero: 0.
cogit AndCq: 1 R: destReg.
jumpCompare := cogit Jump: 0.
"Get least significant half of header word in destReg"
self flag: #endianness.
jumpNotImm jmpTarget:
(cogit MoveMw: 0 r: sourceReg R: destReg).
jumpCompare jmpTarget:
(cogit AndCq: objectMemory classIndexMask R: destReg)]
ifTrue:
[cogit AlignmentNops: objectMemory wordSize.
immLabel := cogit Label.
cogit AndCq: 1 R: destReg.
jumpCompare := cogit Jump: 0.
cogit AlignmentNops: objectMemory wordSize.
entryLabel := cogit Label.
cogit AndCq: objectMemory tagMask R: sourceReg R: destReg.
cogit JumpNonZero: immLabel.
self flag: #endianness.
"Get least significant half of header word in destReg"
cogit MoveMw: 0 r: sourceReg R: destReg.
cogit AndCq: objectMemory classIndexMask R: destReg.
jumpCompare jmpTarget: cogit Label].
^entryLabel
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genGetNumBytesOf: srcReg into: destReg [
"Get the size in byte-sized slots of the object in srcReg into destReg.
srcReg may equal destReg.
destReg <- numSlots << self shiftForWord - (fmt bitAnd: 3).
Assumes the object in srcReg has a byte format, i.e. 16 to 23 or 24 to 31 "
<var: #jmp type: #'AbstractInstruction *'>
| jmp |
self genGetRawSlotSizeOfNonImm: srcReg into: destReg.
cogit CmpCq: objectMemory numSlotsMask R: destReg.
jmp := cogit JumpLess: 0.
self genGetOverflowSlotsOf: srcReg into: destReg.
jmp jmpTarget: (cogit LogicalShiftLeftCq: objectMemory shiftForWord R: destReg).
self genGetBits: 3 ofFormatByteOf: srcReg into: TempReg.
"Now: fmt bitAnd: 3 in TempReg"
cogit SubR: TempReg R: destReg.
^0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genGetOverflowSlotsOf: srcReg into: destReg [
cogit MoveMw: objectMemory baseHeaderSize negated r: srcReg R: destReg.
^0
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor32BitSpur >> genGetSizeOf: sourceReg into: destReg formatReg: formatReg scratchReg: scratchReg abortJumpsInto: aBinaryBlock [
"Get the size of the non-immediate object in sourceReg into destReg using formatReg
and scratchReg as temps. None of these registers can overlap. Supply the jumps
taken if the object in sourceReg is not indexable, or if the object in sourceReg is a
context.. Hack: If the object has a pointer format other than 2 leave the number of
fixed fields in formatReg. Used by primitiveSize, primitiveAt, and primitiveAtPut"
<returnTypeC: #'AbstractInstruction *'>
| jumpNotIndexable
jumpBytesDone jumpShortsDone jumpArrayDone jump32BitLongsDone jump64BitLongsDone
jumpIsBytes jumpHasFixedFields jumpIsShorts jumpIs64BitLongs jumpIsContext |
"c.f. StackInterpreter>>stSizeOf: SpurMemoryManager>>lengthOf:format: fixedFieldsOf:format:length:"
"formatReg := self formatOf: sourceReg"
self genGetFormatOf: sourceReg
into: formatReg
leastSignificantHalfOfBaseHeaderIntoScratch: scratchReg.
self genGetNumSlotsOf: sourceReg into: destReg.
"dispatch on format in a combination of highest dynamic frequency order first and convenience.
0 = 0 sized objects (UndefinedObject True False et al)
1 = non-indexable objects with inst vars (Point et al)
2 = indexable objects with no inst vars (Array et al)
3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al)
4 = weak indexable objects with inst vars (WeakArray et al)
5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron)
6 unused, reserved for exotic pointer objects?
7 Forwarded Object, 1st field is pointer, rest of fields are ignored
8 unused, reserved for exotic non-pointer objects?
9 64-bit indexable
10 - 11 32-bit indexable
12 - 15 16-bit indexable
16 - 23 byte indexable
24 - 31 compiled method"
cogit CmpCq: objectMemory firstByteFormat R: formatReg.
jumpIsBytes := cogit JumpGreaterOrEqual: 0.
cogit CmpCq: objectMemory arrayFormat R: formatReg.
jumpArrayDone := cogit JumpZero: 0.
jumpNotIndexable := cogit JumpLess: 0.
cogit CmpCq: objectMemory weakArrayFormat R: formatReg.
jumpHasFixedFields := cogit JumpLessOrEqual: 0.
cogit CmpCq: objectMemory firstShortFormat R: formatReg.
jumpIsShorts := cogit JumpGreaterOrEqual: 0.
cogit CmpCq: objectMemory firstLongFormat R: formatReg.
jump32BitLongsDone := cogit JumpGreaterOrEqual: 0.
cogit CmpCq: objectMemory sixtyFourBitIndexableFormat R: formatReg.
jumpIs64BitLongs := cogit JumpZero: 0.
"For now ignore 64-bit indexability."
jumpNotIndexable jmpTarget: cogit Label.
jumpNotIndexable := cogit Jump: 0.
jumpIsBytes jmpTarget:
(cogit LogicalShiftLeftCq: objectMemory shiftForWord R: destReg).
cogit AndCq: objectMemory wordSize - 1 R: formatReg.
cogit SubR: formatReg R: destReg.
jumpBytesDone := cogit Jump: 0.
jumpIsShorts jmpTarget:
(cogit LogicalShiftLeftCq: objectMemory shiftForWord - 1 R: destReg).
cogit AndCq: 1 R: formatReg.
cogit SubR: formatReg R: destReg.
jumpShortsDone := cogit Jump: 0.
jumpIs64BitLongs jmpTarget:
(cogit LogicalShiftRightCq: 1 R: destReg).
jump64BitLongsDone := cogit Jump: 0.
"formatReg contains fmt, now up for grabs.
destReg contains numSlots, precious.
sourceReg must be preserved"
jumpHasFixedFields jmpTarget:
(cogit AndCq: objectMemory classIndexMask R: scratchReg).
cogit MoveR: scratchReg R: formatReg.
cogit CmpCq: ClassMethodContextCompactIndex R: scratchReg.
jumpIsContext := cogit JumpZero: 0.
cogit PushR: destReg.
self genGetClassObjectOfClassIndex: formatReg into: destReg scratchReg: scratchReg.
self genLoadSlot: InstanceSpecificationIndex sourceReg: destReg destReg: formatReg.
self genConvertSmallIntegerToIntegerInReg: formatReg.
cogit
PopR: destReg;
AndCq: objectMemory fixedFieldsOfClassFormatMask R: formatReg;
SubR: formatReg R: destReg.
jumpArrayDone jmpTarget:
(jump64BitLongsDone jmpTarget:
(jump32BitLongsDone jmpTarget:
(jumpShortsDone jmpTarget:
(jumpBytesDone jmpTarget:
cogit Label)))).
aBinaryBlock value: jumpNotIndexable value: jumpIsContext
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genJumpIsSmallIntegerValue: aRegister scratch: scratchReg [
"Generate a test for aRegister containing an integer value in the SmallInteger range, and a jump if so, answering the jump.
c.f. Spur32BitMemoryManager>>isIntegerValue:"
<returnTypeC: #'AbstractInstruction *'>
^cogit
MoveR: aRegister R: scratchReg;
LogicalShiftLeftCq: 1 R: scratchReg;
XorR: aRegister R: scratchReg;
JumpGreaterOrEqual: 0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genJumpNotSmallInteger: aRegister [
<returnTypeC: #'AbstractInstruction *'>
cogit TstCq: 1 R: aRegister.
^cogit JumpZero: 0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genJumpNotSmallIntegerInScratchReg: aRegister [
<returnTypeC: #'AbstractInstruction *'>
cogit AndCq: 1 R: aRegister.
^cogit JumpZero: 0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genJumpNotSmallIntegerValue: aRegister scratch: scratchReg [
"Generate a test for aRegister containing an integer value outside the SmallInteger range, and a jump if so, answering the jump.
c.f. Spur32BitMemoryManager>>isIntegerValue:"
<returnTypeC: #'AbstractInstruction *'>
^cogit
MoveR: aRegister R: scratchReg;
LogicalShiftLeftCq: 1 R: scratchReg;
XorR: aRegister R: scratchReg;
JumpLess: 0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genJumpSmallInteger: aRegister [
<returnTypeC: #'AbstractInstruction *'>
cogit TstCq: 1 R: aRegister.
^cogit JumpNonZero: 0
]
{ #category : #'compile abstract instructions' }
CogObjectRepresentationFor32BitSpur >> genJumpSmallIntegerInScratchReg: aRegister [
<returnTypeC: #'AbstractInstruction *'>
cogit AndCq: 1 R: aRegister.
^cogit JumpNonZero: 0
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor32BitSpur >> genPrimitiveAtPut [
| formatReg nSlotsOrBytesReg methodInBounds
jumpImmediate jumpBadIndex jumpImmutable jumpNotIndexablePointers jumpNotIndexableBits
jumpIsContext jumpIsCompiledMethod jumpIsBytes jumpIsShorts jumpHasFixedFields
jumpArrayOutOfBounds jumpFixedFieldsOutOfBounds
jumpWordsOutOfBounds jumpShortsOutOfBounds jumpBytesOutOfBounds
jumpShortsOutOfRange jumpWordsOutOfRange jumpBytesOutOfRange
jumpNonSmallIntegerValue jumpNotPointers
|
"c.f. StackInterpreter>>stSizeOf: SpurMemoryManager>>lengthOf:format: fixedFieldsOf:format:length:"
<var: #jumpIsBytes type: #'AbstractInstruction *'>
<var: #jumpIsShorts type: #'AbstractInstruction *'>
<var: #jumpBadIndex type: #'AbstractInstruction *'>
<var: #jumpIsContext type: #'AbstractInstruction *'>
<var: #jumpImmediate type: #'AbstractInstruction *'>
<var: #methodInBounds type: #'AbstractInstruction *'>
<var: #jumpHasFixedFields type: #'AbstractInstruction *'>
<var: #jumpNotIndexableBits type: #'AbstractInstruction *'>
<var: #jumpBytesOutOfRange type: #'AbstractInstruction *'>
<var: #jumpWordsOutOfRange type: #'AbstractInstruction *'>
<var: #jumpShortsOutOfRange type: #'AbstractInstruction *'>
<var: #jumpArrayOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpBytesOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpWordsOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpShortsOutOfBounds type: #'AbstractInstruction *'>
<var: #jumpNotIndexablePointers type: #'AbstractInstruction *'>
nSlotsOrBytesReg := ClassReg.
cogit genLoadArgAtDepth: 1 into: Arg0Reg.
cogit genLoadArgAtDepth: 0 into: Arg1Reg.
jumpImmediate := self genJumpImmediate: ReceiverResultReg.
jumpBadIndex := self genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg.
self genConvertSmallIntegerToIntegerInReg: Arg0Reg.
cogit SubCq: 1 R: Arg0Reg. "1-rel => 0-rel"
"formatReg := self formatOf: ReceiverResultReg"
self cppIf: IMMUTABILITY
ifTrue:
[ self genGetFormatOf: ReceiverResultReg
into: (formatReg := SendNumArgsReg)
leastSignificantHalfOfBaseHeaderIntoScratch: TempReg.
jumpImmutable := self genJumpBaseHeaderImmutable: TempReg ]
ifFalse:
[ self genGetFormatOf: ReceiverResultReg
into: (formatReg := SendNumArgsReg)
leastSignificantHalfOfBaseHeaderIntoScratch: NoReg ].
self genGetNumSlotsOf: ReceiverResultReg into: nSlotsOrBytesReg.
"dispatch on format in a combination of highest dynamic frequency order first and convenience.
0 = 0 sized objects (UndefinedObject True False et al)
1 = non-indexable objects with inst vars (Point et al)
2 = indexable objects with no inst vars (Array et al)
3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al)
4 = weak indexable objects with inst vars (WeakArray et al)
5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron)
6 unused, reserved for exotic pointer objects?
7 Forwarded Object, 1st field is pointer, rest of fields are ignored
8 unused, reserved for exotic non-pointer objects?
9 64-bit indexable
10 - 11 32-bit indexable
12 - 15 16-bit indexable
16 - 23 byte indexable
24 - 31 compiled method"
cogit CmpCq: objectMemory weakArrayFormat R: formatReg.
jumpNotPointers := cogit JumpAbove: 0.
"optimistic store check; assume index in range (almost always is)."
self genStoreCheckReceiverReg: ReceiverResultReg
valueReg: Arg1Reg
scratchReg: TempReg
inFrame: false.
cogit CmpCq: objectMemory arrayFormat R: formatReg.
jumpNotIndexablePointers := cogit JumpBelow: 0.
jumpHasFixedFields := cogit JumpNonZero: 0.
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
jumpArrayOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg0Reg.
cogit MoveR: Arg1Reg Xwr: Arg0Reg R: ReceiverResultReg.
cogit MoveR: Arg1Reg R: ReceiverResultReg.
cogit genPrimReturn.
jumpHasFixedFields jmpTarget: cogit Label.
self genGetClassIndexOfNonImm: ReceiverResultReg into: formatReg.
cogit CmpCq: ClassMethodContextCompactIndex R: formatReg.
jumpIsContext := cogit JumpZero: 0.
"get # fixed fields in formatReg"
cogit PushR: nSlotsOrBytesReg.
self genGetClassObjectOfClassIndex: formatReg into: nSlotsOrBytesReg scratchReg: TempReg.
self genLoadSlot: InstanceSpecificationIndex sourceReg: nSlotsOrBytesReg destReg: formatReg.
cogit PopR: nSlotsOrBytesReg.
self genConvertSmallIntegerToIntegerInReg: formatReg.
cogit AndCq: objectMemory fixedFieldsOfClassFormatMask R: formatReg.
cogit SubR: formatReg R: nSlotsOrBytesReg.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: formatReg.
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
jumpFixedFieldsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddR: formatReg R: Arg0Reg.
cogit MoveR: Arg1Reg Xwr: Arg0Reg R: ReceiverResultReg.
cogit MoveR: Arg1Reg R: ReceiverResultReg.
cogit genPrimReturn.
jumpNotPointers jmpTarget: cogit Label.
jumpNonSmallIntegerValue := self genJumpNotSmallInteger: Arg1Reg scratchReg: TempReg.
cogit CmpCq: objectMemory firstByteFormat R: formatReg.
jumpIsBytes := cogit JumpAboveOrEqual: 0.
cogit CmpCq: objectMemory firstShortFormat R: formatReg.
jumpIsShorts := cogit JumpAboveOrEqual: 0.
cogit CmpCq: objectMemory firstLongFormat R: formatReg.
"For now ignore 64-bit indexability."
jumpNotIndexableBits := cogit JumpBelow: 0.
"fall through to double words"
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
jumpWordsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit MoveR: Arg1Reg R: TempReg.
self genConvertSmallIntegerToIntegerInReg: TempReg.
(cogit lastOpcode setsConditionCodesFor: JumpLess) ifFalse:
[cogit CmpCq: 0 R: TempReg]. "N.B. FLAGS := TempReg - 0"
jumpWordsOutOfRange := cogit JumpLess: 0.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg0Reg.
cogit MoveR: TempReg Xwr: Arg0Reg R: ReceiverResultReg.
cogit MoveR: Arg1Reg R: ReceiverResultReg.
cogit genPrimReturn.
jumpIsBytes jmpTarget:
(cogit CmpCq: (objectMemory integerObjectOf: 255) R: Arg1Reg).
jumpBytesOutOfRange := cogit JumpAbove: 0.
cogit LogicalShiftLeftCq: objectMemory shiftForWord R: nSlotsOrBytesReg.
cogit AndCq: objectMemory wordSize - 1 R: formatReg R: TempReg.
cogit SubR: TempReg R: nSlotsOrBytesReg.
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
jumpBytesOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit CmpCq: objectMemory firstCompiledMethodFormat R: formatReg.
jumpIsCompiledMethod := cogit JumpAboveOrEqual: 0.
methodInBounds :=
cogit MoveR: Arg1Reg R: TempReg.
self genConvertSmallIntegerToIntegerInReg: TempReg.
cogit AddCq: objectMemory baseHeaderSize R: Arg0Reg.
cogit MoveR: TempReg Xbr: Arg0Reg R: ReceiverResultReg.
cogit MoveR: Arg1Reg R: ReceiverResultReg.
cogit genPrimReturn.
jumpIsShorts jmpTarget:
(cogit CmpCq: (objectMemory integerObjectOf: 65535) R: Arg1Reg).
jumpShortsOutOfRange := cogit JumpAbove: 0.
cogit LogicalShiftLeftCq: objectMemory shiftForWord - 1 R: nSlotsOrBytesReg.
cogit AndCq: objectMemory wordSize / 2 - 1 R: formatReg.
cogit SubR: formatReg R: nSlotsOrBytesReg.
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
jumpShortsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit MoveR: Arg1Reg R: TempReg.
self genConvertSmallIntegerToIntegerInReg: TempReg.
cogit AddR: Arg0Reg R: ReceiverResultReg.
cogit AddR: Arg0Reg R: ReceiverResultReg.
cogit MoveR: TempReg M16: objectMemory baseHeaderSize r: ReceiverResultReg.
cogit MoveR: Arg1Reg R: ReceiverResultReg.
cogit genPrimReturn.
"Now check that the index is beyond the method's literals..."
jumpIsCompiledMethod jmpTarget: cogit Label.
self getLiteralCountOf: ReceiverResultReg plusOne: true inBytes: true into: nSlotsOrBytesReg scratch: TempReg.
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
cogit JumpBelow: methodInBounds.
jumpIsContext jmpTarget:
(jumpNotIndexableBits jmpTarget:
(jumpBytesOutOfRange jmpTarget:
(jumpWordsOutOfRange jmpTarget:
(jumpShortsOutOfRange jmpTarget:
(jumpIsCompiledMethod jmpTarget:
(jumpArrayOutOfBounds jmpTarget:
(jumpBytesOutOfBounds jmpTarget:
(jumpShortsOutOfBounds jmpTarget:
(jumpWordsOutOfBounds jmpTarget:
(jumpNotIndexablePointers jmpTarget:
(jumpNonSmallIntegerValue jmpTarget:
(jumpFixedFieldsOutOfBounds jmpTarget: cogit Label)))))))))))).
self cppIf: IMMUTABILITY
ifTrue: [jumpImmutable jmpTarget: jumpIsContext getJmpTarget].
cogit AddCq: 1 R: Arg0Reg. "0-rel => 1-rel"
self genConvertIntegerToSmallIntegerInReg: Arg0Reg.
jumpBadIndex jmpTarget: (jumpImmediate jmpTarget: cogit Label).
^0 "Can't be complete because of contexts."
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor32BitSpur >> genPrimitiveAtPutSigned: signedVersion [
"Generate the code for primitives 61 & 165, at:put:/basicAt:put: & integerAt:put:. If signedVersion is true
then generate signed accesses to the bits classes (a la 164 & 165). If signedVersion is false,
generate unsigned accesses (a la 60, 61, 63 & 64)."
| formatReg nSlotsOrBytesReg methodInBounds
jumpImmediate jumpBadIndex jumpImmutable jumpNotIndexablePointers jumpNotIndexableBits
jumpIsContext jumpIsCompiledMethod jumpIsBytes jumpIsShorts jumpHasFixedFields
jumpArrayOutOfBounds jumpFixedFieldsOutOfBounds
jumpWordsOutOfBounds jumpShortsOutOfBounds jumpBytesOutOfBounds
jumpShortsOutOfRange jumpWordsOutOfRange jumpBytesOutOfRange
jumpNonSmallIntegerValue jumpNotPointers
|
"c.f. StackInterpreter>>stSizeOf: SpurMemoryManager>>lengthOf:format: fixedFieldsOf:format:length:"
nSlotsOrBytesReg := ClassReg.
cogit genLoadArgAtDepth: 1 into: Arg0Reg.
cogit genLoadArgAtDepth: 0 into: Arg1Reg.
jumpImmediate := self genJumpImmediate: ReceiverResultReg.
jumpBadIndex := self genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg.
self genConvertSmallIntegerToIntegerInReg: Arg0Reg.
cogit SubCq: 1 R: Arg0Reg. "1-rel => 0-rel"
"formatReg := self formatOf: ReceiverResultReg"
self cppIf: IMMUTABILITY
ifTrue:
[ self genGetFormatOf: ReceiverResultReg
into: (formatReg := SendNumArgsReg)
leastSignificantHalfOfBaseHeaderIntoScratch: TempReg.
jumpImmutable := self genJumpBaseHeaderImmutable: TempReg ]
ifFalse:
[ self genGetFormatOf: ReceiverResultReg
into: (formatReg := SendNumArgsReg)
leastSignificantHalfOfBaseHeaderIntoScratch: NoReg ].
self genGetNumSlotsOf: ReceiverResultReg into: nSlotsOrBytesReg.
"dispatch on format in a combination of highest dynamic frequency order first and convenience.
0 = 0 sized objects (UndefinedObject True False et al)
1 = non-indexable objects with inst vars (Point et al)
2 = indexable objects with no inst vars (Array et al)
3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al)
4 = weak indexable objects with inst vars (WeakArray et al)
5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron)
6 unused, reserved for exotic pointer objects?
7 Forwarded Object, 1st field is pointer, rest of fields are ignored
8 unused, reserved for exotic non-pointer objects?
9 64-bit indexable
10 - 11 32-bit indexable
12 - 15 16-bit indexable
16 - 23 byte indexable
24 - 31 compiled method"
cogit CmpCq: objectMemory weakArrayFormat R: formatReg.
jumpNotPointers := cogit JumpAbove: 0.
"optimistic store check; assume index in range (almost always is)."
self genStoreCheckReceiverReg: ReceiverResultReg
valueReg: Arg1Reg
scratchReg: TempReg
inFrame: false.
cogit CmpCq: objectMemory arrayFormat R: formatReg.
jumpNotIndexablePointers := cogit JumpBelow: 0.
jumpHasFixedFields := cogit JumpNonZero: 0.
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
jumpArrayOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg0Reg.
cogit MoveR: Arg1Reg Xwr: Arg0Reg R: ReceiverResultReg.
cogit MoveR: Arg1Reg R: ReceiverResultReg.
cogit genPrimReturn.
jumpHasFixedFields jmpTarget: cogit Label.
self genGetClassIndexOfNonImm: ReceiverResultReg into: formatReg.
cogit CmpCq: ClassMethodContextCompactIndex R: formatReg.
jumpIsContext := cogit JumpZero: 0.
"get # fixed fields in formatReg"
cogit PushR: nSlotsOrBytesReg.
self genGetClassObjectOfClassIndex: formatReg into: nSlotsOrBytesReg scratchReg: TempReg.
self genLoadSlot: InstanceSpecificationIndex sourceReg: nSlotsOrBytesReg destReg: formatReg.
cogit PopR: nSlotsOrBytesReg.
self genConvertSmallIntegerToIntegerInReg: formatReg.
cogit AndCq: objectMemory fixedFieldsOfClassFormatMask R: formatReg.
cogit SubR: formatReg R: nSlotsOrBytesReg.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: formatReg.
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
jumpFixedFieldsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddR: formatReg R: Arg0Reg.
cogit MoveR: Arg1Reg Xwr: Arg0Reg R: ReceiverResultReg.
cogit MoveR: Arg1Reg R: ReceiverResultReg.
cogit genPrimReturn.
jumpNotPointers jmpTarget: cogit Label.
jumpNonSmallIntegerValue := self genJumpNotSmallInteger: Arg1Reg scratchReg: TempReg.
cogit CmpCq: objectMemory firstByteFormat R: formatReg.
jumpIsBytes := cogit JumpAboveOrEqual: 0.
cogit CmpCq: objectMemory firstShortFormat R: formatReg.
jumpIsShorts := cogit JumpAboveOrEqual: 0.
cogit CmpCq: objectMemory firstLongFormat R: formatReg.
"For now ignore 64-bit indexability."
jumpNotIndexableBits := cogit JumpBelow: 0.
"fall through to words"
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
jumpWordsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit MoveR: Arg1Reg R: TempReg.
self genConvertSmallIntegerToIntegerInReg: TempReg.
signedVersion ifFalse:
[(cogit lastOpcode setsConditionCodesFor: JumpLess) ifFalse:
[cogit CmpCq: 0 R: TempReg]. "N.B. FLAGS := TempReg - 0"
jumpWordsOutOfRange := cogit JumpLess: 0].
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg0Reg.
cogit MoveR: TempReg Xwr: Arg0Reg R: ReceiverResultReg.
cogit MoveR: Arg1Reg R: ReceiverResultReg.
cogit genPrimReturn.
signedVersion
ifTrue:
[jumpIsBytes jmpTarget:
(cogit MoveR: SendNumArgsReg R: TempReg).
cogit ArithmeticShiftRightCq: 7 R: TempReg. "Maps in range to -1,0".
cogit AddCq: 1 R: TempReg. "Maps in range to 0,1"
cogit CmpCq: 1 R: TempReg]
ifFalse:
[jumpIsBytes jmpTarget:
(cogit CmpCq: (objectMemory integerObjectOf: 255) R: Arg1Reg)].
jumpBytesOutOfRange := cogit JumpAbove: 0.
cogit LogicalShiftLeftCq: objectMemory shiftForWord R: nSlotsOrBytesReg.
cogit AndCq: objectMemory wordSize - 1 R: formatReg R: TempReg.
cogit SubR: TempReg R: nSlotsOrBytesReg.
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
jumpBytesOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit CmpCq: objectMemory firstCompiledMethodFormat R: formatReg.
jumpIsCompiledMethod := cogit JumpAboveOrEqual: 0.
methodInBounds :=
cogit MoveR: Arg1Reg R: TempReg.
self genConvertSmallIntegerToIntegerInReg: TempReg.
cogit AddCq: objectMemory baseHeaderSize R: Arg0Reg.
cogit MoveR: TempReg Xbr: Arg0Reg R: ReceiverResultReg.
cogit MoveR: Arg1Reg R: ReceiverResultReg.
cogit genPrimReturn.
signedVersion
ifTrue:
[jumpIsShorts jmpTarget:
(cogit MoveR: SendNumArgsReg R: TempReg).
cogit ArithmeticShiftRightCq: 15 R: TempReg. "Maps in range to -1,0".
cogit AddCq: 1 R: TempReg. "Maps in range to 0,1"
cogit CmpCq: 1 R: TempReg]
ifFalse:
[jumpIsShorts jmpTarget:
(cogit CmpCq: (objectMemory integerObjectOf: 65535) R: Arg1Reg)].
jumpShortsOutOfRange := cogit JumpAbove: 0.
cogit LogicalShiftLeftCq: objectMemory shiftForWord - 1 R: nSlotsOrBytesReg.
cogit AndCq: objectMemory wordSize / 2 - 1 R: formatReg.
cogit SubR: formatReg R: nSlotsOrBytesReg.
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
jumpShortsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit MoveR: Arg1Reg R: TempReg.
self genConvertSmallIntegerToIntegerInReg: TempReg.
cogit AddR: Arg0Reg R: ReceiverResultReg.
cogit AddR: Arg0Reg R: ReceiverResultReg.
cogit MoveR: TempReg M16: objectMemory baseHeaderSize r: ReceiverResultReg.
cogit MoveR: Arg1Reg R: ReceiverResultReg.
cogit genPrimReturn.
"Now check that the index is beyond the method's literals..."
jumpIsCompiledMethod jmpTarget: cogit Label.
self getLiteralCountOf: ReceiverResultReg plusOne: true inBytes: true into: nSlotsOrBytesReg scratch: TempReg.
cogit CmpR: Arg0Reg R: nSlotsOrBytesReg.
cogit JumpBelow: methodInBounds.
jumpIsContext jmpTarget:
(jumpNotIndexableBits jmpTarget:
(jumpBytesOutOfRange jmpTarget:
(jumpShortsOutOfRange jmpTarget:
(jumpIsCompiledMethod jmpTarget:
(jumpArrayOutOfBounds jmpTarget:
(jumpBytesOutOfBounds jmpTarget:
(jumpShortsOutOfBounds jmpTarget:
(jumpWordsOutOfBounds jmpTarget:
(jumpNotIndexablePointers jmpTarget:
(jumpNonSmallIntegerValue jmpTarget:
(jumpFixedFieldsOutOfBounds jmpTarget: cogit Label))))))))))).
signedVersion ifFalse:
[jumpWordsOutOfRange jmpTarget: jumpIsContext getJmpTarget].
self cppIf: IMMUTABILITY
ifTrue: [jumpImmutable jmpTarget: jumpIsContext getJmpTarget].
cogit AddCq: 1 R: Arg0Reg. "0-rel => 1-rel"
self genConvertIntegerToSmallIntegerInReg: Arg0Reg.
jumpBadIndex jmpTarget: (jumpImmediate jmpTarget: cogit Label).
^0 "Can't be complete because of contexts."
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor32BitSpur >> genPrimitiveAtSigned: signedVersion [
"Generate the code for primitives 60 & 164, at:/basicAt: & integerAt:. If signedVersion is true
then generate signed accesses to the bits classes (a la 164 & 165). If signedVersion is false,
generate unsigned accesses (a la 60, 61, 63 & 64)."
| formatReg nSlotsOrBytesReg convertToIntAndReturn methodInBounds
jumpNotIndexable jumpImmediate jumpBadIndex
jumpIsBytes jumpIsShorts jumpIsWords jumpIsMethod
jumpWordTooBig jumpIsArray jumpHasFixedFields jumpIsContext
jumpBytesOutOfBounds jumpShortsOutOfBounds jumpWordsOutOfBounds
jumpArrayOutOfBounds jumpFixedFieldsOutOfBounds |
"c.f. StackInterpreter>>stSizeOf: SpurMemoryManager>>lengthOf:format: fixedFieldsOf:format:length:"
nSlotsOrBytesReg := ClassReg.
cogit genLoadArgAtDepth: 0 into: Arg0Reg.
jumpImmediate := self genJumpImmediate: ReceiverResultReg.
cogit MoveR: Arg0Reg R: Arg1Reg.
jumpBadIndex := self genJumpNotSmallInteger: Arg0Reg scratchReg: TempReg.
self genConvertSmallIntegerToIntegerInReg: Arg1Reg.
cogit SubCq: 1 R: Arg1Reg. "1-rel => 0-rel"
"formatReg := self formatOf: ReceiverResultReg"
self genGetFormatOf: ReceiverResultReg
into: (formatReg := SendNumArgsReg)
leastSignificantHalfOfBaseHeaderIntoScratch: TempReg.
self genGetNumSlotsOf: ReceiverResultReg into: nSlotsOrBytesReg.
"dispatch on format in a combination of highest dynamic frequency order first and convenience.
0 = 0 sized objects (UndefinedObject True False et al)
1 = non-indexable objects with inst vars (Point et al)
2 = indexable objects with no inst vars (Array et al)
3 = indexable objects with inst vars (MethodContext AdditionalMethodState et al)
4 = weak indexable objects with inst vars (WeakArray et al)
5 = weak non-indexable objects with inst vars (ephemerons) (Ephemeron)
6 unused, reserved for exotic pointer objects?
7 Forwarded Object, 1st field is pointer, rest of fields are ignored
8 unused, reserved for exotic non-pointer objects?
9 64-bit indexable
10 - 11 32-bit indexable
12 - 15 16-bit indexable
16 - 23 byte indexable
24 - 31 compiled method"
cogit CmpCq: objectMemory firstByteFormat R: formatReg.
jumpIsBytes := cogit JumpAboveOrEqual: 0.
cogit CmpCq: objectMemory arrayFormat R: formatReg.
jumpIsArray := cogit JumpZero: 0.
jumpNotIndexable := cogit JumpBelow: 0.
cogit CmpCq: objectMemory weakArrayFormat R: formatReg.
jumpHasFixedFields := cogit JumpBelowOrEqual: 0.
cogit CmpCq: objectMemory firstShortFormat R: formatReg.
jumpIsShorts := cogit JumpAboveOrEqual: 0.
cogit CmpCq: objectMemory firstLongFormat R: formatReg.
jumpIsWords := cogit JumpAboveOrEqual: 0.
"For now ignore 64-bit indexability."
jumpNotIndexable jmpTarget: cogit Label.
jumpNotIndexable := cogit Jump: 0.
jumpIsArray jmpTarget:
(cogit CmpR: Arg1Reg R: nSlotsOrBytesReg).
jumpArrayOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg1Reg.
cogit MoveXwr: Arg1Reg R: ReceiverResultReg R: ReceiverResultReg.
cogit genPrimReturn.
jumpIsBytes jmpTarget:
(cogit LogicalShiftLeftCq: objectMemory shiftForWord R: nSlotsOrBytesReg).
cogit AndCq: objectMemory wordSize - 1 R: formatReg R: TempReg.
cogit SubR: TempReg R: nSlotsOrBytesReg;
CmpR: Arg1Reg R: nSlotsOrBytesReg.
jumpBytesOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit CmpCq: objectMemory firstCompiledMethodFormat R: formatReg.
jumpIsMethod := cogit JumpAboveOrEqual: 0.
methodInBounds :=
cogit AddCq: objectMemory baseHeaderSize R: Arg1Reg.
(cogit backEnd byteReadsZeroExtend
or: [signedVersion])
ifTrue:
[cogit MoveXbr: Arg1Reg R: ReceiverResultReg R: ReceiverResultReg]
ifFalse:
[cogit "formatReg already contains a value <= 16r1f, so no need to zero it"
MoveXbr: Arg1Reg R: ReceiverResultReg R: formatReg;
MoveR: formatReg R: ReceiverResultReg].
signedVersion ifTrue:
[cogit SignExtend8R: ReceiverResultReg R: ReceiverResultReg].
convertToIntAndReturn := cogit Label.
self genConvertIntegerToSmallIntegerInReg: ReceiverResultReg.
cogit genPrimReturn.
jumpIsShorts jmpTarget:
(cogit LogicalShiftLeftCq: objectMemory shiftForWord - 1 R: nSlotsOrBytesReg).
cogit AndCq: 1 R: formatReg.
cogit SubR: formatReg R: nSlotsOrBytesReg;
CmpR: Arg1Reg R: nSlotsOrBytesReg.
jumpShortsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddR: Arg1Reg R: ReceiverResultReg.
cogit AddR: Arg1Reg R: ReceiverResultReg.
cogit MoveM16: objectMemory baseHeaderSize r: ReceiverResultReg R: ReceiverResultReg.
signedVersion ifTrue:
[cogit SignExtend16R: ReceiverResultReg R: ReceiverResultReg].
cogit Jump: convertToIntAndReturn.
jumpIsWords jmpTarget:
(cogit CmpR: Arg1Reg R: nSlotsOrBytesReg).
jumpWordsOutOfBounds := cogit JumpBelowOrEqual: 0.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg1Reg.
cogit MoveXwr: Arg1Reg R: ReceiverResultReg R: TempReg.
jumpWordTooBig := self jumpNotSmallIntegerUnsignedValueInRegister: TempReg.
cogit MoveR: TempReg R: ReceiverResultReg.
cogit Jump: convertToIntAndReturn.
jumpHasFixedFields jmpTarget:
(cogit AndCq: objectMemory classIndexMask R: TempReg).
cogit MoveR: TempReg R: formatReg.
cogit CmpCq: ClassMethodContextCompactIndex R: TempReg.
jumpIsContext := cogit JumpZero: 0.
cogit PushR: nSlotsOrBytesReg.
self genGetClassObjectOfClassIndex: formatReg into: nSlotsOrBytesReg scratchReg: TempReg.
self genLoadSlot: InstanceSpecificationIndex sourceReg: nSlotsOrBytesReg destReg: formatReg.
cogit PopR: nSlotsOrBytesReg.
self genConvertSmallIntegerToIntegerInReg: formatReg.
cogit
AndCq: objectMemory fixedFieldsOfClassFormatMask R: formatReg;
SubR: formatReg R: nSlotsOrBytesReg;
CmpR: Arg1Reg R: nSlotsOrBytesReg.
jumpFixedFieldsOutOfBounds := cogit JumpBelowOrEqual: 0.
"index is (formatReg (fixed fields) + Arg1Reg (0-rel index)) * wordSize + baseHeaderSize"
cogit AddR: formatReg R: Arg1Reg.
cogit AddCq: objectMemory baseHeaderSize >> objectMemory shiftForWord R: Arg1Reg.
cogit MoveXwr: Arg1Reg R: ReceiverResultReg R: ReceiverResultReg.
cogit genPrimReturn.
jumpIsMethod jmpTarget: cogit Label.
"Now check that the index is beyond the method's literals..."
self getLiteralCountOf: ReceiverResultReg plusOne: true inBytes: true into: nSlotsOrBytesReg scratch: TempReg.
cogit CmpR: Arg1Reg R: nSlotsOrBytesReg.
cogit JumpBelow: methodInBounds.
jumpWordTooBig jmpTarget:
(jumpFixedFieldsOutOfBounds jmpTarget:
(jumpArrayOutOfBounds jmpTarget:
(jumpBytesOutOfBounds jmpTarget:
(jumpShortsOutOfBounds jmpTarget:
(jumpWordsOutOfBounds jmpTarget:
(jumpNotIndexable jmpTarget:
(jumpIsContext jmpTarget:
(jumpBadIndex jmpTarget:
(jumpImmediate jmpTarget: cogit Label))))))))).
^0 "Can't be complete because of contexts."
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor32BitSpur >> genPrimitiveIdentityHash [
"Arguably we should fail for immediates, but so far no one has complained, so..."
| jumpImm jumpSI jumpNotSet ret |
<var: #jumpSI type: #'AbstractInstruction *'>
<var: #jumpImm type: #'AbstractInstruction *'>
<var: #jumpNotSet type: #'AbstractInstruction *'>
jumpImm := self genJumpImmediate: ReceiverResultReg.
self genGetHashFieldNonImmOf: ReceiverResultReg asSmallIntegerInto: TempReg.
cogit CmpCq: ConstZero R: TempReg.
jumpNotSet := cogit JumpZero: 0.
cogit MoveR: TempReg R: ReceiverResultReg.
ret := cogit genPrimReturn.
jumpImm jmpTarget: cogit Label.
jumpSI := self genJumpSmallInteger: ReceiverResultReg.
jumpSI jmpTarget: ret.
self genConvertCharacterToSmallIntegerInReg: ReceiverResultReg.
cogit Jump: ret.
jumpNotSet jmpTarget: cogit Label.
"For non-behaviors we can call ceNewHash to assign a fresh hash.
For behaviors we must fail into the interpreter primitive to enter the receiver into the class table."
cogit getPrimitiveIndex = 75 ifFalse:
[^0].
cogit backEnd saveAndRestoreLinkRegAround:
[cogit CallRT: ceNewHashTrampoline].
cogit genPrimReturn.
^UnfailingPrimitive
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor32BitSpur >> genPrimitiveImmediateAsInteger [
":Assume the receiuver is never a SmallInteger. One would use ^self for that."
self genConvertCharacterToSmallIntegerInReg: ReceiverResultReg.
cogit genPrimReturn.
^UnfailingPrimitive
]
{ #category : #'primitive generators' }
CogObjectRepresentationFor32BitSpur >> genPrimitiveNew [
"Implement primitiveNew for convenient cases:
- the receiver has a hash
- the receiver is fixed size (excluding ephemerons to save instructions & miniscule time)
- single word header/num slots < numSlotsMask
- the result fits in eden (actually below scavengeThreshold)"
| halfHeaderReg fillReg instSpecReg byteSizeReg
jumpUnhashed jumpVariableOrEphemeron jumpNoSpace jumpTooBig jumpHasSlots
fillLoop skip |
<var: 'skip' type: #'AbstractInstruction *'>
<var: 'fillLoop' type: #'AbstractInstruction *'>